ab_core_primitives/
hashes.rs1use ab_io_type::trivial_type::TrivialType;
4use blake3::{Hash, OUT_LEN};
5use core::fmt;
6use derive_more::{AsMut, AsRef, Deref, DerefMut, From, Into};
7#[cfg(feature = "scale-codec")]
8use parity_scale_codec::{Decode, Encode, MaxEncodedLen};
9#[cfg(feature = "serde")]
10use serde::{Deserialize, Deserializer, Serialize, Serializer};
11use transparent_wrapper::TransparentWrapper;
12
13#[derive(
15 Copy,
16 Clone,
17 Eq,
18 PartialEq,
19 Ord,
20 PartialOrd,
21 Hash,
22 From,
23 Into,
24 AsRef,
25 AsMut,
26 Deref,
27 DerefMut,
28 TrivialType,
29 TransparentWrapper,
30)]
31#[cfg_attr(feature = "scale-codec", derive(Encode, Decode, MaxEncodedLen))]
32#[repr(C)]
33pub struct Blake3Hash([u8; Blake3Hash::SIZE]);
34
35const impl Default for Blake3Hash {
36 #[inline(always)]
37 fn default() -> Self {
38 Self([0; _])
39 }
40}
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(always)]
102 fn as_ref(&self) -> &[u8] {
103 &self.0
104 }
105}
106
107impl AsMut<[u8]> for Blake3Hash {
108 #[inline(always)]
109 fn as_mut(&mut self) -> &mut [u8] {
110 &mut self.0
111 }
112}
113
114impl From<Hash> for Blake3Hash {
115 #[inline(always)]
116 fn from(value: Hash) -> Self {
117 Self(value.into())
118 }
119}
120
121impl Blake3Hash {
122 pub const SIZE: usize = OUT_LEN;
124
125 #[inline(always)]
127 pub const fn new(hash: [u8; OUT_LEN]) -> Self {
128 Self(hash)
129 }
130
131 #[inline(always)]
133 pub const fn as_bytes(&self) -> &[u8; Self::SIZE] {
134 &self.0
135 }
136
137 #[inline(always)]
139 pub const fn slice_from_repr(value: &[[u8; Self::SIZE]]) -> &[Self] {
140 Self::wrap_slice(value)
141 }
142
143 #[inline(always)]
145 pub const fn repr_from_slice(value: &[Self]) -> &[[u8; Self::SIZE]] {
146 Self::peel_slice(value)
147 }
148}