use crate::Model;
pub trait Crc<T>: core::fmt::Debug {
#[must_use]
fn model(&self) -> &Model<T>;
#[must_use]
fn checksum(&self, data: &[u8]) -> T {
self.finalize(self.update(self.init(), data))
}
#[must_use]
fn init(&self) -> T;
#[must_use]
fn update(&self, crc: T, data: &[u8]) -> T;
#[must_use]
fn finalize(&self, crc: T) -> T;
#[must_use]
fn undo_finalize(&self, crc: T) -> T;
}
#[cfg(feature = "std")]
#[derive(Copy, Clone, PartialEq, Eq)]
pub enum CrcType {
U8(u8),
U16(u16),
U32(u32),
U64(u64),
U128(u128),
}
macro_rules! fwd_fmt {
($($trait:path),*) => {
$(
#[cfg(feature = "std")]
impl $trait for CrcType {
fn fmt(&self, fmt: &mut core::fmt::Formatter) -> core::fmt::Result {
use CrcType::*;
match self {
U8(x) => <u8 as $trait>::fmt(x, fmt),
U16(x) => <u16 as $trait>::fmt(x, fmt),
U32(x) => <u32 as $trait>::fmt(x, fmt),
U64(x) => <u64 as $trait>::fmt(x, fmt),
U128(x) => <u128 as $trait>::fmt(x, fmt),
}
}
}
)*
}
}
use core::fmt::{Debug, Display, Octal, Binary, LowerHex, UpperHex};
fwd_fmt!(Debug, Display, Octal, Binary, LowerHex, UpperHex);
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum GenericModel {
U8(Model<u8>),
U16(Model<u16>),
U32(Model<u32>),
U64(Model<u64>),
U128(Model<u128>),
}
impl core::fmt::Display for GenericModel {
fn fmt(&self, fmt: &mut core::fmt::Formatter) -> core::fmt::Result {
use GenericModel::*;
match self {
U8(model) => {
write!(
fmt,
"{}:\twidth={}\tpoly={:#X}\tinit={:#X}\trefin={:?}\trefout={:?}\txorout={:#X}\tcheck={:#X}\tresidue={:#X}",
model.name.unwrap_or("<unnamed>"),
model.width,
model.poly,
model.init,
model.refin,
model.refout,
model.xorout,
model.check,
model.residue
)
},
U16(model) => {
write!(
fmt,
"{}:\twidth={}\tpoly={:#X}\tinit={:#X}\trefin={:?}\trefout={:?}\txorout={:#X}\tcheck={:#X}\tresidue={:#X}",
model.name.unwrap_or("<unnamed>"),
model.width,
model.poly,
model.init,
model.refin,
model.refout,
model.xorout,
model.check,
model.residue
)
},
U32(model) => {
write!(
fmt,
"{}:\twidth={}\tpoly={:#X}\tinit={:#X}\trefin={:?}\trefout={:?}\txorout={:#X}\tcheck={:#X}\tresidue={:#X}",
model.name.unwrap_or("<unnamed>"),
model.width,
model.poly,
model.init,
model.refin,
model.refout,
model.xorout,
model.check,
model.residue
)
},
U64(model) => {
write!(
fmt,
"{}:\twidth={}\tpoly={:#X}\tinit={:#X}\trefin={:?}\trefout={:?}\txorout={:#X}\tcheck={:#X}\tresidue={:#X}",
model.name.unwrap_or("<unnamed>"),
model.width,
model.poly,
model.init,
model.refin,
model.refout,
model.xorout,
model.check,
model.residue
)
},
U128(model) => {
write!(
fmt,
"{}:\twidth={}\tpoly={:#X}\tinit={:#X}\trefin={:?}\trefout={:?}\txorout={:#X}\tcheck={:#X}\tresidue={:#X}",
model.name.unwrap_or("<unnamed>"),
model.width,
model.poly,
model.init,
model.refin,
model.refout,
model.xorout,
model.check,
model.residue
)
},
}
}
}
#[cfg(feature = "std")]
impl GenericModel {
#[must_use]
#[inline]
pub fn slice_by<const N: usize>(&self) -> GenericCrc {
match self {
GenericModel::U8(m) => GenericCrc::U8(Box::new(crate::slice_by::Crc::<u8, N>::new(*m))),
GenericModel::U16(m) => GenericCrc::U16(Box::new(crate::slice_by::Crc::<u16, N>::new(*m))),
GenericModel::U32(m) => GenericCrc::U32(Box::new(crate::slice_by::Crc::<u32, N>::new(*m))),
GenericModel::U64(m) => GenericCrc::U64(Box::new(crate::slice_by::Crc::<u64, N>::new(*m))),
GenericModel::U128(m) => GenericCrc::U128(Box::new(crate::slice_by::Crc::<u128, N>::new(*m))),
}
}
#[must_use]
#[inline]
pub fn width(&self) -> u32 {
match self {
GenericModel::U8(m) => m.width,
GenericModel::U16(m) => m.width,
GenericModel::U32(m) => m.width,
GenericModel::U64(m) => m.width,
GenericModel::U128(m) => m.width,
}
}
}
#[cfg(feature = "std")]
#[derive(Debug)]
pub enum GenericCrc {
U8(Box<dyn Crc<u8>>),
U16(Box<dyn Crc<u16>>),
U32(Box<dyn Crc<u32>>),
U64(Box<dyn Crc<u64>>),
U128(Box<dyn Crc<u128>>),
}
#[cfg(feature = "std")]
impl GenericCrc {
#[must_use]
#[inline]
pub fn model(&self) -> GenericModel {
match self {
GenericCrc::U8(m) => GenericModel::U8(m.model().clone()),
GenericCrc::U16(m) => GenericModel::U16(m.model().clone()),
GenericCrc::U32(m) => GenericModel::U32(m.model().clone()),
GenericCrc::U64(m) => GenericModel::U64(m.model().clone()),
GenericCrc::U128(m) => GenericModel::U128(m.model().clone()),
}
}
#[must_use]
#[inline]
pub fn checksum(&self, data: &[u8]) -> CrcType {
match self {
GenericCrc::U8(m) => CrcType::U8(m.checksum(data)),
GenericCrc::U16(m) => CrcType::U16(m.checksum(data)),
GenericCrc::U32(m) => CrcType::U32(m.checksum(data)),
GenericCrc::U64(m) => CrcType::U64(m.checksum(data)),
GenericCrc::U128(m) => CrcType::U128(m.checksum(data)),
}
}
#[must_use]
#[inline]
pub fn init(&self) -> CrcType {
match self {
GenericCrc::U8(m) => CrcType::U8(m.init()),
GenericCrc::U16(m) => CrcType::U16(m.init()),
GenericCrc::U32(m) => CrcType::U32(m.init()),
GenericCrc::U64(m) => CrcType::U64(m.init()),
GenericCrc::U128(m) => CrcType::U128(m.init()),
}
}
#[must_use]
#[inline]
pub fn update(&self, crc: CrcType, data: &[u8]) -> CrcType {
match (self, crc) {
(GenericCrc::U8(s), CrcType::U8(c)) => CrcType::U8(s.update(c, data)),
(GenericCrc::U16(s), CrcType::U16(c)) => CrcType::U16(s.update(c, data)),
(GenericCrc::U32(s), CrcType::U32(c)) => CrcType::U32(s.update(c, data)),
(GenericCrc::U64(s), CrcType::U64(c)) => CrcType::U64(s.update(c, data)),
(GenericCrc::U128(s), CrcType::U128(c)) => CrcType::U128(s.update(c, data)),
_ => panic!("crc type mismatch"),
}
}
#[must_use]
#[inline]
pub fn finalize(&self, crc: CrcType) -> CrcType {
match (self, crc) {
(GenericCrc::U8(s), CrcType::U8(c)) => CrcType::U8(s.finalize(c)),
(GenericCrc::U16(s), CrcType::U16(c)) => CrcType::U16(s.finalize(c)),
(GenericCrc::U32(s), CrcType::U32(c)) => CrcType::U32(s.finalize(c)),
(GenericCrc::U64(s), CrcType::U64(c)) => CrcType::U64(s.finalize(c)),
(GenericCrc::U128(s), CrcType::U128(c)) => CrcType::U128(s.finalize(c)),
_ => panic!("crc type mismatch"),
}
}
}