use crate::crc::Crc;
use crate::model::bitwise::BitwiseModel;
use crate::spec::Spec;
use crate::util::{ones, reverse};
pub struct BytewiseModel {
model: BitwiseModel,
pub table: [u128; 256],
}
impl BytewiseModel {
pub fn reflect(&self) -> bool {
self.model.reflect()
}
pub fn reverse(&self) -> bool {
self.model.reverse()
}
pub fn width(&self) -> u16 {
self.model.width()
}
pub fn xorout(&self) -> u128 {
self.model.xorout()
}
pub fn init(&self) -> u128 {
self.model.init()
}
fn fill_table(&mut self) {
for k in 0..256_usize {
let byte = k as _;
let mut crc = self.model.add_bytes(0, &[byte][..]);
if self.model.reverse() {
crc = reverse(crc, self.model.width());
}
if self.model.width() < 8 && !self.model.reflect() {
crc <<= 8 - self.model.width();
}
self.table[k] = crc;
}
}
pub fn from_spec(spec: Spec) -> BytewiseModel {
let mut me = BytewiseModel {
model: BitwiseModel::from_spec(spec),
table: [0; 256],
};
me.fill_table();
me
}
}
impl Crc for BytewiseModel {
type Int = u128;
fn init(&self) -> u128 {
self.init() as _
}
fn add_bytes(&self, mut crc: u128, bytes: &[u8]) -> u128 {
if bytes.is_empty() {
return crc;
}
if self.model.reverse() {
crc = reverse(crc, self.model.width());
}
if self.model.reflect() {
crc &= ones(self.model.width());
for byte in bytes {
crc = (crc >> 8) ^ self.table[(crc ^ (*byte as u128)) as u8 as usize];
}
} else if self.model.width() < 8 {
let shift = 8 - self.model.width();
crc <<= shift;
for byte in bytes {
crc = self.table[(crc ^ (*byte as u128)) as usize];
}
crc >>= shift;
} else {
let shift = self.model.width() - 8;
for byte in bytes {
crc = (crc << 8) ^ self.table[(((crc >> shift) ^ (*byte as u128)) as u8) as usize];
}
crc &= ones(self.model.width());
}
if self.model.reverse() {
crc = reverse(crc, self.model.width());
}
crc as _
}
}