1use std::collections::{BTreeMap, BTreeSet, BinaryHeap, LinkedList, VecDeque};
36
37use futures::future::{FutureExt, TryFutureExt};
38use futures::stream::{Stream, StreamExt, TryStream, TryStreamExt};
39
40pub use sha2::digest::generic_array;
41pub use sha2::digest::{Digest, Output};
42pub use sha2::Sha256;
43
44pub trait Hash<D: Digest>: Sized {
46 fn hash(self) -> Output<D>;
48}
49
50impl<D: Digest> Hash<D> for () {
51 fn hash(self) -> Output<D> {
52 default_hash::<D>()
53 }
54}
55
56impl<D: Digest> Hash<D> for bool {
57 fn hash(self) -> Output<D> {
58 D::digest([self as u8])
59 }
60}
61
62macro_rules! hash_number {
63 ($n:literal, $ty:ty) => {
64 impl<D: Digest> Hash<D> for $ty {
65 fn hash(self) -> Output<D> {
66 D::digest(self.to_be_bytes())
67 }
68 }
69 };
70}
71
72hash_number!(4, f32);
73hash_number!(8, f64);
74hash_number!(1, i8);
75hash_number!(2, i16);
76hash_number!(4, i32);
77hash_number!(8, i64);
78hash_number!(16, i128);
79hash_number!(1, u8);
80hash_number!(2, u16);
81hash_number!(4, u32);
82hash_number!(8, u64);
83hash_number!(16, u128);
84
85impl<D: Digest> Hash<D> for isize {
86 fn hash(self) -> Output<D> {
87 Hash::<D>::hash(self as i64)
88 }
89}
90
91impl<D: Digest> Hash<D> for usize {
92 fn hash(self) -> Output<D> {
93 Hash::<D>::hash(self as u64)
94 }
95}
96
97impl<'a, D: Digest> Hash<D> for &'a str {
98 fn hash(self) -> Output<D> {
99 D::digest(self.as_bytes())
100 }
101}
102
103impl<D: Digest> Hash<D> for String {
104 fn hash(self) -> Output<D> {
105 Hash::<D>::hash(self.as_str())
106 }
107}
108
109impl<'a, D: Digest> Hash<D> for &'a String {
110 fn hash(self) -> Output<D> {
111 Hash::<D>::hash(self.as_str())
112 }
113}
114
115impl<D: Digest, T: Hash<D>> Hash<D> for Option<T> {
116 fn hash(self) -> Output<D> {
117 if let Some(value) = self {
118 value.hash()
119 } else {
120 default_hash::<D>()
121 }
122 }
123}
124
125macro_rules! hash_tuple {
126 ($($len:expr => ($($n:tt $name:ident)+))+) => {
127 $(
128 impl<D: Digest, $($name),+> Hash<D> for ($($name,)+)
129 where
130 $($name: Hash<D>,)+
131 {
132 fn hash(self) -> Output<D> {
133 let mut hasher = D::new();
134 $(
135 let hash = self.$n.hash();
136 hasher.update(hash);
137 )+
138 hasher.finalize()
139 }
140 }
141
142 impl<'a, D: Digest, $($name),+> Hash<D> for &'a ($($name,)+)
143 where
144 $(&'a $name: Hash<D>,)+
145 {
146 fn hash(self) -> Output<D> {
147 let mut hasher = D::new();
148 $(
149 let hash = self.$n.hash();
150 hasher.update(hash);
151 )+
152 hasher.finalize()
153 }
154 }
155 )+
156 }
157}
158
159hash_tuple! {
160 1 => (0 T0)
161 2 => (0 T0 1 T1)
162 3 => (0 T0 1 T1 2 T2)
163 4 => (0 T0 1 T1 2 T2 3 T3)
164 5 => (0 T0 1 T1 2 T2 3 T3 4 T4)
165 6 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5)
166 7 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6)
167 8 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7)
168 9 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8)
169 10 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9)
170 11 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10)
171 12 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11)
172 13 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12)
173 14 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12 13 T13)
174 15 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12 13 T13 14 T14)
175 16 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12 13 T13 14 T14 15 T15)
176}
177
178impl<D: Digest, T: Hash<D>> Hash<D> for [T; 0] {
179 fn hash(self) -> Output<D> {
180 default_hash::<D>()
181 }
182}
183
184macro_rules! hash_array {
185 ($($len:tt)+) => {
186 $(
187 impl<D: Digest, T: Hash<D>> Hash<D> for [T; $len] {
188 fn hash(self) -> Output<D> {
189 if self.is_empty() {
190 return default_hash::<D>();
191 }
192
193 let mut hasher = D::new();
194
195 for item in self {
196 hasher.update(item.hash());
197 }
198
199 hasher.finalize()
200 }
201 }
202 )+
203 }
204}
205
206hash_array! {
207 01 02 03 04 05 06 07 08 09 10
208 11 12 13 14 15 16 17 18 19 20
209 21 22 23 24 25 26 27 28 29 30
210 31 32
211}
212
213macro_rules! hash_seq {
214 ($ty:ty) => {
215 impl<D: Digest, T: Hash<D>> Hash<D> for $ty {
216 fn hash(self) -> Output<D> {
217 if self.is_empty() {
218 return default_hash::<D>();
219 }
220
221 let mut hasher = D::new();
222
223 for item in self.into_iter() {
224 hasher.update(item.hash());
225 }
226
227 hasher.finalize()
228 }
229 }
230
231 impl<'a, D, T> Hash<D> for &'a $ty
232 where
233 D: Digest,
234 &'a T: Hash<D>,
235 {
236 fn hash(self) -> Output<D> {
237 if self.is_empty() {
238 return default_hash::<D>();
239 }
240
241 let mut hasher = D::new();
242 for item in self.into_iter() {
243 hasher.update(item.hash());
244 }
245 hasher.finalize()
246 }
247 }
248 };
249}
250
251hash_seq!(BTreeSet<T>);
252hash_seq!(BinaryHeap<T>);
253hash_seq!(LinkedList<T>);
254hash_seq!(Vec<T>);
255hash_seq!(VecDeque<T>);
256
257#[cfg(feature = "smallvec")]
258impl<const N: usize, D: Digest, T> Hash<D> for smallvec::SmallVec<[T; N]>
259where
260 [T; N]: smallvec::Array,
261 <smallvec::SmallVec<[T; N]> as IntoIterator>::Item: Hash<D>,
262{
263 fn hash(self) -> Output<D> {
264 if self.is_empty() {
265 return default_hash::<D>();
266 }
267
268 let mut hasher = D::new();
269
270 for item in self.into_iter() {
271 hasher.update(item.hash());
272 }
273
274 hasher.finalize()
275 }
276}
277
278#[cfg(feature = "smallvec")]
279impl<'a, const N: usize, D: Digest, T> Hash<D> for &'a smallvec::SmallVec<[T; N]>
280where
281 [T; N]: smallvec::Array,
282 <&'a smallvec::SmallVec<[T; N]> as IntoIterator>::Item: Hash<D>,
283{
284 fn hash(self) -> Output<D> {
285 if self.is_empty() {
286 return default_hash::<D>();
287 }
288
289 let mut hasher = D::new();
290
291 for item in self.into_iter() {
292 hasher.update(item.hash());
293 }
294
295 hasher.finalize()
296 }
297}
298
299impl<D: Digest, K: Hash<D>, V: Hash<D>> Hash<D> for BTreeMap<K, V> {
300 fn hash(self) -> Output<D> {
301 if self.is_empty() {
302 return default_hash::<D>();
303 }
304
305 let mut hasher = D::new();
306
307 for item in self {
308 hasher.update(item.hash());
309 }
310
311 hasher.finalize()
312 }
313}
314
315impl<'a, D, K, V> Hash<D> for &'a BTreeMap<K, V>
316where
317 D: Digest,
318 &'a K: Hash<D>,
319 &'a V: Hash<D>,
320{
321 fn hash(self) -> Output<D> {
322 if self.is_empty() {
323 return default_hash::<D>();
324 }
325
326 let mut hasher = D::new();
327
328 for item in self {
329 hasher.update(item.hash());
330 }
331
332 hasher.finalize()
333 }
334}
335
336pub async fn hash_stream<D, T, S>(stream: S) -> Output<D>
338where
339 D: Digest,
340 T: Hash<D>,
341 S: Stream<Item = T>,
342{
343 stream
344 .map(|item| Hash::<D>::hash(item))
345 .fold(D::new(), |mut hasher, hash| {
346 hasher.update(hash);
347 futures::future::ready(hasher)
348 })
349 .map(|hasher| hasher.finalize())
350 .await
351}
352
353pub async fn hash_try_stream<D, T, E, S>(stream: S) -> Result<Output<D>, E>
355where
356 D: Digest,
357 T: Hash<D>,
358 E: std::error::Error,
359 S: TryStream<Ok = T, Error = E>,
360{
361 stream
362 .map_ok(|item| Hash::<D>::hash(item))
363 .try_fold(D::new(), |mut hasher, hash| {
364 hasher.update(hash);
365 futures::future::ready(Ok(hasher))
366 })
367 .map_ok(|hasher| hasher.finalize())
368 .await
369}
370
371pub fn default_hash<D: Digest>() -> Output<D> {
373 generic_array::GenericArray::default()
374}