dot15d4_frame/ie/
payloads.rs1use super::NestedInformationElementsIterator;
2use super::{Error, Result};
3
4#[derive(Debug, Eq, PartialEq)]
6pub struct PayloadInformationElement<T: AsRef<[u8]>> {
7 data: T,
8}
9
10impl<T: AsRef<[u8]>> PayloadInformationElement<T> {
11 pub fn new(data: T) -> Result<Self> {
19 let ie = Self::new_unchecked(data);
20
21 if !ie.check_len() {
22 return Err(Error);
23 }
24
25 Ok(ie)
26 }
27
28 fn check_len(&self) -> bool {
31 self.data.as_ref().len() >= 2
32 }
33
34 pub fn new_unchecked(data: T) -> Self {
37 Self { data }
38 }
39
40 #[allow(clippy::len_without_is_empty)]
42 pub fn len(&self) -> usize {
43 let b = &self.data.as_ref()[0..2];
44 u16::from_le_bytes([b[0], b[1]]) as usize & 0b1111111111
45 }
46
47 pub fn group_id(&self) -> PayloadGroupId {
49 let b = &self.data.as_ref()[0..2];
50 let id = (u16::from_le_bytes([b[0], b[1]]) >> 11) & 0b111;
51 PayloadGroupId::from(id as u8)
52 }
53
54 pub fn content(&self) -> &[u8] {
56 &self.data.as_ref()[2..][..self.len()]
57 }
58
59 pub fn nested_information_elements(&self) -> NestedInformationElementsIterator {
67 assert!(self.group_id() == PayloadGroupId::Mlme);
68 NestedInformationElementsIterator::new(self.content())
69 }
70}
71
72impl<T: AsRef<[u8]> + AsMut<[u8]>> PayloadInformationElement<T> {
73 pub fn clear(&mut self) {
75 self.data.as_mut().fill(0);
76 }
77
78 pub fn set_length(&mut self, len: u16) {
80 const MASK: u16 = 0b0000_0111_1111_1111;
81 let b = &mut self.data.as_mut()[0..2];
82 let value = u16::from_le_bytes([b[0], b[1]]) & !MASK;
83 let value = value | (len & MASK);
84 b.copy_from_slice(&value.to_le_bytes());
85 }
86
87 pub fn set_group_id(&mut self, id: PayloadGroupId) {
89 const MASK: u16 = 0b0111_1000_0000_0000;
90 let b = &mut self.data.as_mut()[0..2];
91 let value = u16::from_le_bytes([b[0], b[1]]) & !MASK;
92 let value = value | ((id as u16) << 11) | 0b1000_0000_0000_0000;
93 b.copy_from_slice(&value.to_le_bytes());
94 }
95
96 pub fn content_mut(&mut self) -> &mut [u8] {
98 &mut self.data.as_mut()[2..]
99 }
100}
101
102impl<T: AsRef<[u8]>> core::fmt::Display for PayloadInformationElement<T> {
103 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
104 match self.group_id() {
105 PayloadGroupId::Mlme => {
106 writeln!(f, "{:?}", self.group_id())?;
107
108 for nested in self.nested_information_elements() {
109 writeln!(f, " {}", nested)?;
110 }
111
112 Ok(())
113 }
114 id => write!(f, "{:?}({:0x?})", id, self.content()),
115 }
116 }
117}
118
119#[derive(Debug, Eq, PartialEq)]
121pub enum PayloadGroupId {
122 Esdu = 0x00,
124 Mlme = 0x1,
126 VendorSpecific = 0x02,
128 PayloadTermination = 0x0f,
130 Unknown,
132}
133
134impl From<u8> for PayloadGroupId {
135 fn from(value: u8) -> Self {
136 match value {
137 0x00 => Self::Esdu,
138 0x01 => Self::Mlme,
139 0x02 => Self::VendorSpecific,
140 0x0f => Self::PayloadTermination,
141 _ => Self::Unknown,
142 }
143 }
144}
145
146#[derive(Debug)]
148pub struct PayloadInformationElementsIterator<'f> {
149 pub(crate) data: &'f [u8],
150 pub(crate) offset: usize,
151 pub(crate) terminated: bool,
152}
153
154impl PayloadInformationElementsIterator<'_> {
155 pub fn offset(&self) -> usize {
157 self.offset
158 }
159}
160
161impl<'f> Iterator for PayloadInformationElementsIterator<'f> {
162 type Item = PayloadInformationElement<&'f [u8]>;
163
164 fn next(&mut self) -> Option<Self::Item> {
165 if self.terminated {
166 None
167 } else {
168 let Ok(ie) = PayloadInformationElement::new(&self.data[self.offset..]) else {
169 self.terminated = true;
170 return None;
171 };
172
173 self.terminated = matches!(ie.group_id(), PayloadGroupId::PayloadTermination);
174
175 self.offset += ie.len() + 2;
176
177 if self.offset >= self.data.len() {
178 self.terminated = true;
179 }
180
181 Some(ie)
182 }
183 }
184}