Skip to main content

object_rainbow/
hash.rs

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}