msg_tool\utils/
murmur2.rs

1use std::hash::Hasher;
2
3const M: u32 = 0x5bd1e995;
4const R: u32 = 24;
5
6pub struct StreamingMurmur2 {
7    h: u32,
8    buf: [u8; 4],
9    buf_len: usize,
10}
11
12impl StreamingMurmur2 {
13    /// Create a hasher with already known size.
14    pub fn new(seed: u32, total_len: u32) -> Self {
15        let h = seed ^ total_len;
16        Self {
17            h,
18            buf: [0; 4],
19            buf_len: 0,
20        }
21    }
22}
23
24#[inline]
25fn mix_block(mut h: u32, mut k: u32) -> u32 {
26    k = k.wrapping_mul(M);
27    k ^= k >> R;
28    k = k.wrapping_mul(M);
29    h = h.wrapping_mul(M);
30    h ^= k;
31    h
32}
33
34impl Hasher for StreamingMurmur2 {
35    fn write(&mut self, mut bytes: &[u8]) {
36        // Try process buf first
37        if self.buf_len > 0 {
38            let needed = 4 - self.buf_len;
39            if bytes.len() >= needed {
40                self.buf[self.buf_len..4].copy_from_slice(&bytes[..needed]);
41                bytes = &bytes[needed..];
42
43                // Process block
44                let k = u32::from_le_bytes(self.buf);
45                self.h = mix_block(self.h, k);
46                self.buf_len = 0;
47            } else {
48                // Write to buffer is buffer len not enough
49                self.buf[self.buf_len..self.buf_len + bytes.len()].copy_from_slice(bytes);
50                self.buf_len += bytes.len();
51                return;
52            }
53        }
54
55        // Process blocks
56        while bytes.len() >= 4 {
57            let k = u32::from_le_bytes([bytes[0], bytes[1], bytes[2], bytes[3]]);
58            self.h = mix_block(self.h, k);
59            bytes = &bytes[4..];
60        }
61
62        // Write to buffer
63        if !bytes.is_empty() {
64            self.buf[..bytes.len()].copy_from_slice(bytes);
65            self.buf_len = bytes.len();
66        }
67    }
68
69    fn finish(&self) -> u64 {
70        let mut h = self.h;
71
72        // Tail
73        if self.buf_len > 0 {
74            if self.buf_len >= 3 {
75                h ^= (self.buf[2] as u32) << 16;
76            }
77            if self.buf_len >= 2 {
78                h ^= (self.buf[1] as u32) << 8;
79            }
80            if self.buf_len >= 1 {
81                h ^= self.buf[0] as u32;
82            }
83            h = h.wrapping_mul(M);
84        }
85
86        // Finalization
87        h ^= h >> 13;
88        h = h.wrapping_mul(M);
89        h ^= h >> 15;
90
91        h as u64
92    }
93}
94
95pub struct Murmur2 {
96    seed: u32,
97    buf: Vec<u8>,
98}
99
100impl Murmur2 {
101    pub fn new(seed: u32) -> Self {
102        Self {
103            seed,
104            buf: Vec::new(),
105        }
106    }
107}
108
109impl Hasher for Murmur2 {
110    fn write(&mut self, bytes: &[u8]) {
111        self.buf.extend_from_slice(bytes);
112    }
113
114    fn finish(&self) -> u64 {
115        let mut hasher = StreamingMurmur2::new(self.seed, self.buf.len() as u32);
116        hasher.write(&self.buf);
117        hasher.finish()
118    }
119}
120
121#[test]
122fn test_streaming_murmur2() {
123    let mut hasher = StreamingMurmur2::new(0, 4);
124    hasher.write(b"TEST");
125    assert_eq!(hasher.finish(), 2297143075);
126    hasher = StreamingMurmur2::new(0x300, 11);
127    hasher.write(b"HELLO");
128    hasher.write(b" WORLD");
129    assert_eq!(hasher.finish(), 3206656488);
130}