1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
use const_for::const_for;
use gf256::p64;

const POLYNOMIAL: p64 = p64(0x104c11db7);

const CRC_TABLE: [u32; 256] = {
    let mut table = [0; 256];
    const_for!(i in 0..table.len() => {
        let x = (i as u32).reverse_bits();
        let x = p64((x as u64) << 8).naive_rem(POLYNOMIAL).0 as u32;
        table[i] = x.reverse_bits();
    });

    table
};

pub fn crc32(data: &[u8]) -> u32 {
    let mut crc = 0xffffffff;

    for b in data {
        crc = (crc >> 8) ^ CRC_TABLE[usize::from((crc as u8) ^ b)];
    }

    crc ^ 0xffffffff
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn hello_world() {
        let input = b"Hello World!";
        let expected = 0x1c291ca3;
        assert_eq!(crc32(input), expected);
    }
}