1#[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 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 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 for byte in 5u8..=255 {
77 assert_eq!(Flags::from_u8(byte).as_u8(), 0);
78 }
79 }
80}