ab_core_primitives/
hashes.rs1use ab_io_type::trivial_type::TrivialType;
4use blake3::{Hash, OUT_LEN};
5use core::{fmt, mem};
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};
11
12#[derive(
14 Copy,
15 Clone,
16 Eq,
17 PartialEq,
18 Ord,
19 PartialOrd,
20 Hash,
21 From,
22 Into,
23 AsRef,
24 AsMut,
25 Deref,
26 DerefMut,
27 TrivialType,
28)]
29#[cfg_attr(feature = "scale-codec", derive(Encode, Decode, MaxEncodedLen))]
30#[repr(C)]
31pub struct Blake3Hash([u8; Blake3Hash::SIZE]);
32
33impl const Default for Blake3Hash {
34 #[inline(always)]
35 fn default() -> Self {
36 Self([0; Self::SIZE])
37 }
38}
39
40impl fmt::Display for Blake3Hash {
41 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
42 for byte in self.0 {
43 write!(f, "{byte:02x}")?;
44 }
45 Ok(())
46 }
47}
48
49#[cfg(feature = "serde")]
50#[derive(Serialize, Deserialize)]
51#[serde(transparent)]
52struct Blake3HashBinary([u8; Blake3Hash::SIZE]);
53
54#[cfg(feature = "serde")]
55#[derive(Serialize, Deserialize)]
56#[serde(transparent)]
57struct Blake3HashHex(#[serde(with = "hex")] [u8; Blake3Hash::SIZE]);
58
59#[cfg(feature = "serde")]
60impl Serialize for Blake3Hash {
61 #[inline]
62 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
63 where
64 S: Serializer,
65 {
66 if serializer.is_human_readable() {
67 Blake3HashHex(self.0).serialize(serializer)
68 } else {
69 Blake3HashBinary(self.0).serialize(serializer)
70 }
71 }
72}
73
74#[cfg(feature = "serde")]
75impl<'de> Deserialize<'de> for Blake3Hash {
76 #[inline]
77 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
78 where
79 D: Deserializer<'de>,
80 {
81 Ok(Self(if deserializer.is_human_readable() {
82 Blake3HashHex::deserialize(deserializer)?.0
83 } else {
84 Blake3HashBinary::deserialize(deserializer)?.0
85 }))
86 }
87}
88
89impl fmt::Debug for Blake3Hash {
90 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
91 for byte in self.0 {
92 write!(f, "{byte:02x}")?;
93 }
94 Ok(())
95 }
96}
97
98impl AsRef<[u8]> for Blake3Hash {
99 #[inline(always)]
100 fn as_ref(&self) -> &[u8] {
101 &self.0
102 }
103}
104
105impl AsMut<[u8]> for Blake3Hash {
106 #[inline(always)]
107 fn as_mut(&mut self) -> &mut [u8] {
108 &mut self.0
109 }
110}
111
112impl From<Hash> for Blake3Hash {
113 #[inline(always)]
114 fn from(value: Hash) -> Self {
115 Self(value.into())
116 }
117}
118
119impl Blake3Hash {
120 pub const SIZE: usize = OUT_LEN;
122
123 #[inline(always)]
125 pub const fn new(hash: [u8; OUT_LEN]) -> Self {
126 Self(hash)
127 }
128
129 #[inline(always)]
131 pub const fn as_bytes(&self) -> &[u8; Self::SIZE] {
132 &self.0
133 }
134
135 #[inline(always)]
137 pub const fn slice_from_repr(value: &[[u8; Self::SIZE]]) -> &[Self] {
138 unsafe { mem::transmute(value) }
140 }
141
142 #[inline(always)]
144 pub const fn repr_from_slice(value: &[Self]) -> &[[u8; Self::SIZE]] {
145 unsafe { mem::transmute(value) }
147 }
148}