module Streaming.Binary
( decode
, decodeWith
, decoded
, decodedWith
, encode
, encodeWith
, encoded
, encodedWith
) where
import qualified Data.Binary.Get as Binary
import qualified Data.Binary.Put as Binary
import Data.Binary (Binary(..))
import qualified Data.ByteString.Builder.Extra as BS
import qualified Data.ByteString.Streaming as Q
import Data.ByteString.Streaming (ByteString)
import Data.Int (Int64)
import Streaming
import qualified Streaming.Prelude as S
decode
:: (Binary a, Monad m)
=> ByteString m r
-> m (ByteString m r, Int64, Either String a)
decode = decodeWith get
decodeWith
:: Monad m
=> Binary.Get a
-> ByteString m r
-> m (ByteString m r, Int64, Either String a)
decodeWith getter = go 0 (Binary.runGetIncremental getter)
where
go !total (Binary.Fail leftover nconsumed err) p = do
return (Q.chunk leftover >> p, total + nconsumed, Left err)
go !total (Binary.Done leftover nconsumed x) p = do
return (Q.chunk leftover >> p, total + nconsumed, Right x)
go !total (Binary.Partial k) p = do
Q.nextChunk p >>= \case
Left res -> go total (k Nothing) (return res)
Right (bs, p') -> go total (k (Just bs)) p'
decoded
:: (Binary a, Monad m)
=> ByteString m r
-> Stream (Of a) m (ByteString m r, Int64, Either String r)
decoded = decodedWith get
decodedWith
:: Monad m
=> Binary.Get a
-> ByteString m r
-> Stream (Of a) m (ByteString m r, Int64, Either String r)
decodedWith getter = go 0 decoder0
where
decoder0 = Binary.runGetIncremental getter
go !total (Binary.Fail leftover nconsumed err) p = do
return (Q.chunk leftover >> p, total + nconsumed, Left err)
go !total (Binary.Done "" nconsumed x) p = do
S.yield x
lift (Q.nextChunk p) >>= \case
Left res -> return (return res, total + nconsumed, Right res)
Right (bs, p') -> do
go (total + nconsumed) decoder0 (Q.chunk bs >> p')
go !total (Binary.Done leftover nconsumed x) p = do
S.yield x
go (total + nconsumed) (decoder0 `Binary.pushChunk` leftover) p
go !total (Binary.Partial k) p = do
lift (Q.nextChunk p) >>= \case
Left res -> go total (k Nothing) (return res)
Right (bs, p') -> go total (k (Just bs)) p'
encode
:: (Binary a, MonadIO m)
=> a
-> ByteString m ()
encode = encodeWith put
encodeWith
:: MonadIO m
=> (a -> Binary.Put)
-> a
-> ByteString m ()
encodeWith putter x =
Q.toStreamingByteStringWith
(BS.untrimmedStrategy BS.smallChunkSize BS.defaultChunkSize)
(Binary.execPut (putter x))
encoded
:: (Binary a, MonadIO m)
=> Stream (Of a) IO ()
-> ByteString m ()
encoded = encodedWith put
encodedWith
:: MonadIO m
=> (a -> Binary.Put)
-> Stream (Of a) IO ()
-> ByteString m ()
encodedWith putter xs =
hoist liftIO $
Q.toStreamingByteStringWith strategy $
Q.concatBuilders $
S.map (Binary.execPut . putter) xs
where
strategy = BS.untrimmedStrategy BS.smallChunkSize BS.defaultChunkSize