Skip to main content

const_murmur3/
lib.rs

1#![no_std]
2
3#[cfg(test)]
4mod tests {
5    use super::murmur3_32;
6    #[test]
7    fn standard_murmur3_32() {
8        assert_eq!(murmur3_32(&[], 0), 0);
9        assert_eq!(murmur3_32(&[], 1), 0x514E28B7);
10        assert_eq!(murmur3_32(&[], 0xffffffff), 0x81F16F39);
11        assert_eq!(murmur3_32(&[0, 0, 0, 0], 0), 0x2362F9DE);
12        assert_eq!(murmur3_32(&[0x74, 0x61, 0x72, 0x69], 0), 0x78ab8db9);
13        assert_eq!(
14            murmur3_32(&[0x21, 0x43, 0x65, 0x87], 0x5082EDEE),
15            0x2362F9DE
16        );
17        assert_eq!(murmur3_32(&[0x21, 0x43, 0x65], 0), 0x7E4A8634);
18        assert_eq!(murmur3_32(&[0x21, 0x43], 0), 0xA0F7B07A);
19        assert_eq!(murmur3_32(&[0x21], 0), 0x72661CF4);
20    }
21}
22
23/// A const fn implementation of the murmur32_32 algorithm
24pub const fn murmur3_32(data: &[u8], seed: u32) -> u32 {
25    let slice_size: usize = data.len();
26
27    let c1: u32 = 0xcc9e2d51;
28    let c2: u32 = 0x1b873593;
29    let r2 = 13;
30    let m = 5;
31    let n: u32 = 0xe6546b64;
32
33    let mut hash = seed;
34
35    let mut i = 0;
36    let iterator = slice_size / 4;
37    while i < iterator {
38        let data = [
39            data[i * 4],
40            data[i * 4 + 1],
41            data[i * 4 + 2],
42            data[i * 4 + 3],
43        ];
44        let mut k = u32::from_le_bytes(data);
45        k = k.wrapping_mul(c1);
46        k = k.rotate_left(15);
47        k = k.wrapping_mul(c2);
48
49        hash = hash ^ k;
50        hash = hash.rotate_left(r2);
51        hash = hash.wrapping_mul(m).wrapping_add(n);
52
53        i += 1;
54    }
55    match slice_size % 4 {
56        0 => (),
57        1 => {
58            let data = [data[i * 4], 0, 0, 0];
59            let k = mix_bytes_32(data);
60            hash = hash ^ k;
61        }
62        2 => {
63            let data = [data[i * 4], data[i * 4 + 1], 0, 0];
64            let k = mix_bytes_32(data);
65            hash = hash ^ k;
66        }
67        3 => {
68            let data = [data[i * 4], data[i * 4 + 1], data[i * 4 + 2], 0];
69            let k = mix_bytes_32(data);
70            hash = hash ^ k;
71        }
72        _ => unsafe { core::hint::unreachable_unchecked() },
73    }
74
75    hash = hash ^ slice_size as u32;
76    hash = hash ^ (hash.wrapping_shr(16));
77    hash = hash.wrapping_mul(0x85ebca6b);
78    hash = hash ^ (hash.wrapping_shr(13));
79    hash = hash.wrapping_mul(0xc2b2ae35);
80    hash = hash ^ (hash.wrapping_shr(16));
81
82    hash
83}
84
85const fn mix_bytes_32(data: [u8; 4]) -> u32 {
86    let r1 = 15;
87    let c1: u32 = 0xcc9e2d51;
88    let c2: u32 = 0x1b873593;
89    let mut k = u32::from_le_bytes(data);
90    k = k.wrapping_mul(c1);
91    k = k.rotate_left(r1);
92    k = k.wrapping_mul(c2);
93    return k;
94}