#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct CrcParams {
pub width: u8, pub poly: u128,
pub init: u128,
pub refin: bool,
pub refout: bool,
pub xorout: u128,
pub msb_first: bool, }
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum CrcPreset {
Crc8SaeJ1850, Crc8H2F, Crc16CcittFalse, Crc32IsoHdlc, Crc64Ecma182, Custom(CrcParams),
}
pub fn params_for(preset: CrcPreset) -> CrcParams {
match preset {
CrcPreset::Crc8SaeJ1850 => CrcParams { width:8, poly:0x1D, init:0xFF, refin:false, refout:false, xorout:0xFF, msb_first:true },
CrcPreset::Crc8H2F => CrcParams { width:8, poly:0x2F, init:0xFF, refin:false, refout:false, xorout:0xFF, msb_first:true },
CrcPreset::Crc16CcittFalse => CrcParams { width:16, poly:0x1021, init:0xFFFF, refin:false, refout:false, xorout:0x0000, msb_first:true },
CrcPreset::Crc32IsoHdlc => CrcParams { width:32, poly:0x04C11DB7, init:0xFFFF_FFFF, refin:true, refout:true, xorout:0xFFFF_FFFF, msb_first:true },
CrcPreset::Crc64Ecma182 => CrcParams { width:64, poly:0x42F0E1EBA9EA3693, init:0, refin:false, refout:false, xorout:0, msb_first:true },
CrcPreset::Custom(p) => p,
}
}
#[inline]
fn reflect(mut x: u128, bits: u8) -> u128 {
let mut r = 0u128;
for _ in 0..bits { r = (r << 1) | (x & 1); x >>= 1; }
r
}
pub fn crc_compute(p: CrcParams, data: &[u8]) -> u128 {
debug_assert!(p.width >= 8 && p.width <= 64);
debug_assert!(p.msb_first);
let w = p.width;
let top_bit = 1u128 << (w - 1);
let mask = if w == 128 { !0 } else { (1u128 << w) - 1 };
let mut reg = p.init & mask;
for &b in data {
let byte = if p.refin { reflect(b as u128, 8) as u8 } else { b };
reg ^= (byte as u128) << (w - 8);
for _ in 0..8 {
if (reg & top_bit) != 0 { reg = ((reg << 1) ^ p.poly) & mask; }
else { reg = (reg << 1) & mask; }
}
}
if p.refout { reg = reflect(reg, w); }
(reg ^ p.xorout) & mask
}