pub(crate) fn crc32(data: &[u8]) -> u32 {
crc32_finalize(crc32_update(crc32_init(), data))
}
pub(crate) fn crc32_init() -> u32 {
0xFFFF_FFFF
}
pub(crate) fn crc32_update(mut state: u32, data: &[u8]) -> u32 {
for &byte in data {
let idx = (state ^ u32::from(byte)) & 0xFF;
let table_val = match TABLE.get(idx as usize) {
Some(&v) => v,
None => 0,
};
state = (state >> 8) ^ table_val;
}
state
}
pub(crate) fn crc32_finalize(state: u32) -> u32 {
state ^ 0xFFFF_FFFF
}
const TABLE: [u32; 256] = compute_table();
#[allow(clippy::arithmetic_side_effects, clippy::indexing_slicing)]
const fn compute_table() -> [u32; 256] {
let mut table = [0u32; 256];
let mut i: u32 = 0;
while i < 256 {
let mut c = i;
let mut j = 0;
while j < 8 {
c = if c & 1 != 0 {
0xEDB8_8320 ^ (c >> 1)
} else {
c >> 1
};
j += 1;
}
table[i as usize] = c;
i += 1;
}
table
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn matches_canonical_test_vector() {
assert_eq!(crc32(b"123456789"), 0xCBF4_3926);
}
#[test]
fn empty_input_is_zero_crc() {
assert_eq!(crc32(b""), 0);
}
}