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