coap_handler_implementations/
forking_helpers.rs

1//! Types that are necessarily public (because the Forking implementations need to expose suitable
2//! associated types) but that are not intended to ever be stabilized.
3//!
4//! While they do have concrete associated types, these should not be relied on externally; once
5//! type_alias_impl_trait can be used, they should all switch to opaque types if just to ease API
6//! stability.
7
8use coap_handler::{Attribute, Record};
9
10pub enum ForkingIterator<T, I1: Iterator<Item = T>, I2: Iterator<Item = T>> {
11    First(I1),
12    Second(I2),
13}
14impl<T, I1: Iterator<Item = T>, I2: Iterator<Item = T>> Iterator for ForkingIterator<T, I1, I2> {
15    type Item = T;
16
17    fn next(&mut self) -> Option<T> {
18        match self {
19            ForkingIterator::First(i) => i.next(),
20            ForkingIterator::Second(i) => i.next(),
21        }
22    }
23}
24
25pub enum ForkingAsrefstr<AR1: AsRef<str>, AR2: AsRef<str>> {
26    First(AR1),
27    Second(AR2),
28}
29impl<AR1: AsRef<str>, AR2: AsRef<str>> AsRef<str> for ForkingAsrefstr<AR1, AR2> {
30    fn as_ref(&self) -> &str {
31        match self {
32            Self::First(s) => s.as_ref(),
33            Self::Second(s) => s.as_ref(),
34        }
35    }
36}
37pub enum ForkingAsrefstrIterator<
38    AR1: AsRef<str>,
39    AR2: AsRef<str>,
40    I1: Iterator<Item = AR1>,
41    I2: Iterator<Item = AR2>,
42> {
43    First(I1),
44    Second(I2),
45}
46impl<AR1: AsRef<str>, AR2: AsRef<str>, I1: Iterator<Item = AR1>, I2: Iterator<Item = AR2>> Iterator
47    for ForkingAsrefstrIterator<AR1, AR2, I1, I2>
48{
49    type Item = ForkingAsrefstr<AR1, AR2>;
50
51    fn next(&mut self) -> Option<Self::Item> {
52        match self {
53            Self::First(i) => i.next().map(ForkingAsrefstr::First),
54            Self::Second(i) => i.next().map(ForkingAsrefstr::Second),
55        }
56    }
57}
58
59pub enum ForkingRecord<H1R, H2R> {
60    First(H1R),
61    Second(H2R),
62}
63// FIXME: The rest of Forking is relatively sane (worst part so far is iterating over the path
64// options many times), but this has potential to compile into quadratic insanity!
65impl<H1R: Record, H2R: Record> Record for ForkingRecord<H1R, H2R> {
66    type PathElement = ForkingAsrefstr<H1R::PathElement, H2R::PathElement>;
67    type PathElements = ForkingAsrefstrIterator<
68        H1R::PathElement,
69        H2R::PathElement,
70        H1R::PathElements,
71        H2R::PathElements,
72    >;
73    type Attributes = ForkingIterator<Attribute, H1R::Attributes, H2R::Attributes>;
74
75    fn path(&self) -> Self::PathElements {
76        match self {
77            ForkingRecord::First(h1) => ForkingAsrefstrIterator::First(h1.path()),
78            ForkingRecord::Second(h2) => ForkingAsrefstrIterator::Second(h2.path()),
79        }
80    }
81    fn rel(&self) -> Option<&'static str> {
82        None
83    }
84    fn attributes(&self) -> Self::Attributes {
85        match self {
86            ForkingRecord::First(h1) => ForkingIterator::First(h1.attributes()),
87            ForkingRecord::Second(h2) => ForkingIterator::Second(h2.attributes()),
88        }
89    }
90}
91
92pub struct PrefixedRecord<'a, R> {
93    pub(crate) prefix: &'a [&'a str],
94    pub(crate) prefixed: R,
95}
96
97impl<'a, R: Record> Record for PrefixedRecord<'a, R> {
98    // Usually we use Forking as "First if one type of request comes in, Second for the other", but
99    // here it changes when going through the items.
100    type PathElement = ForkingAsrefstr<&'a &'a str, R::PathElement>;
101    type PathElements = core::iter::Chain<
102        core::iter::Map<core::slice::Iter<'a, &'a str>, fn(&'a &'a str) -> Self::PathElement>,
103        core::iter::Map<R::PathElements, fn(R::PathElement) -> Self::PathElement>,
104    >;
105    type Attributes = R::Attributes;
106
107    fn path(&self) -> Self::PathElements {
108        self.prefix
109            .iter()
110            .map(ForkingAsrefstr::First as fn(_) -> _)
111            .chain(
112                self.prefixed
113                    .path()
114                    .map(ForkingAsrefstr::Second as fn(_) -> _),
115            )
116    }
117    fn rel(&self) -> Option<&str> {
118        self.prefixed.rel()
119    }
120    fn attributes(&self) -> Self::Attributes {
121        self.prefixed.attributes()
122    }
123}