rattletrap-10.0.0: src/lib/Rattletrap/BitGet.hs
module Rattletrap.BitGet where
import qualified Control.Monad as Monad
import qualified Data.Binary.Bits.Get as BinaryBits
import qualified Data.Binary.Get as Binary
import qualified Data.Bits as Bits
import qualified Data.ByteString as ByteString
import qualified Data.ByteString.Lazy as LazyByteString
import qualified Data.Word as Word
import qualified Rattletrap.ByteGet as ByteGet
import qualified Rattletrap.Get as Get
import qualified Rattletrap.Utility.Bytes as Utility
type BitGet = BinaryBits.BitGet
toByteGet :: BitGet a -> ByteGet.ByteGet a
toByteGet = binaryGetToByteGet . BinaryBits.runBitGet
binaryGetToByteGet :: Binary.Get a -> ByteGet.ByteGet a
binaryGetToByteGet g = do
s1 <- Get.get
case Binary.runGetOrFail g $ LazyByteString.fromStrict s1 of
Left (_, _, x) -> fail x
Right (s2, _, x) -> do
Get.put $ LazyByteString.toStrict s2
pure x
fromByteGet :: ByteGet.ByteGet a -> Int -> BitGet a
fromByteGet f n = do
x <- BinaryBits.getByteString n
either fail pure . ByteGet.run f $ Utility.reverseBytes x
bits :: Bits.Bits a => Int -> BitGet a
bits n =
foldr
(\bit x -> let y = Bits.shiftL x 1 in if bit then Bits.setBit y 0 else y
)
Bits.zeroBits
<$> Monad.replicateM n bool
bool :: BitGet Bool
bool = BinaryBits.getBool
byteString :: Int -> BitGet ByteString.ByteString
byteString = BinaryBits.getByteString
word8 :: Int -> BitGet Word.Word8
word8 = BinaryBits.getWord8