module Util.Binary ( runGetA
, runPutA
, putFloatbe
, putFloatle
, putFloathost
, putDoublebe
, putDoublele
, putDoublehost
, putLength16beByteString
, putLength32beByteString
, putWithLength16be
, putWithLength32be
, putChar8
, getChar8
, getFloatbe
, getFloatle
, getFloathost
, getDoublebe
, getDoublele
, getDoublehost
, getLength8ByteString
, getLength16beByteString
, getLength32beByteString
, getWithLength16be
, matchWord8
, matchChar8
)
where
import qualified Data.ByteString as BS
import qualified Data.ByteString.Lazy as BL
import Data.Binary.Get
import Data.Binary.Put
import Data.Word
import Data.Char
import Util.FloatCast
runGetA :: (Monad m) => (Int -> m BS.ByteString) -> (BS.ByteString -> m ()) -> Get a -> m (Either String a)
runGetA readA unreadA getA = feed (runGetIncremental getA) (readA 2048)
where
feed (Done unused _pos output) _input = do unreadA unused ; return $ Right output
feed (Fail unused pos msg) _input = do unreadA unused ; return $ Left $ "runGetA: pos " ++ show pos ++ ": " ++ show msg
feed (Partial k) input = do
chunk <- input
if BS.null chunk then
feed (k Nothing) input
else
feed (k (Just chunk)) input
runPutA :: (BL.ByteString -> m ()) -> Put -> m ()
runPutA = (. runPut)
putFloatbe :: Float -> Put
putFloatbe = putWord32be . floatToWord
putFloatle :: Float -> Put
putFloatle = putWord32le . floatToWord
putFloathost :: Float -> Put
putFloathost = putWord32host . floatToWord
putDoublebe :: Double -> Put
putDoublebe = putWord64be . doubleToWord
putDoublele :: Double -> Put
putDoublele = putWord64le . doubleToWord
putDoublehost :: Double -> Put
putDoublehost = putWord64host . doubleToWord
putLength16beByteString :: BS.ByteString -> Put
putLength16beByteString bs = do
putWord16be (fromIntegral (BS.length bs))
putByteString bs
putLength32beByteString :: BS.ByteString -> Put
putLength32beByteString bs = do
putWord32be (fromIntegral (BS.length bs))
putByteString bs
putWithLength16be :: Put -> Put
putWithLength16be putA = do
let bl = runPut putA
len = BL.length bl
putWord16be (fromIntegral len)
putLazyByteString bl
putWithLength32be :: Put -> Put
putWithLength32be putA = do
let bl = runPut putA
len = BL.length bl
putWord32be (fromIntegral len)
putLazyByteString bl
putChar8 :: Char -> Put
putChar8 c = do
putWord8 $ fromIntegral $ ord c
getChar8 :: Get Char
getChar8 = (chr . fromIntegral ) <$> getWord8
getFloatbe :: Get Float
getFloatbe = wordToFloat <$> getWord32be
getFloatle :: Get Float
getFloatle = wordToFloat <$> getWord32le
getFloathost :: Get Float
getFloathost = wordToFloat <$> getWord32host
getDoublebe :: Get Double
getDoublebe = wordToDouble <$> getWord64be
getDoublele :: Get Double
getDoublele = wordToDouble <$> getWord64le
getDoublehost :: Get Double
getDoublehost = wordToDouble <$> getWord64host
getLength8ByteString :: Get BS.ByteString
getLength8ByteString = getWord8 >>= getByteString . fromIntegral
getLength16beByteString :: Get BS.ByteString
getLength16beByteString = getWord16be >>= getByteString . fromIntegral
getLength32beByteString :: Get BS.ByteString
getLength32beByteString = getWord32be >>= getByteString . fromIntegral
getWithLength16be :: Get a -> Get (a, Word16)
getWithLength16be getA = do
pos0 <- bytesRead
res <- getA
pos1 <- bytesRead
return (res, fromIntegral (pos1 pos0))
matchWord8 :: Word8 -> Get ()
matchWord8 expected = do
actual <- getWord8
if expected == actual
then return ()
else fail $ "expected " ++ show expected ++ ", actual " ++ show actual
matchChar8 :: Char -> Get ()
matchChar8 expected = do
matchWord8 $ fromIntegral $ ord expected