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