apis_saltans_aps/frame/
control.rs1use bitflags::bitflags;
2use le_stream::{FromLeStream, ToLeStream};
3
4pub use self::delivery_mode::DeliveryMode;
5pub use self::frame_type::FrameType;
6use crate::Extended;
7use crate::frame::destination::WeakDestination;
8
9mod delivery_mode;
10mod frame_type;
11
12#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, FromLeStream, ToLeStream)]
14#[repr(transparent)]
15pub struct Control(u8);
16
17bitflags! {
18 impl Control: u8 {
19 const FRAME_TYPE = 0b1100_0000;
21
22 const DELIVERY_MODE = 0b0011_0000;
24
25 const ACK_FORMAT = 0b0000_1000;
27
28 const SECURITY = 0b0000_0100;
30
31 const ACK_REQUEST = 0b0000_0010;
33
34 const EXTENDED_HEADER = 0b0000_0001;
36 }
37}
38
39impl core::fmt::Display for Control {
40 fn fmt(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
41 bitflags::parser::to_writer(self, formatter)
42 }
43}
44
45impl core::str::FromStr for Control {
46 type Err = bitflags::parser::ParseError;
47
48 fn from_str(flags: &str) -> Result<Self, Self::Err> {
49 bitflags::parser::from_str(flags)
50 }
51}
52
53impl Control {
54 #[must_use]
56 pub fn frame_type(self) -> FrameType {
57 FrameType::try_from(
58 (self & Self::FRAME_TYPE).bits() >> Self::FRAME_TYPE.bits().trailing_zeros(),
59 )
60 .unwrap_or_else(|_| unreachable!("Frame type covers all possible values."))
61 }
62
63 pub const fn set_frame_type(&mut self, frame_type: FrameType) {
65 self.0 = (self.bits() & !Self::FRAME_TYPE.bits())
66 | ((frame_type as u8) << Self::FRAME_TYPE.bits().trailing_zeros());
67 }
68
69 #[must_use]
71 pub fn delivery_mode(self) -> Option<DeliveryMode> {
72 DeliveryMode::try_from(
73 (self & Self::DELIVERY_MODE).bits() >> Self::DELIVERY_MODE.bits().trailing_zeros(),
74 )
75 .ok()
76 }
77
78 pub const fn set_delivery_mode(&mut self, delivery_mode: DeliveryMode) {
80 self.0 = (self.bits() & !Self::DELIVERY_MODE.bits())
81 | ((delivery_mode as u8) << Self::DELIVERY_MODE.bits().trailing_zeros());
82 }
83
84 pub const fn set_destination(&mut self, destination: WeakDestination) {
86 match destination {
87 WeakDestination::Unicast(_) => {
88 self.set_delivery_mode(DeliveryMode::Unicast);
89 }
90 WeakDestination::Broadcast(_) => {
91 self.set_delivery_mode(DeliveryMode::Broadcast);
92 }
93 WeakDestination::Group(_) => {
94 self.set_delivery_mode(DeliveryMode::Group);
95 }
96 }
97 }
98
99 pub fn set_extended_header(&mut self, extended_header_present: bool) {
101 if extended_header_present {
102 self.insert(Self::EXTENDED_HEADER);
103 } else {
104 self.remove(Self::EXTENDED_HEADER);
105 }
106 }
107
108 pub(crate) fn deserialize_extended_header<T>(self, mut bytes: T) -> Result<Option<Extended>, ()>
109 where
110 T: Iterator<Item = u8>,
111 {
112 if self.contains(Self::EXTENDED_HEADER) {
113 let Some(extended) = Extended::from_le_stream(
114 matches!(self.frame_type(), FrameType::Acknowledgment),
115 &mut bytes,
116 ) else {
117 return Err(());
118 };
119
120 Ok(Some(extended))
121 } else {
122 Ok(None)
123 }
124 }
125
126 pub(crate) fn deserialize_destination<T>(self, mut bytes: T) -> Option<WeakDestination>
127 where
128 T: Iterator<Item = u8>,
129 {
130 self.delivery_mode()
131 .and_then(|delivery_mode| match delivery_mode {
132 DeliveryMode::Unicast => {
133 u8::from_le_stream(&mut bytes).map(WeakDestination::Unicast)
134 }
135 DeliveryMode::Broadcast => {
136 u8::from_le_stream(&mut bytes).map(WeakDestination::Broadcast)
137 }
138 DeliveryMode::Group => u16::from_le_stream(&mut bytes).map(WeakDestination::Group),
139 })
140 }
141}