Skip to main content

stwo_gpu/core/vcs/
blake3_hash.rs

1use core::fmt;
2
3use serde::{Deserialize, Serialize};
4use std_shims::Vec;
5
6use crate::core::vcs::hash::Hash;
7
8// Wrapper for the blake3 hash type.
9#[derive(Clone, Copy, PartialEq, Default, Eq, Serialize, Deserialize)]
10pub struct Blake3Hash([u8; 32]);
11
12impl From<Blake3Hash> for Vec<u8> {
13    fn from(value: Blake3Hash) -> Self {
14        Vec::from(value.0)
15    }
16}
17
18impl From<Vec<u8>> for Blake3Hash {
19    fn from(value: Vec<u8>) -> Self {
20        Self(
21            value
22                .try_into()
23                .expect("Failed converting Vec<u8> to Blake3Hash Type!"),
24        )
25    }
26}
27
28impl From<&[u8]> for Blake3Hash {
29    fn from(value: &[u8]) -> Self {
30        Self(
31            value
32                .try_into()
33                .expect("Failed converting &[u8] to Blake3Hash Type!"),
34        )
35    }
36}
37
38impl AsRef<[u8]> for Blake3Hash {
39    fn as_ref(&self) -> &[u8] {
40        &self.0
41    }
42}
43
44impl fmt::Display for Blake3Hash {
45    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
46        f.write_str(&hex::encode(self.0))
47    }
48}
49
50impl fmt::Debug for Blake3Hash {
51    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
52        <Blake3Hash as fmt::Display>::fmt(self, f)
53    }
54}
55
56impl Hash for Blake3Hash {}
57
58// Wrapper for the blake3 Hashing functionalities.
59#[derive(Clone, Default)]
60pub struct Blake3Hasher {
61    state: blake3::Hasher,
62}
63
64impl Blake3Hasher {
65    pub fn new() -> Self {
66        Self {
67            state: blake3::Hasher::new(),
68        }
69    }
70    pub fn update(&mut self, data: &[u8]) {
71        self.state.update(data);
72    }
73
74    pub fn finalize(self) -> Blake3Hash {
75        Blake3Hash(self.state.finalize().into())
76    }
77
78    pub fn concat_and_hash(v1: &Blake3Hash, v2: &Blake3Hash) -> Blake3Hash {
79        let mut hasher = Self::new();
80        hasher.update(v1.as_ref());
81        hasher.update(v2.as_ref());
82        hasher.finalize()
83    }
84
85    pub fn hash(data: &[u8]) -> Blake3Hash {
86        let mut hasher = Self::new();
87        hasher.update(data);
88        hasher.finalize()
89    }
90}
91
92#[cfg(test)]
93impl Blake3Hasher {
94    fn finalize_reset(&mut self) -> Blake3Hash {
95        let res = Blake3Hash(self.state.finalize().into());
96        self.state.reset();
97        res
98    }
99}
100
101#[cfg(test)]
102mod tests {
103    use std_shims::ToString;
104
105    use crate::core::vcs::blake3_hash::Blake3Hasher;
106
107    #[test]
108    fn single_hash_test() {
109        let hash_a = Blake3Hasher::hash(b"a");
110        assert_eq!(
111            hash_a.to_string(),
112            "17762fddd969a453925d65717ac3eea21320b66b54342fde15128d6caf21215f"
113        );
114    }
115
116    #[test]
117    fn hash_state_test() {
118        let mut state = Blake3Hasher::new();
119        state.update(b"a");
120        state.update(b"b");
121        let hash = state.finalize_reset();
122        let hash_empty = state.finalize();
123
124        assert_eq!(hash.to_string(), Blake3Hasher::hash(b"ab").to_string());
125        assert_eq!(hash_empty.to_string(), Blake3Hasher::hash(b"").to_string())
126    }
127}