{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE RankNTypes #-}
module Data.Conduit.Zlib (
compress, decompress, gzip, ungzip,
compressFlush, decompressFlush,
multiple,
WindowBits (..), defaultWindowBits
) where
import Data.Streaming.Zlib
import Data.Conduit
import Data.ByteString (ByteString)
import qualified Data.ByteString as S
import Control.Monad (unless, liftM)
import Control.Monad.Trans.Class (lift, MonadTrans)
import Control.Monad.Primitive (PrimMonad, unsafePrimToPrim)
import Control.Monad.Trans.Resource (MonadThrow, throwM)
import Data.Function (fix)
gzip :: (MonadThrow m, PrimMonad m) => ConduitT ByteString ByteString m ()
gzip :: ConduitT ByteString ByteString m ()
gzip = Int -> WindowBits -> ConduitT ByteString ByteString m ()
forall (m :: * -> *).
(PrimMonad m, MonadThrow m) =>
Int -> WindowBits -> ConduitT ByteString ByteString m ()
compress (-Int
1) (Int -> WindowBits
WindowBits Int
31)
ungzip :: (PrimMonad m, MonadThrow m) => ConduitT ByteString ByteString m ()
ungzip :: ConduitT ByteString ByteString m ()
ungzip = WindowBits -> ConduitT ByteString ByteString m ()
forall (m :: * -> *).
(PrimMonad m, MonadThrow m) =>
WindowBits -> ConduitT ByteString ByteString m ()
decompress (Int -> WindowBits
WindowBits Int
31)
unsafeLiftIO :: (PrimMonad m, MonadThrow m) => IO a -> m a
unsafeLiftIO :: IO a -> m a
unsafeLiftIO = IO a -> m a
forall (m1 :: * -> *) (m2 :: * -> *) a.
(PrimBase m1, PrimMonad m2) =>
m1 a -> m2 a
unsafePrimToPrim
decompress
:: (PrimMonad m, MonadThrow m)
=> WindowBits
-> ConduitT ByteString ByteString m ()
decompress :: WindowBits -> ConduitT ByteString ByteString m ()
decompress =
ConduitT ByteString ByteString m (Maybe (Flush ByteString))
-> (Flush ByteString -> ConduitT ByteString ByteString m ())
-> (ByteString -> ConduitT ByteString ByteString m ())
-> WindowBits
-> ConduitT ByteString ByteString m ()
forall (t :: (* -> *) -> * -> *) (m :: * -> *).
(Monad (t m), PrimMonad m, MonadThrow m, MonadTrans t) =>
t m (Maybe (Flush ByteString))
-> (Flush ByteString -> t m ())
-> (ByteString -> t m ())
-> WindowBits
-> t m ()
helperDecompress ((Maybe ByteString -> Maybe (Flush ByteString))
-> ConduitT ByteString ByteString m (Maybe ByteString)
-> ConduitT ByteString ByteString m (Maybe (Flush ByteString))
forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
liftM ((ByteString -> Flush ByteString)
-> Maybe ByteString -> Maybe (Flush ByteString)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ByteString -> Flush ByteString
forall a. a -> Flush a
Chunk) ConduitT ByteString ByteString m (Maybe ByteString)
forall (m :: * -> *) i. Monad m => Consumer i m (Maybe i)
await) Flush ByteString -> ConduitT ByteString ByteString m ()
forall (m :: * -> *) o i. Monad m => Flush o -> ConduitT i o m ()
yield' ByteString -> ConduitT ByteString ByteString m ()
forall i o (m :: * -> *). i -> ConduitT i o m ()
leftover
where
yield' :: Flush o -> ConduitT i o m ()
yield' Flush o
Flush = () -> ConduitT i o m ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
yield' (Chunk o
bs) = o -> ConduitT i o m ()
forall (m :: * -> *) o i. Monad m => o -> ConduitT i o m ()
yield o
bs
decompressFlush
:: (PrimMonad m, MonadThrow m)
=> WindowBits
-> ConduitT (Flush ByteString) (Flush ByteString) m ()
decompressFlush :: WindowBits -> ConduitT (Flush ByteString) (Flush ByteString) m ()
decompressFlush = ConduitT
(Flush ByteString) (Flush ByteString) m (Maybe (Flush ByteString))
-> (Flush ByteString
-> ConduitT (Flush ByteString) (Flush ByteString) m ())
-> (ByteString
-> ConduitT (Flush ByteString) (Flush ByteString) m ())
-> WindowBits
-> ConduitT (Flush ByteString) (Flush ByteString) m ()
forall (t :: (* -> *) -> * -> *) (m :: * -> *).
(Monad (t m), PrimMonad m, MonadThrow m, MonadTrans t) =>
t m (Maybe (Flush ByteString))
-> (Flush ByteString -> t m ())
-> (ByteString -> t m ())
-> WindowBits
-> t m ()
helperDecompress ConduitT
(Flush ByteString) (Flush ByteString) m (Maybe (Flush ByteString))
forall (m :: * -> *) i. Monad m => Consumer i m (Maybe i)
await Flush ByteString
-> ConduitT (Flush ByteString) (Flush ByteString) m ()
forall (m :: * -> *) o i. Monad m => o -> ConduitT i o m ()
yield (Flush ByteString
-> ConduitT (Flush ByteString) (Flush ByteString) m ()
forall i o (m :: * -> *). i -> ConduitT i o m ()
leftover (Flush ByteString
-> ConduitT (Flush ByteString) (Flush ByteString) m ())
-> (ByteString -> Flush ByteString)
-> ByteString
-> ConduitT (Flush ByteString) (Flush ByteString) m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> Flush ByteString
forall a. a -> Flush a
Chunk)
helperDecompress :: (Monad (t m), PrimMonad m, MonadThrow m, MonadTrans t)
=> t m (Maybe (Flush ByteString))
-> (Flush ByteString -> t m ())
-> (ByteString -> t m ())
-> WindowBits
-> t m ()
helperDecompress :: t m (Maybe (Flush ByteString))
-> (Flush ByteString -> t m ())
-> (ByteString -> t m ())
-> WindowBits
-> t m ()
helperDecompress t m (Maybe (Flush ByteString))
await' Flush ByteString -> t m ()
yield' ByteString -> t m ()
leftover' WindowBits
config = do
Inflate
inf <- m Inflate -> t m Inflate
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m Inflate -> t m Inflate) -> m Inflate -> t m Inflate
forall a b. (a -> b) -> a -> b
$ IO Inflate -> m Inflate
forall (m :: * -> *) a. (PrimMonad m, MonadThrow m) => IO a -> m a
unsafeLiftIO (IO Inflate -> m Inflate) -> IO Inflate -> m Inflate
forall a b. (a -> b) -> a -> b
$ WindowBits -> IO Inflate
initInflate WindowBits
config
let
flush :: t m ()
flush = do
ByteString
chunk <- m ByteString -> t m ByteString
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m ByteString -> t m ByteString) -> m ByteString -> t m ByteString
forall a b. (a -> b) -> a -> b
$ IO ByteString -> m ByteString
forall (m :: * -> *) a. (PrimMonad m, MonadThrow m) => IO a -> m a
unsafeLiftIO (IO ByteString -> m ByteString) -> IO ByteString -> m ByteString
forall a b. (a -> b) -> a -> b
$ Inflate -> IO ByteString
flushInflate Inflate
inf
Bool -> t m () -> t m ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (ByteString -> Bool
S.null ByteString
chunk) (t m () -> t m ()) -> t m () -> t m ()
forall a b. (a -> b) -> a -> b
$ Flush ByteString -> t m ()
yield' (Flush ByteString -> t m ()) -> Flush ByteString -> t m ()
forall a b. (a -> b) -> a -> b
$ ByteString -> Flush ByteString
forall a. a -> Flush a
Chunk ByteString
chunk
getUnused :: t m ByteString
getUnused = m ByteString -> t m ByteString
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m ByteString -> t m ByteString) -> m ByteString -> t m ByteString
forall a b. (a -> b) -> a -> b
$ IO ByteString -> m ByteString
forall (m :: * -> *) a. (PrimMonad m, MonadThrow m) => IO a -> m a
unsafeLiftIO (IO ByteString -> m ByteString) -> IO ByteString -> m ByteString
forall a b. (a -> b) -> a -> b
$ Inflate -> IO ByteString
getUnusedInflate Inflate
inf
unused :: t m ()
unused = do
ByteString
rem' <- t m ByteString
getUnused
Bool -> t m () -> t m ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (ByteString -> Bool
S.null ByteString
rem') (t m () -> t m ()) -> t m () -> t m ()
forall a b. (a -> b) -> a -> b
$ ByteString -> t m ()
leftover' ByteString
rem'
(t m () -> t m ()) -> t m ()
forall a. (a -> a) -> a
fix ((t m () -> t m ()) -> t m ()) -> (t m () -> t m ()) -> t m ()
forall a b. (a -> b) -> a -> b
$ \t m ()
feeder -> do
Maybe (Flush ByteString)
mnext <- t m (Maybe (Flush ByteString))
await'
case Maybe (Flush ByteString)
mnext of
Maybe (Flush ByteString)
Nothing -> do
t m ()
flush
t m ()
unused
Just (Chunk ByteString
x) -> do
Popper
popper <- m Popper -> t m Popper
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m Popper -> t m Popper) -> m Popper -> t m Popper
forall a b. (a -> b) -> a -> b
$ IO Popper -> m Popper
forall (m :: * -> *) a. (PrimMonad m, MonadThrow m) => IO a -> m a
unsafeLiftIO (IO Popper -> m Popper) -> IO Popper -> m Popper
forall a b. (a -> b) -> a -> b
$ Inflate -> ByteString -> IO Popper
feedInflate Inflate
inf ByteString
x
(t m () -> t m ()) -> t m ()
forall a. (a -> a) -> a
fix ((t m () -> t m ()) -> t m ()) -> (t m () -> t m ()) -> t m ()
forall a b. (a -> b) -> a -> b
$ \t m ()
pop -> do
PopperRes
mbs <- m PopperRes -> t m PopperRes
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m PopperRes -> t m PopperRes) -> m PopperRes -> t m PopperRes
forall a b. (a -> b) -> a -> b
$ Popper -> m PopperRes
forall (m :: * -> *) a. (PrimMonad m, MonadThrow m) => IO a -> m a
unsafeLiftIO Popper
popper
case PopperRes
mbs of
PopperRes
PRDone -> do
ByteString
rem' <- t m ByteString
getUnused
if ByteString -> Bool
S.null ByteString
rem'
then t m ()
feeder
else do
t m ()
flush
ByteString -> t m ()
leftover' ByteString
rem'
PRNext ByteString
bs -> do
Flush ByteString -> t m ()
yield' (ByteString -> Flush ByteString
forall a. a -> Flush a
Chunk ByteString
bs)
t m ()
pop
PRError ZlibException
e -> m () -> t m ()
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m () -> t m ()) -> m () -> t m ()
forall a b. (a -> b) -> a -> b
$ ZlibException -> m ()
forall (m :: * -> *) e a. (MonadThrow m, Exception e) => e -> m a
throwM ZlibException
e
Just Flush ByteString
Flush -> do
t m ()
flush
Flush ByteString -> t m ()
yield' Flush ByteString
forall a. Flush a
Flush
t m ()
feeder
compress
:: (PrimMonad m, MonadThrow m)
=> Int
-> WindowBits
-> ConduitT ByteString ByteString m ()
compress :: Int -> WindowBits -> ConduitT ByteString ByteString m ()
compress =
ConduitT ByteString ByteString m (Maybe (Flush ByteString))
-> (Flush ByteString -> ConduitT ByteString ByteString m ())
-> Int
-> WindowBits
-> ConduitT ByteString ByteString m ()
forall (t :: (* -> *) -> * -> *) (m :: * -> *).
(Monad (t m), PrimMonad m, MonadThrow m, MonadTrans t) =>
t m (Maybe (Flush ByteString))
-> (Flush ByteString -> t m ()) -> Int -> WindowBits -> t m ()
helperCompress ((Maybe ByteString -> Maybe (Flush ByteString))
-> ConduitT ByteString ByteString m (Maybe ByteString)
-> ConduitT ByteString ByteString m (Maybe (Flush ByteString))
forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
liftM ((ByteString -> Flush ByteString)
-> Maybe ByteString -> Maybe (Flush ByteString)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ByteString -> Flush ByteString
forall a. a -> Flush a
Chunk) ConduitT ByteString ByteString m (Maybe ByteString)
forall (m :: * -> *) i. Monad m => Consumer i m (Maybe i)
await) Flush ByteString -> ConduitT ByteString ByteString m ()
forall (m :: * -> *) o i. Monad m => Flush o -> ConduitT i o m ()
yield'
where
yield' :: Flush o -> ConduitT i o m ()
yield' Flush o
Flush = () -> ConduitT i o m ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
yield' (Chunk o
bs) = o -> ConduitT i o m ()
forall (m :: * -> *) o i. Monad m => o -> ConduitT i o m ()
yield o
bs
compressFlush
:: (PrimMonad m, MonadThrow m)
=> Int
-> WindowBits
-> ConduitT (Flush ByteString) (Flush ByteString) m ()
compressFlush :: Int
-> WindowBits
-> ConduitT (Flush ByteString) (Flush ByteString) m ()
compressFlush = ConduitT
(Flush ByteString) (Flush ByteString) m (Maybe (Flush ByteString))
-> (Flush ByteString
-> ConduitT (Flush ByteString) (Flush ByteString) m ())
-> Int
-> WindowBits
-> ConduitT (Flush ByteString) (Flush ByteString) m ()
forall (t :: (* -> *) -> * -> *) (m :: * -> *).
(Monad (t m), PrimMonad m, MonadThrow m, MonadTrans t) =>
t m (Maybe (Flush ByteString))
-> (Flush ByteString -> t m ()) -> Int -> WindowBits -> t m ()
helperCompress ConduitT
(Flush ByteString) (Flush ByteString) m (Maybe (Flush ByteString))
forall (m :: * -> *) i. Monad m => Consumer i m (Maybe i)
await Flush ByteString
-> ConduitT (Flush ByteString) (Flush ByteString) m ()
forall (m :: * -> *) o i. Monad m => o -> ConduitT i o m ()
yield
helperCompress :: (Monad (t m), PrimMonad m, MonadThrow m, MonadTrans t)
=> t m (Maybe (Flush ByteString))
-> (Flush ByteString -> t m ())
-> Int
-> WindowBits
-> t m ()
helperCompress :: t m (Maybe (Flush ByteString))
-> (Flush ByteString -> t m ()) -> Int -> WindowBits -> t m ()
helperCompress t m (Maybe (Flush ByteString))
await' Flush ByteString -> t m ()
yield' Int
level WindowBits
config =
t m (Maybe (Flush ByteString))
await' t m (Maybe (Flush ByteString))
-> (Maybe (Flush ByteString) -> t m ()) -> t m ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= t m ()
-> (Flush ByteString -> t m ())
-> Maybe (Flush ByteString)
-> t m ()
forall b a. b -> (a -> b) -> Maybe a -> b
maybe (() -> t m ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()) Flush ByteString -> t m ()
start
where
start :: Flush ByteString -> t m ()
start Flush ByteString
input = do
Deflate
def <- m Deflate -> t m Deflate
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m Deflate -> t m Deflate) -> m Deflate -> t m Deflate
forall a b. (a -> b) -> a -> b
$ IO Deflate -> m Deflate
forall (m :: * -> *) a. (PrimMonad m, MonadThrow m) => IO a -> m a
unsafeLiftIO (IO Deflate -> m Deflate) -> IO Deflate -> m Deflate
forall a b. (a -> b) -> a -> b
$ Int -> WindowBits -> IO Deflate
initDeflate Int
level WindowBits
config
Deflate -> Flush ByteString -> t m ()
push Deflate
def Flush ByteString
input
continue :: Deflate -> t m ()
continue Deflate
def = t m (Maybe (Flush ByteString))
await' t m (Maybe (Flush ByteString))
-> (Maybe (Flush ByteString) -> t m ()) -> t m ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= t m ()
-> (Flush ByteString -> t m ())
-> Maybe (Flush ByteString)
-> t m ()
forall b a. b -> (a -> b) -> Maybe a -> b
maybe (Deflate -> t m ()
close Deflate
def) (Deflate -> Flush ByteString -> t m ()
push Deflate
def)
goPopper :: Popper -> t m ()
goPopper Popper
popper = do
PopperRes
mbs <- m PopperRes -> t m PopperRes
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m PopperRes -> t m PopperRes) -> m PopperRes -> t m PopperRes
forall a b. (a -> b) -> a -> b
$ Popper -> m PopperRes
forall (m :: * -> *) a. (PrimMonad m, MonadThrow m) => IO a -> m a
unsafeLiftIO Popper
popper
case PopperRes
mbs of
PopperRes
PRDone -> () -> t m ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
PRNext ByteString
bs -> Flush ByteString -> t m ()
yield' (ByteString -> Flush ByteString
forall a. a -> Flush a
Chunk ByteString
bs) t m () -> t m () -> t m ()
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Popper -> t m ()
goPopper Popper
popper
PRError ZlibException
e -> m () -> t m ()
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m () -> t m ()) -> m () -> t m ()
forall a b. (a -> b) -> a -> b
$ ZlibException -> m ()
forall (m :: * -> *) e a. (MonadThrow m, Exception e) => e -> m a
throwM ZlibException
e
push :: Deflate -> Flush ByteString -> t m ()
push Deflate
def (Chunk ByteString
x) = do
Popper
popper <- m Popper -> t m Popper
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m Popper -> t m Popper) -> m Popper -> t m Popper
forall a b. (a -> b) -> a -> b
$ IO Popper -> m Popper
forall (m :: * -> *) a. (PrimMonad m, MonadThrow m) => IO a -> m a
unsafeLiftIO (IO Popper -> m Popper) -> IO Popper -> m Popper
forall a b. (a -> b) -> a -> b
$ Deflate -> ByteString -> IO Popper
feedDeflate Deflate
def ByteString
x
Popper -> t m ()
goPopper Popper
popper
Deflate -> t m ()
continue Deflate
def
push Deflate
def Flush ByteString
Flush = do
PopperRes
mchunk <- m PopperRes -> t m PopperRes
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m PopperRes -> t m PopperRes) -> m PopperRes -> t m PopperRes
forall a b. (a -> b) -> a -> b
$ Popper -> m PopperRes
forall (m :: * -> *) a. (PrimMonad m, MonadThrow m) => IO a -> m a
unsafeLiftIO (Popper -> m PopperRes) -> Popper -> m PopperRes
forall a b. (a -> b) -> a -> b
$ Deflate -> Popper
flushDeflate Deflate
def
case PopperRes
mchunk of
PopperRes
PRDone -> () -> t m ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
PRNext ByteString
x -> Flush ByteString -> t m ()
yield' (Flush ByteString -> t m ()) -> Flush ByteString -> t m ()
forall a b. (a -> b) -> a -> b
$ ByteString -> Flush ByteString
forall a. a -> Flush a
Chunk ByteString
x
PRError ZlibException
e -> m () -> t m ()
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m () -> t m ()) -> m () -> t m ()
forall a b. (a -> b) -> a -> b
$ ZlibException -> m ()
forall (m :: * -> *) e a. (MonadThrow m, Exception e) => e -> m a
throwM ZlibException
e
Flush ByteString -> t m ()
yield' Flush ByteString
forall a. Flush a
Flush
Deflate -> t m ()
continue Deflate
def
close :: Deflate -> t m ()
close Deflate
def = do
PopperRes
mchunk <- m PopperRes -> t m PopperRes
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m PopperRes -> t m PopperRes) -> m PopperRes -> t m PopperRes
forall a b. (a -> b) -> a -> b
$ Popper -> m PopperRes
forall (m :: * -> *) a. (PrimMonad m, MonadThrow m) => IO a -> m a
unsafeLiftIO (Popper -> m PopperRes) -> Popper -> m PopperRes
forall a b. (a -> b) -> a -> b
$ Deflate -> Popper
finishDeflate Deflate
def
case PopperRes
mchunk of
PopperRes
PRDone -> () -> t m ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
PRNext ByteString
chunk -> Flush ByteString -> t m ()
yield' (ByteString -> Flush ByteString
forall a. a -> Flush a
Chunk ByteString
chunk) t m () -> t m () -> t m ()
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Deflate -> t m ()
close Deflate
def
PRError ZlibException
e -> m () -> t m ()
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m () -> t m ()) -> m () -> t m ()
forall a b. (a -> b) -> a -> b
$ ZlibException -> m ()
forall (m :: * -> *) e a. (MonadThrow m, Exception e) => e -> m a
throwM ZlibException
e
multiple :: Monad m
=> ConduitT ByteString a m ()
-> ConduitT ByteString a m ()
multiple :: ConduitT ByteString a m () -> ConduitT ByteString a m ()
multiple ConduitT ByteString a m ()
inner =
ConduitT ByteString a m ()
loop
where
loop :: ConduitT ByteString a m ()
loop = do
Maybe ByteString
mbs <- ConduitT ByteString a m (Maybe ByteString)
forall (m :: * -> *) i. Monad m => Consumer i m (Maybe i)
await
case Maybe ByteString
mbs of
Maybe ByteString
Nothing -> () -> ConduitT ByteString a m ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
Just ByteString
bs
| ByteString -> Bool
S.null ByteString
bs -> ConduitT ByteString a m ()
loop
| Bool
otherwise -> do
ByteString -> ConduitT ByteString a m ()
forall i o (m :: * -> *). i -> ConduitT i o m ()
leftover ByteString
bs
ConduitT ByteString a m ()
inner
ConduitT ByteString a m ()
loop