1use {
2 crate::ADDRESS_BYTES,
3 core::{
4 cell::Cell,
5 hash::{BuildHasher, Hasher},
6 mem,
7 },
8 rand::{thread_rng, Rng},
9};
10
11#[derive(Default)]
19pub struct AddressHasher {
20 offset: usize,
21 state: u64,
22}
23
24impl Hasher for AddressHasher {
25 #[inline]
26 fn finish(&self) -> u64 {
27 self.state
28 }
29 #[inline]
30 fn write(&mut self, bytes: &[u8]) {
31 debug_assert_eq!(
32 bytes.len(),
33 ADDRESS_BYTES,
34 "This hasher is intended to be used with addresses and nothing else"
35 );
36 let chunk: &[u8; mem::size_of::<u64>()] = bytes
38 [self.offset..self.offset + mem::size_of::<u64>()]
39 .try_into()
40 .unwrap();
41 self.state = u64::from_ne_bytes(*chunk);
42 }
43}
44
45#[derive(Clone)]
53pub struct AddressHasherBuilder {
54 offset: usize,
55}
56
57impl Default for AddressHasherBuilder {
58 fn default() -> Self {
66 std::thread_local!(static OFFSET: Cell<usize> = {
67 let mut rng = thread_rng();
68 Cell::new(rng.gen_range(0..ADDRESS_BYTES - mem::size_of::<u64>()))
69 });
70
71 let offset = OFFSET.with(|offset| {
72 let mut next_offset = offset.get() + 1;
73 if next_offset > ADDRESS_BYTES - mem::size_of::<u64>() {
74 next_offset = 0;
75 }
76 offset.set(next_offset);
77 next_offset
78 });
79 AddressHasherBuilder { offset }
80 }
81}
82
83impl BuildHasher for AddressHasherBuilder {
84 type Hasher = AddressHasher;
85 #[inline]
86 fn build_hasher(&self) -> Self::Hasher {
87 AddressHasher {
88 offset: self.offset,
89 state: 0,
90 }
91 }
92}
93
94#[cfg(test)]
95mod tests {
96 use {
97 super::AddressHasherBuilder,
98 crate::Address,
99 core::hash::{BuildHasher, Hasher},
100 };
101 #[test]
102 fn test_address_hasher_builder() {
103 let key = Address::new_unique();
104 let builder = AddressHasherBuilder::default();
105 let mut hasher1 = builder.build_hasher();
106 let mut hasher2 = builder.build_hasher();
107 hasher1.write(key.as_array());
108 hasher2.write(key.as_array());
109 assert_eq!(
110 hasher1.finish(),
111 hasher2.finish(),
112 "Hashers made with same builder should be identical"
113 );
114 let builder2 = AddressHasherBuilder::default();
117 for _ in 0..64 {
118 let mut hasher3 = builder2.build_hasher();
119 hasher3.write(key.as_array());
120 std::dbg!(hasher1.finish());
121 std::dbg!(hasher3.finish());
122 if hasher1.finish() != hasher3.finish() {
123 return;
124 }
125 }
126 panic!("Hashers built with different builder should be different due to random offset");
127 }
128
129 #[test]
130 fn test_address_hasher() {
131 let key1 = Address::new_unique();
132 let key2 = Address::new_unique();
133 let builder = AddressHasherBuilder::default();
134 let mut hasher1 = builder.build_hasher();
135 let mut hasher2 = builder.build_hasher();
136 hasher1.write(key1.as_array());
137 hasher2.write(key2.as_array());
138 assert_ne!(hasher1.finish(), hasher2.finish());
139 }
140}