{-# LANGUAGE FlexibleInstances    #-}
{-# LANGUAGE UndecidableInstances #-}
{-# OPTIONS_GHC -Wno-orphans      #-}
{-|
 - This module provides a conversion function between a
 - 'Flake' and a lazy 'ByteString'.
-}

module Data.Snowchecked.Encoding.ByteString.Lazy
	( module Data.Snowchecked.Encoding.Class
	) where

import           Data.ByteString.Lazy
import           Data.Snowchecked.Encoding.Class
import           Data.Snowchecked.Encoding.Integral ()
import           Data.Snowchecked.Internal.Import
import           Prelude                            hiding (foldr)

integerToBS :: Integer -> ByteString
integerToBS :: Integer -> ByteString
integerToBS = [Word8] -> ByteString
pack ([Word8] -> ByteString)
-> (Integer -> [Word8]) -> Integer -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Integer -> [Word8]
forall t a. (Integral t, Num a, Bits t) => t -> [a]
mkBytes
	where
		mkBytes :: t -> [a]
mkBytes t
0 = [a]
forall a. Monoid a => a
mempty
		mkBytes t
n
			= t -> a
forall a b. (Integral a, Num b) => a -> b
fromIntegral t
n
			a -> [a] -> [a]
forall a. a -> [a] -> [a]
: t -> [a]
mkBytes (t
n t -> Int -> t
forall a. Bits a => a -> Int -> a
`shiftR` Int
8)
{-# INLINE integerToBS #-}

bsToInteger :: ByteString -> Integer
bsToInteger :: ByteString -> Integer
bsToInteger = (Word8 -> Integer -> Integer) -> Integer -> ByteString -> Integer
forall a. (Word8 -> a -> a) -> a -> ByteString -> a
foldr Word8 -> Integer -> Integer
mkInteger Integer
0
	where
		mkInteger :: Word8 -> Integer -> Integer
		mkInteger :: Word8 -> Integer -> Integer
mkInteger Word8
nxt Integer
memo = Integer
memo Integer -> Int -> Integer
forall a. Bits a => a -> Int -> a
`shiftL` Int
8 Integer -> Integer -> Integer
forall a. Bits a => a -> a -> a
.|. Word8 -> Integer
forall a. Integral a => a -> Integer
toInteger Word8
nxt
{-# INLINE bsToInteger #-}

instance IsFlake ByteString where
	fromFlake :: Flake -> ByteString
fromFlake = Integer -> ByteString
integerToBS (Integer -> ByteString)
-> (Flake -> Integer) -> Flake -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Flake -> Integer
forall a. IsFlake a => Flake -> a
fromFlake
	{-# INLINE fromFlake #-}

	parseFish :: SnowcheckedConfig -> ByteString -> m Flakeish
parseFish SnowcheckedConfig
cfg = SnowcheckedConfig -> Integer -> m Flakeish
forall a (m :: * -> *).
(IsFlake a, MonadFail m) =>
SnowcheckedConfig -> a -> m Flakeish
parseFish SnowcheckedConfig
cfg (Integer -> m Flakeish)
-> (ByteString -> Integer) -> ByteString -> m Flakeish
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> Integer
bsToInteger
	{-# INLINE parseFish #-}