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