module Data.Conduit.Cereal where
import qualified Data.ByteString as BS
import qualified Data.ByteString.Lazy as LBS
import Data.Typeable (Typeable)
import Control.Exception (Exception)
import Control.Monad.Trans
import qualified Data.Conduit as DC
import Data.Conduit.List (sourceList)
import Data.Serialize.Get
import Data.Serialize.Put
data GetError = GetError String
| PrematureClose
deriving (Show, Typeable)
instance Exception GetError
sinkGet :: DC.ResourceThrow m => Get output -> DC.Sink BS.ByteString m output
sinkGet get = DC.SinkData { DC.sinkPush = push (runGetPartial get)
, DC.sinkClose = close
}
where push f input = do
case f input of
Fail s -> lift $ DC.resourceThrow $ GetError s
Partial f' -> return $ DC.Processing (push f') close
Done r rest -> return $ DC.Done (if BS.null rest
then Nothing
else Just rest
) r
close = lift $ DC.resourceThrow PrematureClose
sourcePut :: DC.Resource m => Put -> DC.Source m BS.ByteString
sourcePut put = sourceList $ LBS.toChunks $ runPutLazy put