All,
Recently I was looking for a way to calculate the SHA256 hash of a
stream of ByteStrings, but not only calculate this hash: also pass on
the stream so it could be stored to a file (use-case: receiving data
from a socket, which needs to be saved to a file, named after a hash of
the content, then returning this 'name' to the client).
I couldn't find any such library of-the-shelve in the Pipes ecosystem,
so I tried to implement something myself (with some help from IRC), and
just now pushed a first version of the code to GitHub.
So, consider this a 'request for feedback/review' :-)
The hashing itself is based on the 'cryptohash' library.
There are 2 interfaces:
- One where a (strict or lazy) ByteString Producer can be wrapped,
resulting in a new Producer which will yield the exact same values as
the original one, but tupling the result of the original Producer with a
digest. E.g.
hash :: (HashAlgorithm a, Monad m)
=> Producer ByteString (Producer ByteString m) r
-> Producer ByteString m (r, Digest a)
- One which acts as a real 'Pipe' which passes along every (strict or
lazy) ByteString it receives, and updates a hashing Context kept in a
State layer of the monad stack. E.g.
hashPipe :: (HashAlgorithm a, MonadState (Context a) m)
=> Pipe ByteString ByteString m r
These have some variants: working over streams of strict or lazy
bytestrings, requiring type inference to determine the hash type, or an
explicit value, or allowing to pass in an existing context (e.g.
generated by another stream before).
Code @
https://github.com/NicolasT/pipes-cryptohash/
Please let me know if you think the API could be enhanced, I'm doing
something utterly wrong,...
Thanks!
Nicolas