coap_message_implementations/
option_iteration.rs1use crate::option_extension::take_extension;
6
7#[derive(Debug)]
9#[cfg_attr(feature = "defmt", derive(defmt::Format))]
10pub enum OptItem<'a> {
11 Option { number: u16, data: &'a [u8] },
12 Payload(&'a [u8]),
13 Error(&'static str),
14}
15
16pub struct OptPayloadReader<'a> {
29 slice: &'a [u8],
30 option_base: u16,
31}
32
33impl<'a> OptPayloadReader<'a> {
34 #[must_use]
39 pub fn new(slice: &'a [u8]) -> Self {
40 Self {
41 slice,
42 option_base: 0,
43 }
44 }
45
46 pub(crate) fn new_from(slice: &'a [u8], option_base: u16) -> Self {
48 Self { slice, option_base }
49 }
50
51 pub(crate) fn destruct(self) -> (&'a [u8], u16) {
53 (self.slice, self.option_base)
54 }
55}
56
57impl<'a> Iterator for OptPayloadReader<'a> {
58 type Item = OptItem<'a>;
59
60 fn next(&mut self) -> Option<OptItem<'a>> {
61 let delta_len = *self.slice.first()?;
62 self.slice = &self.slice[1..];
63
64 if delta_len == 0xff {
65 return Some(OptItem::Payload(core::mem::take(&mut self.slice)));
66 }
67
68 let mut delta = u16::from(delta_len) >> 4;
69 let mut len = u16::from(delta_len) & 0x0f;
70
71 if take_extension(&mut delta, &mut self.slice).is_err() {
72 return Some(OptItem::Error("Erroneous delta"));
75 }
76 if take_extension(&mut len, &mut self.slice).is_err() {
77 return Some(OptItem::Error("Erroneous len"));
78 }
79
80 if let Some(s) = self.option_base.checked_add(delta) {
81 self.option_base = s;
82 } else {
83 return Some(OptItem::Error("Options wrap"));
84 }
85
86 let len = len.into();
87
88 if self.slice.len() < len {
89 return Some(OptItem::Error("Too short for option"));
90 }
91
92 let (retslice, tail) = self.slice.split_at(len);
93 self.slice = tail;
94
95 Some(OptItem::Option {
96 number: self.option_base,
97 data: retslice,
98 })
99 }
100}