coap_handler_implementations/
wkc.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
//! Tools to implement a .well-known/core resource easily

use coap_handler::Handler;
use coap_message::{MinimalWritableMessage, MutableWritableMessage, ReadableMessage};

use coap_handler::{Attribute, Record, Reporting};

/// Wrapper around arbitrary Handlers to make them not report in .well-known/core.
///
/// This helps integrating handler implementations that do not yet also implement Reporting by
/// providing a blank report.
///
/// (With specialization, this could be moved into the default implementation).
pub struct NotReporting<H: Handler>(H);

impl<H: Handler> NotReporting<H> {
    pub fn new(handler: H) -> Self {
        NotReporting(handler)
    }
}

// Is DerefMut appropriate? Would be less code...
impl<H: Handler> Handler for NotReporting<H> {
    type RequestData = H::RequestData;
    type ExtractRequestError = H::ExtractRequestError;
    type BuildResponseError<M: MinimalWritableMessage> = H::BuildResponseError<M>;
    fn extract_request_data<M: ReadableMessage>(
        &mut self,
        m: &M,
    ) -> Result<H::RequestData, Self::ExtractRequestError> {
        self.0.extract_request_data(m)
    }
    fn estimate_length(&mut self, r: &Self::RequestData) -> usize {
        self.0.estimate_length(r)
    }
    fn build_response<M: MutableWritableMessage>(
        &mut self,
        m: &mut M,
        r: Self::RequestData,
    ) -> Result<(), Self::BuildResponseError<M>> {
        self.0.build_response(m, r)
    }
}

/// A report with no path, relation or attributes
///
/// This is convenient both in places where a type is needed as an element for an Empty iterator
/// (as in NotReporting) and to wrap a resource with no further properties in (in a Once iterator,
/// relying on the tree builder to augment the empty path with the actual path).
pub struct EmptyRecord;

impl Record for EmptyRecord {
    type PathElement = &'static &'static str; // could just as well be !
    type PathElements = core::iter::Empty<&'static &'static str>;
    type Attributes = core::iter::Empty<Attribute>;

    fn path(&self) -> Self::PathElements {
        core::iter::empty()
    }
    fn rel(&self) -> Option<&str> {
        None
    }
    fn attributes(&self) -> Self::Attributes {
        core::iter::empty()
    }
}

impl<H: Handler> Reporting for NotReporting<H> {
    type Record<'a> = EmptyRecord
    where
        Self: 'a,
    ;
    type Reporter<'a> = core::iter::Empty<EmptyRecord>
    where
        Self: 'a,
    ;

    fn report(&self) -> Self::Reporter<'_> {
        core::iter::empty()
    }
}

/// Wrapper around arbitrary Handlers to make them report some attributes. The path is often
/// configured empty, relying on the tree builder to augment it with the actual path.
///
/// This helps integrating handler implementations that do not manually implement Reporting.
///
/// Any Reporting the handler might implement is overridden by this.
pub struct ConstantSingleRecordReport<'a, H: Handler> {
    handler: H,
    path: &'a [&'a str],
    attributes: &'a [Attribute],
}

impl<'a, H: Handler> ConstantSingleRecordReport<'a, H> {
    /// Wrap a handler with attributes reported at its single path
    pub fn new(handler: H, attributes: &'a [Attribute]) -> Self {
        ConstantSingleRecordReport {
            handler,
            path: &[],
            attributes,
        }
    }

