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 ParseAsInline,
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}