const POLY_REFLECTED: u32 = 0x82F63B78;
const TABLE: [u32; 256] = build_table();
const fn build_table() -> [u32; 256] {
let mut table = [0u32; 256];
let mut i = 0;
while i < 256 {
let mut c = i as u32;
let mut j = 0;
while j < 8 {
c = if c & 1 != 0 {
(c >> 1) ^ POLY_REFLECTED
} else {
c >> 1
};
j += 1;
}
table[i] = c;
i += 1;
}
table
}
pub const fn compute(bytes: &[u8]) -> u32 {
let mut crc = 0xFFFF_FFFFu32;
let mut i = 0;
while i < bytes.len() {
let idx = ((crc ^ bytes[i] as u32) & 0xFF) as usize;
crc = TABLE[idx] ^ (crc >> 8);
i += 1;
}
!crc
}
#[cfg(test)]
mod tests {
use super::compute;
#[test]
fn empty_input() {
assert_eq!(compute(b""), 0x0000_0000);
}
#[test]
fn single_byte_a() {
assert_eq!(compute(b"a"), 0xC1D0_4330);
}
#[test]
fn check_sequence_123456789() {
assert_eq!(compute(b"123456789"), 0xE306_9283);
}
#[test]
fn thirty_two_zero_bytes() {
assert_eq!(compute(&[0u8; 32]), 0x8A91_36AA);
}
#[test]
fn thirty_two_all_ones_bytes() {
assert_eq!(compute(&[0xFFu8; 32]), 0x62A8_AB43);
}
const _: () = assert!(compute(b"") == 0x0000_0000);
const _: () = assert!(compute(b"123456789") == 0xE306_9283);
}