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