use coap_handler::{Attribute, Handler, Reporting};
use coap_message::{
error::RenderableOnMinimal, MessageOption, MinimalWritableMessage, MutableWritableMessage,
ReadableMessage,
};
use coap_numbers::option;
use crate::forking_helpers::{ForkingRecord, PrefixedRecord};
use crate::helpers::{MaskingUriUpToPath, MaskingUriUpToPathN};
use crate::{wkc, wkc_implementation, NeverFound};
trait IterOrderByBackport: Iterator {
fn cmp_by<I, F>(mut self, other: I, mut cmp: F) -> core::cmp::Ordering
where
Self: Sized,
I: IntoIterator,
F: FnMut(Self::Item, I::Item) -> core::cmp::Ordering,
{
let mut other = other.into_iter();
loop {
let x = match self.next() {
None => {
if other.next().is_none() {
return core::cmp::Ordering::Equal;
} else {
return core::cmp::Ordering::Less;
}
}
Some(val) => val,
};
let y = match other.next() {
None => return core::cmp::Ordering::Greater,
Some(val) => val,
};
match cmp(x, y) {
core::cmp::Ordering::Equal => (),
non_eq => return non_eq,
}
}
}
}
impl<T: Iterator> IterOrderByBackport for T {}
#[cfg(not(feature = "leaky_names"))]
pub fn new_dispatcher() -> impl Handler + Reporting {
wkc::NotReporting::new(NeverFound {})
}
#[cfg(feature = "leaky_names")]
pub fn new_dispatcher() -> wkc::NotReporting<NeverFound> {
wkc::NotReporting::new(NeverFound {})
}
pub trait HandlerBuilder<'a, OldRD>
where
Self: Handler + Sized,
{
fn at<H>(self, path: &'a [&'a str], handler: H) -> ForkingHandler<'a, H, Self>
where
H: Handler + Sized,
{
ForkingHandler {
h1: handler,
h2: self,
h1_condition: path,
}
}
fn at_with_attributes<H>(
self,
path: &'a [&'a str],
attributes: &'a [Attribute],
handler: H,
) -> ForkingHandler<'a, wkc::ConstantSingleRecordReport<'a, H>, Self>
where
H: Handler + Sized,
{
ForkingHandler {
h1: wkc::ConstantSingleRecordReport::new(handler, attributes),
h2: self,
h1_condition: path,
}
}
fn below<H>(self, path: &'a [&'a str], handler: H) -> ForkingTreeHandler<'a, H, Self> {
ForkingTreeHandler {
h1: handler,
h2: self,
h1_condition: path,
}
}
}
impl<'a, OldRD, OldH> HandlerBuilder<'a, OldRD> for OldH
where
Self: Handler<RequestData = OldRD> + Sized,
{
}
pub trait ReportingHandlerBuilder<'a, OldRD>: HandlerBuilder<'a, OldRD> + Reporting {
fn with_wkc(self) -> wkc_implementation::WellKnownCore<Self> {
wkc_implementation::WellKnownCore::new(self)
}
}
impl<'a, OldRD, OldH> ReportingHandlerBuilder<'a, OldRD> for OldH
where
OldH: Handler<RequestData = OldRD> + Reporting,
{
}
pub struct ForkingHandler<'a, H1, H2> {
h1: H1,
h2: H2,
h1_condition: &'a [&'a str],
}
#[derive(Debug)]
pub enum ForkingRequestData<RD1, RD2> {
First(RD1),
Second(RD2),
}
impl<RE1, RE2> RenderableOnMinimal for ForkingRequestData<RE1, RE2>
where
RE1: RenderableOnMinimal + core::fmt::Debug,
RE2: RenderableOnMinimal + core::fmt::Debug,
{
type Error<IE: RenderableOnMinimal + core::fmt::Debug> = ForkingRequestData<
<RE1 as RenderableOnMinimal>::Error<IE>,
<RE2 as RenderableOnMinimal>::Error<IE>,
>;
fn render<M: MinimalWritableMessage>(
self,
message: &mut M,
) -> Result<(), Self::Error<M::UnionError>> {
use ForkingRequestData::*;
match self {
First(e) => e.render(message).map_err(First),
Second(e) => e.render(message).map_err(Second),
}
}
}
impl<'a, RD1, H1, RD2, H2> Handler for ForkingHandler<'a, H1, H2>
where
H1: Handler<RequestData = RD1>,
H2: Handler<RequestData = RD2>,
{
type RequestData = ForkingRequestData<RD1, RD2>;
type ExtractRequestError = ForkingRequestData<H1::ExtractRequestError, H2::ExtractRequestError>;
type BuildResponseError<M: MinimalWritableMessage> =
ForkingRequestData<H1::BuildResponseError<M>, H2::BuildResponseError<M>>;
fn extract_request_data<M: ReadableMessage>(
&mut self,
request: &M,
) -> Result<Self::RequestData, Self::ExtractRequestError> {
let expected_path = self.h1_condition.iter().map(|s| s.as_bytes());
let actual_path = request.options().filter(|o| o.number() == option::URI_PATH);
Ok(
if IterOrderByBackport::cmp_by(expected_path, actual_path, |e, a| e.cmp(a.value()))
== core::cmp::Ordering::Equal
{
let masked = MaskingUriUpToPath(request);
ForkingRequestData::First(
self.h1
.extract_request_data(&masked)
.map_err(ForkingRequestData::First)?,
)
} else {
ForkingRequestData::Second(
self.h2
.extract_request_data(request)
.map_err(ForkingRequestData::Second)?,
)
},
)
}
fn estimate_length(&mut self, request: &Self::RequestData) -> usize {
match request {
ForkingRequestData::First(r) => self.h1.estimate_length(r),
ForkingRequestData::Second(r) => self.h2.estimate_length(r),
}
}
fn build_response<M: MutableWritableMessage>(
&mut self,
response: &mut M,
request: Self::RequestData,
) -> Result<(), Self::BuildResponseError<M>> {
match request {
ForkingRequestData::First(r) => self
.h1
.build_response(response, r)
.map_err(ForkingRequestData::First)?,
ForkingRequestData::Second(r) => self
.h2
.build_response(response, r)
.map_err(ForkingRequestData::Second)?,
}
Ok(())
}
}
impl<'a, RD1, H1, RD2, H2> Reporting for ForkingHandler<'a, H1, H2>
where
H1: Handler<RequestData = RD1> + Reporting,
H2: Handler<RequestData = RD2> + Reporting,
{
type Record<'b> = ForkingRecord<PrefixedRecord<'b, H1::Record<'b>>, H2::Record<'b>>
where
Self: 'b,
;
type Reporter<'b> = core::iter::Chain<
core::iter::Map<H2::Reporter<'b>, fn(H2::Record<'b>) -> Self::Record<'b>>,
core::iter::Map<
core::iter::Zip<H1::Reporter<'b>, core::iter::Repeat<&'b [&'b str]>>,
fn((H1::Record<'b>, &'b [&'b str])) -> Self::Record<'b>,
>,
>
where
Self: 'b,
;
fn report(&self) -> Self::Reporter<'_> {
fn first<'c, H1R, H2R>(
prefixed_prefix: (H1R, &'c [&'c str]),
) -> ForkingRecord<PrefixedRecord<'c, H1R>, H2R> {
let (prefixed, prefix) = prefixed_prefix;
ForkingRecord::First(PrefixedRecord { prefix, prefixed })
}
self.h2
.report()
.map(ForkingRecord::Second as fn(_) -> _)
.chain(
self.h1
.report()
.zip(core::iter::repeat(self.h1_condition))
.map(first as fn(_) -> _),
)
}
}
pub struct ForkingTreeHandler<'a, H1, H2> {
h1: H1,
h2: H2,
h1_condition: &'a [&'a str],
}
impl<'a, RD1, H1, RD2, H2> Handler for ForkingTreeHandler<'a, H1, H2>
where
H1: Handler<RequestData = RD1>,
H2: Handler<RequestData = RD2>,
{
type RequestData = ForkingRequestData<RD1, RD2>;
type ExtractRequestError = ForkingRequestData<H1::ExtractRequestError, H2::ExtractRequestError>;
type BuildResponseError<M: MinimalWritableMessage> =
ForkingRequestData<H1::BuildResponseError<M>, H2::BuildResponseError<M>>;
fn extract_request_data<M: ReadableMessage>(
&mut self,
request: &M,
) -> Result<Self::RequestData, Self::ExtractRequestError> {
use ForkingRequestData::*;
let expected_path = self.h1_condition.iter().map(|s| s.as_bytes());
let actual_path = request
.options()
.filter(|o| o.number() == option::URI_PATH)
.take(self.h1_condition.len());
if IterOrderByBackport::cmp_by(expected_path, actual_path, |e, a| e.cmp(a.value()))
== core::cmp::Ordering::Equal
{
let masked = MaskingUriUpToPathN::new(request, self.h1_condition.len());
self.h1
.extract_request_data(&masked)
.map(First)
.map_err(First)
} else {
self.h2
.extract_request_data(request)
.map(Second)
.map_err(Second)
}
}
fn estimate_length(&mut self, request: &Self::RequestData) -> usize {
match request {
ForkingRequestData::First(r) => self.h1.estimate_length(r),
ForkingRequestData::Second(r) => self.h2.estimate_length(r),
}
}
fn build_response<M: MutableWritableMessage>(
&mut self,
response: &mut M,
request: Self::RequestData,
) -> Result<(), Self::BuildResponseError<M>> {
use ForkingRequestData::*;
match request {
First(r) => self.h1.build_response(response, r).map_err(First),
Second(r) => self.h2.build_response(response, r).map_err(Second),
}
}
}
impl<'a, RD1, H1, RD2, H2> Reporting for ForkingTreeHandler<'a, H1, H2>
where
H1: Handler<RequestData = RD1> + Reporting,
H2: Handler<RequestData = RD2> + Reporting,
{
type Record<'b> = ForkingRecord<PrefixedRecord<'b, H1::Record<'b>>, H2::Record<'b>>
where
Self: 'b,
;
#[cfg(feature = "_nontrivial_option_processing")]
type Reporter<'b> = impl Iterator<Item = Self::Record<'b>>
where
Self: 'b,
;
#[cfg(feature = "_nontrivial_option_processing")]
fn report(&self) -> Self::Reporter<'_> {
self.h2
.report()
.map(ForkingRecord::Second as fn(_) -> _)
.chain(self.h1.report().map(|f| {
ForkingRecord::First(PrefixedRecord {
prefix: self.h1_condition,
prefixed: f,
})
}))
}
#[cfg(not(feature = "_nontrivial_option_processing"))]
type Reporter<'b> = core::iter::Chain<
core::iter::Map<H2::Reporter<'b>, fn(H2::Record<'b>) -> Self::Record<'b>>,
core::iter::Map<
core::iter::Zip<H1::Reporter<'b>, core::iter::Repeat<&'b [&'b str]>>,
fn((H1::Record<'b>, &'b [&'b str])) -> Self::Record<'b>,
>,
>
where
Self: 'b,
;
#[cfg(not(feature = "_nontrivial_option_processing"))]
fn report(&self) -> Self::Reporter<'_> {
fn first<'c, H1R, H2R>(
prefixed_prefix: (H1R, &'c [&'c str]),
) -> ForkingRecord<PrefixedRecord<'c, H1R>, H2R> {
let (prefixed, prefix) = prefixed_prefix;
ForkingRecord::First(PrefixedRecord { prefix, prefixed })
}
self.h2
.report()
.map(ForkingRecord::Second as fn(_) -> _)
.chain(
self.h1
.report()
.zip(core::iter::repeat(self.h1_condition))
.map(first as fn(_) -> _),
)
}
}