scsys_crypto/hash/
h256.rs

1/*
2    Appellation: h256 <module>
3    Contrib: @FL03
4*/
5
6#[cfg(feature = "blake3")]
7mod impl_blake3;
8mod impl_convert;
9mod impl_ops;
10
11use crate::utils::digest_to_hash;
12
13/// The [`H256Hash`] type is a 32-byte hash.
14pub type H256Array = [u8; 32];
15
16/// A SHA256 hash.
17#[cfg_attr(
18    feature = "serde",
19    derive(serde::Deserialize, serde::Serialize),
20    serde(default, transparent)
21)]
22#[derive(Clone, Copy, Default, Eq, Hash, PartialEq)]
23#[repr(transparent)]
24pub struct H256(pub H256Array);
25
26impl H256 {
27    /// returns a new instance of the hash without any adjustments
28    pub fn new(raw: H256Array) -> Self {
29        Self(raw)
30    }
31    /// returns a new instance of the hash from a digest
32    pub fn from_digest<D>(digest: D) -> Self
33    where
34        D: AsRef<[u8]>,
35    {
36        let hash = digest_to_hash::<32>(digest);
37        Self::new(hash)
38    }
39    /// hash some data using the [`blake3`] algorithm
40    #[cfg(feature = "blake3")]
41    pub fn b3(data: impl AsRef<[u8]>) -> Self {
42        let hash = blake3::hash(data.as_ref());
43        H256(digest_to_hash::<32>(hash.as_bytes()))
44    }
45    /// generate a randome hash
46    #[cfg(feature = "rand")]
47    pub fn random() -> Self {
48        let data = rand::random::<H256Array>();
49        let mut raw_bytes = [0; 32];
50        raw_bytes.copy_from_slice(&data);
51        (&raw_bytes).into()
52    }
53    /// returns the hash as a byte array
54    pub const fn get(&self) -> &H256Array {
55        &self.0
56    }
57    /// returns a mutable reference to the hash as a byte array
58    pub fn get_mut(&mut self) -> &mut H256Array {
59        &mut self.0
60    }
61    /// copies the hash into the provided buffer
62    pub fn set(&mut self, value: H256Array) -> &mut Self {
63        self.0 = value;
64        self
65    }
66    /// [`replace`](core::mem::replace) and return the current value with another
67    pub fn replace(&mut self, value: &H256Array) -> H256Array {
68        core::mem::replace(&mut self.0, *value)
69    }
70    /// [`swap`](core::mem::swap) the current value with another
71    pub fn swap(&mut self, other: &mut Self) {
72        core::mem::swap(&mut self.0, &mut other.0)
73    }
74    /// returns the hash as a byte array
75    pub const fn as_slice(&self) -> &[u8] {
76        &self.0
77    }
78    /// returns a mutable reference to the hash as a byte array
79    pub fn as_slice_mut(&mut self) -> &mut [u8] {
80        &mut self.0
81    }
82    /// copies the hash into the provided buffer
83    pub fn copy_from_slice(&mut self, value: &[u8]) -> &mut Self {
84        self.0.copy_from_slice(value);
85        self
86    }
87    /// returns a [`Vec<u8>`](alloc::vec::Vec) representation of the hash
88    #[cfg(feature = "alloc")]
89    #[inline]
90    pub fn to_vec(&self) -> alloc::vec::Vec<u8> {
91        self.get().to_vec()
92    }
93    /// this method generically concatenates two hashes based upon the given type and its
94    /// corresponding implementations(s)
95    #[inline]
96    pub fn concat<Rhs>(&self, other: Rhs) -> Self
97    where
98        Self: crate::Concat<Rhs, Output = Self>,
99    {
100        crate::Concat::concat(self, other)
101    }
102}
103
104impl core::ops::Deref for H256 {
105    type Target = H256Array;
106
107    fn deref(&self) -> &Self::Target {
108        &self.0
109    }
110}
111
112impl core::ops::DerefMut for H256 {
113    fn deref_mut(&mut self) -> &mut Self::Target {
114        &mut self.0
115    }
116}
117
118impl AsMut<[u8]> for H256 {
119    fn as_mut(&mut self) -> &mut [u8] {
120        &mut self.0
121    }
122}
123
124impl AsRef<[u8]> for H256 {
125    fn as_ref(&self) -> &[u8] {
126        &self.0
127    }
128}
129
130impl AsMut<[u8; 32]> for H256 {
131    fn as_mut(&mut self) -> &mut [u8; 32] {
132        &mut self.0
133    }
134}
135
136impl AsRef<[u8; 32]> for H256 {
137    fn as_ref(&self) -> &[u8; 32] {
138        &self.0
139    }
140}
141
142impl Ord for H256 {
143    fn cmp(&self, other: &H256) -> core::cmp::Ordering {
144        let self_higher = u128::from_be_bytes(self[0..16].try_into().unwrap());
145        let self_lower = u128::from_be_bytes(self[16..32].try_into().unwrap());
146        let other_higher = u128::from_be_bytes(other[0..16].try_into().unwrap());
147        let other_lower = u128::from_be_bytes(other[16..32].try_into().unwrap());
148        let higher = self_higher.cmp(&other_higher);
149        match higher {
150            core::cmp::Ordering::Equal => self_lower.cmp(&other_lower),
151            _ => higher,
152        }
153    }
154}
155
156impl PartialOrd for H256 {
157    fn partial_cmp(&self, other: &H256) -> Option<core::cmp::Ordering> {
158        Some(self.cmp(other))
159    }
160}
161
162impl core::fmt::Debug for H256 {
163    fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
164        write!(
165            f,
166            "{:>02x}{:>02x}..{:>02x}{:>02x}",
167            &self[0], &self[1], &self[30], &self[31]
168        )
169    }
170}
171
172impl core::fmt::Display for H256 {
173    fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
174        let start = if let Some(precision) = f.precision() {
175            if precision >= 64 {
176                0
177            } else {
178                32 - precision / 2
179            }
180        } else {
181            0
182        };
183        for byte_idx in start..32 {
184            write!(f, "{:>02x}", &self.0[byte_idx])?;
185        }
186        Ok(())
187    }
188}