async_coap/option/
iter.rs1use super::*;
17use std::convert::Into;
18
19#[derive(Debug, Clone)]
21pub struct OptionIterator<'a> {
22 iter: core::slice::Iter<'a, u8>,
23 last_option: OptionNumber,
24}
25
26impl<'a> Default for OptionIterator<'a> {
27 fn default() -> Self {
28 OptionIterator::new(&[])
29 }
30}
31
32impl<'a> OptionIterator<'a> {
33 pub fn new(buffer: &'a [u8]) -> OptionIterator<'a> {
35 OptionIterator {
36 iter: buffer.iter(),
37 last_option: Default::default(),
38 }
39 }
40
41 pub fn as_slice(&self) -> &'a [u8] {
43 self.iter.as_slice()
44 }
45
46 pub fn peek(&mut self) -> Option<Result<(OptionNumber, &'a [u8]), Error>> {
48 decode_option(&mut self.iter.clone(), self.last_option).transpose()
49 }
50
51 pub fn peek_eq<T>(&mut self, key: OptionKey<T>, value: T) -> bool
54 where
55 T: Into<OptionValue<'a>>,
56 {
57 let mut temp_array = [0; 8];
58 match decode_option(&mut self.iter.clone(), self.last_option) {
59 Ok(Some((number, iter_value))) => {
60 number == key.0
61 && (match value.into() {
62 OptionValue::Integer(x) => encode_u32(x, &mut temp_array),
63 OptionValue::Bytes(x) => x,
64 OptionValue::ETag(x) => {
65 let temp_slice = &mut temp_array[0..x.len()];
66 temp_slice.copy_from_slice(x.as_bytes());
67 temp_slice
68 }
69 } == iter_value)
70 }
71 _ => false,
72 }
73 }
74}
75
76impl<'a> Iterator for OptionIterator<'a> {
77 type Item = Result<(OptionNumber, &'a [u8]), Error>;
78
79 fn next(&mut self) -> Option<Self::Item> {
80 let ret = decode_option(&mut self.iter, self.last_option).transpose();
81 if let Some(Ok((key, _))) = ret {
82 self.last_option = key;
83 }
84 ret
85 }
86}
87
88impl AsRef<[u8]> for OptionIterator<'_> {
89 fn as_ref(&self) -> &[u8] {
90 self.as_slice()
91 }
92}
93
94pub trait OptionIteratorExt<'a>: Iterator<Item = Result<(OptionNumber, &'a [u8]), Error>> {
96 fn find_next(&mut self, key: OptionNumber) -> Option<Result<(OptionNumber, &'a [u8]), Error>>;
104
105 fn find_next_of<T>(&mut self, key: OptionKey<T>) -> Option<Result<T, Error>>
115 where
116 T: TryOptionValueFrom<'a> + Sized,
117 {
118 if let Some(result) = self.find_next(key.0) {
119 match result {
120 Ok((_, value)) => {
121 if let Some(x) = T::try_option_value_from(value) {
122 return Some(Ok(x));
123 } else {
124 return Some(Err(Error::ParseFailure));
125 }
126 }
127 Err(e) => return Some(Err(e)),
128 }
129 }
130
131 None
132 }
133
134 fn extract_uri(&self) -> Result<RelRefBuf, Error>
137 where
138 Self: Sized + Clone,
139 {
140 let mut copy = self.clone();
141 let mut buf = String::new();
142
143 while let Some(seg) = copy.find_next_of(option::URI_PATH).transpose()? {
144 if !buf.is_empty() {
145 buf.push('/');
146 }
147 buf.extend(seg.escape_uri());
148 }
149
150 let mut has_query = false;
151
152 while let Some(item) = copy.find_next_of(option::URI_QUERY).transpose()? {
153 if has_query {
154 buf.push('&');
155 } else {
156 buf.push('?');
157 has_query = true;
158 }
159 buf.extend(item.escape_uri().for_query());
160 }
161
162 let mut ret = RelRefBuf::from_string(buf).expect("Constructed URI was malformed");
163
164 ret.disambiguate();
165
166 Ok(ret)
167 }
168
169 fn extract_location(&self) -> Result<RelRefBuf, Error>
172 where
173 Self: Sized + Clone,
174 {
175 let mut copy = self.clone();
176 let mut buf = String::new();
177
178 while let Some(seg) = copy.find_next_of(option::LOCATION_PATH).transpose()? {
179 if !buf.is_empty() {
180 buf.push('/');
181 }
182 buf.extend(seg.escape_uri());
183 }
184
185 let mut has_query = false;
186
187 while let Some(item) = copy.find_next_of(option::LOCATION_QUERY).transpose()? {
188 if has_query {
189 buf.push('&');
190 } else {
191 buf.push('?');
192 has_query = true;
193 }
194 buf.extend(item.escape_uri().for_query());
195 }
196
197 Ok(RelRefBuf::from_string(buf).expect("Constructed URI was malformed"))
201 }
202}
203
204impl<'a, I> OptionIteratorExt<'a> for I
205where
206 I: Iterator<Item = Result<(OptionNumber, &'a [u8]), Error>> + Sized + Clone,
207{
208 fn find_next(&mut self, key: OptionNumber) -> Option<Result<(OptionNumber, &'a [u8]), Error>> {
209 let next_value = loop {
210 let mut iter = self.clone();
211
212 match iter.next()? {
213 Err(x) => return Some(Err(x)),
214 Ok((number, value)) => {
215 if number == key {
216 *self = iter;
217 break (key, value);
218 }
219 if number < key.0 {
220 *self = iter;
221 continue;
222 }
223 }
224 };
225
226 return None;
227 };
228
229 Some(Ok(next_value))
230 }
231}