use crate::header::SyncType;
pub fn is_sync(b1: u8, b2: u8) -> Option<SyncType> {
match (b1, b2) {
(b'I', b'X') => Some(SyncType::NavData),
(b'C', b'M') => Some(SyncType::Command),
(b'A', b'N') => Some(SyncType::Answer),
_ => None,
}
}
pub fn calculate_checksum(data: &[u8]) -> u32 {
data.iter().map(|&b| b as u32).sum()
}
pub fn validate_checksum(frame: &[u8]) -> Option<bool> {
if frame.len() < 4 {
return None;
}
let (data, cksum_bytes) = frame.split_at(frame.len() - 4);
let expected = u32::from_be_bytes([
cksum_bytes[0],
cksum_bytes[1],
cksum_bytes[2],
cksum_bytes[3],
]);
let calculated = calculate_checksum(data);
Some(calculated == expected)
}
#[cfg(test)]
mod tests {
use crate::{framing, header::SyncType};
#[test]
fn test_checksum_empty() {
assert_eq!(framing::calculate_checksum(&[]), 0);
}
#[test]
fn test_checksum_simple() {
assert_eq!(framing::calculate_checksum(&[1, 2, 3, 4]), 10);
}
#[test]
fn test_sync_detection() {
assert_eq!(framing::is_sync(b'I', b'X'), Some(SyncType::NavData));
assert_eq!(framing::is_sync(b'C', b'M'), Some(SyncType::Command));
assert_eq!(framing::is_sync(b'A', b'N'), Some(SyncType::Answer));
assert_eq!(framing::is_sync(b'X', b'X'), None);
}
#[test]
fn test_validate_checksum() {
let frame = [0x01, 0x02, 0x00, 0x00, 0x00, 0x03];
assert_eq!(framing::validate_checksum(&frame), Some(true));
let bad_frame = [0x01, 0x02, 0x00, 0x00, 0x00, 0x04];
assert_eq!(framing::validate_checksum(&bad_frame), Some(false));
let short_frame = [0x01, 0x02, 0x00];
assert!(framing::validate_checksum(&short_frame).is_none());
}
}