inohashmap/
hasher.rs

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    //Cases 0. .31
59    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    //Cases 0. .15
69    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    //Cases:0. .7
75    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    // //Cases:0. .3
81    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}