Skip to main content

osdp/command/
local_status.rs

1//! Status-request commands with empty payloads:
2//!
3//! - `osdp_LSTAT` (`0x64`) — local (tamper/power) status.
4//! - `osdp_ISTAT` (`0x65`) — input contact status.
5//! - `osdp_OSTAT` (`0x66`) — output status.
6//! - `osdp_RSTAT` (`0x67`) — reader-tamper status.
7//!
8//! # Spec: §6.4 – §6.7
9
10use crate::error::Error;
11use crate::payload_util::require_exact_len;
12use alloc::vec::Vec;
13
14macro_rules! empty_status {
15    ($Ty:ident, $code:expr, $name:literal) => {
16        #[doc = concat!("`", $name, "` body (empty).")]
17        #[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
18        pub struct $Ty;
19
20        impl $Ty {
21            /// Encode (always empty).
22            pub fn encode(&self) -> Result<Vec<u8>, Error> {
23                Ok(Vec::new())
24            }
25
26            /// Decode (must be empty).
27            pub fn decode(data: &[u8]) -> Result<Self, Error> {
28                require_exact_len(data, 0, $code)?;
29                Ok(Self)
30            }
31        }
32    };
33}
34
35empty_status!(LocalStatus, 0x64, "osdp_LSTAT");
36empty_status!(InputStatus, 0x65, "osdp_ISTAT");
37empty_status!(OutputStatus, 0x66, "osdp_OSTAT");
38empty_status!(ReaderStatus, 0x67, "osdp_RSTAT");
39
40#[cfg(test)]
41mod tests {
42    use super::*;
43
44    #[test]
45    fn lstat_roundtrip_empty() {
46        assert!(LocalStatus.encode().unwrap().is_empty());
47        assert_eq!(LocalStatus::decode(&[]).unwrap(), LocalStatus);
48    }
49
50    #[test]
51    fn lstat_rejects_payload() {
52        assert!(matches!(
53            LocalStatus::decode(&[0x00]),
54            Err(Error::PayloadLength { code: 0x64, .. })
55        ));
56    }
57
58    #[test]
59    fn istat_rejects_payload() {
60        assert!(matches!(
61            InputStatus::decode(&[0x00]),
62            Err(Error::PayloadLength { code: 0x65, .. })
63        ));
64    }
65
66    #[test]
67    fn ostat_rejects_payload() {
68        assert!(matches!(
69            OutputStatus::decode(&[0x00]),
70            Err(Error::PayloadLength { code: 0x66, .. })
71        ));
72    }
73
74    #[test]
75    fn rstat_rejects_payload() {
76        assert!(matches!(
77            ReaderStatus::decode(&[0x00]),
78            Err(Error::PayloadLength { code: 0x67, .. })
79        ));
80    }
81}