object_rainbow/
hash.rs

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