1use std::ptr::copy_nonoverlapping;
2
3#[inline]
4fn rotl32(x: u32, r: u8) -> u32 {
5 (x << r) | (x >> (32 - r))
6}
7
8#[inline]
9fn read_u32_p(p: *const u8) -> u32 {
10 let mut out: u32 = 0;
11 unsafe {
12 copy_nonoverlapping(p, &mut out as *mut u32 as *mut u8, 4);
13 }
14 out
15}
16
17#[inline]
18fn read_u16_p(p: *const u8) -> u16 {
19 let mut out: u16 = 0;
20 unsafe {
21 copy_nonoverlapping(p, &mut out as *mut u16 as *mut u8, 2);
22 }
23 out
24}
25
26#[inline(never)]
27pub fn fnv32a_yoshimitsu_hasher(bytes: &[u8]) -> u32 {
28 fnv32a_yoshimitsu_triad(0xD8AF_FD71, bytes)
29}
30
31#[inline]
32pub fn fnv32a_yoshimitsu_triad(seed: u32, bytes: &[u8]) -> u32 {
33 let mut len: u32 = bytes.len() as u32;
34 let mut p: *const u8 = bytes.as_ptr();
35
36 const PRIME: u32 = 709_607;
37 let mut hash32_a: u32 = seed ^ 2_166_136_261;
38 let mut hash32_b: u32 = 2_166_136_261 + len;
39 let mut hash32_c: u32 = 2_166_136_261;
40 while len >= 24 {
41 hash32_a = (hash32_a ^ (rotl32(read_u32_p(p), 5) ^ read_u32_p(unsafe { p.offset(4) })))
42 .wrapping_mul(PRIME);
43 hash32_b = (hash32_b
44 ^ (rotl32(read_u32_p(unsafe { p.offset(8) }), 5)
45 ^ read_u32_p(unsafe { p.offset(12) })))
46 .wrapping_mul(PRIME);
47 hash32_c = (hash32_c
48 ^ (rotl32(read_u32_p(unsafe { p.offset(16) }), 5)
49 ^ read_u32_p(unsafe { p.offset(20) })))
50 .wrapping_mul(PRIME);
51 len -= 24;
52 p = unsafe { p.offset(24) };
53 }
54
55 if p == bytes.as_ptr() {
56 hash32_a = (hash32_a ^ rotl32(hash32_c, 5)).wrapping_mul(PRIME);
57 }
58 if (len & 16) != 0 {
60 hash32_a = (hash32_a ^ (rotl32(read_u32_p(p), 5) ^ read_u32_p(unsafe { p.offset(4) })))
61 .wrapping_mul(PRIME);
62 hash32_b = (hash32_b
63 ^ (rotl32(read_u32_p(unsafe { p.offset(8) }), 5)
64 ^ read_u32_p(unsafe { p.offset(12) })))
65 .wrapping_mul(PRIME);
66 p = unsafe { p.offset(16) };
67 }
68 if (len & 8) != 0 {
70 hash32_a = (hash32_a ^ read_u32_p(p)).wrapping_mul(PRIME);
71 hash32_b = (hash32_b ^ read_u32_p(unsafe { p.offset(4) })).wrapping_mul(PRIME);
72 p = unsafe { p.offset(8) };
73 }
74 if (len & 4) != 0 {
76 hash32_a = (hash32_a ^ u32::from(read_u16_p(p))).wrapping_mul(PRIME);
77 hash32_b = (hash32_b ^ u32::from(read_u16_p(unsafe { p.offset(2) }))).wrapping_mul(PRIME);
78 p = unsafe { p.offset(4) };
79 }
80 if (len & 2) != 0 {
82 hash32_a = (hash32_a ^ u32::from(read_u16_p(p))).wrapping_mul(PRIME);
83 p = unsafe { p.offset(2) };
84 }
85 if (len & 1) != 0 {
86 hash32_a = (hash32_a ^ u32::from(unsafe { *p })).wrapping_mul(PRIME);
87 }
88 hash32_a = (hash32_a ^ rotl32(hash32_b, 5)).wrapping_mul(PRIME);
89 hash32_a ^ (hash32_a >> 16)
90}