#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct Crc16 {
state: u16,
}
impl Crc16 {
pub const fn new() -> Self {
Crc16 { state: 0xFFFF }
}
pub fn update(&mut self, data: &[u8]) {
for &byte in data {
self.state ^= u16::from(byte) << 8;
for _ in 0..8 {
if self.state & 0x8000 != 0 {
self.state = (self.state << 1) ^ 0x1021;
} else {
self.state <<= 1;
}
}
}
}
pub fn finish(&self) -> u16 {
self.state
}
}
impl Default for Crc16 {
fn default() -> Self {
Self::new()
}
}
pub fn crc16(data: &[u8]) -> u16 {
let mut crc = Crc16::new();
crc.update(data);
crc.finish()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn matches_the_standard_check_value() {
assert_eq!(crc16(b"123456789"), 0x29B1);
}
#[test]
fn an_empty_slice_is_the_initial_value() {
assert_eq!(crc16(&[]), 0xFFFF);
}
#[test]
fn updating_in_parts_matches_one_shot() {
let mut split = Crc16::new();
split.update(b"123");
split.update(b"456789");
assert_eq!(split.finish(), crc16(b"123456789"));
}
}