pub const ACARS_CRC_INIT: u16 = 0x0000;
pub const ACARS_CRC_POLY_REFLECTED: u16 = 0x8408;
const BITS_PER_BYTE: usize = 8;
const CRC_LSB_MASK: u16 = 0x0001;
#[must_use]
pub fn update(crc: u16, byte: u8) -> u16 {
let mut crc = crc ^ u16::from(byte);
for _ in 0..BITS_PER_BYTE {
if crc & CRC_LSB_MASK != 0 {
crc = (crc >> 1) ^ ACARS_CRC_POLY_REFLECTED;
} else {
crc >>= 1;
}
}
crc
}
#[must_use]
pub fn compute(bytes: &[u8]) -> u16 {
bytes.iter().fold(ACARS_CRC_INIT, |crc, &b| update(crc, b))
}
#[cfg(test)]
#[allow(clippy::unwrap_used)]
mod tests {
use super::*;
#[test]
fn crc_matches_known_test_vector() {
let crc = compute(b"123456789");
assert_eq!(crc, 0x2189, "raw KERMIT register for '123456789'");
}
#[test]
fn crc_is_zero_after_appending_its_own_value() {
let payload = b"HELLO ACARS";
let crc = compute(payload);
let mut frame = payload.to_vec();
frame.push((crc & 0xff) as u8); frame.push((crc >> 8) as u8); assert_eq!(compute(&frame), 0);
}
}