1use std::sync::LazyLock;
10
11static FAST_CRC_TABLE: LazyLock<[u32; 256]> = LazyLock::new(|| {
12 let mut data = [0_u32; 256];
13
14 for (n, c) in data.iter_mut().enumerate() {
15 *c = n as u32;
16 for _ in 0..8 {
17 if *c % 2 == 0 {
18 *c >>= 1;
19 } else {
20 *c = 0xedb88320 ^ *c >> 1;
21 }
22 }
23 }
24
25 data
26});
27
28pub fn update_crc(crc: u32, bytes: &[u8]) -> u32 {
29 let mut c = crc ^ u32::MAX;
30
31 for byte in bytes {
32 let idx: usize = ((c as usize) ^ (*byte as usize)) & 0xFF;
33 c = (*FAST_CRC_TABLE)[idx] ^ (c >> 8);
34 }
35
36 c ^ u32::MAX
37}
38
39pub fn crc(bytes: &[u8]) -> u32 {
40 update_crc(0, bytes)
41}
42
43#[cfg(test)]
44mod tests {
45 use super::*;
46
47 #[test]
48 fn it_works() {
49 let input = b"hello world";
50
51 let actual = crc(input);
52
53 let expected = 0xd4a1185;
55
56 assert_eq!(actual, expected);
57 }
58}