-- | A safe interface to SHA that still lets you digest incrementally module Codec.Digest.SHA.Monad( SHA, SHAT, Length(..), runSHAT, runSHA, Hashable(..), showBSasHex ) where import Codec.Digest.SHA.IO import qualified Data.ByteString as B import qualified Data.ByteString.Lazy as BL import Control.Monad.ST import Control.Monad.UnsafeIO import Control.Monad.Reader type SHAT m a = ReaderT SHACtx m a type SHA s a = SHAT (ST s) a runSHAT :: MonadUnsafeIO m => Length -> SHAT m a -> m (a,B.ByteString) runSHAT len shat = do ctx <- liftUnsafeIO $ newCtx len wrapped <- runReaderT shat ctx hash <- liftUnsafeIO $ unsafeFinalizeCtx ctx return (wrapped,hash) runSHA :: Length -> (forall s. SHA s a) -> (a,B.ByteString) runSHA len sha = runST $ runSHAT len sha -- | Hash some data, combining it with everything already hashed in -- this context class Hashable a where update :: MonadUnsafeIO m => a -> SHAT m () instance Hashable B.ByteString where update bs = do ctx <- ask liftUnsafeIO $ unsafeUpdateCtx ctx bs instance Hashable BL.ByteString where update bs = mapM_ update (BL.toChunks bs)