    module Network.HTTP.Semantics.Trailer where

    import Network.ByteOrder
    import qualified Network.HTTP.Types as H

    -- | Trailers maker. A chunks of the response body is passed
    --   with 'Just'. The maker should update internal state
    --   with the 'ByteString' and return the next trailers maker.
    --   When response body reaches its end,
    --   'Nothing' is passed and the maker should generate
    --   trailers. An example:
    --
    --   > {-# LANGUAGE BangPatterns #-}
    --   > import Data.ByteString (ByteString)
    --   > import qualified Data.ByteString.Char8 as C8
    --   > import Crypto.Hash (Context, SHA1) -- cryptonite
    --   > import qualified Crypto.Hash as CH
    --   >
    --   > -- Strictness is important for Context.
    --   > trailersMaker :: Context SHA1 -> Maybe ByteString -> IO NextTrailersMaker
    --   > trailersMaker ctx Nothing = return $ Trailers [("X-SHA1", sha1)]
    --   >   where
    --   >     !sha1 = C8.pack $ show $ CH.hashFinalize ctx
    --   > trailersMaker ctx (Just bs) = return $ NextTrailersMaker $ trailersMaker ctx'
    --   >   where
    --   >     !ctx' = CH.hashUpdate ctx bs
    --
    --   Usage example:
    --
    --   > let h2rsp = responseFile ...
    --   >     maker = trailersMaker (CH.hashInit :: Context SHA1)
    --   >     h2rsp' = setResponseTrailersMaker h2rsp maker
    type TrailersMaker = Maybe ByteString -> IO NextTrailersMaker

    -- | TrailersMake to create no trailers.
    defaultTrailersMaker :: TrailersMaker
    defaultTrailersMaker :: TrailersMaker
    defaultTrailersMaker Maybe ByteString
    Nothing = NextTrailersMaker -> IO NextTrailersMaker
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (NextTrailersMaker -> IO NextTrailersMaker)
    -> NextTrailersMaker -> IO NextTrailersMaker
    forall a b. (a -> b) -> a -> b
    $ [Header] -> NextTrailersMaker
    Trailers []
    defaultTrailersMaker Maybe ByteString
    _ = NextTrailersMaker -> IO NextTrailersMaker
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (NextTrailersMaker -> IO NextTrailersMaker)
    -> NextTrailersMaker -> IO NextTrailersMaker
    forall a b. (a -> b) -> a -> b
    $ TrailersMaker -> NextTrailersMaker
    NextTrailersMaker TrailersMaker
    defaultTrailersMaker

    -- | Either the next trailers maker or final trailers.
    data NextTrailersMaker
        = NextTrailersMaker TrailersMaker
        | Trailers [H.Header]

    ----------------------------------------------------------------

    -- | Running trailers-maker.
    --
    -- > bufferIO buf siz $ \bs -> tlrmkr (Just bs)
    runTrailersMaker :: TrailersMaker -> Buffer -> Int -> IO NextTrailersMaker
    runTrailersMaker :: TrailersMaker -> Buffer -> Int -> IO NextTrailersMaker
    runTrailersMaker TrailersMaker
    tlrmkr Buffer
    buf Int
    siz = Buffer
    -> Int
    -> (ByteString -> IO NextTrailersMaker)
    -> IO NextTrailersMaker
    forall a. Buffer -> Int -> (ByteString -> IO a) -> IO a
    bufferIO Buffer
    buf Int
    siz ((ByteString -> IO NextTrailersMaker) -> IO NextTrailersMaker)
    -> (ByteString -> IO NextTrailersMaker) -> IO NextTrailersMaker
    forall a b. (a -> b) -> a -> b
    $ \ByteString
    bs -> TrailersMaker
    tlrmkr (ByteString -> Maybe ByteString
    forall a. a -> Maybe a
    Just ByteString
    bs)