use crcxx::crc16;
use crcxx::crc32;
const SLICES: usize = 16;
const CRC_32: crc32::Crc<crc32::LookupTable256xN<SLICES>> =
crc32::Crc::<crc32::LookupTable256xN<SLICES>>::new(&crc32::catalog::CRC_32_ISO_HDLC);
const CRC_16: crc16::Crc<crc16::LookupTable256xN<SLICES>> =
crc16::Crc::<crc16::LookupTable256xN<SLICES>>::new(&crc16::catalog::CRC_16_IBM_3740);
pub fn crc32(bytes: &[u8]) -> u32 {
CRC_32.compute(bytes)
}
pub fn crc16(bytes: &[u8]) -> u16 {
CRC_16.compute(bytes)
}
pub struct Crc32Stream<'a>(crc32::ComputeMultipart<'a, crc32::LookupTable256xN<SLICES>>);
impl Crc32Stream<'_> {
pub fn new() -> Crc32Stream<'static> {
Crc32Stream(CRC_32.compute_multipart())
}
pub fn update(&mut self, bytes: &[u8]) {
self.0.update(bytes);
}
pub fn value(&self) -> u32 {
self.0.value()
}
}
pub struct Crc16Stream<'a>(crc16::ComputeMultipart<'a, crc16::LookupTable256xN<SLICES>>);
impl Crc16Stream<'_> {
pub fn new() -> Crc16Stream<'static> {
Crc16Stream(CRC_16.compute_multipart())
}
pub fn update(&mut self, bytes: &[u8]) {
self.0.update(bytes);
}
pub fn value(&self) -> u16 {
self.0.value()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn the_algorithms_are_the_cataloged_ones() {
assert_eq!(crc32(b"123456789"), 0xCBF4_3926, "not CRC-32/ISO-HDLC");
assert_eq!(crc16(b"123456789"), 0x29B1, "not CRC-16/IBM-3740");
}
#[test]
fn streams_match_slices() {
let data: Vec<u8> = (0u8..=255).cycle().take(1000).collect();
let mut s32 = Crc32Stream::new();
let mut s16 = Crc16Stream::new();
for chunk in data.chunks(7) {
s32.update(chunk);
s16.update(chunk);
}
assert_eq!(s32.value(), crc32(&data));
assert_eq!(s16.value(), crc16(&data));
}
}