toad_common/
hash.rs

1use core::fmt::Debug;
2use core::hash::Hasher;
3
4use blake2::digest::typenum::U8;
5use blake2::{Blake2b, Digest};
6
7/// Heap-allocless [`Hasher`] implementation that uses
8/// the [`blake2`] algo to generate a 64 bit hash.
9///
10/// ```
11/// use core::hash::{Hash, Hasher};
12///
13/// use toad_common::hash::Blake2Hasher;
14///
15/// let mut hasher_a = Blake2Hasher::new();
16/// let mut hasher_b = Blake2Hasher::new();
17///
18/// let bytes = core::iter::repeat(0u8..255).take(512)
19///                                         .flatten()
20///                                         .collect::<Vec<u8>>();
21///
22/// bytes.hash(&mut hasher_a);
23/// bytes.hash(&mut hasher_b);
24/// assert_eq!(hasher_a.finish(), hasher_b.finish());
25///
26/// "hello".hash(&mut hasher_a);
27/// "hello".hash(&mut hasher_b);
28/// assert_eq!(hasher_a.finish(), hasher_b.finish());
29///
30/// 123_u16.hash(&mut hasher_a);
31/// "not 123!".hash(&mut hasher_b);
32/// assert_ne!(hasher_a.finish(), hasher_b.finish());
33/// ```
34#[derive(Default, Clone)]
35pub struct Blake2Hasher(Blake2b<U8>);
36
37impl Blake2Hasher {
38  /// Create a new `Blake2Hasher`
39  pub fn new() -> Self {
40    Self::default()
41  }
42}
43
44impl Debug for Blake2Hasher {
45  fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
46    f.debug_tuple("Blake2Hasher")
47     .field(&"<Blake2bCore<U8>>")
48     .finish()
49  }
50}
51
52impl Hasher for Blake2Hasher {
53  fn finish(&self) -> u64 {
54    u64::from_be_bytes(self.0.clone().finalize().into())
55  }
56
57  fn write(&mut self, bytes: &[u8]) {
58    self.0.update(bytes);
59  }
60}