Struct Hasher

struct Hasher { ... }

An incremental hash state that can accept any number of writes.

The rayon and mmap Cargo features enable additional methods on this type related to multithreading and memory-mapped IO.

When the traits-preview Cargo feature is enabled, this type implements several commonly used traits from the digest crate. However, those traits aren't stable, and they're expected to change in incompatible ways before that crate reaches 1.0. For that reason, this crate makes no SemVer guarantees for this feature, and callers who use it should expect breaking changes between patch versions.

Examples

# fn main() -> Result<(), Box<dyn std::error::Error>> {
// Hash an input incrementally.
let mut hasher = blake3::Hasher::new();
hasher.update(b"foo");
hasher.update(b"bar");
hasher.update(b"baz");
assert_eq!(hasher.finalize(), blake3::hash(b"foobarbaz"));

// Extended output. OutputReader also implements Read and Seek.
# #[cfg(feature = "std")] {
let mut output = [0; 1000];
let mut output_reader = hasher.finalize_xof();
output_reader.fill(&mut output);
assert_eq!(&output[..32], blake3::hash(b"foobarbaz").as_bytes());
# }
# Ok(())
# }

Implementations

impl Hasher

fn new() -> Self

Construct a new Hasher for the regular hash function.

fn new_keyed(key: &[u8; 32]) -> Self

Construct a new Hasher for the keyed hash function. See keyed_hash.

fn new_derive_key(context: &str) -> Self

Construct a new Hasher for the key derivation function. See derive_key. The context string should be hardcoded, globally unique, and application-specific.

fn reset(self: &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.

fn update(self: &mut Self, input: &[u8]) -> &mut Self

Add input bytes to the hash state. You can call this any number of times.

This method is always single-threaded. For multithreading support, see update_rayon (enabled with the rayon Cargo feature).

Note that the degree of SIMD parallelism that update can use is limited by the size of this input buffer. See update_reader.

fn finalize(self: &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.

fn finalize_xof(self: &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.

fn count(self: &Self) -> u64

Return the total number of bytes hashed so far.

fn update_reader<impl std::io::Read: std::io::Read>(self: &mut Self, reader: impl std::io::Read) -> std::io::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, but note that memory mapping can be faster than this method for hashing large files. See update_mmap and update_mmap_rayon, which require the mmap and (for the latter) rayon Cargo features.

This method requires the std Cargo feature, which is enabled by default.

Example

# use std::fs::File;
# use std::io;
# fn main() -> io::Result<()> {
// Hash standard input.
let mut hasher = blake3::Hasher::new();
hasher.update_reader(std::io::stdin().lock())?;
println!("{}", hasher.finalize());
# Ok(())
# }

impl Clone for Hasher

fn clone(self: &Self) -> Hasher

impl Debug for Hasher

fn fmt(self: &Self, f: &mut fmt::Formatter<'_>) -> fmt::Result

impl Default for Hasher

fn default() -> Self

impl Freeze for Hasher

impl RefUnwindSafe for Hasher

impl Send for Hasher

impl Sync for Hasher

impl Unpin for Hasher

impl UnwindSafe for Hasher

impl Write for Hasher

fn write(self: &mut Self, input: &[u8]) -> std::io::Result<usize>

This is equivalent to update.

fn flush(self: &mut Self) -> std::io::Result<()>

impl<T> Any for Hasher

fn type_id(self: &Self) -> TypeId

impl<T> Borrow for Hasher

fn borrow(self: &Self) -> &T

impl<T> BorrowMut for Hasher

fn borrow_mut(self: &mut Self) -> &mut T

impl<T> CloneToUninit for Hasher

unsafe fn clone_to_uninit(self: &Self, dest: *mut u8)

impl<T> From for Hasher

fn from(t: T) -> T

Returns the argument unchanged.

impl<T> ToOwned for Hasher

fn to_owned(self: &Self) -> T
fn clone_into(self: &Self, target: &mut T)

impl<T, U> Into for Hasher

fn into(self: Self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of [From]<T> for U chooses to do.

impl<T, U> TryFrom for Hasher

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

impl<T, U> TryInto for Hasher

fn try_into(self: Self) -> Result<U, <U as TryFrom<T>>::Error>