const POLY: u32 = 0x82f6_3b78;
const fn make_table() -> [u32; 256] {
let mut table = [0u32; 256];
let mut i = 0;
while i < 256 {
let mut crc = i as u32;
let mut bit = 0;
while bit < 8 {
if crc & 1 != 0 {
crc = (crc >> 1) ^ POLY;
} else {
crc >>= 1;
}
bit += 1;
}
table[i] = crc;
i += 1;
}
table
}
const TABLE: [u32; 256] = make_table();
#[inline]
#[allow(dead_code)] pub(crate) fn crc32c(data: &[u8]) -> u32 {
crc32c_append(0, data)
}
#[inline]
pub(crate) fn crc32c_append(crc: u32, data: &[u8]) -> u32 {
let mut crc = !crc;
for &b in data {
let idx = ((crc as u8) ^ b) as usize;
crc = TABLE[idx] ^ (crc >> 8);
}
!crc
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn matches_java_castagnoli_check_vector() {
assert_eq!(crc32c(b"123456789"), 0xe3069283);
assert_eq!(crc32c(b""), 0);
let incremental = crc32c_append(crc32c(b"12345"), b"6789");
assert_eq!(incremental, 0xe3069283);
}
#[test]
fn matches_crc32c_crate_hello_world() {
assert_eq!(crc32c(b"Hello world!"), 0x7b98_e751);
}
#[test]
fn multi_block_e2e_payload_golden() {
let block = 64 * 1024;
let payload: Vec<u8> = (0..block * 3 + 123).map(|i| (i % 251) as u8).collect();
assert_eq!(crc32c(&payload), 0x9fa3_63fa);
}
}