Skip to main content

osdp/packet/
checksum.rs

1//! 8-bit two's-complement checksum used for the weak frame trailer.
2//!
3//! # Spec: ยง5.9
4//!
5//! The transmitted byte is the negation of the modulo-256 sum so that the sum
6//! of all bytes including the trailer is `0`.
7
8/// Compute the 8-bit OSDP checksum over `bytes`.
9#[inline]
10pub fn checksum8(bytes: &[u8]) -> u8 {
11    let sum: u32 = bytes.iter().map(|&b| u32::from(b)).sum();
12    (!(sum as u8)).wrapping_add(1)
13}
14
15#[cfg(test)]
16mod tests {
17    use super::*;
18
19    /// `osdp_COMSET` packet trailer.
20    #[test]
21    fn comset_vector() {
22        let buf = [0x53, 0x7F, 0x0C, 0x00, 0x00, 0x6E, 0x00, 0x80, 0x25, 0x00];
23        assert_eq!(checksum8(&buf), 0x0F);
24    }
25
26    /// `osdp_ID` packet trailer.
27    #[test]
28    fn id_vector() {
29        let buf = [0x53, 0x00, 0x08, 0x00, 0x00, 0x61];
30        assert_eq!(checksum8(&buf), 0x44);
31    }
32
33    /// Trailer is its own inverse: sum of all bytes including the checksum is 0.
34    #[test]
35    fn trailer_closes_to_zero() {
36        let buf = [0x53, 0x7F, 0x0C, 0x00, 0x00, 0x6E, 0x00, 0x80, 0x25, 0x00];
37        let trailer = checksum8(&buf);
38        let total: u32 = buf
39            .iter()
40            .copied()
41            .chain(core::iter::once(trailer))
42            .map(u32::from)
43            .sum();
44        assert_eq!(total & 0xFF, 0);
45    }
46}