canontra-0.1.0.0: src/Canontra/Canonical/StreamingHash.hs
{- |
Module : Canontra.Canonical.StreamingHash
Description : Zero-allocation direct ByteString.Builder streaming into SHA-256 context.
This module provides high-throughput streaming hashing directly from
pure Haskell 'Data.ByteString.Builder' streams into 'Crypto.Hash.SHA256'
contexts without allocating intermediate contiguous ByteString buffers on the heap.
-}
module Canontra.Canonical.StreamingHash
( hashBuilderDirect
, streamBuilderToSHA256
) where
import qualified Crypto.Hash.SHA256 as SHA256
import qualified Data.ByteString.Builder as BB
import qualified Data.ByteString.Builder.Extra as BBE
import qualified Data.ByteString.Lazy as LBS
import qualified Data.Text as T
import Text.Printf (printf)
import Canontra.Types (Fingerprint (..))
-- | Stream a ByteString Builder directly into a SHA-256 context fold.
hashBuilderDirect :: BB.Builder -> Fingerprint
hashBuilderDirect builder =
let lazyBs = BBE.toLazyByteStringWith
(BBE.safeStrategy 32768 32768)
LBS.empty
builder
finalCtx = LBS.foldlChunks SHA256.update SHA256.init lazyBs
digest = SHA256.finalize finalCtx
hexStr = concatMap (printf "%02x") (LBS.unpack (LBS.fromStrict digest))
in Fingerprint (T.pack hexStr)
-- | Incrementally update an existing SHA-256 context with Builder chunks.
streamBuilderToSHA256 :: SHA256.Ctx -> BB.Builder -> SHA256.Ctx
streamBuilderToSHA256 initialCtx builder =
let lazyBs = BBE.toLazyByteStringWith
(BBE.safeStrategy 32768 32768)
LBS.empty
builder
in LBS.foldlChunks SHA256.update initialCtx lazyBs