ez_hash/
hashable.rs

1pub trait Hashable {
2    fn update_hasher(&self, hasher: &mut dyn FnMut(&[u8]));
3}
4
5impl Hashable for u8 {
6    fn update_hasher(&self, hasher: &mut dyn FnMut(&[u8])) {
7        hasher(core::slice::from_ref(self))
8    }
9}
10
11impl Hashable for [u8] {
12    fn update_hasher(&self, hasher: &mut dyn FnMut(&[u8])) {
13        hasher(self)
14    }
15}
16
17impl Hashable for str {
18    fn update_hasher(&self, hasher: &mut dyn FnMut(&[u8])) {
19        hasher(str::as_bytes(self))
20    }
21}
22
23impl Hashable for String {
24    fn update_hasher(&self, hasher: &mut dyn FnMut(&[u8])) {
25        hasher(String::as_bytes(self))
26    }
27}
28
29impl<T: Hashable + ?Sized> Hashable for &T {
30    fn update_hasher(&self, hasher: &mut dyn FnMut(&[u8])) {
31        (**self).update_hasher(hasher)
32    }
33}
34
35impl<T: Hashable, const N: usize> Hashable for [T; N] {
36    fn update_hasher(&self, hasher: &mut dyn FnMut(&[u8])) {
37        for item in self {
38            item.update_hasher(hasher);
39        }
40    }
41}
42
43impl<T: Hashable> Hashable for Vec<T> {
44    fn update_hasher(&self, hasher: &mut dyn FnMut(&[u8])) {
45        for item in self {
46            item.update_hasher(hasher);
47        }
48    }
49}
50
51macro_rules! impl_tuple {
52    ($($T:ident),+) => {
53        impl<$($T: Hashable),+> Hashable for ($($T,)+) {
54            fn update_hasher(&self, hasher: &mut dyn FnMut(&[u8])) {
55                #[allow(non_snake_case)]
56                let ($($T,)+) = self;
57                $($T.update_hasher(hasher);)+
58            }
59        }
60    };
61}
62
63impl_tuple!(A);
64impl_tuple!(A, B);
65impl_tuple!(A, B, C);
66impl_tuple!(A, B, C, D);
67impl_tuple!(A, B, C, D, E);
68impl_tuple!(A, B, C, D, E, F);
69impl_tuple!(A, B, C, D, E, F, G);
70impl_tuple!(A, B, C, D, E, F, G, H);