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