packages feed

md5-0.1.0.0: src/Hash/Md5.hs

{-# language BangPatterns #-}
{-# language DataKinds #-}
{-# language MagicHash #-}
{-# language UnliftedFFITypes #-}

module Hash.Md5
  ( Context(..)
    -- * Context Reuse
  , context
  , reinitialize
  , update
  , finalize
    -- * One Shot
  , boundedBuilder
  ) where

import Control.Monad.ST (ST)
import Data.Bytes.Builder.Bounded as BB
import Data.Bytes.Builder.Bounded.Unsafe as BBU
import Data.Bytes.Types (Bytes(Bytes))
import Data.Primitive (ByteArray(..),MutableByteArray(..))
import Data.Primitive (newByteArray)
import GHC.Exts (Int(I#),Int#,MutableByteArray#,ByteArray#,unsafeCoerce#)
import GHC.Exts (RealWorld)
import GHC.IO (unsafeIOToST)

import Hash.Md5.Internal

newtype Context s = Context (MutableByteArray s)

-- | Create a new context. The context is initialized.
context :: ST s (Context s)
context = do
  b <- newByteArray 88
  reinitialize (Context b)
  pure (Context b)

-- | Reset the context so that it may be used to hash another byte sequence.
reinitialize :: Context s -> ST s ()
reinitialize (Context (MutableByteArray ctx)) =
  unsafeIOToST (c_md5_init (unsafeCoerce# ctx))

finalize ::
     Context s
  -> MutableByteArray s -- ^ Destination, implied length is 16
  -> Int -- ^ Destination offset
  -> ST s ()
finalize (Context (MutableByteArray ctx)) (MutableByteArray x) !a =
  unsafeIOToST (c_md5_finalize (unsafeCoerce# ctx) (unsafeCoerce# x) a)

update ::
     Context s
  -> Bytes
  -> ST s ()
update (Context (MutableByteArray ctx)) (Bytes (ByteArray arr) off len) =
  unsafeIOToST (c_md5_update_unsafe (unsafeCoerce# ctx) arr off len)

performHash :: MutableByteArray s -> Int -> ByteArray -> Int -> Int -> ST s ()
performHash (MutableByteArray x) !a (ByteArray y) !b !c =
  unsafeIOToST $ do
    MutableByteArray ctx <- newByteArray 88
    c_md5_init ctx
    c_md5_update_unsafe ctx y b c
    c_md5_finalize ctx (unsafeCoerce# x) a

boundedBuilder :: Bytes -> BB.Builder 16
boundedBuilder (Bytes arr off len) = BBU.construct
  (\buf ix -> do
    performHash buf ix arr off len
    pure (ix + 16)
  )