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(())
}