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}