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 pub fn new(slice: &'a [u8]) -> Self {
39 Self {
40 slice,
41 option_base: 0,
42 }
43 }
44}
45
46impl<'a> Iterator for OptPayloadReader<'a> {
47 type Item = OptItem<'a>;
48
49 fn next(&mut self) -> Option<OptItem<'a>> {
50 let delta_len = *self.slice.first()?;
51 self.slice = &self.slice[1..];
52
53 if delta_len == 0xff {
54 return Some(OptItem::Payload(core::mem::take(&mut self.slice)));
55 }
56
57 let mut delta = (delta_len as u16) >> 4;
58 let mut len = (delta_len as u16) & 0x0f;
59
60 if take_extension(&mut delta, &mut self.slice).is_err() {
61 return Some(OptItem::Error("Erroneous delta"));
64 }
65 if take_extension(&mut len, &mut self.slice).is_err() {
66 return Some(OptItem::Error("Erroneous len"));
67 }
68
69 if let Some(s) = self.option_base.checked_add(delta) {
70 self.option_base = s;
71 } else {
72 return Some(OptItem::Error("Options wrap"));
73 }
74
75 let len = len.into();
76
77 if self.slice.len() < len {
78 return Some(OptItem::Error("Too short for option"));
79 }
80
81 let (retslice, tail) = self.slice.split_at(len);
82 self.slice = tail;
83
84 Some(OptItem::Option {
85 number: self.option_base,
86 data: retslice,
87 })
88 }
89}