diff options
author | Benjamin Barenblat <bbaren@google.com> | 2018-01-26 20:50:10 -0500 |
---|---|---|
committer | Benjamin Barenblat <bbaren@google.com> | 2018-01-26 20:50:10 -0500 |
commit | 4f5f81d8df452b83dbe0f9f31c4d657200c54dfd (patch) | |
tree | 65ae44835ea86929af3836edd393078123a47201 /src | |
parent | 4e56c79b907da4a4654e5278bdcf94b08480a426 (diff) |
Data.Digest.Sha2: Accept lazy ByteStrings
Switch SHA-2 API to use lazy ByteStrings rather than strict. Lazy
ByteStrings make the hash function compatible with streaming I/O
patterns; users no longer need to preload all the data they wish to hash
into RAM.
Diffstat (limited to 'src')
-rw-r--r-- | src/Data/Digest/Internal.hs | 16 | ||||
-rw-r--r-- | src/Data/Digest/Sha2.hsc | 2 |
2 files changed, 12 insertions, 6 deletions
diff --git a/src/Data/Digest/Internal.hs b/src/Data/Digest/Internal.hs index acfb70c..1538276 100644 --- a/src/Data/Digest/Internal.hs +++ b/src/Data/Digest/Internal.hs @@ -8,6 +8,7 @@ import Control.Exception (assert) import Data.Bits (Bits((.&.)), shiftR) import Data.ByteString (ByteString) import qualified Data.ByteString as ByteString +import qualified Data.ByteString.Lazy as ByteString.Lazy import qualified Data.ByteString.Unsafe as ByteString import Data.Char (intToDigit) import Data.Word (Word8) @@ -18,6 +19,8 @@ import Unsafe.Coerce (unsafeCoerce) import Cleanse (mallocCleansablePtr) +type LazyByteString = ByteString.Lazy.ByteString + -- | A hash algorithm which follows the standard initialize-update-finalize -- pattern. data Algo = forall ctx. Storable ctx => Algo @@ -55,7 +58,7 @@ instance Show Digest where hexit = intToDigit . fromIntegral :: Word8 -> Char -- | Hashes according to the given 'Algo'. -hash :: Algo -> ByteString -> Digest +hash :: Algo -> LazyByteString -> Digest hash (Algo {mdLen, mdInit, mdUpdate, mdFinal}) bytes = let mdLen' = fromIntegral mdLen :: Int in unsafeLocalState $ do @@ -65,10 +68,7 @@ hash (Algo {mdLen, mdInit, mdUpdate, mdFinal}) bytes = ctxFP <- mallocCleansablePtr withForeignPtr ctxFP $ \ctx -> do alwaysSucceeds $ mdInit ctx - -- 'mdUpdate' treats its @buf@ argument as @const@, so the sharing - -- inherent in 'ByteString.unsafeUseAsCStringLen' is fine. - ByteString.unsafeUseAsCStringLen bytes $ \(buf, len) -> - alwaysSucceeds $ mdUpdate ctx buf (fromIntegral len) + mapM_ (updateBytes ctx) (ByteString.Lazy.toChunks bytes) d <- -- We could allocate another cleansable 'ForeignPtr' to store the -- digest, but we're going to be returning a copy of it as a ByteString @@ -84,3 +84,9 @@ hash (Algo {mdLen, mdInit, mdUpdate, mdFinal}) bytes = -- 'Ptr CChar' before it does its 'ByteString' ingestion. ByteString.packCStringLen (unsafeCoerce mdOut, mdLen') return (Digest d) + where + updateBytes ctx chunk = + -- 'mdUpdate' treats its @buf@ argument as @const@, so the sharing + -- inherent in 'ByteString.unsafeUseAsCStringLen' is fine. + ByteString.unsafeUseAsCStringLen chunk $ \(buf, len) -> + alwaysSucceeds $ mdUpdate ctx buf (fromIntegral len) diff --git a/src/Data/Digest/Sha2.hsc b/src/Data/Digest/Sha2.hsc index f587863..aa7c274 100644 --- a/src/Data/Digest/Sha2.hsc +++ b/src/Data/Digest/Sha2.hsc @@ -8,7 +8,7 @@ module Data.Digest.Sha2 , sha512 ) where -import Data.ByteString (ByteString) +import Data.ByteString.Lazy (ByteString) import Foreign (Ptr, Storable(alignment, sizeOf)) import Foreign.C.Types |