pub const TABLE: [u32; 256] = build_table();
const K_POLY: u32 = 0xEDB8_8320;
const fn build_table() -> [u32; 256] {
let mut table = [0u32; 256];
let mut i = 0u32;
while i < 256 {
let mut r = i;
let mut j = 0;
while j < 8 {
if (r & 1) != 0 {
r = (r >> 1) ^ K_POLY;
} else {
r >>= 1;
}
j += 1;
}
table[i as usize] = r;
i += 1;
}
table
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Crc {
value: u32,
}
impl Default for Crc {
fn default() -> Self {
Self { value: 0xFFFF_FFFF }
}
}
impl Crc {
pub fn new() -> Self {
Self::default()
}
pub fn init(&mut self) {
self.value = 0xFFFF_FFFF;
}
pub fn update_byte(&mut self, b: u8) {
self.value = TABLE[((self.value as u8) ^ b) as usize] ^ (self.value >> 8);
}
pub fn update(&mut self, data: &[u8], offset: u32, size: u32) {
let start = (offset as usize).min(data.len());
let end = (offset as usize)
.saturating_add(size as usize)
.min(data.len());
for &b in &data[start..end] {
self.value = TABLE[((self.value as u8) ^ b) as usize] ^ (self.value >> 8);
}
}
pub fn get_digest(&self) -> u32 {
self.value ^ 0xFFFF_FFFF
}
pub fn calculate_digest(data: &[u8], offset: u32, size: u32) -> u32 {
let mut crc = Crc::new();
crc.update(data, offset, size);
crc.get_digest()
}
pub fn verify_digest(digest: u32, data: &[u8], offset: u32, size: u32) -> bool {
Self::calculate_digest(data, offset, size) == digest
}
}