dot15d4_frame/repr/ie/
payloads.rs

1use super::super::super::{Error, Result};
2use super::super::super::{NestedInformationElement, PayloadGroupId, PayloadInformationElement};
3
4use super::NestedInformationElementRepr;
5
6use heapless::Vec;
7
8/// A high-level representation of a Payload Information Element.
9#[derive(Debug)]
10#[allow(clippy::large_enum_variant)]
11pub enum PayloadInformationElementRepr {
12    /// MLME Payload Information Element.
13    Mlme(Vec<NestedInformationElementRepr, 16>),
14    /// Payload Termination Information Element.
15    PayloadTermination,
16}
17
18#[cfg(feature = "fuzz")]
19impl arbitrary::Arbitrary<'_> for PayloadInformationElementRepr {
20    fn arbitrary(u: &mut arbitrary::Unstructured<'_>) -> arbitrary::Result<Self> {
21        match u.int_in_range(0..=1)? {
22            0 => Ok(Self::PayloadTermination),
23            _ => {
24                let mut nested_information_elements = Vec::new();
25
26                for _ in 0..u.int_in_range(0..=15)? {
27                    nested_information_elements
28                        .push(NestedInformationElementRepr::arbitrary(u)?)
29                        .map_err(|_err| arbitrary::Error::IncorrectFormat)?;
30                }
31
32                Ok(Self::Mlme(nested_information_elements))
33            }
34        }
35    }
36}
37
38impl PayloadInformationElementRepr {
39    /// Parse a Payload Information Element.
40    pub fn parse(ie: &PayloadInformationElement<&[u8]>) -> Result<Self> {
41        match ie.group_id() {
42            PayloadGroupId::Mlme => {
43                let mut nested_information_elements = Vec::new();
44
45                for nested_ie in ie.nested_information_elements() {
46                    if nested_information_elements
47                        .push(NestedInformationElementRepr::parse(&nested_ie)?)
48                        .is_err()
49                    {
50                        break;
51                    }
52                }
53
54                Ok(Self::Mlme(nested_information_elements))
55            }
56            _ => Err(Error),
57        }
58    }
59
60    /// The buffer length required to emit the Payload Information Element.
61    pub fn buffer_len(&self) -> usize {
62        2 + self.inner_len()
63    }
64
65    /// The buffer length required to emit the inner part of the Payload
66    /// Information Element.
67    fn inner_len(&self) -> usize {
68        match self {
69            Self::Mlme(nested_ies) => {
70                let mut len = 0;
71
72                for ie in nested_ies.iter() {
73                    len += ie.buffer_len();
74                }
75
76                len
77            }
78            Self::PayloadTermination => 0,
79        }
80    }
81
82    /// Emit the Payload Information Element into a buffer.
83    pub fn emit(&self, w: &mut PayloadInformationElement<&mut [u8]>) {
84        w.clear();
85        w.set_length(self.inner_len() as u16);
86        w.set_group_id(self.into());
87
88        let buffer = w.content_mut();
89        match self {
90            Self::Mlme(nested_ies) => {
91                let mut offset = 0;
92                for ie in nested_ies.iter() {
93                    ie.emit(&mut NestedInformationElement::new_unchecked(
94                        &mut buffer[offset..],
95                    ));
96                    offset += ie.buffer_len();
97                }
98            }
99            Self::PayloadTermination => todo!(),
100        }
101    }
102}
103
104impl From<&PayloadInformationElementRepr> for PayloadGroupId {
105    fn from(val: &PayloadInformationElementRepr) -> Self {
106        use PayloadInformationElementRepr::*;
107        match val {
108            Mlme(_) => PayloadGroupId::Mlme,
109            PayloadTermination => PayloadGroupId::PayloadTermination,
110        }
111    }
112}