module Data.Conduit.Codec.Util
( CodecDecodeException(..)
, encodeI
, decodeI
, decodeII
, encodeII
) where
import Data.Typeable (Typeable)
import Control.Exception (Exception)
import Data.ByteString as BS (ByteString, append, null)
import Data.Conduit (Conduit, MonadThrow, await, monadThrow, yield)
import Data.Maybe (fromJust)
import Control.Monad (unless)
type EncFunc = ByteString -> ByteString
type EncFuncPart = ByteString -> (ByteString, ByteString)
type EncFuncFinal = ByteString -> Maybe ByteString
type DecFunc = ByteString -> Either (ByteString, ByteString) (ByteString, ByteString)
type DecFuncFinal = ByteString -> Maybe ByteString
data CodecDecodeException = CodecDecodeException ByteString
deriving (Typeable, Show)
instance Exception CodecDecodeException
encodeI :: (Monad m) => EncFuncPart -> EncFuncFinal -> ByteString -> Conduit ByteString m ByteString
encodeI enc_part enc_final i = do
clear <- await
case clear of
Nothing -> (yield $ fromJust $ enc_final i) >> return ()
Just s -> let
(a, b) = enc_part (i `append` s)
in do
unless (BS.null a) $ yield a
encodeI enc_part enc_final b
decodeI :: (Monad m, MonadThrow m) => DecFunc -> DecFuncFinal -> ByteString -> Conduit ByteString m ByteString
decodeI dec_part dec_final i = do
enc <- await
case enc of
Nothing ->
case dec_final i of
Nothing -> monadThrow (CodecDecodeException i)
Just s -> yield s >> return ()
Just s ->
case dec_part (i `append` s) of
Left (a, b) -> do
unless (BS.null a) $ yield a
monadThrow (CodecDecodeException b)
Right (a, b) -> do
unless (BS.null a) $ yield a
decodeI dec_part dec_final b
encodeII :: (Monad m) => EncFunc -> Conduit ByteString m ByteString
encodeII enc = do
clear <- await
case clear of
Nothing -> return ()
Just s -> do
yield $ enc s
encodeII enc
decodeII :: (Monad m, MonadThrow m) => DecFunc -> ByteString -> Conduit ByteString m ByteString
decodeII dec i = do
enc <- await
case enc of
Nothing -> if BS.null i
then return ()
else monadThrow $ CodecDecodeException i
Just s -> case (dec $ i `append` s) of
Left (c, b) -> do
unless (BS.null c) $ yield c
monadThrow $ CodecDecodeException b
Right (c, r) -> do
unless (BS.null c) $ yield c
decodeII dec r