polkavm_common/
hasher.rs

1#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
2pub struct Hash(pub [u8; 32]);
3
4impl From<[u8; 32]> for Hash {
5    fn from(hash: [u8; 32]) -> Self {
6        Self(hash)
7    }
8}
9
10impl core::fmt::Display for Hash {
11    fn fmt(&self, fmt: &mut core::fmt::Formatter) -> core::fmt::Result {
12        for &byte in &self.0 {
13            write!(fmt, "{:02x}", byte)?;
14        }
15
16        Ok(())
17    }
18}
19
20impl core::fmt::Debug for Hash {
21    fn fmt(&self, fmt: &mut core::fmt::Formatter) -> core::fmt::Result {
22        for &byte in &self.0 {
23            write!(fmt, "Hash({:02x})", byte)?;
24        }
25
26        Ok(())
27    }
28}
29
30pub struct Hasher {
31    #[cfg(not(feature = "blake3"))]
32    inner: crate::blake3::Hasher,
33    #[cfg(feature = "blake3")]
34    inner: blake3::Hasher,
35}
36
37impl Default for Hasher {
38    fn default() -> Self {
39        Self::new()
40    }
41}
42
43impl Hasher {
44    pub fn new() -> Self {
45        Self {
46            #[cfg(not(feature = "blake3"))]
47            inner: crate::blake3::Hasher::new(),
48            #[cfg(feature = "blake3")]
49            inner: blake3::Hasher::new(),
50        }
51    }
52
53    pub fn update(&mut self, bytes: &[u8]) {
54        self.inner.update(bytes);
55    }
56
57    pub fn update_u32_array<const N: usize>(&mut self, values: [u32; N]) {
58        if cfg!(target_endian = "little") {
59            let new_length = values.len().checked_mul(4).expect("overflow");
60
61            // SAFETY: An u32 slice can always be safely reinterpreted as an u8 slice.
62            #[allow(unsafe_code)]
63            let bytes: &[u8] = unsafe { core::slice::from_raw_parts(values.as_ptr().cast::<u8>(), new_length) };
64
65            self.update(bytes)
66        } else {
67            for value in values {
68                self.update(&value.to_le_bytes());
69            }
70        }
71    }
72
73    pub fn finalize(&self) -> Hash {
74        #[cfg(not(feature = "blake3"))]
75        {
76            let mut hash = [0; 32];
77            self.inner.finalize(&mut hash);
78            Hash(hash)
79        }
80        #[cfg(feature = "blake3")]
81        {
82            let h = self.inner.finalize();
83            Hash(*h.as_bytes())
84        }
85    }
86}
87
88impl core::hash::Hasher for Hasher {
89    fn finish(&self) -> u64 {
90        let h = self.finalize().0;
91        u64::from_le_bytes([h[0], h[1], h[2], h[3], h[4], h[5], h[6], h[7]])
92    }
93
94    fn write(&mut self, bytes: &[u8]) {
95        self.update(bytes);
96    }
97}