1use kwap_common::{Array, GetSize};
2use kwap_macros::rfc_7252_doc;
3
4use crate::from_bytes::*;
5
6#[doc = rfc_7252_doc!("5.4")]
7#[doc = concat!("\n#", rfc_7252_doc!("3.1"))]
9#[derive(Clone, PartialEq, PartialOrd, Debug, Default)]
20pub struct Opt<C: Array<Item = u8>> {
21 pub delta: OptDelta,
23 pub value: OptValue<C>,
25}
26
27impl<C: Array<Item = u8>> GetSize for Opt<C> {
28 fn get_size(&self) -> usize {
29 let header_size = 1;
30 let delta_size = match self.delta.0 {
31 | n if n >= 269 => 2,
32 | n if n >= 13 => 1,
33 | _ => 0,
34 };
35
36 let value_len_size = match self.value.0.get_size() {
37 | n if n >= 269 => 2,
38 | n if n >= 13 => 1,
39 | _ => 0,
40 };
41
42 header_size + delta_size + value_len_size + self.value.0.get_size()
43 }
44
45 fn max_size(&self) -> Option<usize> {
46 None
47 }
48}
49
50impl<C: Array<Item = u8>> Opt<C> {
51 pub fn extend_bytes(self, bytes: &mut impl Extend<u8>) {
53 let (del, del_bytes) = crate::to_bytes::opt_len_or_delta(self.delta.0);
54 let (len, len_bytes) = crate::to_bytes::opt_len_or_delta(self.value.0.get_size() as u16);
55 let del = del << 4;
56
57 let header = del | len;
58
59 bytes.extend(Some(header));
60
61 if let Some(bs) = del_bytes {
62 bytes.extend(bs);
63 }
64
65 if let Some(bs) = len_bytes {
66 bytes.extend(bs);
67 }
68
69 bytes.extend(self.value.0);
70 }
71}
72
73#[derive(Copy, Clone, PartialEq, PartialOrd, Debug, Default)]
84pub struct OptDelta(pub u16);
85
86#[doc = rfc_7252_doc!("5.4.6")]
87#[doc = concat!("\n#", rfc_7252_doc!("12.2"))]
89#[derive(Copy, Clone, PartialEq, PartialOrd, Debug, Default)]
95pub struct OptNumber(pub u32);
96
97#[doc = rfc_7252_doc!("5.4.1")]
98#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
99pub enum OptionMustBeProcessed {
100 Yes,
107 No,
115}
116
117#[doc = rfc_7252_doc!("5.4.2")]
118#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
119pub enum WhenOptionUnsupportedByProxy {
120 Error,
126 Forward,
132}
133
134#[doc = rfc_7252_doc!("5.4.2")]
135#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
136pub enum WhenOptionChanges {
137 ResponseChanges,
144 ResponseDoesNotChange,
152}
153
154impl OptNumber {
155 pub fn must_be_processed(&self) -> OptionMustBeProcessed {
157 #[allow(clippy::wildcard_in_or_patterns)] match self.0 & 0b1 {
159 | 1 => OptionMustBeProcessed::Yes,
160 | 0 | _ => OptionMustBeProcessed::No,
161 }
162 }
163
164 pub fn when_unsupported_by_proxy(&self) -> WhenOptionUnsupportedByProxy {
167 #[allow(clippy::wildcard_in_or_patterns)] match (self.0 & 0b10) >> 1 {
169 | 1 => WhenOptionUnsupportedByProxy::Error,
170 | 0 | _ => WhenOptionUnsupportedByProxy::Forward,
171 }
172 }
173
174 pub fn when_option_changes(&self) -> WhenOptionChanges {
180 match (self.0 & 0b11100) >> 2 {
181 | 0b111 => WhenOptionChanges::ResponseDoesNotChange,
182 | _ => WhenOptionChanges::ResponseChanges,
183 }
184 }
185}
186
187#[doc = rfc_7252_doc!("3.2")]
188#[derive(Default, Clone, PartialEq, PartialOrd, Debug)]
189pub struct OptValue<C: Array<Item = u8>>(pub C);
190
191pub(crate) fn opt_header<I: Iterator<Item = u8>>(mut bytes: I) -> Result<u8, OptParseError> {
196 let opt_header = bytes.next();
197
198 if let Some(0b11111111) | None = opt_header {
199 return Err(OptParseError::OptionsExhausted);
201 }
202
203 Ok(opt_header.unwrap())
204}
205
206impl<C: Array<Item = u8>, OptArray: Array<Item = Opt<C>>, I: Iterator<Item = u8>> TryConsumeBytes<I>
207 for OptArray
208{
209 type Error = OptParseError;
210
211 fn try_consume_bytes(bytes: &mut I) -> Result<Self, Self::Error> {
212 let mut opts = OptArray::default();
213
214 loop {
215 match Opt::try_consume_bytes(bytes) {
216 | Ok(opt) => {
217 if !opts.is_full() {
218 opts.extend(Some(opt));
219 } else {
220 break Err(Self::Error::TooManyOptions(opts.get_size()));
221 }
222 },
223 | Err(OptParseError::OptionsExhausted) => break Ok(opts),
224 | Err(e) => break Err(e),
225 }
226 }
227 }
228}
229
230impl<I: Iterator<Item = u8>, C: Array<Item = u8>> TryConsumeBytes<I> for Opt<C> {
231 type Error = OptParseError;
232
233 fn try_consume_bytes(bytes: &mut I) -> Result<Self, Self::Error> {
234 let opt_header = opt_header(bytes.by_ref())?;
235
236 let delta =
238 OptDelta::try_consume_bytes(&mut core::iter::once(opt_header).chain(bytes.by_ref()))?;
239 let len = opt_header & 0b00001111;
240 let len = parse_opt_len_or_delta(len,
241 bytes.by_ref(),
242 OptParseError::ValueLengthReservedValue(15))?;
243 let value = OptValue::try_consume_n_bytes(len as usize, bytes)?;
244 Ok(Opt { delta, value })
245 }
246}
247
248impl<I: Iterator<Item = u8>, C: Array<Item = u8>> TryConsumeNBytes<I> for OptValue<C> {
249 type Error = OptParseError;
250
251 fn try_consume_n_bytes(n: usize, bytes: &mut I) -> Result<Self, Self::Error> {
252 let mut data = C::reserve(n);
253 data.extend(&mut bytes.take(n));
254
255 if data.get_size() < n {
256 Err(Self::Error::UnexpectedEndOfStream)
257 } else {
258 Ok(OptValue(data))
259 }
260 }
261}
262
263pub trait EnumerateOptNumbers<T>
267 where Self: Sized + Iterator<Item = T>
268{
269 fn enumerate_option_numbers(self) -> EnumerateOptNumbersIter<T, Self>;
287}
288
289impl<C: Array<Item = u8>, I: Iterator<Item = Opt<C>>> EnumerateOptNumbers<Opt<C>> for I {
290 fn enumerate_option_numbers(self) -> EnumerateOptNumbersIter<Opt<C>, Self> {
291 EnumerateOptNumbersIter { number: 0,
292 iter: self }
293 }
294}
295
296impl<'a, C: Array<Item = u8>, I: Iterator<Item = &'a Opt<C>>> EnumerateOptNumbers<&'a Opt<C>>
297 for I
298{
299 fn enumerate_option_numbers(self) -> EnumerateOptNumbersIter<&'a Opt<C>, Self> {
300 EnumerateOptNumbersIter { number: 0,
301 iter: self }
302 }
303}
304
305#[derive(Clone, Debug)]
313pub struct EnumerateOptNumbersIter<T, I: Iterator<Item = T>> {
314 number: u32,
315 iter: I,
316}
317
318impl<C: Array<Item = u8>, I: Iterator<Item = Opt<C>>> Iterator
319 for EnumerateOptNumbersIter<Opt<C>, I>
320{
321 type Item = (OptNumber, Opt<C>);
322
323 fn next(&mut self) -> Option<Self::Item> {
324 self.iter.next().map(|opt| {
325 self.number += opt.delta.0 as u32;
326 (OptNumber(self.number), opt)
327 })
328 }
329}
330
331impl<'a, C: Array<Item = u8>, I: Iterator<Item = &'a Opt<C>>> Iterator
332 for EnumerateOptNumbersIter<&'a Opt<C>, I>
333{
334 type Item = (OptNumber, &'a Opt<C>);
335
336 fn next(&mut self) -> Option<Self::Item> {
337 self.iter.next().map(|opt| {
338 self.number += opt.delta.0 as u32;
339 (OptNumber(self.number), opt)
340 })
341 }
342}
343
344#[cfg(test)]
345mod tests {
346 use core::iter::{once, repeat};
347
348 use super::*;
349
350 #[test]
351 fn parse_opt_delta() {
352 let mut del_4bit = [0b00010000u8].into_iter();
353 let del_4bit = OptDelta::try_consume_bytes(&mut del_4bit).unwrap();
354 assert_eq!(del_4bit, OptDelta(1));
355
356 let mut del_1byte = [0b11010000u8, 0b00000000].into_iter();
357 let del_1byte = OptDelta::try_consume_bytes(&mut del_1byte).unwrap();
358 assert_eq!(del_1byte, OptDelta(13));
359
360 let mut del_2bytes = [[0b11100000u8].as_ref(), u16::to_be_bytes(12076).as_ref()].concat()
361 .into_iter();
362 let del_2bytes = OptDelta::try_consume_bytes(&mut del_2bytes).unwrap();
363 assert_eq!(del_2bytes, OptDelta(12345));
364
365 let errs = [[0b11010000u8].as_ref().iter(), [0b11100000u8, 0b00000001].as_ref().iter(), [].as_ref().iter()];
368
369 errs.into_iter().for_each(|iter| {
370 let del = OptDelta::try_consume_bytes(&mut iter.copied());
371 assert_eq!(del, Err(OptParseError::UnexpectedEndOfStream))
372 });
373 }
374
375 #[test]
376 fn parse_opt_value() {
377 let mut val_1byte = once(2);
378 let val_1byte = OptValue::try_consume_n_bytes(1, &mut val_1byte).unwrap();
379 assert_eq!(val_1byte, OptValue(vec![2]));
380
381 let data13bytes = repeat(1u8).take(13).collect::<Vec<_>>();
382 let mut val_13bytes = data13bytes.iter().copied();
383 let val_13bytes = OptValue::try_consume_n_bytes(13, &mut val_13bytes).unwrap();
384 assert_eq!(val_13bytes, OptValue(data13bytes));
385
386 let data270bytes = repeat(1u8).take(270).collect::<Vec<_>>();
387 let mut val_270bytes = data270bytes.iter().copied();
388 let val_270bytes = OptValue::try_consume_n_bytes(270, &mut val_270bytes).unwrap();
389 assert_eq!(val_270bytes, OptValue(data270bytes));
390
391 let errs = [(1, [].into_iter())];
392
393 errs.into_iter().for_each(|(n, mut bytes)| {
394 let del = OptValue::<Vec<_>>::try_consume_n_bytes(n, &mut bytes);
395 assert_eq!(del, Err(OptParseError::UnexpectedEndOfStream))
396 });
397 }
398
399 #[test]
400 fn parse_opt() {
401 let opt_bytes: [u8; 2] = [0b00000001, 0b00000001];
402 let opt = Opt::try_consume_bytes(&mut opt_bytes.into_iter()).unwrap();
403 assert_eq!(opt,
404 Opt { delta: OptDelta(0),
405 value: OptValue(vec![1]) });
406
407 let opt_bytes: [u8; 5] = [0b00000001, 0b00000001, 0b00010001, 0b00000011, 0b11111111];
408 let opt = Vec::<Opt<Vec<_>>>::try_consume_bytes(&mut opt_bytes.into_iter()).unwrap();
409 assert_eq!(opt,
410 vec![Opt { delta: OptDelta(0),
411 value: OptValue(vec![1]) },
412 Opt { delta: OptDelta(1),
413 value: OptValue(vec![3]) },]);
414 }
415
416 #[test]
417 fn opt_number_qualities() {
418 let if_match = OptNumber(1);
420
421 let uri_host = OptNumber(3);
423
424 let etag = OptNumber(4);
426
427 let size1 = OptNumber(60);
429
430 [&if_match, &uri_host].into_iter()
431 .for_each(|num| {
432 assert_eq!(num.must_be_processed(), OptionMustBeProcessed::Yes);
433 });
434
435 [&etag, &size1].into_iter().for_each(|num| {
436 assert_eq!(num.must_be_processed(), OptionMustBeProcessed::No);
437 });
438
439 [&if_match, &etag, &size1].into_iter().for_each(|num| {
440 assert_eq!(num.when_unsupported_by_proxy(),
441 WhenOptionUnsupportedByProxy::Forward);
442 });
443
444 [&uri_host].into_iter().for_each(|num| {
445 assert_eq!(num.when_unsupported_by_proxy(),
446 WhenOptionUnsupportedByProxy::Error);
447 });
448
449 [&if_match, &uri_host, &etag].into_iter().for_each(|num| {
450 assert_eq!(num.when_option_changes(),
451 WhenOptionChanges::ResponseChanges);
452 });
453
454 [&size1].into_iter().for_each(|num| {
455 assert_eq!(num.when_option_changes(),
456 WhenOptionChanges::ResponseDoesNotChange);
457 });
458 }
459}