Skip to main content

ab_core_primitives/
hashes.rs

1//! Hashes-related data structures and functions.
2
3use 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/// BLAKE3 hash output transparent wrapper
14#[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    /// Size in bytes
123    pub const SIZE: usize = OUT_LEN;
124
125    /// Create a new instance
126    #[inline(always)]
127    pub const fn new(hash: [u8; OUT_LEN]) -> Self {
128        Self(hash)
129    }
130
131    /// Get internal representation
132    #[inline(always)]
133    pub const fn as_bytes(&self) -> &[u8; Self::SIZE] {
134        &self.0
135    }
136
137    /// Convenient conversion from slice of underlying representation for efficiency purposes
138    #[inline(always)]
139    pub const fn slice_from_repr(value: &[[u8; Self::SIZE]]) -> &[Self] {
140        Self::wrap_slice(value)
141    }
142
143    /// Convenient conversion to slice of underlying representation for efficiency purposes
144    #[inline(always)]
145    pub const fn repr_from_slice(value: &[Self]) -> &[[u8; Self::SIZE]] {
146        Self::peel_slice(value)
147    }
148}