1use core::hash::Hash;
2use core::iter::FromIterator;
3use core::marker::PhantomData;
4use core::ops::{Add, Sub};
5
6#[cfg(feature = "alloc")]
7use std_alloc::vec::Vec;
8use tinyvec::ArrayVec;
9use toad_array::{AppendCopy, Array, Indexed};
10use toad_cursor::Cursor;
11use toad_len::Len;
12use toad_macros::rfc_7252_doc;
13use toad_map::Map;
14
15use crate::from_bytes::*;
16
17pub mod parse_error;
19pub use parse_error::*;
20
21pub mod known;
23pub use known::*;
24
25use self::no_repeat::{BLOCK1, BLOCK2};
26
27#[derive(Debug, Clone)]
29pub struct OptIter<M, I>
30 where M: OptionMap
31{
32 iter: I,
33 last_seen_num: OptNumber,
34 repeated: Option<(OptNumber, M::OptValues)>,
35 __p: PhantomData<M>,
36}
37
38#[derive(Debug, Clone)]
40pub struct OptRefIter<'a, M, I>
41 where M: OptionMap
42{
43 iter: I,
44 last_seen_num: OptNumber,
45 repeated: Option<(OptNumber, &'a M::OptValues, usize)>,
46 __p: PhantomData<M>,
47}
48
49impl<M, I> Iterator for OptIter<M, I>
50 where I: Iterator<Item = (OptNumber, M::OptValues)>,
51 M: OptionMap
52{
53 type Item = Opt<M::OptValue>;
54
55 fn next(&mut self) -> Option<Self::Item> {
56 let (num, values) = Option::take(&mut self.repeated).or_else(|| self.iter.next())?;
57
58 match values.len() {
59 | 1 => {
60 let OptNumber(delta) = num - self.last_seen_num;
61 let delta = OptDelta(delta as u16);
62 self.last_seen_num = num;
63
64 Some(Opt { value: values.into_iter().next().unwrap(),
65 delta })
66 },
67 | _ => {
68 let mut values = values.into_iter();
69 if let Some(value) = values.next() {
70 self.repeated = Some((num, values.collect()));
71
72 let OptNumber(delta) = num - self.last_seen_num;
73 let delta = OptDelta(delta as u16);
74 self.last_seen_num = num;
75
76 Some(Opt { value, delta })
77 } else {
78 self.repeated = None;
79 self.next()
80 }
81 },
82 }
83 }
84}
85
86impl<'a, M, I> Iterator for OptRefIter<'a, M, I>
87 where I: Iterator<Item = (&'a OptNumber, &'a M::OptValues)>,
88 Self: 'a,
89 M: 'a + OptionMap
90{
91 type Item = OptRef<'a, M::OptValue>;
92
93 fn next(&mut self) -> Option<Self::Item> {
94 let (num, values, ix) = self.repeated
95 .or_else(|| self.iter.next().map(|(a, b)| (*a, b, 0)))?;
96
97 match values.len() {
98 | 1 => {
99 let OptNumber(delta) = num - self.last_seen_num;
100 let delta = OptDelta(delta as u16);
101 self.last_seen_num = num;
102
103 Some(OptRef { value: &values[0],
104 delta })
105 },
106 | _ => {
107 if let Some(value) = values.get(ix) {
108 self.repeated = Some((num, values, ix + 1));
109
110 let OptNumber(delta) = num - self.last_seen_num;
111 let delta = OptDelta(delta as u16);
112 self.last_seen_num = num;
113
114 Some(OptRef { value, delta })
115 } else {
116 self.repeated = None;
117 self.next()
118 }
119 },
120 }
121 }
122}
123
124pub trait OptionMap
126 where Self: Map<OptNumber, Self::OptValues>
127{
128 type OptValue: Array<Item = u8> + AppendCopy<u8>;
130
131 type OptValues: Array<Item = OptValue<Self::OptValue>>;
135
136 fn opts(self) -> OptIter<Self, Self::IntoIter> {
138 OptIter { iter: self.into_iter(),
139 last_seen_num: OptNumber(0),
140 __p: PhantomData,
141 repeated: None }
142 }
143
144 fn opt_refs(&self) -> OptRefIter<'_, Self, toad_map::Iter<'_, OptNumber, Self::OptValues>> {
146 OptRefIter { iter: self.iter(),
147 last_seen_num: OptNumber(0),
148 __p: PhantomData,
149 repeated: None }
150 }
151}
152
153#[cfg(feature = "alloc")]
154impl OptionMap for std_alloc::collections::BTreeMap<OptNumber, Vec<OptValue<Vec<u8>>>> {
155 type OptValue = Vec<u8>;
156 type OptValues = Vec<OptValue<Vec<u8>>>;
157}
158
159type ArrayVecMap<const N: usize, K, V> = ArrayVec<[(K, V); N]>;
160
161impl<const MAX_OPTS: usize, const MAX_INSTANCES: usize, const MAX_BYTES_PER_INSTANCE: usize>
162 OptionMap
163 for ArrayVecMap<MAX_OPTS,
164 OptNumber,
165 ArrayVec<[OptValue<ArrayVec<[u8; MAX_BYTES_PER_INSTANCE]>>; MAX_INSTANCES]>>
166{
167 type OptValue = ArrayVec<[u8; MAX_BYTES_PER_INSTANCE]>;
168 type OptValues = ArrayVec<[OptValue<Self::OptValue>; MAX_INSTANCES]>;
169}
170
171impl<B: AsRef<[u8]>, M: OptionMap> TryConsumeBytes<B> for M {
172 type Error = OptParseError;
173
174 fn try_consume_bytes(bytes: &mut Cursor<B>) -> Result<Self, Self::Error> {
175 let mut map = Self::default();
176
177 let mut last_inserted = OptNumber(0);
178
179 loop {
180 match Opt::try_consume_bytes(bytes) {
181 | Ok(opt) => {
182 if map.is_full() {
183 break Err(Self::Error::TooManyOptions(map.len()));
184 }
185
186 let OptDelta(d) = opt.delta;
187 let num = last_inserted + OptNumber(d as u32);
188
189 let mut values = M::OptValues::default();
190 values.push(opt.value);
191
192 map.insert(num, values).ok();
193 last_inserted = num;
194 },
195 | Err(OptParseError::OptionsExhausted) => break Ok(map),
196 | Err(e) => break Err(e),
197 }
198 }
199 }
200}
201
202pub(crate) fn parse_opt_len_or_delta<A: AsRef<[u8]>>(head: u8,
203 bytes: &mut Cursor<A>,
204 reserved_err: OptParseError)
205 -> Result<u16, OptParseError> {
206 match head {
207 | 13 => {
208 let n = bytes.next().ok_or_else(OptParseError::eof)?;
209 Ok((n as u16) + 13)
210 },
211 | 14 => match bytes.take_exact(2) {
212 | Some(&[a, b]) => Ok(u16::from_be_bytes([a, b]) + 269),
213 | _ => Err(OptParseError::eof()),
214 },
215 | 15 => Err(reserved_err),
216 | _ => Ok(head as u16),
217 }
218}
219
220#[doc = rfc_7252_doc!("5.4")]
221#[doc = concat!("\n#", rfc_7252_doc!("3.1"))]
223#[derive(Clone, Debug, Default)]
232pub struct Opt<C> {
233 pub delta: OptDelta,
235 pub value: OptValue<C>,
237}
238
239impl<C> PartialOrd for Opt<C> where C: Array<Item = u8>
240{
241 fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
242 Some(self.cmp(other))
243 }
244}
245
246impl<C> PartialEq for Opt<C> where C: Array<Item = u8>
247{
248 fn eq(&self, other: &Self) -> bool {
249 self.delta.eq(&other.delta) && self.value.eq(&other.value)
250 }
251}
252
253impl<C> Ord for Opt<C> where C: Array<Item = u8>
254{
255 fn cmp(&self, other: &Self) -> core::cmp::Ordering {
256 self.delta
257 .cmp(&other.delta)
258 .then_with(|| self.value.cmp(&other.value))
259 }
260}
261
262impl<C> Eq for Opt<C> where C: Array<Item = u8> {}
263
264#[derive(Copy, Clone, Debug)]
266#[allow(missing_docs)]
267pub struct OptRef<'a, C> {
268 pub delta: OptDelta,
269 pub value: &'a OptValue<C>,
270}
271
272impl<'a, C> PartialOrd for OptRef<'a, C> where C: Array<Item = u8>
273{
274 fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
275 Some(self.cmp(other))
276 }
277}
278
279impl<'a, C> PartialEq for OptRef<'a, C> where C: Array<Item = u8>
280{
281 fn eq(&self, other: &Self) -> bool {
282 self.delta.eq(&other.delta) && self.value.eq(other.value)
283 }
284}
285
286impl<'a, C> Ord for OptRef<'a, C> where C: Array<Item = u8>
287{
288 fn cmp(&self, other: &Self) -> core::cmp::Ordering {
289 self.delta
290 .cmp(&other.delta)
291 .then_with(|| self.value.cmp(other.value))
292 }
293}
294
295impl<'a, C> Eq for OptRef<'a, C> where C: Array<Item = u8> {}
296
297impl<'a, C: Array<Item = u8>> Len for OptRef<'a, C> {
298 const CAPACITY: Option<usize> = None;
299
300 fn len(&self) -> usize {
301 let header_size = 1;
302 let delta_size = match self.delta.0 {
303 | n if n >= 269 => 2,
304 | n if n >= 13 => 1,
305 | _ => 0,
306 };
307
308 let value_len_size = match self.value.0.len() {
309 | n if n >= 269 => 2,
310 | n if n >= 13 => 1,
311 | _ => 0,
312 };
313
314 header_size + delta_size + value_len_size + self.value.0.len()
315 }
316
317 fn is_full(&self) -> bool {
318 false
319 }
320}
321
322impl<'a, V> From<&'a Opt<V>> for OptRef<'a, V> {
323 fn from(o: &'a Opt<V>) -> Self {
324 Self { value: &o.value,
325 delta: o.delta }
326 }
327}
328
329impl<C: Array<Item = u8>> Opt<C> {
330 pub fn extend_bytes(self, bytes: &mut impl Extend<u8>) {
332 let (del, del_bytes) = crate::to_bytes::opt_len_or_delta(self.delta.0);
333 let (len, len_bytes) = crate::to_bytes::opt_len_or_delta(self.value.0.len() as u16);
334 let del = del << 4;
335
336 let header = del | len;
337
338 bytes.extend(Some(header));
339
340 if let Some(bs) = del_bytes {
341 bytes.extend(bs);
342 }
343
344 if let Some(bs) = len_bytes {
345 bytes.extend(bs);
346 }
347
348 bytes.extend(self.value.0);
349 }
350}
351
352#[derive(Copy, Clone, Hash, PartialEq, PartialOrd, Eq, Ord, Debug, Default)]
361pub struct OptDelta(pub u16);
362
363#[doc = rfc_7252_doc!("5.4.6")]
364#[doc = concat!("\n#", rfc_7252_doc!("12.2"))]
366#[derive(Copy, Clone, Hash, PartialEq, PartialOrd, Eq, Ord, Debug, Default)]
368pub struct OptNumber(pub u32);
369
370impl Add for OptNumber {
371 type Output = OptNumber;
372
373 fn add(self, rhs: Self) -> Self::Output {
374 Self(self.0 + rhs.0)
375 }
376}
377
378impl Sub for OptNumber {
379 type Output = OptNumber;
380
381 fn sub(self, rhs: Self) -> Self::Output {
382 Self(self.0 - rhs.0)
383 }
384}
385
386#[doc = rfc_7252_doc!("5.4.1")]
387#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
388pub enum OptionMustBeProcessed {
389 Yes,
396 No,
404}
405
406#[doc = rfc_7252_doc!("5.4.2")]
407#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
408pub enum WhenOptionUnsupportedByProxy {
409 Error,
415 Forward,
421}
422
423#[doc = rfc_7252_doc!("5.4.2")]
424#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
425pub enum WhenOptionChanges {
426 ResponseChanges,
433 ResponseDoesNotChange,
441}
442
443impl OptNumber {
444 pub fn must_be_processed(&self) -> OptionMustBeProcessed {
446 #[allow(clippy::wildcard_in_or_patterns)] match self.0 & 0b1 {
448 | 1 => OptionMustBeProcessed::Yes,
449 | 0 | _ => OptionMustBeProcessed::No,
450 }
451 }
452
453 pub fn when_unsupported_by_proxy(&self) -> WhenOptionUnsupportedByProxy {
456 #[allow(clippy::wildcard_in_or_patterns)] match (self.0 & 0b10) >> 1 {
458 | 1 => WhenOptionUnsupportedByProxy::Error,
459 | 0 | _ => WhenOptionUnsupportedByProxy::Forward,
460 }
461 }
462
463 pub fn when_option_changes(&self) -> WhenOptionChanges {
469 match (self.0 & 0b11100) >> 2 {
470 | 0b111 => WhenOptionChanges::ResponseDoesNotChange,
471 | _ => WhenOptionChanges::ResponseChanges,
472 }
473 }
474
475 pub fn include_in_cache_key(&self) -> bool {
477 self.when_option_changes() == WhenOptionChanges::ResponseChanges
478 && self != &BLOCK1
479 && self != &BLOCK2
480 }
481}
482
483#[doc = rfc_7252_doc!("3.2")]
484#[derive(Default, Clone, Debug)]
485pub struct OptValue<C>(pub C);
486
487impl<C> PartialOrd for OptValue<C> where C: Array<Item = u8>
488{
489 fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
490 self.0.iter().partial_cmp(other.0.iter())
491 }
492}
493
494impl<C> PartialEq for OptValue<C> where C: Array<Item = u8>
495{
496 fn eq(&self, other: &Self) -> bool {
497 self.0.iter().eq(other.0.iter())
498 }
499}
500
501impl<C> Ord for OptValue<C> where C: Array<Item = u8>
502{
503 fn cmp(&self, other: &Self) -> core::cmp::Ordering {
504 self.0.iter().cmp(other.0.iter())
505 }
506}
507
508impl<C> Eq for OptValue<C> where C: Array<Item = u8> {}
509
510impl<C> Hash for OptValue<C> where C: Array<Item = u8>
511{
512 fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
513 state.write(&self.0)
514 }
515}
516
517impl<C> OptValue<C> where C: Array<Item = u8>
518{
519 pub fn as_bytes(&self) -> &[u8] {
521 &self.0
522 }
523}
524
525impl<C> FromIterator<u8> for OptValue<C> where C: FromIterator<u8>
526{
527 fn from_iter<T: IntoIterator<Item = u8>>(iter: T) -> Self {
528 Self(iter.into_iter().collect::<C>())
529 }
530}
531
532impl<Bytes: AsRef<[u8]>, V: Array<Item = u8> + AppendCopy<u8>> TryConsumeBytes<Bytes> for Opt<V> {
533 type Error = OptParseError;
534
535 fn try_consume_bytes(bytes: &mut Cursor<Bytes>) -> Result<Self, Self::Error> {
536 let byte1 = bytes.next()
537 .ok_or(OptParseError::OptionsExhausted)
538 .and_then(|b| {
539 if b == 0b11111111 {
540 Err(OptParseError::OptionsExhausted)
541 } else {
542 Ok(b)
543 }
544 })?;
545
546 let delta = parse_opt_len_or_delta(byte1 >> 4,
548 bytes,
549 OptParseError::OptionDeltaReservedValue(15))?;
550 let delta = OptDelta(delta);
551
552 let len = parse_opt_len_or_delta(byte1 & 0b00001111,
553 bytes,
554 OptParseError::ValueLengthReservedValue(15))?
555 as usize;
556
557 let mut value = V::reserve(len);
558 value.append_copy(bytes.take(len));
559
560 if value.len() < len {
561 return Err(Self::Error::UnexpectedEndOfStream);
562 }
563
564 let value = OptValue(value);
565
566 Ok(Opt { delta, value })
567 }
568}
569
570#[cfg(test)]
571mod tests {
572 use std_alloc::collections::BTreeMap;
573
574 use super::*;
575
576 #[test]
577 fn parse_opt() {
578 let mut opt_bytes = Cursor::new([0b00010001, 0b00000001]);
579 let opt = Opt::try_consume_bytes(&mut opt_bytes).unwrap();
580 assert_eq!(opt,
581 Opt { delta: OptDelta(1),
582 value: OptValue(vec![1]) });
583
584 let mut opt_bytes = Cursor::new([0b11010001, 0b00000001, 0b00000001]);
585 let opt = Opt::try_consume_bytes(&mut opt_bytes).unwrap();
586 assert_eq!(opt,
587 Opt { delta: OptDelta(14),
588 value: OptValue(vec![1]) });
589
590 let mut opt_bytes = Cursor::new([0b11100001, 0b00000000, 0b00000001, 0b00000001]);
591 let opt = Opt::try_consume_bytes(&mut opt_bytes).unwrap();
592 assert_eq!(opt,
593 Opt { delta: OptDelta(270),
594 value: OptValue(vec![1]) });
595
596 let mut opt_bytes = Cursor::new([0b00000001, 0b00000001]);
597 let opt = Opt::try_consume_bytes(&mut opt_bytes).unwrap();
598 assert_eq!(opt,
599 Opt { delta: OptDelta(0),
600 value: OptValue(vec![1]) });
601
602 let mut opt_bytes = Cursor::new([0b00000001, 0b00000001, 0b00010001, 0b00000011, 0b11111111]);
603 let opt =
604 BTreeMap::<OptNumber, Vec<OptValue<Vec<u8>>>>::try_consume_bytes(&mut opt_bytes).unwrap();
605 assert_eq!(opt,
606 BTreeMap::from([(OptNumber(0), vec![OptValue(vec![1])]),
607 (OptNumber(1), vec![OptValue(vec![3])])]));
608 }
609
610 #[test]
611 fn opt_number_qualities() {
612 let if_match = OptNumber(1);
614
615 let uri_host = OptNumber(3);
617
618 let etag = OptNumber(4);
620
621 let size1 = OptNumber(60);
623
624 [&if_match, &uri_host].into_iter()
625 .for_each(|num| {
626 assert_eq!(num.must_be_processed(), OptionMustBeProcessed::Yes);
627 });
628
629 [&etag, &size1].into_iter().for_each(|num| {
630 assert_eq!(num.must_be_processed(), OptionMustBeProcessed::No);
631 });
632
633 [&if_match, &etag, &size1].into_iter().for_each(|num| {
634 assert_eq!(num.when_unsupported_by_proxy(),
635 WhenOptionUnsupportedByProxy::Forward);
636 });
637
638 [&uri_host].into_iter().for_each(|num| {
639 assert_eq!(num.when_unsupported_by_proxy(),
640 WhenOptionUnsupportedByProxy::Error);
641 });
642
643 [&if_match, &uri_host, &etag].into_iter().for_each(|num| {
644 assert_eq!(num.when_option_changes(),
645 WhenOptionChanges::ResponseChanges);
646 });
647
648 [&size1].into_iter().for_each(|num| {
649 assert_eq!(num.when_option_changes(),
650 WhenOptionChanges::ResponseDoesNotChange);
651 });
652 }
653}