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)]
95pub struct OptionalHash([u8; HASH_SIZE]);
96
97impl MaybeHasNiche for OptionalHash {
98    type MnArray = SomeNiche<HashNiche<U1>>;
99}
100
101impl Default for OptionalHash {
102    fn default() -> Self {
103        Self::NONE
104    }
105}
106
107impl From<[u8; HASH_SIZE]> for OptionalHash {
108    fn from(hash: [u8; HASH_SIZE]) -> Self {
109        Self(hash)
110    }
111}
112
113impl From<Hash> for OptionalHash {
114    fn from(value: Hash) -> Self {
115        value.0.into()
116    }
117}
118
119impl OptionalHash {
120    pub const NONE: Self = Self([0; HASH_SIZE]);
121
122    pub fn get(&self) -> Option<Hash> {
123        self.is_some().then_some(Hash(self.0))
124    }
125
126    pub fn is_some(&self) -> bool {
127        !self.is_none()
128    }
129
130    pub fn is_none(&self) -> bool {
131        *self == Self::NONE
132    }
133
134    pub(crate) fn unwrap(&self) -> Hash {
135        self.get().unwrap()
136    }
137
138    pub(crate) fn clear(&mut self) {
139        *self = Self::NONE;
140    }
141}
142
143impl PartialEq<Hash> for OptionalHash {
144    fn eq(&self, hash: &Hash) -> bool {
145        self.0 == hash.0
146    }
147}
148
149impl PartialEq<OptionalHash> for Hash {
150    fn eq(&self, hash: &OptionalHash) -> bool {
151        self.0 == hash.0
152    }
153}
154
155#[test]
156fn none_is_zeros() {
157    assert_eq!(
158        None::<Hash>.to_array().into_array(),
159        [
160            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,
161            0, 0, 0,
162        ]
163    );
164}
165
166#[test]
167fn none_none_is_one() {
168    assert_eq!(
169        None::<Option<Hash>>.to_array().into_array(),
170        [
171            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,
172            0, 0, 1,
173        ]
174    );
175}
176
177#[test]
178fn none_none_none_is_two() {
179    assert_eq!(
180        None::<Option<Option<Hash>>>.to_array().into_array(),
181        [
182            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,
183            0, 0, 2,
184        ]
185    );
186}