-- |
-- Module      : Crypto.Hash.Types
-- License     : BSD-style
-- Maintainer  : Vincent Hanquez <vincent@snarc.org>
-- Stability   : experimental
-- Portability : unknown
--
-- Crypto hash types definitions
--
module Crypto.Hash.Types
    ( HashAlgorithm(..)
    , Context(..)
    , Digest(..)
    -- * deprecated
    , contextToByteString
    , digestToByteString
    )
    where

import Data.ByteString (ByteString)
import Data.Byteable
import qualified Data.ByteString.Char8 as BC
import Crypto.Hash.Utils (toHex)

-- | Class representing hashing algorithms.
--
-- The hash algorithm is built over 3 primitives:
--
-- * init     : create a new hashing context
--
-- * updates  : update the hashing context with some strict bytestrings
--              and return the new context
--
-- * finalize : finalize the context into a digest
--
class HashAlgorithm a where
    -- | Block size in bytes the hash algorithm operates on
    hashBlockSize :: Context a -> Int

    -- | Initialize a new context for this hash algorithm
    hashInit     :: Context a

    -- | Update the context with a list of strict bytestring,
    -- and return a new context with the updates.
    hashUpdates  :: Context a -> [ByteString] -> Context a

    -- | Finalize a context and return a digest.
    hashFinalize :: Context a -> Digest a

    -- | Try to convert a binary digest bytestring to a digest.
    digestFromByteString :: ByteString -> Maybe (Digest a)

-- | Represent a context for a given hash algorithm.
newtype Context a = Context ByteString

instance Byteable (Context a) where
    toBytes (Context bs) = bs

-- | return the binary bytestring. deprecated use toBytes.
contextToByteString :: Context a -> ByteString
contextToByteString = toBytes

-- | Represent a digest for a given hash algorithm.
newtype Digest a = Digest ByteString
    deriving (Eq,Ord)

instance Byteable (Digest a) where
    toBytes (Digest bs) = bs

-- | return the binary bytestring. deprecated use toBytes.
{-# DEPRECATED digestToByteString "use toBytes from byteable:Data.Byteable" #-}
digestToByteString :: Digest a -> ByteString
digestToByteString = toBytes

instance Show (Digest a) where
    show (Digest bs) = BC.unpack $ toHex bs