const fn crc8_table() -> [u8; 256] {
let mut t = [0u8; 256];
let mut i = 0;
while i < 256 {
let mut crc = i as u8;
let mut j = 0;
while j < 8 {
crc = (crc << 1) ^ if crc & 0x80 != 0 { 0x07 } else { 0 };
j += 1;
}
t[i] = crc;
i += 1;
}
t
}
const fn crc16_table() -> [u16; 256] {
let mut t = [0u16; 256];
let mut i = 0;
while i < 256 {
let mut crc = (i as u16) << 8;
let mut j = 0;
while j < 8 {
crc = (crc << 1) ^ if crc & 0x8000 != 0 { 0x8005 } else { 0 };
j += 1;
}
t[i] = crc;
i += 1;
}
t
}
static CRC8_TABLE: [u8; 256] = crc8_table();
static CRC16_TABLE: [u16; 256] = crc16_table();
pub fn crc8(data: &[u8]) -> u8 {
let mut crc = 0u8;
for &b in data {
crc = CRC8_TABLE[(crc ^ b) as usize];
}
crc
}
pub fn crc16(data: &[u8]) -> u16 {
let mut crc = 0u16;
for &b in data {
crc = (crc << 8) ^ CRC16_TABLE[((crc >> 8) as u8 ^ b) as usize];
}
crc
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn crc8_known_vectors() {
assert_eq!(crc8(&[]), 0);
assert_eq!(crc8(&[0x01]), 0x07);
assert_eq!(crc8(&[0x02]), 0x0E);
assert_eq!(crc8(&[0xFF]), 0xF3);
}
#[test]
fn crc16_known_vectors() {
assert_eq!(crc16(&[]), 0);
assert_eq!(crc16(b"123456789"), 0xFEE8);
}
#[test]
fn crc8_first_table_row_matches_reference() {
let t = crc8_table();
assert_eq!(t[0], 0x00);
assert_eq!(t[7], 0x15);
assert_eq!(t[8], 0x38);
assert_eq!(t[255], 0xF3);
}
#[test]
fn crc16_first_table_row_matches_reference() {
let t = crc16_table();
assert_eq!(t[0], 0x0000);
assert_eq!(t[1], 0x8005);
assert_eq!(t[2], 0x800F);
assert_eq!(t[255], 0x0202);
}
}