    /// Wrap a handler with attributes and additional path components
    ///
    /// Compared to [`.new()`](ConstantSingleRecordReport::new), this is primarily useful for
    /// handlers that *do* perform own path processing (and are thus instanciated `.below()` some
    /// path), but whose root resource is not the resource below which is put. This is a typical
    /// case: To use relative references, it is convenient to make a handler go
    /// `.below(&["path"])`, but then expect an extra `/` segment (an empty component in the path
    /// list) at the end -- and then deal out relative references like `1` or `./2` to go to
    /// `/path/2`. Such handlers put `&[""]` in the path argument.
    pub fn new_with_path(handler: H, attributes: &'a [Attribute], path: &'a [&'a str]) -> Self {
        ConstantSingleRecordReport {
            handler,
            path,
            attributes,
        }
    }
}

// Is DerefMut appropriate? Would be less code...
impl<'a, H: Handler> Handler for ConstantSingleRecordReport<'a, H> {
    type RequestData = H::RequestData;
    type ExtractRequestError = H::ExtractRequestError;
    type BuildResponseError<M: MinimalWritableMessage> = H::BuildResponseError<M>;
    fn extract_request_data<M: ReadableMessage>(
        &mut self,
        m: &M,
    ) -> Result<H::RequestData, Self::ExtractRequestError> {
        self.handler.extract_request_data(m)
    }
    fn estimate_length(&mut self, r: &Self::RequestData) -> usize {
        self.handler.estimate_length(r)
    }
    fn build_response<M: MutableWritableMessage>(
        &mut self,
        m: &mut M,
        r: Self::RequestData,
    ) -> Result<(), Self::BuildResponseError<M>> {
        self.handler.build_response(m, r)
    }
}

pub struct ConstantSliceRecord<'a> {
    path: &'a [&'a str],
    attributes: &'a [Attribute],
}

impl<'a> Record for ConstantSliceRecord<'a> {
    type PathElement = &'a &'a str;
    type PathElements = core::slice::Iter<'a, &'a str>;
    type Attributes = core::iter::Cloned<core::slice::Iter<'a, Attribute>>;

    fn path(&self) -> Self::PathElements {
        self.path.iter()
    }
    fn rel(&self) -> Option<&str> {
        None
    }
    fn attributes(&self) -> Self::Attributes {
        self.attributes.iter().cloned()
    }
}

impl<'a, H: Handler> Reporting for ConstantSingleRecordReport<'a, H> {
    type Record<'b> = ConstantSliceRecord<'b>
    where
        Self: 'b,
    ;
    type Reporter<'b> = core::iter::Once<ConstantSliceRecord<'b>>
    where
        Self: 'b,
    ;

    fn report(&self) -> Self::Reporter<'_> {
        core::iter::once(ConstantSliceRecord {
            path: self.path,
            attributes: self.attributes,
        })
    }
}

/// Write a Report into a text write in application/link-format.
///
/// As the reports that applications typically get their hands on (as they implement it themselves)
/// don't have the components to make them into an absolute path, but link-format requires using
/// absolute paths, this takes a prefix argument into which the caller has to feed information
/// about where on the CoAP server the resources are actually located.
///
/// Resources that don't ask that information at construction time (it is gone at run time) can not
/// produce meaningful link-format links to their own resources; they could produce output in HTML
/// or CoRAL, but there are currently no Reporting renderers for those.
pub fn write_link_format(
    w: &mut impl core::fmt::Write,
    report: &impl Reporting,
    prefix: &[&str],
) -> core::fmt::Result {
    let mut first = true;
    for record in report.report() {
        if !first {
            write!(w, ",")?;
            first = true;
        }
        write!(w, "<")?;
        for p in prefix.iter() {
            write!(w, "/{}", p)?;
        }
        for p in record.path() {
            write!(w, "/{}", p.as_ref())?;
        }
        write!(w, ">")?;
        if let Some(rel) = record.rel() {
            write!(w, ";rel=\"{}\"", rel)?;
        }
        for attr in record.attributes() {
            match attr {
                Attribute::Observable => write!(w, ";obs")?,
                Attribute::ResourceType(s) => write!(w, ";rt=\"{}\"", s)?,
                Attribute::Interface(s) => write!(w, ";if=\"{}\"", s)?,
                Attribute::Title(s) => write!(w, ";title=\"{}\"", s)?,
                Attribute::Ct(s) => write!(w, ";ct={}", s)?,
                Attribute::Sz(s) => write!(w, ";sz={}", s)?,
                // New attributes are ignored -- as a matter of best practice, when a new attribute
                // is added, it should be covered here.
                _ => (),
            }
        }
    }
    Ok(())
}