ab_core_primitives/
hashes.rs1use ab_io_type::trivial_type::TrivialType;
4use blake3::OUT_LEN;
5use core::array::TryFromSliceError;
6use core::fmt;
7use derive_more::{AsMut, AsRef, Deref, DerefMut, From, Into};
8#[cfg(feature = "scale-codec")]
9use parity_scale_codec::{Decode, Encode, MaxEncodedLen};
10#[cfg(feature = "scale-codec")]
11use scale_info::TypeInfo;
12#[cfg(feature = "serde")]
13use serde::{Deserialize, Serialize};
14#[cfg(feature = "serde")]
15use serde::{Deserializer, Serializer};
16
17#[derive(
19 Default,
20 Copy,
21 Clone,
22 Eq,
23 PartialEq,
24 Ord,
25 PartialOrd,
26 Hash,
27 From,
28 Into,
29 AsRef,
30 AsMut,
31 Deref,
32 DerefMut,
33 TrivialType,
34)]
35#[cfg_attr(
36 feature = "scale-codec",
37 derive(Encode, Decode, TypeInfo, MaxEncodedLen)
38)]
39#[repr(C)]
40pub struct Blake3Hash([u8; Blake3Hash::SIZE]);
41
42impl fmt::Display for Blake3Hash {
43 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
44 for byte in self.0 {
45 write!(f, "{byte:02x}")?;
46 }
47 Ok(())
48 }
49}
50
51#[cfg(feature = "serde")]
52#[derive(Serialize, Deserialize)]
53#[serde(transparent)]
54struct Blake3HashBinary([u8; Blake3Hash::SIZE]);
55
56#[cfg(feature = "serde")]
57#[derive(Serialize, Deserialize)]
58#[serde(transparent)]
59struct Blake3HashHex(#[serde(with = "hex")] [u8; Blake3Hash::SIZE]);
60
61#[cfg(feature = "serde")]
62impl Serialize for Blake3Hash {
63 #[inline]
64 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
65 where
66 S: Serializer,
67 {
68 if serializer.is_human_readable() {
69 Blake3HashHex(self.0).serialize(serializer)
70 } else {
71 Blake3HashBinary(self.0).serialize(serializer)
72 }
73 }
74}
75
76#[cfg(feature = "serde")]
77impl<'de> Deserialize<'de> for Blake3Hash {
78 #[inline]
79 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
80 where
81 D: Deserializer<'de>,
82 {
83 Ok(Self(if deserializer.is_human_readable() {
84 Blake3HashHex::deserialize(deserializer)?.0
85 } else {
86 Blake3HashBinary::deserialize(deserializer)?.0
87 }))
88 }
89}
90
91impl fmt::Debug for Blake3Hash {
92 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
93 for byte in self.0 {
94 write!(f, "{byte:02x}")?;
95 }
96 Ok(())
97 }
98}
99
100impl AsRef<[u8]> for Blake3Hash {
101 #[inline]
102 fn as_ref(&self) -> &[u8] {
103 &self.0
104 }
105}
106
107impl AsMut<[u8]> for Blake3Hash {
108 #[inline]
109 fn as_mut(&mut self) -> &mut [u8] {
110 &mut self.0
111 }
112}
113
114impl From<&[u8; Self::SIZE]> for Blake3Hash {
115 #[inline]
116 fn from(value: &[u8; Self::SIZE]) -> Self {
117 Self(*value)
118 }
119}
120
121impl TryFrom<&[u8]> for Blake3Hash {
122 type Error = TryFromSliceError;
123
124 #[inline]
125 fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
126 Ok(Self(value.try_into()?))
127 }
128}
129
130impl Blake3Hash {
131 pub const SIZE: usize = OUT_LEN;
133
134 pub const fn new(hash: [u8; OUT_LEN]) -> Self {
136 Self(hash)
137 }
138
139 pub const fn as_bytes(&self) -> &[u8; Self::SIZE] {
141 &self.0
142 }
143}
144
145#[inline(always)]
147pub fn blake3_hash(data: &[u8]) -> Blake3Hash {
148 Blake3Hash(*blake3::hash(data).as_bytes())
149}
150
151#[cfg(feature = "parallel")]
153#[inline(always)]
154pub fn blake3_hash_parallel(data: &[u8]) -> Blake3Hash {
155 let mut state = blake3::Hasher::new();
156 state.update_rayon(data);
157 state.finalize().as_bytes().into()
158}
159
160#[inline(always)]
162pub fn blake3_hash_with_key(key: &[u8; 32], data: &[u8]) -> Blake3Hash {
163 blake3::keyed_hash(key, data).as_bytes().into()
164}
165
166#[inline(always)]
168pub fn blake3_hash_list_with_key(key: &[u8; 32], data: &[&[u8]]) -> Blake3Hash {
169 let mut state = blake3::Hasher::new_keyed(key);
170 for d in data {
171 state.update(d);
172 }
173 state.finalize().as_bytes().into()
174}
175
176#[inline(always)]
178pub fn blake3_hash_list(data: &[&[u8]]) -> Blake3Hash {
179 let mut state = blake3::Hasher::new();
180 for d in data {
181 state.update(d);
182 }
183 state.finalize().as_bytes().into()
184}