Skip to main content

bzip2_rs/
crc.rs

1pub struct Hasher {
2    // CRC32B hasher
3    val: crc32fast::Hasher,
4    // reversed bits
5    bytes: [u8; 512],
6}
7
8impl Hasher {
9    pub fn new() -> Self {
10        Self {
11            val: crc32fast::Hasher::new(),
12            bytes: [0; 512],
13        }
14    }
15
16    pub fn update(&mut self, mut bytes: &[u8]) {
17        while !bytes.is_empty() {
18            let len = bytes.len().min(self.bytes.len());
19            self.bytes[..len].copy_from_slice(&bytes[..len]);
20            bytes = &bytes[len..];
21
22            for byte in self.bytes.iter_mut() {
23                #[cfg(feature = "rustc_1_37")]
24                {
25                    *byte = byte.reverse_bits();
26                }
27
28                #[cfg(not(feature = "rustc_1_37"))]
29                {
30                    *byte = (*byte & 0xF0) >> 4 | (*byte & 0x0F) << 4;
31                    *byte = (*byte & 0xCC) >> 2 | (*byte & 0x33) << 2;
32                    *byte = (*byte & 0xAA) >> 1 | (*byte & 0x55) << 1;
33                }
34            }
35            self.val.update(&self.bytes[..len]);
36        }
37    }
38
39    pub fn finalyze(&self) -> u32 {
40        let reversed = self.val.clone().finalize();
41        // CRC32B to CRC32
42        #[cfg(feature = "rustc_1_37")]
43        {
44            reversed.reverse_bits()
45        }
46        #[cfg(not(feature = "rustc_1_37"))]
47        {
48            let mut reversed = reversed;
49            reversed = (reversed >> 1) & 0x55555555 | (reversed << 1) & 0xaaaaaaaa;
50            reversed = (reversed >> 2) & 0x33333333 | (reversed << 2) & 0xcccccccc;
51            reversed = (reversed >> 4) & 0x0f0f0f0f | (reversed << 4) & 0xf0f0f0f0;
52            reversed = (reversed >> 8) & 0x00ff00ff | (reversed << 8) & 0xff00ff00;
53            (reversed >> 16) & 0x0000ffff | (reversed << 16) & 0xffff0000
54        }
55    }
56}
57
58#[cfg(test)]
59mod tests {
60    use super::*;
61
62    #[test]
63    fn crc() {
64        let mut hasher = Hasher::new();
65        hasher.update(b"123456789");
66        assert_eq!(hasher.finalyze(), 0xFC891918);
67    }
68}