dot15d4_frame/repr/ie/
nested.rs

1use super::super::super::{
2    ChannelHopping, NestedInformationElement, NestedSubId, NestedSubIdLong, NestedSubIdShort,
3    TschSlotframeAndLink, TschSynchronization, TschTimeslot,
4};
5use super::super::super::{Error, Result};
6
7/// A high-level representation of a MLME Payload Information Element.
8#[derive(Debug)]
9#[cfg_attr(feature = "fuzz", derive(arbitrary::Arbitrary))]
10pub enum NestedInformationElementRepr {
11    /// TSCH Synchronization Information Element.
12    TschSynchronization(TschSynchronizationRepr),
13    /// TSCH Timeslot Information Element.
14    TschTimeslot(TschTimeslotRepr),
15    /// TSCH Slotframe and Link Information Element.
16    TschSlotframeAndLink(TschSlotframeAndLinkRepr),
17    /// Channel Hopping Information Element.
18    ChannelHopping(ChannelHoppingRepr),
19}
20
21impl NestedInformationElementRepr {
22    /// Parse a Nested Information Element.
23    pub fn parse(ie: &NestedInformationElement<&[u8]>) -> Result<Self> {
24        Ok(match ie.sub_id() {
25            NestedSubId::Short(NestedSubIdShort::TschSynchronization) => Self::TschSynchronization(
26                TschSynchronizationRepr::parse(&TschSynchronization::new(ie.content())?),
27            ),
28            NestedSubId::Short(NestedSubIdShort::TschTimeslot) => {
29                Self::TschTimeslot(TschTimeslotRepr::parse(&TschTimeslot::new(ie.content())?))
30            }
31            NestedSubId::Short(NestedSubIdShort::TschSlotframeAndLink) => {
32                Self::TschSlotframeAndLink(TschSlotframeAndLinkRepr::parse(
33                    &TschSlotframeAndLink::new(ie.content())?,
34                ))
35            }
36            NestedSubId::Long(NestedSubIdLong::ChannelHopping) => Self::ChannelHopping(
37                ChannelHoppingRepr::parse(&ChannelHopping::new(ie.content())?),
38            ),
39            _ => return Err(Error),
40        })
41    }
42
43    /// The buffer length required to emit the Nested Information Element.
44    pub fn buffer_len(&self) -> usize {
45        2 + self.inner_len()
46    }
47
48    /// The buffer length required to emit the inner part of the Nested
49    /// Information Element.
50    pub fn inner_len(&self) -> usize {
51        match self {
52            Self::TschSynchronization(repr) => repr.buffer_len(),
53            Self::TschTimeslot(repr) => repr.buffer_len(),
54            Self::TschSlotframeAndLink(repr) => repr.buffer_len(),
55            Self::ChannelHopping(repr) => repr.buffer_len(),
56        }
57    }
58
59    /// Emit the Nested Information Element into a buffer.
60    pub fn emit(&self, w: &mut NestedInformationElement<&mut [u8]>) {
61        let id = NestedSubId::from(self);
62
63        w.clear();
64        w.set_length(self.inner_len() as u16, id);
65        w.set_sub_id(id);
66
67        match self {
68            Self::TschSynchronization(repr) => {
69                repr.emit(&mut TschSynchronization::new_unchecked(w.content_mut()))
70            }
71            Self::TschTimeslot(repr) => {
72                repr.emit(&mut TschTimeslot::new_unchecked(w.content_mut()))
73            }
74            Self::TschSlotframeAndLink(repr) => {
75                repr.emit(&mut TschSlotframeAndLink::new_unchecked(w.content_mut()))
76            }
77            Self::ChannelHopping(repr) => {
78                repr.emit(&mut ChannelHopping::new_unchecked(w.content_mut()))
79            }
80        }
81    }
82}
83
84impl From<&NestedInformationElementRepr> for NestedSubId {
85    fn from(value: &NestedInformationElementRepr) -> Self {
86        match value {
87            NestedInformationElementRepr::TschSynchronization(_) => {
88                NestedSubId::Short(NestedSubIdShort::TschSynchronization)
89            }
90            NestedInformationElementRepr::TschTimeslot(_) => {
91                NestedSubId::Short(NestedSubIdShort::TschTimeslot)
92            }
93            NestedInformationElementRepr::TschSlotframeAndLink(_) => {
94                NestedSubId::Short(NestedSubIdShort::TschSlotframeAndLink)
95            }
96            NestedInformationElementRepr::ChannelHopping(_) => {
97                NestedSubId::Long(NestedSubIdLong::ChannelHopping)
98            }
99        }
100    }
101}
102
103/// A high-level representation of a TSCH Synchronization Nested Information
104/// Element.
105#[derive(Debug)]
106#[cfg_attr(feature = "fuzz", derive(arbitrary::Arbitrary))]
107pub struct TschSynchronizationRepr {
108    /// The absolute slot number (ASN).
109    pub absolute_slot_number: u64,
110    /// The join metric.
111    pub join_metric: u8,
112}
113
114impl TschSynchronizationRepr {
115    /// Parse a TSCH Synchronization Information Element.
116    pub fn parse(ie: &TschSynchronization<&[u8]>) -> Self {
117        Self {
118            absolute_slot_number: ie.absolute_slot_number(),
119            join_metric: ie.join_metric(),
120        }
121    }
122
123    /// The buffer length required to emit the TSCH Synchronization Information
124    /// Element.
125    pub const fn buffer_len(&self) -> usize {
126        6
127    }
128
129    /// Emit the TSCH Synchronization Information Element into a buffer.
130    pub fn emit(&self, ie: &mut TschSynchronization<&mut [u8]>) {
131        ie.set_absolute_slot_number(self.absolute_slot_number);
132        ie.set_join_metric(self.join_metric);
133    }
134}
135
136/// A high-level representation of a TSCH Slotframe and Link Nested Information
137/// Element.
138#[derive(Debug)]
139#[cfg_attr(feature = "fuzz", derive(arbitrary::Arbitrary))]
140pub struct TschSlotframeAndLinkRepr {
141    /// The number of slotframes.
142    pub number_of_slot_frames: u8,
143}
144
145impl TschSlotframeAndLinkRepr {
146    /// Parse a TSCH Slotframe and Link Information Element.
147    pub fn parse(ie: &TschSlotframeAndLink<&[u8]>) -> Self {
148        Self {
149            number_of_slot_frames: ie.number_of_slot_frames(),
150        }
151    }
152
153    /// The buffer length required to emit the TSCH Slotframe and Link
154    /// Information Element.
155    pub fn buffer_len(&self) -> usize {
156        1
157    }
158
159    /// Emit the TSCH Slotframe and Link Information Element into a buffer.
160    pub fn emit(&self, ie: &mut TschSlotframeAndLink<&mut [u8]>) {
161        ie.set_number_of_slot_frames(self.number_of_slot_frames);
162    }
163}
164
165/// A high-level representation of a TSCH Timeslot Nested Information Element.
166#[derive(Debug)]
167#[cfg_attr(feature = "fuzz", derive(arbitrary::Arbitrary))]
168pub struct TschTimeslotRepr {
169    /// The timeslot ID.
170    pub id: u8,
171}
172
173impl TschTimeslotRepr {
174    /// Parse a TSCH Timeslot Information Element.
175    pub fn parse(ie: &TschTimeslot<&[u8]>) -> Self {
176        Self { id: ie.id() }
177    }
178
179    /// The buffer length required to emit the TSCH Timeslot Information
180    /// Element.
181    pub fn buffer_len(&self) -> usize {
182        // TODO: allow to set other time slots than the default one.
183        1
184    }
185
186    /// Emit the TSCH Timeslot Information Element into a buffer.
187    pub fn emit(&self, ie: &mut TschTimeslot<&mut [u8]>) {
188        ie.set_time_slot_id(self.id);
189    }
190}
191
192/// A high-level representation of a Channel Hopping Nested Information Element.
193#[derive(Debug)]
194#[cfg_attr(feature = "fuzz", derive(arbitrary::Arbitrary))]
195pub struct ChannelHoppingRepr {
196    /// The hopping sequence ID.
197    pub hopping_sequence_id: u8,
198}
199
200impl ChannelHoppingRepr {
201    /// Parse a Channel Hopping Information Element.
202    pub fn parse(ie: &ChannelHopping<&[u8]>) -> Self {
203        Self {
204            hopping_sequence_id: ie.hopping_sequence_id(),
205        }
206    }
207
208    /// The buffer length required to emit the Channel Hopping Information
209    /// Element.
210    pub fn buffer_len(&self) -> usize {
211        1
212    }
213
214    /// Emit the Channel Hopping Information Element into a buffer.
215    pub fn emit(&self, ie: &mut ChannelHopping<&mut [u8]>) {
216        ie.set_hopping_sequence_id(self.hopping_sequence_id);
217    }
218}