#![allow(dead_code)]
const POLY: u32 = 0x04C1_1DB7;
const TABLE: [u32; 256] = {
let mut t = [0u32; 256];
let mut i = 0;
while i < 256 {
let mut c = (i as u32) << 24;
let mut k = 0;
while k < 8 {
c = if c & 0x8000_0000 != 0 {
(c << 1) ^ POLY
} else {
c << 1
};
k += 1;
}
t[i] = c;
i += 1;
}
t
};
#[derive(Clone, Copy)]
pub(crate) struct Crc32 {
state: u32,
}
impl Crc32 {
pub(crate) const fn new() -> Self {
Self { state: 0xFFFF_FFFF }
}
pub(crate) fn update(&mut self, bytes: &[u8]) {
let mut s = self.state;
for &b in bytes {
let idx = ((s >> 24) ^ b as u32) & 0xFF;
s = (s << 8) ^ TABLE[idx as usize];
}
self.state = s;
}
pub(crate) fn value(&self) -> u32 {
self.state ^ 0xFFFF_FFFF
}
pub(crate) fn reset(&mut self) {
self.state = 0xFFFF_FFFF;
}
}
#[cfg(test)]
pub(crate) fn crc32_mpeg2(bytes: &[u8]) -> u32 {
let mut c = Crc32::new();
c.update(bytes);
c.value()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn empty_is_zero_after_final_xor() {
assert_eq!(crc32_mpeg2(b""), 0);
}
#[test]
fn known_vectors() {
assert_eq!(crc32_mpeg2(b"123456789"), 0xFC89_1918);
assert_eq!(crc32_mpeg2(b"hello world"), 0x44F7_1378);
}
}