const CRC32C_POLY: u32 = 0x82F6_3B78;
const CRC32C_TABLE: [u32; 256] = {
let mut table = [0u32; 256];
let mut i = 0usize;
while i < 256 {
let mut c = i as u32;
let mut k = 0;
while k < 8 {
c = if c & 1 != 0 {
CRC32C_POLY ^ (c >> 1)
} else {
c >> 1
};
k += 1;
}
table[i] = c;
i += 1;
}
table
};
#[must_use]
pub fn crc32c(data: &[u8]) -> u32 {
let mut crc = 0xFFFF_FFFFu32;
for &byte in data {
crc = CRC32C_TABLE[((crc ^ u32::from(byte)) & 0xFF) as usize] ^ (crc >> 8);
}
crc ^ 0xFFFF_FFFF
}
#[cfg(test)]
mod tests {
use super::crc32c;
#[test]
fn rfc_3720_b4_vectors() {
assert_eq!(crc32c(&[0x00; 32]), 0x8a91_36aa);
assert_eq!(crc32c(&[0xff; 32]), 0x62a8_ab43);
let increasing: Vec<u8> = (0..=0x1f).collect();
assert_eq!(crc32c(&increasing), 0x46dd_794e);
let decreasing: Vec<u8> = (0..=0x1f).rev().collect();
assert_eq!(crc32c(&decreasing), 0x113f_db5c);
assert_eq!(crc32c(b"123456789"), 0xe306_9283);
assert_eq!(crc32c(b""), 0);
}
}