    {-# LANGUAGE FlexibleContexts #-}
    {-# LANGUAGE RankNTypes #-}
    -- | Streaming compression and decompression using conduits.
    --
    -- Parts of this code were taken from zlib-enum and adapted for conduits.
    module Data.Conduit.Zlib (
        -- * Conduits
        compress, decompress, gzip, ungzip,
        -- * Flushing
        compressFlush, decompressFlush,
        -- * Decompression combinators
        multiple,
        -- * Re-exported from zlib-bindings
        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 compression with default parameters.
    gzip :: (MonadThrow m, PrimMonad m) => ConduitT ByteString ByteString m ()
    gzip :: forall (m :: * -> *).
    (MonadThrow m, PrimMonad m) =>
    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)

    -- | Gzip decompression with default parameters.
    ungzip :: (PrimMonad m, MonadThrow m) => ConduitT ByteString ByteString m ()
    ungzip :: forall (m :: * -> *).
    (PrimMonad m, MonadThrow m) =>
    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 :: forall (m :: * -> *) a. (PrimMonad m, MonadThrow m) => IO a -> m a
    unsafeLiftIO = IO a -> m a
    forall (m1 :: * -> *) (m2 :: * -> *) a.
    (PrimBase m1, PrimMonad m2) =>
    m1 a -> m2 a
    unsafePrimToPrim

    -- |
    -- Decompress (inflate) a stream of 'ByteString's. For example:
    --
    -- >    sourceFile "test.z" $= decompress defaultWindowBits $$ sinkFile "test"

    decompress
        :: (PrimMonad m, MonadThrow m)
        => WindowBits -- ^ Zlib parameter (see the zlib-bindings package as well as the zlib C library)
        -> ConduitT ByteString ByteString m ()
    decompress :: forall (m :: * -> *).
    (PrimMonad m, MonadThrow m) =>
    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 a b. (a -> b) -> Maybe a -> Maybe b
    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 o. Monad m => ConduitT i o 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 a. a -> ConduitT i o m a
    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

    -- | Same as 'decompress', but allows you to explicitly flush the stream.
    decompressFlush
        :: (PrimMonad m, MonadThrow m)
        => WindowBits -- ^ Zlib parameter (see the zlib-bindings package as well as the zlib C library)
        -> ConduitT (Flush ByteString) (Flush ByteString) m ()
    decompressFlush :: forall (m :: * -> *).
    (PrimMonad m, MonadThrow m) =>
    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 o. Monad m => ConduitT i o 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 :: 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 t m (Maybe (Flush ByteString))
    await' Flush ByteString -> t m ()
    yield' ByteString -> t m ()
    leftover' WindowBits
    config = do
        -- Initialize the stateful inflater, which will be used below
        -- This inflater is never exposed outside of this function
        Inflate
    inf <- m Inflate -> t m Inflate
    forall (m :: * -> *) a. Monad m => m a -> t m a
    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

        -- Some helper functions used by the main feeder loop below

        let -- Flush any remaining inflated bytes downstream
            flush :: t m ()
    flush = do
                ByteString
    chunk <- m ByteString -> t m ByteString
    forall (m :: * -> *) a. Monad m => m a -> t m a
    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

            -- Get any input which is unused by the inflater
            getUnused :: t m ByteString
    getUnused = m ByteString -> t m ByteString
    forall (m :: * -> *) a. Monad m => m a -> t m a
    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

            -- If there is any unused data, return it as leftovers to the stream
            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'

        -- Main loop: feed data from upstream into the inflater
        (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
                -- No more data is available from upstream
                Maybe (Flush ByteString)
    Nothing -> do
                    -- Flush any remaining uncompressed data
                    t m ()
    flush
                    -- Return the rest of the unconsumed data as leftovers
                    t m ()
    unused
                -- Another chunk of compressed data arrived
                Just (Chunk ByteString
    x) -> do
                    -- Feed the compressed data into the inflater, returning a
                    -- "popper" which will return chunks of decompressed data
                    Popper
    popper <- m Popper -> t m Popper
    forall (m :: * -> *) a. Monad m => m a -> t m a
    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

                    -- Loop over the popper grabbing decompressed chunks and
                    -- yielding them downstream
                    (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 (m :: * -> *) a. Monad m => m a -> t m a
    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
                            -- No more data from this popper
                            PopperRes
    PRDone -> do
                                ByteString
    rem' <- t m ByteString
    getUnused
                                if ByteString -> Bool
    S.null ByteString
    rem'
                                    -- No data was unused by the inflater, so let's
                                    -- fill it up again and get more data out of it
                                    then t m ()
    feeder
                                    -- In this case, there is some unconsumed data,
                                    -- meaning the compressed stream is complete.
                                    -- At this point, we need to stop feeding,
                                    -- return the unconsumed data as leftovers, and
                                    -- flush any remaining content (which should be
                                    -- nothing)
                                    else do
                                        t m ()
    flush
                                        ByteString -> t m ()
    leftover' ByteString
    rem'
                            -- Another chunk available, yield it downstream and
                            -- loop again
                            PRNext ByteString
    bs -> do
                                Flush ByteString -> t m ()
    yield' (ByteString -> Flush ByteString
    forall a. a -> Flush a
    Chunk ByteString
    bs)
                                t m ()
    pop
                            -- An error occurred inside zlib, throw it
                            PRError ZlibException
    e -> m () -> t m ()
    forall (m :: * -> *) a. Monad m => m a -> t m a
    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 e a. Exception e => e -> m a
    forall (m :: * -> *) e a. (MonadThrow m, Exception e) => e -> m a
    throwM ZlibException
    e
                -- We've been asked to flush the stream
                Just Flush ByteString
    Flush -> do
                    -- Get any uncompressed data waiting for us
                    t m ()
    flush
                    -- Put a Flush in the stream
                    Flush ByteString -> t m ()
    yield' Flush ByteString
    forall a. Flush a
    Flush
                    -- Feed in more data
                    t m ()
    feeder

    -- |
    -- Compress (deflate) a stream of 'ByteString's. The 'WindowBits' also control
    -- the format (zlib vs. gzip).

    compress
        :: (PrimMonad m, MonadThrow m)
        => Int         -- ^ Compression level
        -> WindowBits  -- ^ Zlib parameter (see the zlib-bindings package as well as the zlib C library)
        -> ConduitT ByteString ByteString m ()
    compress :: forall (m :: * -> *).
    (PrimMonad m, MonadThrow m) =>
    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 a b. (a -> b) -> Maybe a -> Maybe b
    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 o. Monad m => ConduitT i o 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 a. a -> ConduitT i o m a
    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

    -- | Same as 'compress', but allows you to explicitly flush the stream.
    compressFlush
        :: (PrimMonad m, MonadThrow m)
        => Int         -- ^ Compression level
        -> WindowBits  -- ^ Zlib parameter (see the zlib-bindings package as well as the zlib C library)
        -> ConduitT (Flush ByteString) (Flush ByteString) m ()
    compressFlush :: forall (m :: * -> *).
    (PrimMonad m, MonadThrow m) =>
    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 o. Monad m => ConduitT i o 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 :: 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 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 a b. t m a -> (a -> t m b) -> t m b
    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 a. a -> t m a
    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 (m :: * -> *) a. Monad m => m a -> t m a
    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 a b. t m a -> (a -> t m b) -> t m b
    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 (m :: * -> *) a. Monad m => m a -> t m a
    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 a. a -> t m a
    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 a b. t m a -> t m b -> t m b
    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 (m :: * -> *) a. Monad m => m a -> t m a
    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 e a. Exception e => e -> m a
    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 (m :: * -> *) a. Monad m => m a -> t m a
    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 (m :: * -> *) a. Monad m => m a -> t m a
    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 a. a -> t m a
    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 (m :: * -> *) a. Monad m => m a -> t m a
    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 e a. Exception e => e -> m a
    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 (m :: * -> *) a. Monad m => m a -> t m a
    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 a. a -> t m a
    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 a b. t m a -> t m b -> t m b
    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 (m :: * -> *) a. Monad m => m a -> t m a
    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 e a. Exception e => e -> m a
    forall (m :: * -> *) e a. (MonadThrow m, Exception e) => e -> m a
    throwM ZlibException
    e

    -- | The standard 'decompress' and 'ungzip' functions will only decompress a
    -- single compressed entity from the stream. This combinator will exhaust the
    -- stream completely of all individual compressed entities. This is useful for
    -- cases where you have a concatenated archive, e.g. @cat file1.gz file2.gz >
    -- combined.gz@.
    --
    -- Usage:
    --
    -- > sourceFile "combined.gz" $$ multiple ungzip =$ consume
    --
    -- This combinator will not fail on an empty stream. If you want to ensure that
    -- at least one compressed entity in the stream exists, consider a usage such
    -- as:
    --
    -- > sourceFile "combined.gz" $$ (ungzip >> multiple ungzip) =$ consume
    --
    -- @since 1.1.10
    multiple :: Monad m
             => ConduitT ByteString a m ()
             -> ConduitT ByteString a m ()
    multiple :: forall (m :: * -> *) a.
    Monad m =>
    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 o. Monad m => ConduitT i o m (Maybe i)
    await
            case Maybe ByteString
    mbs of
                Maybe ByteString
    Nothing -> () -> ConduitT ByteString a m ()
    forall a. a -> ConduitT ByteString a m a
    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