const CRC_TABLE: [u32; 256] = crc_table();
const fn crc_table() -> [u32; 256] {
let mut table = [0u32; 256];
let mut n = 0;
while n < 256 {
let mut c = n as u32;
let mut k = 0;
while k < 8 {
c = if c & 1 != 0 {
0xedb8_8320 ^ (c >> 1)
} else {
c >> 1
};
k += 1;
}
table[n] = c;
n += 1;
}
table
}
#[derive(Clone, Copy)]
pub(crate) struct Crc32(u32);
impl Crc32 {
pub(crate) fn new() -> Self {
Self(0xffff_ffff)
}
pub(crate) fn update(&mut self, bytes: &[u8]) {
let mut c = self.0;
for &b in bytes {
c = CRC_TABLE[((c ^ b as u32) & 0xff) as usize] ^ (c >> 8);
}
self.0 = c;
}
pub(crate) fn finish(self) -> u32 {
self.0 ^ 0xffff_ffff
}
}
pub(crate) fn crc32(bytes: &[u8]) -> u32 {
let mut crc = Crc32::new();
crc.update(bytes);
crc.finish()
}
pub(crate) fn adler32(bytes: &[u8]) -> u32 {
const MOD: u32 = 65521;
let (mut a, mut b) = (1u32, 0u32);
for chunk in bytes.chunks(5552) {
for &byte in chunk {
a += byte as u32;
b += a;
}
a %= MOD;
b %= MOD;
}
(b << 16) | a
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn known_values() {
assert_eq!(crc32(b""), 0);
assert_eq!(crc32(b"123456789"), 0xcbf4_3926);
assert_eq!(crc32(b"IEND"), 0xae42_6082);
assert_eq!(adler32(b""), 1);
assert_eq!(adler32(b"Wikipedia"), 0x11e6_0398);
let long = vec![0xffu8; 100_000];
assert_eq!(adler32(&long), 0x149a_302c);
}
}