    -- |
    -- Module      : Crypto.Hash.SHA512t
    -- License     : BSD-style
    -- Maintainer  : Vincent Hanquez <vincent@snarc.org>
    -- Stability   : experimental
    -- Portability : unknown
    --
    -- A module containing SHA512/t
    --
    module Crypto.Hash.SHA512t
        ( Ctx(..)

        -- * Incremental hashing Functions
        , init     -- :: Ctx
        , update   -- :: Ctx -> ByteString -> Ctx
        , finalize -- :: Ctx -> ByteString

        -- * Single Pass hashing
        , hash     -- :: ByteString -> ByteString
        , hashlazy -- :: ByteString -> ByteString
        ) where

    import Prelude hiding (init)
    import Data.List (foldl')
    import Data.ByteString (ByteString)
    import qualified Data.ByteString as B
    import qualified Data.ByteString.Lazy as L

    import qualified Crypto.Hash.SHA512 as SHA512

    -- | SHA512 Context with variable size output
    data Ctx = Ctx !Int !SHA512.Ctx

    -- | init a context
    init :: Int -> Ctx
    init :: Int -> Ctx
    init Int
    t = Int -> Ctx -> Ctx
    Ctx Int
    t (Int -> Ctx
    SHA512.init_t Int
    t)

    -- | update a context with a bytestring
    update :: Ctx -> ByteString -> Ctx
    update :: Ctx -> ByteString -> Ctx
    update (Ctx Int
    t Ctx
    ctx) ByteString
    d = Int -> Ctx -> Ctx
    Ctx Int
    t (Ctx -> ByteString -> Ctx
    SHA512.update Ctx
    ctx ByteString
    d)

    -- | finalize the context into a digest bytestring
    finalize :: Ctx -> ByteString
    finalize :: Ctx -> ByteString
    finalize (Ctx Int
    sz Ctx
    ctx) = Int -> ByteString -> ByteString
    B.take (Int
    sz Int -> Int -> Int
    forall a. Integral a => a -> a -> a
    `div` Int
    8) (Ctx -> ByteString
    SHA512.finalize Ctx
    ctx)

    -- | hash a strict bytestring into a digest bytestring
    hash :: Int -> ByteString -> ByteString
    hash :: Int -> ByteString -> ByteString
    hash Int
    t = Ctx -> ByteString
    finalize (Ctx -> ByteString)
    -> (ByteString -> Ctx) -> ByteString -> ByteString
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Ctx -> ByteString -> Ctx
    update (Int -> Ctx
    init Int
    t)

    -- | hash a lazy bytestring into a digest bytestring
    hashlazy :: Int -> L.ByteString -> ByteString
    hashlazy :: Int -> ByteString -> ByteString
    hashlazy Int
    t = Ctx -> ByteString
    finalize (Ctx -> ByteString)
    -> (ByteString -> Ctx) -> ByteString -> ByteString
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (Ctx -> ByteString -> Ctx) -> Ctx -> [ByteString] -> Ctx
    forall b a. (b -> a -> b) -> b -> [a] -> b
    forall (t :: * -> *) b a.
    Foldable t =>
    (b -> a -> b) -> b -> t a -> b
    foldl' Ctx -> ByteString -> Ctx
    update (Int -> Ctx
    init Int
    t) ([ByteString] -> Ctx)
    -> (ByteString -> [ByteString]) -> ByteString -> Ctx
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . ByteString -> [ByteString]
    L.toChunks