1 use crate::convert::*;
2 use crate::operations::*;
3 use crate::random_state::PI;
4 use crate::RandomState;
5 use core::hash::Hasher;
6 
7 /// A `Hasher` for hashing an arbitrary stream of bytes.
8 ///
9 /// Instances of [`AHasher`] represent state that is updated while hashing data.
10 ///
11 /// Each method updates the internal state based on the new data provided. Once
12 /// all of the data has been provided, the resulting hash can be obtained by calling
13 /// `finish()`
14 ///
15 /// [Clone] is also provided in case you wish to calculate hashes for two different items that
16 /// start with the same data.
17 ///
18 #[derive(Debug, Clone)]
19 pub struct AHasher {
20     enc: u128,
21     sum: u128,
22     key: u128,
23 }
24 
25 impl AHasher {
26     /// Creates a new hasher keyed to the provided keys.
27     ///
28     /// Normally hashers are created via `AHasher::default()` for fixed keys or `RandomState::new()` for randomly
29     /// generated keys and `RandomState::with_seeds(a,b)` for seeds that are set and can be reused. All of these work at
30     /// map creation time (and hence don't have any overhead on a per-item bais).
31     ///
32     /// This method directly creates the hasher instance and performs no transformation on the provided seeds. This may
33     /// be useful where a HashBuilder is not desired, such as for testing purposes.
34     ///
35     /// # Example
36     ///
37     /// ```
38     /// use std::hash::Hasher;
39     /// use ahash::AHasher;
40     ///
41     /// let mut hasher = AHasher::new_with_keys(1234, 5678);
42     ///
43     /// hasher.write_u32(1989);
44     /// hasher.write_u8(11);
45     /// hasher.write_u8(9);
46     /// hasher.write(b"Huh?");
47     ///
48     /// println!("Hash is {:x}!", hasher.finish());
49     /// ```
50     #[inline]
new_with_keys(key1: u128, key2: u128) -> Self51     pub(crate) fn new_with_keys(key1: u128, key2: u128) -> Self {
52         let pi: [u128; 2] = PI.convert();
53         let key1 = key1 ^ pi[0];
54         let key2 = key2 ^ pi[1];
55         Self {
56             enc: key1,
57             sum: key2,
58             key: key1 ^ key2,
59         }
60     }
61 
62     #[allow(unused)] // False positive
test_with_keys(key1: u128, key2: u128) -> Self63     pub(crate) fn test_with_keys(key1: u128, key2: u128) -> Self {
64         Self {
65             enc: key1,
66             sum: key2,
67             key: key1 ^ key2,
68         }
69     }
70 
71     #[inline]
from_random_state(rand_state: &RandomState) -> Self72     pub(crate) fn from_random_state(rand_state: &RandomState) -> Self {
73         let key1 = [rand_state.k0, rand_state.k1].convert();
74         let key2 = [rand_state.k2, rand_state.k3].convert();
75         Self {
76             enc: key1,
77             sum: key2,
78             key: key1 ^ key2,
79         }
80     }
81 
82     #[inline(always)]
hash_in(&mut self, new_value: u128)83     fn hash_in(&mut self, new_value: u128) {
84         self.enc = aesdec(self.enc, new_value);
85         self.sum = shuffle_and_add(self.sum, new_value);
86     }
87 
88     #[inline(always)]
hash_in_2(&mut self, v1: u128, v2: u128)89     fn hash_in_2(&mut self, v1: u128, v2: u128) {
90         self.enc = aesdec(self.enc, v1);
91         self.sum = shuffle_and_add(self.sum, v1);
92         self.enc = aesdec(self.enc, v2);
93         self.sum = shuffle_and_add(self.sum, v2);
94     }
95 
96     #[inline]
97     #[cfg(feature = "specialize")]
short_finish(&self) -> u6498     fn short_finish(&self) -> u64 {
99         let combined = aesenc(self.sum, self.enc);
100         let result: [u64; 2] = aesdec(combined, combined).convert();
101         result[0]
102     }
103 }
104 
105 /// Provides [Hasher] methods to hash all of the primitive types.
106 ///
107 /// [Hasher]: core::hash::Hasher
108 impl Hasher for AHasher {
109     #[inline]
write_u8(&mut self, i: u8)110     fn write_u8(&mut self, i: u8) {
111         self.write_u64(i as u64);
112     }
113 
114     #[inline]
write_u16(&mut self, i: u16)115     fn write_u16(&mut self, i: u16) {
116         self.write_u64(i as u64);
117     }
118 
119     #[inline]
write_u32(&mut self, i: u32)120     fn write_u32(&mut self, i: u32) {
121         self.write_u64(i as u64);
122     }
123 
124     #[inline]
write_u128(&mut self, i: u128)125     fn write_u128(&mut self, i: u128) {
126         self.hash_in(i);
127     }
128 
129     #[inline]
130     #[cfg(any(
131         target_pointer_width = "64",
132         target_pointer_width = "32",
133         target_pointer_width = "16"
134     ))]
write_usize(&mut self, i: usize)135     fn write_usize(&mut self, i: usize) {
136         self.write_u64(i as u64);
137     }
138 
139     #[inline]
140     #[cfg(target_pointer_width = "128")]
write_usize(&mut self, i: usize)141     fn write_usize(&mut self, i: usize) {
142         self.write_u128(i as u128);
143     }
144 
145     #[inline]
write_u64(&mut self, i: u64)146     fn write_u64(&mut self, i: u64) {
147         self.write_u128(i as u128);
148     }
149 
150     #[inline]
151     #[allow(clippy::collapsible_if)]
write(&mut self, input: &[u8])152     fn write(&mut self, input: &[u8]) {
153         let mut data = input;
154         let length = data.len();
155         add_in_length(&mut self.enc, length as u64);
156 
157         //A 'binary search' on sizes reduces the number of comparisons.
158         if data.len() <= 8 {
159             let value = read_small(data);
160             self.hash_in(value.convert());
161         } else {
162             if data.len() > 32 {
163                 if data.len() > 64 {
164                     let tail = data.read_last_u128x4();
165                     let mut current: [u128; 4] = [self.key; 4];
166                     current[0] = aesenc(current[0], tail[0]);
167                     current[1] = aesdec(current[1], tail[1]);
168                     current[2] = aesenc(current[2], tail[2]);
169                     current[3] = aesdec(current[3], tail[3]);
170                     let mut sum: [u128; 2] = [self.key, !self.key];
171                     sum[0] = add_by_64s(sum[0].convert(), tail[0].convert()).convert();
172                     sum[1] = add_by_64s(sum[1].convert(), tail[1].convert()).convert();
173                     sum[0] = shuffle_and_add(sum[0], tail[2]);
174                     sum[1] = shuffle_and_add(sum[1], tail[3]);
175                     while data.len() > 64 {
176                         let (blocks, rest) = data.read_u128x4();
177                         current[0] = aesdec(current[0], blocks[0]);
178                         current[1] = aesdec(current[1], blocks[1]);
179                         current[2] = aesdec(current[2], blocks[2]);
180                         current[3] = aesdec(current[3], blocks[3]);
181                         sum[0] = shuffle_and_add(sum[0], blocks[0]);
182                         sum[1] = shuffle_and_add(sum[1], blocks[1]);
183                         sum[0] = shuffle_and_add(sum[0], blocks[2]);
184                         sum[1] = shuffle_and_add(sum[1], blocks[3]);
185                         data = rest;
186                     }
187                     self.hash_in_2(current[0], current[1]);
188                     self.hash_in_2(current[2], current[3]);
189                     self.hash_in_2(sum[0], sum[1]);
190                 } else {
191                     //len 33-64
192                     let (head, _) = data.read_u128x2();
193                     let tail = data.read_last_u128x2();
194                     self.hash_in_2(head[0], head[1]);
195                     self.hash_in_2(tail[0], tail[1]);
196                 }
197             } else {
198                 if data.len() > 16 {
199                     //len 17-32
200                     self.hash_in_2(data.read_u128().0, data.read_last_u128());
201                 } else {
202                     //len 9-16
203                     let value: [u64; 2] = [data.read_u64().0, data.read_last_u64()];
204                     self.hash_in(value.convert());
205                 }
206             }
207         }
208     }
209     #[inline]
finish(&self) -> u64210     fn finish(&self) -> u64 {
211         let combined = aesenc(self.sum, self.enc);
212         let result: [u64; 2] = aesdec(aesdec(combined, self.key), combined).convert();
213         result[0]
214     }
215 }
216 
217 #[cfg(feature = "specialize")]
218 pub(crate) struct AHasherU64 {
219     pub(crate) buffer: u64,
220     pub(crate) pad: u64,
221 }
222 
223 /// A specialized hasher for only primitives under 64 bits.
224 #[cfg(feature = "specialize")]
225 impl Hasher for AHasherU64 {
226     #[inline]
finish(&self) -> u64227     fn finish(&self) -> u64 {
228         folded_multiply(self.buffer, self.pad)
229     }
230 
231     #[inline]
write(&mut self, _bytes: &[u8])232     fn write(&mut self, _bytes: &[u8]) {
233         unreachable!("Specialized hasher was called with a different type of object")
234     }
235 
236     #[inline]
write_u8(&mut self, i: u8)237     fn write_u8(&mut self, i: u8) {
238         self.write_u64(i as u64);
239     }
240 
241     #[inline]
write_u16(&mut self, i: u16)242     fn write_u16(&mut self, i: u16) {
243         self.write_u64(i as u64);
244     }
245 
246     #[inline]
write_u32(&mut self, i: u32)247     fn write_u32(&mut self, i: u32) {
248         self.write_u64(i as u64);
249     }
250 
251     #[inline]
write_u64(&mut self, i: u64)252     fn write_u64(&mut self, i: u64) {
253         self.buffer = folded_multiply(i ^ self.buffer, MULTIPLE);
254     }
255 
256     #[inline]
write_u128(&mut self, _i: u128)257     fn write_u128(&mut self, _i: u128) {
258         unreachable!("Specialized hasher was called with a different type of object")
259     }
260 
261     #[inline]
write_usize(&mut self, _i: usize)262     fn write_usize(&mut self, _i: usize) {
263         unreachable!("Specialized hasher was called with a different type of object")
264     }
265 }
266 
267 #[cfg(feature = "specialize")]
268 pub(crate) struct AHasherFixed(pub AHasher);
269 
270 /// A specialized hasher for fixed size primitives larger than 64 bits.
271 #[cfg(feature = "specialize")]
272 impl Hasher for AHasherFixed {
273     #[inline]
finish(&self) -> u64274     fn finish(&self) -> u64 {
275         self.0.short_finish()
276     }
277 
278     #[inline]
write(&mut self, bytes: &[u8])279     fn write(&mut self, bytes: &[u8]) {
280         self.0.write(bytes)
281     }
282 
283     #[inline]
write_u8(&mut self, i: u8)284     fn write_u8(&mut self, i: u8) {
285         self.write_u64(i as u64);
286     }
287 
288     #[inline]
write_u16(&mut self, i: u16)289     fn write_u16(&mut self, i: u16) {
290         self.write_u64(i as u64);
291     }
292 
293     #[inline]
write_u32(&mut self, i: u32)294     fn write_u32(&mut self, i: u32) {
295         self.write_u64(i as u64);
296     }
297 
298     #[inline]
write_u64(&mut self, i: u64)299     fn write_u64(&mut self, i: u64) {
300         self.0.write_u64(i);
301     }
302 
303     #[inline]
write_u128(&mut self, i: u128)304     fn write_u128(&mut self, i: u128) {
305         self.0.write_u128(i);
306     }
307 
308     #[inline]
write_usize(&mut self, i: usize)309     fn write_usize(&mut self, i: usize) {
310         self.0.write_usize(i);
311     }
312 }
313 
314 #[cfg(feature = "specialize")]
315 pub(crate) struct AHasherStr(pub AHasher);
316 
317 /// A specialized hasher for strings
318 /// Note that the other types don't panic because the hash impl for String tacks on an unneeded call. (As does vec)
319 #[cfg(feature = "specialize")]
320 impl Hasher for AHasherStr {
321     #[inline]
finish(&self) -> u64322     fn finish(&self) -> u64 {
323         let result: [u64; 2] = self.0.enc.convert();
324         result[0]
325     }
326 
327     #[inline]
write(&mut self, bytes: &[u8])328     fn write(&mut self, bytes: &[u8]) {
329         if bytes.len() > 8 {
330             self.0.write(bytes);
331             self.0.enc = aesenc(self.0.sum, self.0.enc);
332             self.0.enc = aesdec(aesdec(self.0.enc, self.0.key), self.0.enc);
333         } else {
334             add_in_length(&mut self.0.enc, bytes.len() as u64);
335 
336             let value = read_small(bytes).convert();
337             self.0.sum = shuffle_and_add(self.0.sum, value);
338             self.0.enc = aesenc(self.0.sum, self.0.enc);
339             self.0.enc = aesdec(aesdec(self.0.enc, self.0.key), self.0.enc);
340         }
341     }
342 
343     #[inline]
write_u8(&mut self, _i: u8)344     fn write_u8(&mut self, _i: u8) {}
345 
346     #[inline]
write_u16(&mut self, _i: u16)347     fn write_u16(&mut self, _i: u16) {}
348 
349     #[inline]
write_u32(&mut self, _i: u32)350     fn write_u32(&mut self, _i: u32) {}
351 
352     #[inline]
write_u64(&mut self, _i: u64)353     fn write_u64(&mut self, _i: u64) {}
354 
355     #[inline]
write_u128(&mut self, _i: u128)356     fn write_u128(&mut self, _i: u128) {}
357 
358     #[inline]
write_usize(&mut self, _i: usize)359     fn write_usize(&mut self, _i: usize) {}
360 }
361 
362 #[cfg(test)]
363 mod tests {
364     use super::*;
365     use crate::convert::Convert;
366     use crate::operations::aesenc;
367     use crate::RandomState;
368     use std::hash::{BuildHasher, Hasher};
369     #[test]
test_sanity()370     fn test_sanity() {
371         let mut hasher = RandomState::with_seeds(1, 2, 3, 4).build_hasher();
372         hasher.write_u64(0);
373         let h1 = hasher.finish();
374         hasher.write(&[1, 0, 0, 0, 0, 0, 0, 0]);
375         let h2 = hasher.finish();
376         assert_ne!(h1, h2);
377     }
378 
379     #[cfg(feature = "compile-time-rng")]
380     #[test]
test_builder()381     fn test_builder() {
382         use std::collections::HashMap;
383         use std::hash::BuildHasherDefault;
384 
385         let mut map = HashMap::<u32, u64, BuildHasherDefault<AHasher>>::default();
386         map.insert(1, 3);
387     }
388 
389     #[cfg(feature = "compile-time-rng")]
390     #[test]
test_default()391     fn test_default() {
392         let hasher_a = AHasher::default();
393         let a_enc: [u64; 2] = hasher_a.enc.convert();
394         let a_sum: [u64; 2] = hasher_a.sum.convert();
395         assert_ne!(0, a_enc[0]);
396         assert_ne!(0, a_enc[1]);
397         assert_ne!(0, a_sum[0]);
398         assert_ne!(0, a_sum[1]);
399         assert_ne!(a_enc[0], a_enc[1]);
400         assert_ne!(a_sum[0], a_sum[1]);
401         assert_ne!(a_enc[0], a_sum[0]);
402         assert_ne!(a_enc[1], a_sum[1]);
403         let hasher_b = AHasher::default();
404         let b_enc: [u64; 2] = hasher_b.enc.convert();
405         let b_sum: [u64; 2] = hasher_b.sum.convert();
406         assert_eq!(a_enc[0], b_enc[0]);
407         assert_eq!(a_enc[1], b_enc[1]);
408         assert_eq!(a_sum[0], b_sum[0]);
409         assert_eq!(a_sum[1], b_sum[1]);
410     }
411 
412     #[test]
test_hash()413     fn test_hash() {
414         let mut result: [u64; 2] = [0x6c62272e07bb0142, 0x62b821756295c58d];
415         let value: [u64; 2] = [1 << 32, 0xFEDCBA9876543210];
416         result = aesenc(value.convert(), result.convert()).convert();
417         result = aesenc(result.convert(), result.convert()).convert();
418         let mut result2: [u64; 2] = [0x6c62272e07bb0142, 0x62b821756295c58d];
419         let value2: [u64; 2] = [1, 0xFEDCBA9876543210];
420         result2 = aesenc(value2.convert(), result2.convert()).convert();
421         result2 = aesenc(result2.convert(), result.convert()).convert();
422         let result: [u8; 16] = result.convert();
423         let result2: [u8; 16] = result2.convert();
424         assert_ne!(hex::encode(result), hex::encode(result2));
425     }
426 
427     #[test]
test_conversion()428     fn test_conversion() {
429         let input: &[u8] = "dddddddd".as_bytes();
430         let bytes: u64 = as_array!(input, 8).convert();
431         assert_eq!(bytes, 0x6464646464646464);
432     }
433 }
434