    {-# LANGUAGE RankNTypes, BangPatterns #-}
    -- |
    -- Module      : Crypto.MAC.HMAC.Conduit
    -- License     : BSD-style
    -- Maintainer  : Vincent Hanquez <vincent@snarc.org>
    -- Stability   : experimental
    -- Portability : unknown
    --
    -- A module containing Conduit facilities for hmac based functions.
    --
    module Crypto.MAC.HMAC.Conduit
        ( -- * Cryptographic hash functions
          sinkHMAC
        ) where

    import Crypto.Hash
    import Crypto.MAC.HMAC
    import Data.ByteArray
    import Data.Conduit
    import qualified Data.ByteString as BS

    -- | A 'Sink' that calculates HMAC of a stream of 'B.ByteString'@s@ and
    -- returns digest @d@.
    sinkHMAC :: (Monad m, ByteArrayAccess key, HashAlgorithm hash) => key -> ConduitM BS.ByteString o m (HMAC hash)
    sinkHMAC :: key -> ConduitM ByteString o m (HMAC hash)
    sinkHMAC key :: key
    key = Context hash -> ConduitM ByteString o m (HMAC hash)
    forall (m :: * -> *) a message o.
    (Monad m, HashAlgorithm a, ByteArrayAccess message) =>
    Context a -> ConduitT message o m (HMAC a)
    sink (key -> Context hash
    forall key a.
    (ByteArrayAccess key, HashAlgorithm a) =>
    key -> Context a
    initialize key
    key)
      where sink :: Context a -> ConduitT message o m (HMAC a)
    sink ctx :: Context a
    ctx = do
                Maybe message
    b <- ConduitT message o m (Maybe message)
    forall (m :: * -> *) i. Monad m => Consumer i m (Maybe i)
    await
                case Maybe message
    b of
                    Nothing -> HMAC a -> ConduitT message o m (HMAC a)
    forall (m :: * -> *) a. Monad m => a -> m a
    return (HMAC a -> ConduitT message o m (HMAC a))
    -> HMAC a -> ConduitT message o m (HMAC a)
    forall a b. (a -> b) -> a -> b
    $! Context a -> HMAC a
    forall a. HashAlgorithm a => Context a -> HMAC a
    finalize Context a
    ctx
                    Just bs :: message
    bs -> Context a -> ConduitT message o m (HMAC a)
    sink (Context a -> ConduitT message o m (HMAC a))
    -> Context a -> ConduitT message o m (HMAC a)
    forall a b. (a -> b) -> a -> b
    $! Context a -> message -> Context a
    forall message a.
    (ByteArrayAccess message, HashAlgorithm a) =>
    Context a -> message -> Context a
    update Context a
    ctx message
    bs