1const POLY: u32 = 0x82F6_3B78;
5
6static TABLES: [[u32; 256]; 8] = build_tables();
8
9const fn build_tables() -> [[u32; 256]; 8] {
10 let mut t = [[0u32; 256]; 8];
11 let mut i = 0;
12 while i < 256 {
13 let mut c = i as u32;
14 let mut k = 0;
15 while k < 8 {
16 c = if c & 1 != 0 { (c >> 1) ^ POLY } else { c >> 1 };
17 k += 1;
18 }
19 t[0][i] = c;
20 i += 1;
21 }
22 let mut i = 0;
23 while i < 256 {
24 let mut s = 1;
25 while s < 8 {
26 let prev = t[s - 1][i];
27 t[s][i] = (prev >> 8) ^ t[0][(prev & 0xFF) as usize];
28 s += 1;
29 }
30 i += 1;
31 }
32 t
33}
34
35#[doc(hidden)]
37pub fn crc32c_sw(data: &[u8]) -> u32 {
38 let t = &TABLES;
39 let mut crc = !0u32;
40 let mut chunks = data.chunks_exact(8);
41 for c in &mut chunks {
42 let lo = u32::from_le_bytes([c[0], c[1], c[2], c[3]]) ^ crc;
43 let hi = u32::from_le_bytes([c[4], c[5], c[6], c[7]]);
44 crc = t[7][(lo & 0xFF) as usize]
45 ^ t[6][((lo >> 8) & 0xFF) as usize]
46 ^ t[5][((lo >> 16) & 0xFF) as usize]
47 ^ t[4][(lo >> 24) as usize]
48 ^ t[3][(hi & 0xFF) as usize]
49 ^ t[2][((hi >> 8) & 0xFF) as usize]
50 ^ t[1][((hi >> 16) & 0xFF) as usize]
51 ^ t[0][(hi >> 24) as usize];
52 }
53 for &b in chunks.remainder() {
54 crc = (crc >> 8) ^ t[0][((crc ^ b as u32) & 0xFF) as usize];
55 }
56 !crc
57}
58
59#[cfg(feature = "std")]
61pub fn crc32c(data: &[u8]) -> u32 {
62 ::crc32c::crc32c(data)
63}
64
65#[cfg(not(feature = "std"))]
67pub fn crc32c(data: &[u8]) -> u32 {
68 crc32c_sw(data)
69}
70
71#[cfg(test)]
72mod tests {
73 use super::*;
74 use proptest::prelude::*;
75
76 #[test]
77 fn check_value() {
78 assert_eq!(crc32c(b"123456789"), 0xE306_9283);
79 assert_eq!(crc32c_sw(b"123456789"), 0xE306_9283);
80 }
81
82 #[test]
83 fn empty_is_zero() {
84 assert_eq!(crc32c(b""), 0);
85 assert_eq!(crc32c_sw(b""), 0);
86 }
87
88 #[cfg(feature = "std")]
90 proptest! {
91 #[test]
92 fn sw_matches_accel(v in proptest::collection::vec(any::<u8>(), 0..5000)) {
93 prop_assert_eq!(crc32c_sw(&v), crc32c(&v));
94 }
95 }
96}