Skip to main content

rfm69_async/
flags.rs

1// SPDX-License-Identifier: AGPL-3.0-only
2
3#[derive(Debug, Clone, Copy, PartialEq, Eq)]
4#[cfg_attr(feature = "defmt", derive(defmt::Format))]
5pub enum Flags {
6    None,
7    Ack(u8),
8}
9impl Flags {
10    pub(crate) fn from_u8(flags: u8) -> Flags {
11        match flags {
12            0 => Self::None,
13            1..=4 => Self::Ack(flags - 1),
14            _ => Self::None,
15        }
16    }
17
18    pub(crate) fn as_u8(&self) -> u8 {
19        match self {
20            Self::None => 0,
21            Self::Ack(retries) => *retries + 1,
22        }
23    }
24}
25
26#[cfg(test)]
27mod tests {
28    use super::*;
29
30    #[test]
31    fn from_u8_zero_is_none() {
32        assert_eq!(Flags::from_u8(0), Flags::None);
33    }
34
35    #[test]
36    fn from_u8_decodes_ack_with_retry_count_offset_by_one() {
37        // wire encoding adds 1, so byte 1 means "this is an ACK (no retries)",
38        // byte 2 means "want ACK, sender will retry once", up to byte 4.
39        assert_eq!(Flags::from_u8(1), Flags::Ack(0));
40        assert_eq!(Flags::from_u8(2), Flags::Ack(1));
41        assert_eq!(Flags::from_u8(3), Flags::Ack(2));
42        assert_eq!(Flags::from_u8(4), Flags::Ack(3));
43    }
44
45    #[test]
46    fn from_u8_out_of_range_degrades_to_none() {
47        // 5 and above are not valid ACK encodings; degrade rather than panic.
48        assert_eq!(Flags::from_u8(5), Flags::None);
49        assert_eq!(Flags::from_u8(64), Flags::None);
50        assert_eq!(Flags::from_u8(255), Flags::None);
51    }
52
53    #[test]
54    fn as_u8_none_encodes_to_zero() {
55        assert_eq!(Flags::None.as_u8(), 0);
56    }
57
58    #[test]
59    fn as_u8_ack_adds_one_to_retry_count() {
60        assert_eq!(Flags::Ack(0).as_u8(), 1);
61        assert_eq!(Flags::Ack(1).as_u8(), 2);
62        assert_eq!(Flags::Ack(3).as_u8(), 4);
63    }
64
65    #[test]
66    fn roundtrip_preserves_valid_flags() {
67        for byte in 0u8..=4 {
68            assert_eq!(Flags::from_u8(byte).as_u8(), byte);
69        }
70    }
71
72    #[test]
73    fn roundtrip_collapses_invalid_bytes() {
74        // The wire-protocol byte is normalized to 0 (Flags::None) when it is
75        // outside the recognized range, matching what receive_packet sees.
76        for byte in 5u8..=255 {
77            assert_eq!(Flags::from_u8(byte).as_u8(), 0);
78        }
79    }
80}