Skip to main content

object_rainbow/
hash.rs

1use std::ops::Add;
2
3use typenum::{Add1, B0, B1, ToInt, U0, U1};
4
5use crate::*;
6
7#[cfg(feature = "hex")]
8mod hex;
9
10#[derive(
11    Debug,
12    ToOutput,
13    InlineOutput,
14    Tagged,
15    ListHashes,
16    Topological,
17    ParseAsInline,
18    Clone,
19    Copy,
20    PartialEq,
21    Eq,
22    PartialOrd,
23    Ord,
24    Hash,
25    Size,
26)]
27pub struct Hash([u8; HASH_SIZE]);
28
29pub struct HashNiche<N>(N);
30
31impl<N: ToInt<u8> + Add<B1>> Niche for HashNiche<N> {
32    type NeedsTag = B0;
33    type N = <Hash as Size>::Size;
34    fn niche() -> GenericArray<u8, Self::N> {
35        let mut niche = GenericArray::default();
36        let last_byte = niche.len() - 1;
37        niche[last_byte] = N::to_int();
38        niche
39    }
40    type Next = SomeNiche<HashNiche<Add1<N>>>;
41}
42
43impl MaybeHasNiche for Hash {
44    type MnArray = SomeNiche<HashNiche<U0>>;
45}
46
47impl<I: ParseInput> ParseInline<I> for Hash {
48    fn parse_inline(input: &mut I) -> crate::Result<Self> {
49        input
50            .parse_inline::<OptionalHash>()?
51            .get()
52            .ok_or(Error::Zero)
53    }
54}
55
56impl Hash {
57    pub(crate) const fn from_sha256(hash: [u8; HASH_SIZE]) -> Self {
58        Self(hash)
59    }
60
61    pub fn into_bytes(self) -> [u8; HASH_SIZE] {
62        self.0
63    }
64}
65
66impl Deref for Hash {
67    type Target = [u8; HASH_SIZE];
68
69    fn deref(&self) -> &Self::Target {
70        &self.0
71    }
72}
73
74impl AsRef<[u8]> for Hash {
75    fn as_ref(&self) -> &[u8] {
76        self.as_slice()
77    }
78}
79
80#[derive(
81    Debug,
82    Clone,
83    Copy,
84    PartialEq,
85    Eq,
86    PartialOrd,
87    Ord,
88    Hash,
89    ToOutput,
90    InlineOutput,
91    Parse,
92    ParseInline,
93    Tagged,
94    ListHashes,
95    Topological,
96    Size,
97    Default,
98)]
99pub struct OptionalHash([u8; HASH_SIZE]);
100
101impl MaybeHasNiche for OptionalHash {
102    type MnArray = SomeNiche<HashNiche<U1>>;
103}
104
105impl Equivalent<Option<Hash>> for OptionalHash {
106    fn into_equivalent(self) -> Option<Hash> {
107        self.get()
108    }
109
110    fn from_equivalent(object: Option<Hash>) -> Self {
111        object.map(Self::from).unwrap_or_default()
112    }
113}
114
115impl From<[u8; HASH_SIZE]> for OptionalHash {
116    fn from(hash: [u8; HASH_SIZE]) -> Self {
117        Self(hash)
118    }
119}
120
121impl From<Hash> for OptionalHash {
122    fn from(value: Hash) -> Self {
123        value.0.into()
124    }
125}
126
127impl OptionalHash {
128    pub const NONE: Self = Self([0; HASH_SIZE]);
129
130    pub fn get(&self) -> Option<Hash> {
131        self.is_some().then_some(Hash(self.0))
132    }
133
134    pub fn is_some(&self) -> bool {
135        !self.is_none()
136    }
137
138    pub fn is_none(&self) -> bool {
139        *self == Self::NONE
140    }
141
142    pub fn unwrap(&self) -> Hash {
143        self.get().unwrap()
144    }
145
146    pub fn clear(&mut self) {
147        *self = Self::NONE;
148    }
149}
150
151impl PartialEq<Hash> for OptionalHash {
152    fn eq(&self, hash: &Hash) -> bool {
153        self.0 == hash.0
154    }
155}
156
157impl PartialEq<OptionalHash> for Hash {
158    fn eq(&self, hash: &OptionalHash) -> bool {
159        self.0 == hash.0
160    }
161}
162
163#[test]
164fn none_is_zeros() {
165    assert_eq!(
166        None::<Hash>.to_array().into_array(),
167        [
168            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
169            0, 0, 0,
170        ]
171    );
172}
173
174#[test]
175fn none_none_is_one() {
176    assert_eq!(
177        None::<Option<Hash>>.to_array().into_array(),
178        [
179            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
180            0, 0, 1,
181        ]
182    );
183}
184
185#[test]
186fn none_none_none_is_two() {
187    assert_eq!(
188        None::<Option<Option<Hash>>>.to_array().into_array(),
189        [
190            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
191            0, 0, 2,
192        ]
193    );
194}