1#![cfg_attr(bao_nightly, feature(hasher_prefixfree_extras))]
22const PRIMES: [u64; 5] = [
23 0xa0761d6478bd642f,
24 0xe7037ed1a0b428db,
25 0x8ebc6af09c88c6e3,
26 0x589965cc75374cc3,
27 0x1d8e4e27c47d124f,
28];
29
30#[inline(always)]
41fn read_bytes<const BYTES: u8>(data: &[u8]) -> u64 {
42 debug_assert!(data.len() >= usize::from(BYTES));
43 match BYTES {
46 1 => u64::from(data[0]),
47 2 => u64::from(u16::from_le_bytes([data[0], data[1]])),
48 4 => u64::from(u32::from_le(unsafe {
51 core::ptr::read_unaligned(data.as_ptr().cast::<u32>())
52 })),
53 8 => u64::from_le(unsafe { core::ptr::read_unaligned(data.as_ptr().cast::<u64>()) }),
56 _ => unreachable!(),
57 }
58}
59
60#[inline(always)]
61fn read_8bytes_swapped(data: &[u8]) -> u64 {
62 (read_bytes::<4>(data) << 32) | read_bytes::<4>(&data[4..])
63}
64
65#[inline(always)]
76fn mum(a: u64, b: u64) -> u64 {
77 let mut r = (a as u128) * (b as u128);
78 r = (r >> 64) ^ r;
79 r as u64
80}
81
82#[inline(always)]
83fn mix0(a: u64, b: u64, seed: u64) -> u64 {
84 mum(a ^ seed ^ PRIMES[0], b ^ seed ^ PRIMES[1])
85}
86
87#[inline(always)]
88fn mix1(a: u64, b: u64, seed: u64) -> u64 {
89 mum(a ^ seed ^ PRIMES[2], b ^ seed ^ PRIMES[3])
90}
91
92#[cold]
99#[inline(never)]
100fn final_long(seed: u64, key: &[u8]) -> u64 {
101 debug_assert!((17..32).contains(&key.len()));
102
103 let head = mix0(
104 read_8bytes_swapped(key),
105 read_8bytes_swapped(&key[8..]),
106 seed,
107 );
108 let tail = match key.len() {
109 17 => mix1(read_bytes::<1>(&key[16..]), PRIMES[4], seed),
110 18 => mix1(read_bytes::<2>(&key[16..]), PRIMES[4], seed),
111 19 => mix1(
112 (read_bytes::<2>(&key[16..]) << 8) | read_bytes::<1>(&key[18..]),
113 PRIMES[4],
114 seed,
115 ),
116 20 => mix1(read_bytes::<4>(&key[16..]), PRIMES[4], seed),
117 21 => mix1(
118 (read_bytes::<4>(&key[16..]) << 8) | read_bytes::<1>(&key[20..]),
119 PRIMES[4],
120 seed,
121 ),
122 22 => mix1(
123 (read_bytes::<4>(&key[16..]) << 16) | read_bytes::<2>(&key[20..]),
124 PRIMES[4],
125 seed,
126 ),
127 23 => mix1(
128 (read_bytes::<4>(&key[16..]) << 24)
129 | (read_bytes::<2>(&key[20..]) << 8)
130 | read_bytes::<1>(&key[22..]),
131 PRIMES[4],
132 seed,
133 ),
134 24 => mix1(read_8bytes_swapped(&key[16..]), PRIMES[4], seed),
135 25 => mix1(
136 read_8bytes_swapped(&key[16..]),
137 read_bytes::<1>(&key[24..]),
138 seed,
139 ),
140 26 => mix1(
141 read_8bytes_swapped(&key[16..]),
142 read_bytes::<2>(&key[24..]),
143 seed,
144 ),
145 27 => mix1(
146 read_8bytes_swapped(&key[16..]),
147 (read_bytes::<2>(&key[24..]) << 8) | read_bytes::<1>(&key[26..]),
148 seed,
149 ),
150 28 => mix1(
151 read_8bytes_swapped(&key[16..]),
152 read_bytes::<4>(&key[24..]),
153 seed,
154 ),
155 29 => mix1(
156 read_8bytes_swapped(&key[16..]),
157 (read_bytes::<4>(&key[24..]) << 8) | read_bytes::<1>(&key[28..]),
158 seed,
159 ),
160 30 => mix1(
161 read_8bytes_swapped(&key[16..]),
162 (read_bytes::<4>(&key[24..]) << 16) | read_bytes::<2>(&key[28..]),
163 seed,
164 ),
165 31 => mix1(
166 read_8bytes_swapped(&key[16..]),
167 (read_bytes::<4>(&key[24..]) << 24)
168 | (read_bytes::<2>(&key[28..]) << 8)
169 | read_bytes::<1>(&key[30..]),
170 seed,
171 ),
172 _ => unreachable!(),
173 };
174 head ^ tail
175}
176
177#[derive(Clone, Copy)]
181struct WyhashStateless {
182 seed: u64,
183 msg_len: usize,
184}
185
186impl WyhashStateless {
187 #[inline(always)]
188 pub(crate) fn init(seed: u64) -> WyhashStateless {
189 WyhashStateless { seed, msg_len: 0 }
190 }
191
192 #[inline(always)] fn round(&mut self, b: &[u8]) {
194 debug_assert!(b.len() == 32);
195
196 self.seed = mix0(
197 read_bytes::<8>(&b[0..]),
198 read_bytes::<8>(&b[8..]),
199 self.seed,
200 ) ^ mix1(
201 read_bytes::<8>(&b[16..]),
202 read_bytes::<8>(&b[24..]),
203 self.seed,
204 );
205 }
206
207 #[inline(always)] pub(crate) fn update(&mut self, b: &[u8]) {
209 debug_assert!(b.len().is_multiple_of(32));
210
211 let mut off: usize = 0;
212 while off < b.len() {
213 self.round(&b[off..off + 32]);
214 off += 32;
216 }
217
218 self.msg_len += b.len();
219 }
220
221 #[inline(always)]
230 pub(crate) fn final_(&mut self, b: &[u8]) -> u64 {
231 debug_assert!(b.len() < 32);
232
233 let seed = self.seed;
234 let rem_len = b.len();
236 let rem_key = &b[0..rem_len];
237
238 self.seed = match rem_len {
239 0 => seed,
240 1 => mix0(read_bytes::<1>(rem_key), PRIMES[4], seed),
241 2 => mix0(read_bytes::<2>(rem_key), PRIMES[4], seed),
242 3 => mix0(
243 (read_bytes::<2>(rem_key) << 8) | read_bytes::<1>(&rem_key[2..]),
244 PRIMES[4],
245 seed,
246 ),
247 4 => mix0(read_bytes::<4>(rem_key), PRIMES[4], seed),
248 5 => mix0(
249 (read_bytes::<4>(rem_key) << 8) | read_bytes::<1>(&rem_key[4..]),
250 PRIMES[4],
251 seed,
252 ),
253 6 => mix0(
254 (read_bytes::<4>(rem_key) << 16) | read_bytes::<2>(&rem_key[4..]),
255 PRIMES[4],
256 seed,
257 ),
258 7 => mix0(
259 (read_bytes::<4>(rem_key) << 24)
260 | (read_bytes::<2>(&rem_key[4..]) << 8)
261 | read_bytes::<1>(&rem_key[6..]),
262 PRIMES[4],
263 seed,
264 ),
265 8 => mix0(read_8bytes_swapped(rem_key), PRIMES[4], seed),
266 9 => mix0(
267 read_8bytes_swapped(rem_key),
268 read_bytes::<1>(&rem_key[8..]),
269 seed,
270 ),
271 10 => mix0(
272 read_8bytes_swapped(rem_key),
273 read_bytes::<2>(&rem_key[8..]),
274 seed,
275 ),
276 11 => mix0(
277 read_8bytes_swapped(rem_key),
278 (read_bytes::<2>(&rem_key[8..]) << 8) | read_bytes::<1>(&rem_key[10..]),
279 seed,
280 ),
281 12 => mix0(
282 read_8bytes_swapped(rem_key),
283 read_bytes::<4>(&rem_key[8..]),
284 seed,
285 ),
286 13 => mix0(
287 read_8bytes_swapped(rem_key),
288 (read_bytes::<4>(&rem_key[8..]) << 8) | read_bytes::<1>(&rem_key[12..]),
289 seed,
290 ),
291 14 => mix0(
292 read_8bytes_swapped(rem_key),
293 (read_bytes::<4>(&rem_key[8..]) << 16) | read_bytes::<2>(&rem_key[12..]),
294 seed,
295 ),
296 15 => mix0(
297 read_8bytes_swapped(rem_key),
298 (read_bytes::<4>(&rem_key[8..]) << 24)
299 | (read_bytes::<2>(&rem_key[12..]) << 8)
300 | read_bytes::<1>(&rem_key[14..]),
301 seed,
302 ),
303 16 => mix0(
304 read_8bytes_swapped(rem_key),
305 read_8bytes_swapped(&rem_key[8..]),
306 seed,
307 ),
308 _ => final_long(seed, rem_key),
311 };
312
313 self.msg_len += b.len();
314 mum(self.seed ^ (self.msg_len as u64), PRIMES[4])
315 }
316
317 #[inline(always)]
324 pub(crate) fn hash(seed: u64, input: &[u8]) -> u64 {
325 let aligned_len = input.len() - (input.len() % 32);
326
327 let mut c = WyhashStateless::init(seed);
328 c.update(&input[0..aligned_len]);
329 c.final_(&input[aligned_len..])
331 }
333}
334
335pub struct Wyhash11 {
338 state: WyhashStateless,
339
340 buf: [u8; 32],
341 buf_len: usize,
342}
343
344impl Wyhash11 {
345 #[inline]
346 pub fn init(seed: u64) -> Wyhash11 {
347 Wyhash11 {
348 state: WyhashStateless::init(seed),
349 buf: [0; 32], buf_len: 0,
351 }
352 }
353
354 #[inline]
355 pub fn update(&mut self, b: &[u8]) {
356 let mut off: usize = 0;
357
358 if self.buf_len != 0 && self.buf_len + b.len() >= 32 {
359 off += 32 - self.buf_len;
360 self.buf[self.buf_len..self.buf_len + off].copy_from_slice(&b[0..off]);
361 self.state.update(&self.buf[0..]);
362 self.buf_len = 0;
363 }
364
365 let remain_len = b.len() - off;
366 let aligned_len = remain_len - (remain_len % 32);
367 self.state.update(&b[off..off + aligned_len]);
368
369 let tail = &b[off + aligned_len..];
370 self.buf[self.buf_len..self.buf_len + tail.len()].copy_from_slice(tail);
371 self.buf_len += usize::from(u8::try_from(tail.len()).expect("int cast"));
372 }
373
374 #[inline(always)]
377 pub fn final_(&mut self) -> u64 {
378 let rem_key = &self.buf[0..self.buf_len];
379
380 self.state.final_(rem_key)
381 }
382
383 #[inline(always)]
384 pub fn hash(seed: u64, input: &[u8]) -> u64 {
385 WyhashStateless::hash(seed, input)
386 }
387}
388
389impl core::hash::Hasher for Wyhash11 {
393 #[inline]
394 fn write(&mut self, bytes: &[u8]) {
395 self.update(bytes);
396 }
397 #[inline]
398 fn finish(&self) -> u64 {
399 let mut s = self.state;
402 s.final_(&self.buf[0..self.buf_len])
403 }
404}
405
406#[derive(Clone, Copy)]
416pub struct Wyhash {
417 a: u64,
418 b: u64,
419 state: [u64; 3],
420 total_len: usize,
421
422 buf: [u8; 48],
423 buf_len: usize,
424}
425
426impl Wyhash {
427 const SECRET: [u64; 4] = [
428 0xa0761d6478bd642f,
429 0xe7037ed1a0b428db,
430 0x8ebc6af09c88c6e3,
431 0x589965cc75374cc3,
432 ];
433
434 #[inline]
435 pub fn init(seed: u64) -> Wyhash {
436 let s0 = seed ^ Self::mix(seed ^ Self::SECRET[0], Self::SECRET[1]);
437 Wyhash {
438 a: 0, b: 0, state: [s0, s0, s0],
441 total_len: 0,
442 buf: [0; 48], buf_len: 0,
444 }
445 }
446
447 #[inline]
450 pub fn update(&mut self, input: &[u8]) {
451 self.total_len += input.len();
452
453 if input.len() <= 48 - self.buf_len {
454 self.buf[self.buf_len..self.buf_len + input.len()].copy_from_slice(input);
455 self.buf_len += input.len();
456 return;
457 }
458
459 let mut i: usize = 0;
460
461 if self.buf_len > 0 {
462 i = 48 - self.buf_len;
463 self.buf[self.buf_len..48].copy_from_slice(&input[0..i]);
464 let buf = self.buf;
465 self.round(&buf);
466 self.buf_len = 0;
467 }
468
469 while i + 48 < input.len() {
470 self.round(
471 input[i..i + 48]
472 .try_into()
473 .expect("infallible: size matches"),
474 );
475 i += 48;
476 }
477
478 let remaining_bytes = &input[i..];
479 if remaining_bytes.len() < 16 && i >= 48 {
480 let rem = 16 - remaining_bytes.len();
481 self.buf[48 - rem..48].copy_from_slice(&input[i - rem..i]);
483 }
484 self.buf[0..remaining_bytes.len()].copy_from_slice(remaining_bytes);
485 self.buf_len = remaining_bytes.len();
486 }
487
488 #[inline(always)]
489 pub fn final_(&self) -> u64 {
490 let input: &[u8] = &self.buf[0..self.buf_len];
491 let mut new_self = self.shallow_copy(); if self.total_len <= 16 {
494 new_self.small_key(input);
495 } else {
496 let mut scratch: [u8; 16] = [0; 16];
497 let (input, offset) = if self.buf_len < 16 {
498 let rem = 16 - self.buf_len;
499 scratch[0..rem].copy_from_slice(&self.buf[48 - rem..48]);
500 scratch[rem..rem + self.buf_len].copy_from_slice(&self.buf[0..self.buf_len]);
501 (&scratch[..], rem)
503 } else {
504 (input, 0usize)
505 };
506
507 new_self.final0();
508 new_self.final1(input, offset);
509 }
510
511 new_self.final2()
512 }
513
514 #[inline]
516 fn shallow_copy(&self) -> Wyhash {
517 Wyhash {
518 a: self.a,
519 b: self.b,
520 state: self.state,
521 total_len: self.total_len,
522 buf: [0; 48], buf_len: 0, }
525 }
526
527 #[inline(always)] fn small_key(&mut self, input: &[u8]) {
529 debug_assert!(input.len() <= 16);
530
531 if input.len() >= 4 {
532 let end = input.len() - 4;
533 let quarter = (input.len() >> 3) << 2;
534 self.a = (Self::read4(&input[0..]) << 32) | Self::read4(&input[quarter..]);
535 self.b = (Self::read4(&input[end..]) << 32) | Self::read4(&input[end - quarter..]);
536 } else if !input.is_empty() {
537 self.a = (u64::from(input[0]) << 16)
538 | (u64::from(input[input.len() >> 1]) << 8)
539 | u64::from(input[input.len() - 1]);
540 self.b = 0;
541 } else {
542 self.a = 0;
543 self.b = 0;
544 }
545 }
546
547 #[inline]
548 fn round(&mut self, input: &[u8; 48]) {
549 let a0 = Self::read8(&input[0..]);
551 let b0 = Self::read8(&input[8..]);
552 self.state[0] = Self::mix(a0 ^ Self::SECRET[1], b0 ^ self.state[0]);
553
554 let a1 = Self::read8(&input[16..]);
555 let b1 = Self::read8(&input[24..]);
556 self.state[1] = Self::mix(a1 ^ Self::SECRET[2], b1 ^ self.state[1]);
557
558 let a2 = Self::read8(&input[32..]);
559 let b2 = Self::read8(&input[40..]);
560 self.state[2] = Self::mix(a2 ^ Self::SECRET[3], b2 ^ self.state[2]);
561 }
562
563 #[inline(always)]
571 fn read4(data: &[u8]) -> u64 {
572 debug_assert!(data.len() >= 4);
573 u64::from(u32::from_le(unsafe {
576 core::ptr::read_unaligned(data.as_ptr().cast::<u32>())
577 }))
578 }
579
580 #[inline(always)]
581 fn read8(data: &[u8]) -> u64 {
582 debug_assert!(data.len() >= 8);
583 u64::from_le(unsafe { core::ptr::read_unaligned(data.as_ptr().cast::<u64>()) })
586 }
587
588 #[inline]
589 fn mum_(a: &mut u64, b: &mut u64) {
590 let x = (*a as u128).wrapping_mul(*b as u128);
591 *a = x as u64; *b = (x >> 64) as u64; }
594
595 #[inline]
596 fn mix(a_: u64, b_: u64) -> u64 {
597 let mut a = a_;
598 let mut b = b_;
599 Self::mum_(&mut a, &mut b);
600 a ^ b
601 }
602
603 #[inline]
604 fn final0(&mut self) {
605 self.state[0] ^= self.state[1] ^ self.state[2];
606 }
607
608 #[inline]
612 fn final1(&mut self, input_lb: &[u8], start_pos: usize) {
613 debug_assert!(input_lb.len() >= 16);
614 debug_assert!(input_lb.len() - start_pos <= 48);
615 let input = &input_lb[start_pos..];
616
617 let mut i: usize = 0;
618 while i + 16 < input.len() {
619 self.state[0] = Self::mix(
620 Self::read8(&input[i..]) ^ Self::SECRET[1],
621 Self::read8(&input[i + 8..]) ^ self.state[0],
622 );
623 i += 16;
624 }
625
626 self.a = Self::read8(&input_lb[input_lb.len() - 16..]);
627 self.b = Self::read8(&input_lb[input_lb.len() - 8..]);
628 }
629
630 #[inline(always)] fn final2(&mut self) -> u64 {
632 self.a ^= Self::SECRET[1];
633 self.b ^= self.state[0];
634 Self::mum_(&mut self.a, &mut self.b);
635 Self::mix(
636 self.a ^ Self::SECRET[0] ^ (self.total_len as u64),
637 self.b ^ Self::SECRET[1],
638 )
639 }
640
641 #[inline(always)]
646 pub fn hash(seed: u64, input: &[u8]) -> u64 {
647 let mut this = Wyhash::init(seed);
648
649 if input.len() <= 16 {
650 this.small_key(input);
651 } else {
652 let mut i: usize = 0;
653 if input.len() >= 48 {
654 let [mut s0, mut s1, mut s2] = this.state;
662 let (k1, k2, k3) = (Self::SECRET[1], Self::SECRET[2], Self::SECRET[3]);
663 let bound = input.len() - 48;
678 let p = input.as_ptr();
679 while i < bound {
680 macro_rules! r8 {
681 ($o:literal) => {
682 u64::from_le(unsafe {
687 core::ptr::read_unaligned(p.add(i + $o).cast::<u64>())
688 })
689 };
690 }
691 let m0 = ((r8!(0) ^ k1) as u128).wrapping_mul((r8!(8) ^ s0) as u128);
694 s0 = (m0 as u64) ^ ((m0 >> 64) as u64);
695 let m1 = ((r8!(16) ^ k2) as u128).wrapping_mul((r8!(24) ^ s1) as u128);
696 s1 = (m1 as u64) ^ ((m1 >> 64) as u64);
697 let m2 = ((r8!(32) ^ k3) as u128).wrapping_mul((r8!(40) ^ s2) as u128);
698 s2 = (m2 as u64) ^ ((m2 >> 64) as u64);
699 i += 48;
700 }
701 this.state = [s0, s1, s2];
702 this.final0();
703 }
704 this.final1(input, i);
705 }
706
707 this.total_len = input.len();
708 this.final2()
709 }
710}
711
712impl core::hash::Hasher for Wyhash {
715 #[inline]
716 fn write(&mut self, bytes: &[u8]) {
717 self.update(bytes);
718 }
719 #[inline]
720 fn finish(&self) -> u64 {
721 self.final_()
723 }
724}
725
726impl Default for Wyhash {
727 #[inline]
728 fn default() -> Self {
729 Wyhash::init(0)
730 }
731}
732
733#[derive(Default, Clone, Copy)]
745pub struct OneShotHasher {
746 hash: u64,
747}
748
749impl core::hash::Hasher for OneShotHasher {
750 #[inline(always)]
756 fn write(&mut self, bytes: &[u8]) {
757 self.hash = Wyhash11::hash(self.hash, bytes);
762 }
763 #[inline(always)]
764 fn write_u8(&mut self, n: u8) {
765 self.write_u64(u64::from(n));
766 }
767 #[inline(always)]
768 fn write_u16(&mut self, n: u16) {
769 self.write_u64(u64::from(n));
770 }
771 #[inline(always)]
772 fn write_u32(&mut self, n: u32) {
773 self.write_u64(u64::from(n));
774 }
775 #[inline(always)]
776 fn write_u64(&mut self, n: u64) {
777 self.hash = mum(self.hash ^ n, PRIMES[4]);
780 }
781 #[cfg(bao_nightly)]
790 #[inline(always)]
791 fn write_length_prefix(&mut self, _len: usize) {}
792 #[inline(always)]
793 fn write_usize(&mut self, n: usize) {
794 self.write_u64(n as u64);
795 }
796 #[inline(always)]
797 fn finish(&self) -> u64 {
798 self.hash
799 }
800}
801
802#[inline]
806pub fn auto_hash<K: core::hash::Hash + ?Sized>(key: &K) -> u64 {
807 let mut h = OneShotHasher::default();
808 key.hash(&mut h);
809 core::hash::Hasher::finish(&h)
810}
811
812pub type BuildHasher = core::hash::BuildHasherDefault<OneShotHasher>;
816
817#[inline]
819pub fn hash(bytes: &[u8]) -> u64 {
820 Wyhash::hash(0, bytes)
821}
822
823#[inline]
824pub fn hash32(bytes: &[u8]) -> u32 {
825 hash(bytes) as u32 }
827
828#[inline]
830pub fn hash_with_seed(seed: u64, bytes: &[u8]) -> u64 {
831 Wyhash::hash(seed, bytes)
832}
833
834#[inline]
847pub fn hash_ascii_lowercase(seed: u64, bytes: &[u8]) -> u64 {
848 let mut buf = [0u8; 48];
849 if bytes.len() <= buf.len() {
850 let dst = &mut buf[..bytes.len()];
853 for (d, &s) in dst.iter_mut().zip(bytes) {
854 *d = s.to_ascii_lowercase();
855 }
856 return Wyhash::hash(seed, dst);
857 }
858 let mut h = Wyhash::init(seed);
859 let mut remain = bytes;
860 while !remain.is_empty() {
861 let n = remain.len().min(buf.len());
862 let dst = &mut buf[..n];
863 for (d, &s) in dst.iter_mut().zip(&remain[..n]) {
864 *d = s.to_ascii_lowercase();
865 }
866 h.update(dst);
867 remain = &remain[n..];
868 }
869 h.final_()
870}
871
872pub const fn hash_const(seed: u64, input: &[u8]) -> u64 {
882 const SECRET: [u64; 4] = Wyhash::SECRET;
884
885 #[inline]
886 const fn mix(a: u64, b: u64) -> u64 {
887 let x = (a as u128).wrapping_mul(b as u128);
888 (x as u64) ^ ((x >> 64) as u64)
889 }
890 #[inline]
891 const fn read4(d: &[u8], o: usize) -> u64 {
892 u32::from_le_bytes([d[o], d[o + 1], d[o + 2], d[o + 3]]) as u64
893 }
894 #[inline]
895 const fn read8(d: &[u8], o: usize) -> u64 {
896 u64::from_le_bytes([
897 d[o],
898 d[o + 1],
899 d[o + 2],
900 d[o + 3],
901 d[o + 4],
902 d[o + 5],
903 d[o + 6],
904 d[o + 7],
905 ])
906 }
907
908 let s0 = seed ^ mix(seed ^ SECRET[0], SECRET[1]);
909 let mut state = [s0, s0, s0];
910 let len = input.len();
911 let a: u64;
912 let b: u64;
913
914 if len <= 16 {
915 if len >= 4 {
917 let end = len - 4;
918 let quarter = (len >> 3) << 2;
919 a = (read4(input, 0) << 32) | read4(input, quarter);
920 b = (read4(input, end) << 32) | read4(input, end - quarter);
921 } else if len > 0 {
922 a = ((input[0] as u64) << 16)
923 | ((input[len >> 1] as u64) << 8)
924 | (input[len - 1] as u64);
925 b = 0;
926 } else {
927 a = 0;
928 b = 0;
929 }
930 } else {
931 let mut i: usize = 0;
932 if len >= 48 {
933 while i + 48 < len {
934 state[0] = mix(read8(input, i) ^ SECRET[1], read8(input, i + 8) ^ state[0]);
936 state[1] = mix(
937 read8(input, i + 16) ^ SECRET[2],
938 read8(input, i + 24) ^ state[1],
939 );
940 state[2] = mix(
941 read8(input, i + 32) ^ SECRET[3],
942 read8(input, i + 40) ^ state[2],
943 );
944 i += 48;
945 }
946 state[0] ^= state[1] ^ state[2];
948 }
949 let mut j = i;
951 while j + 16 < len {
952 state[0] = mix(read8(input, j) ^ SECRET[1], read8(input, j + 8) ^ state[0]);
953 j += 16;
954 }
955 a = read8(input, len - 16);
956 b = read8(input, len - 8);
957 }
958
959 let x = ((a ^ SECRET[1]) as u128).wrapping_mul((b ^ state[0]) as u128);
961 mix(
962 (x as u64) ^ SECRET[0] ^ (len as u64),
963 ((x >> 64) as u64) ^ SECRET[1],
964 )
965}
966
967#[inline]
971pub fn hash_int<T: HashInt>(input: T) -> T {
972 T::hash_int(input)
973}
974
975pub trait HashInt: Copy {
976 fn hash_int(self) -> Self;
977}
978
979impl HashInt for u16 {
981 #[inline]
982 fn hash_int(self) -> u16 {
983 let mut x = self;
984 x = (x ^ (x >> 7)).wrapping_mul(0x2993);
985 x = (x ^ (x >> 5)).wrapping_mul(0xe877);
986 x = (x ^ (x >> 9)).wrapping_mul(0x0235);
987 x ^ (x >> 10)
988 }
989}
990
991impl HashInt for u32 {
993 #[inline]
994 fn hash_int(self) -> u32 {
995 let mut x = self;
996 x = (x ^ (x >> 17)).wrapping_mul(0xed5a_d4bb);
997 x = (x ^ (x >> 11)).wrapping_mul(0xac4c_1b51);
998 x = (x ^ (x >> 15)).wrapping_mul(0x3184_8bab);
999 x ^ (x >> 14)
1000 }
1001}
1002
1003impl HashInt for u64 {
1005 #[inline]
1006 fn hash_int(self) -> u64 {
1007 const C: u64 = 0xbea2_25f9_eb34_556d;
1008 let mut x = self;
1009 x = (x ^ (x >> 32)).wrapping_mul(C);
1010 x = (x ^ (x >> 29)).wrapping_mul(C);
1011 x = (x ^ (x >> 32)).wrapping_mul(C);
1012 x ^ (x >> 29)
1013 }
1014}
1015
1016#[cfg(test)]
1021mod tests {
1022 use super::*;
1023
1024 struct TestVector {
1026 seed: u64,
1027 expected: u64,
1028 input: &'static [u8],
1029 }
1030
1031 const VECTORS: &[TestVector] = &[
1032 TestVector {
1033 seed: 0,
1034 expected: 0x0409638ee2bde459,
1035 input: b"",
1036 },
1037 TestVector {
1038 seed: 1,
1039 expected: 0xa8412d091b5fe0a9,
1040 input: b"a",
1041 },
1042 TestVector {
1043 seed: 2,
1044 expected: 0x32dd92e4b2915153,
1045 input: b"abc",
1046 },
1047 TestVector {
1048 seed: 3,
1049 expected: 0x8619124089a3a16b,
1050 input: b"message digest",
1051 },
1052 TestVector {
1053 seed: 4,
1054 expected: 0x7a43afb61d7f5f40,
1055 input: b"abcdefghijklmnopqrstuvwxyz",
1056 },
1057 TestVector {
1058 seed: 5,
1059 expected: 0xff42329b90e50d58,
1060 input: b"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
1061 },
1062 TestVector {
1063 seed: 6,
1064 expected: 0xc39cab13b115aad3,
1065 input:
1066 b"12345678901234567890123456789012345678901234567890123456789012345678901234567890",
1067 },
1068 ];
1069
1070 #[test]
1071 fn test_vectors() {
1072 for e in VECTORS {
1073 assert_eq!(
1074 e.expected,
1075 Wyhash::hash(e.seed, e.input),
1076 "input={:?}",
1077 bstr::BStr::new(e.input)
1078 );
1079 }
1080 }
1081
1082 fn smhasher(hash_fn: impl Fn(u64, &[u8]) -> u64) -> u32 {
1087 const HASH_SIZE: usize = core::mem::size_of::<u64>();
1088 let mut buf = [0u8; 256];
1089 let mut buf_all = [0u8; 256 * HASH_SIZE];
1090
1091 for i in 0..256usize {
1092 buf[i] = i as u8;
1093 let h = hash_fn((256 - i) as u64, &buf[0..i]);
1094 buf_all[i * HASH_SIZE..(i + 1) * HASH_SIZE].copy_from_slice(&h.to_le_bytes());
1095 }
1096
1097 hash_fn(0, &buf_all[..]) as u32
1098 }
1099
1100 #[test]
1101 fn test_smhasher() {
1102 assert_eq!(smhasher(Wyhash::hash), 0xBD5E840C);
1103 }
1104
1105 #[test]
1106 fn hash_const_matches_runtime() {
1107 for s in [
1111 &b""[..],
1112 b"a",
1113 b"abc",
1114 b"__require",
1115 b"0123456789abcdef0",
1116 b"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
1117 ] {
1118 assert_eq!(hash_const(0, s), Wyhash::hash(0, s), "input: {s:?}");
1119 }
1120 assert_eq!(smhasher(hash_const), 0xBD5E840C);
1122 }
1123
1124 #[test]
1125 fn test_iterative_api() {
1126 let buf = [0u8; 528];
1128 let mut len: usize = 0;
1129 let seed = 0;
1130
1131 let mut hasher = Wyhash::init(seed);
1132 for i in 1..32usize {
1133 let r = Wyhash::hash(seed, &buf[0..len + i]);
1134 hasher.update(&buf[len..len + i]);
1135 let f1 = hasher.final_();
1136 let f2 = hasher.final_();
1137 assert_eq!(f1, f2, "iterative hash was not idempotent at i={i}");
1138 assert_eq!(f1, r, "iterative hash did not match direct at i={i}");
1139 len += i;
1140 }
1141 }
1142
1143 #[test]
1144 fn test_iterative_maintains_last_sixteen() {
1145 let mut input = [0u8; 48 + 18];
1147 for b in &mut input[..48] {
1148 *b = b'Z';
1149 }
1150 input[48..].copy_from_slice(b"01234567890abcdefg");
1151 let seed = 0;
1152
1153 for i in 0..17usize {
1154 let payload = &input[0..input.len() - i];
1155 let non_iterative_hash = Wyhash::hash(seed, payload);
1156
1157 let mut wh = Wyhash::init(seed);
1158 wh.update(payload);
1159 let iterative_hash = wh.final_();
1160
1161 assert_eq!(non_iterative_hash, iterative_hash, "i={i}");
1162 }
1163 }
1164
1165 #[test]
1166 fn test_iterative_chunked_matches_oneshot() {
1167 let mut data = [0u8; 200];
1169 for (i, b) in data.iter_mut().enumerate() {
1170 *b = (i as u8).wrapping_mul(31).wrapping_add(7);
1171 }
1172 for total in [0usize, 1, 3, 15, 16, 17, 47, 48, 49, 95, 96, 97, 150, 200] {
1173 let direct = Wyhash::hash(42, &data[..total]);
1174 for first in 0..=total {
1175 let mut h = Wyhash::init(42);
1176 h.update(&data[..first]);
1177 h.update(&data[first..total]);
1178 assert_eq!(direct, h.final_(), "total={total} first={first}");
1179 }
1180 }
1181 }
1182
1183 #[test]
1184 fn test_hash_ascii_lowercase() {
1185 let mut data = [0u8; 200];
1189 for (i, b) in data.iter_mut().enumerate() {
1190 *b = b'A' + (i as u8 % 58); }
1192 for total in [0usize, 1, 16, 47, 48, 49, 95, 96, 97, 200] {
1193 let lowered: Vec<u8> = data[..total].iter().map(u8::to_ascii_lowercase).collect();
1194 assert_eq!(
1195 hash_ascii_lowercase(0, &data[..total]),
1196 Wyhash::hash(0, &lowered),
1197 "total={total}"
1198 );
1199 assert_eq!(
1200 hash_ascii_lowercase(0, &data[..total]),
1201 hash_ascii_lowercase(0, &lowered),
1202 "case-fold total={total}"
1203 );
1204 }
1205 }
1206
1207 #[test]
1208 fn test_wyhash_is_not_wyhash11() {
1209 assert_ne!(Wyhash::hash(0, b"abc"), Wyhash11::hash(0, b"abc"));
1211 }
1212}
1213
1214