pub struct Hasher { /* private fields */ }Expand description
A message’s hash, fed in pieces: update with each
piece, in order, then finalize. The pieces may be
of any lengths; the hash is the same as hash of them all at once.
A Hasher is about 18 KiB (it holds short pieces until it has 16 KiB
to hash at once); box it where that matters.
§Examples
// Hash an input incrementally.
let mut hasher = blake3_servil::Hasher::new();
hasher.update(b"foo");
hasher.update(b"bar");
hasher.update(b"baz");
assert_eq!(hasher.finalize(), blake3_servil::hash(b"foobarbaz"));
// Extended output. OutputReader also implements Read and Seek.
let mut output = [0; 1000];
let mut output_reader = hasher.finalize_xof();
output_reader.fill(&mut output);
assert_eq!(&output[..32], blake3_servil::hash(b"foobarbaz").as_bytes());Implementations§
Source§impl Hasher
impl Hasher
Sourcepub fn update_each(hashers: &mut [Hasher], pieces: &[(usize, &[u8])])
pub fn update_each(hashers: &mut [Hasher], pieces: &[(usize, &[u8])])
Feed each piece to its hasher: (i, bytes) does
hashers[i].update(bytes), each hasher’s pieces in their order in
pieces. Call it once with all the pieces your program has in hand
(one turn of its event loop): never slower than one
update each. Requires each i < hashers.len().
use blake3_servil::Hasher;
let mut hashers = vec![Hasher::new(), Hasher::new()];
Hasher::update_each(&mut hashers, &[(0, b"ab"), (1, b"xyz"), (0, b"c")]);
let mut out = [[0u8; 32]; 2];
Hasher::finalize_each(&hashers, &[0, 1], &mut out);
assert_eq!((&out[0], &out[1]), (blake3_servil::hash(b"abc").as_bytes(), blake3_servil::hash(b"xyz").as_bytes()));Sourcepub fn update_each_multithreaded(
hashers: &mut [Hasher],
pieces: &[(usize, &[u8])],
)
pub fn update_each_multithreaded( hashers: &mut [Hasher], pieces: &[(usize, &[u8])], )
update_each, using other CPU cores where
that is faster (pieces of 512 KiB and more): the same result, never
slower.
Requires each i < hashers.len().
Source§impl Hasher
impl Hasher
Sourcepub fn new_with(mode: Mode<'_>) -> Self
pub fn new_with(mode: Mode<'_>) -> Self
Construct a new Hasher in a Mode: the keyed hash, or key
derivation with a context string or a context hashed once.
Sourcepub fn reset(&mut self) -> &mut Self
pub fn reset(&mut self) -> &mut Self
Reset the Hasher to its initial state.
This is functionally the same as overwriting the Hasher with a new
one, using the same key or context string if any.
Sourcepub fn update(&mut self, input: &[u8]) -> &mut Self
pub fn update(&mut self, input: &[u8]) -> &mut Self
Add the message’s next piece, of any length, on the calling thread.
Speed: pieces of any size hash at nearly the speed of whole
buffers: short pieces are copied into the Hasher until it holds
16 KiB, which then hash at once. Pieces of 16 KiB and more, starting
at a multiple of 16 KiB of the message, skip the copy (about 5% of the
time on an Apple M4). For a whole message in memory, hash is a
little faster; for a file or reader, see
update_reader.
Sourcepub fn update_multithreaded(&mut self, input: &[u8]) -> &mut Self
pub fn update_multithreaded(&mut self, input: &[u8]) -> &mut Self
update, using other CPU cores where that is
faster: the same result, never slower. Pieces of 512 KiB and more
use them, as hash_multithreaded does; shorter ones hash on the
calling thread. One Hasher may mix the two calls. When reading
the pieces keeps your thread busy, a stream is faster
(Stream::submit_reader, or Stream::submit_with): it hashes
each piece while your thread reads the next.
let input = vec![7u8; 3 << 20];
let mut hasher = blake3_servil::Hasher::new();
for piece in input.chunks(64 * 1024) {
hasher.update_multithreaded(piece);
}
assert_eq!(hasher.finalize(), blake3_servil::hash(&input));Sourcepub fn finalize(&self) -> Hash
pub fn finalize(&self) -> Hash
Finalize the hash state and return the Hash of
the input.
This method is idempotent. Calling it twice will give the same result. You can also add more input and finalize again.
Sourcepub fn finalize_xof(&self) -> OutputReader ⓘ
pub fn finalize_xof(&self) -> OutputReader ⓘ
Finalize the hash state and return an OutputReader, which can
supply any number of output bytes.
This method is idempotent. Calling it twice will give the same result. You can also add more input and finalize again.
Sourcepub fn update_reader(&mut self, reader: impl Read) -> Result<&mut Self>
pub fn update_reader(&mut self, reader: impl Read) -> Result<&mut Self>
As update, but reading from a
std::io::Read implementation.
Hasher implements
std::io::Write, so it’s possible to
use std::io::copy to update a Hasher
from any reader. Unfortunately, this standard approach can limit performance, because
copy currently uses an internal 8 KiB buffer that isn’t big enough to take advantage of
all SIMD instruction sets. (In particular, AVX-512
needs a 16 KiB buffer.) update_reader avoids this performance problem and is slightly
more convenient.
The internal buffer size this method uses may change at any time, and it may be different for different targets. The only guarantee is that it will be large enough for all of this crate’s SIMD implementations on the current platform.
The most common implementer of
std::io::Read might be
std::fs::File.
This method requires the std Cargo feature, which is enabled by default.
§Example
// Hash standard input.
let mut hasher = blake3_servil::Hasher::new();
hasher.update_reader(std::io::stdin().lock())?;
println!("{}", hasher.finalize());Trait Implementations§
Source§impl Write for Hasher
Available on crate feature std only.
impl Write for Hasher
std only.Source§fn flush(&mut self) -> Result<()>
fn flush(&mut self) -> Result<()>
Source§fn is_write_vectored(&self) -> bool
fn is_write_vectored(&self) -> bool
can_vector)1.0.0 · Source§fn write_all(&mut self, buf: &[u8]) -> Result<(), Error>
fn write_all(&mut self, buf: &[u8]) -> Result<(), Error>
Source§fn write_all_vectored(&mut self, bufs: &mut [IoSlice<'_>]) -> Result<(), Error>
fn write_all_vectored(&mut self, bufs: &mut [IoSlice<'_>]) -> Result<(), Error>
write_all_vectored)