1use coap_handler::{Attribute, Handler, Reporting};
4use coap_message::{
5 error::RenderableOnMinimal, MessageOption, MinimalWritableMessage, MutableWritableMessage,
6 ReadableMessage,
7};
8use coap_numbers::option;
9
10use crate::forking_helpers::{ForkingRecord, PrefixedRecord};
11use crate::helpers::{MaskingUriUpToPath, MaskingUriUpToPathN};
12use crate::{wkc, wkc_implementation, NeverFound};
13
14trait IterOrderByBackport: Iterator {
17 fn cmp_by<I, F>(mut self, other: I, mut cmp: F) -> core::cmp::Ordering
18 where
19 Self: Sized,
20 I: IntoIterator,
21 F: FnMut(Self::Item, I::Item) -> core::cmp::Ordering,
22 {
23 let mut other = other.into_iter();
24
25 loop {
26 let x = match self.next() {
27 None => {
28 if other.next().is_none() {
29 return core::cmp::Ordering::Equal;
30 } else {
31 return core::cmp::Ordering::Less;
32 }
33 }
34 Some(val) => val,
35 };
36
37 let y = match other.next() {
38 None => return core::cmp::Ordering::Greater,
39 Some(val) => val,
40 };
41
42 match cmp(x, y) {
43 core::cmp::Ordering::Equal => (),
44 non_eq => return non_eq,
45 }
46 }
47 }
48}
49
50impl<T: Iterator> IterOrderByBackport for T {}
51
52#[cfg(not(feature = "leaky_names"))]
66pub fn new_dispatcher() -> impl Handler + Reporting {
67 wkc::NotReporting::new(NeverFound {})
68}
69#[cfg(feature = "leaky_names")]
70pub fn new_dispatcher() -> wkc::NotReporting<NeverFound> {
71 wkc::NotReporting::new(NeverFound {})
72}
73
74pub trait HandlerBuilder<'a, OldRD>
82where
83 Self: Handler + Sized,
84{
85 fn at<H>(self, path: &'a [&'a str], handler: H) -> ForkingHandler<'a, H, Self>
93 where
94 H: Handler + Sized,
95 {
96 ForkingHandler {
97 h1: handler,
98 h2: self,
99 h1_condition: path,
100 }
101 }
102
103 fn at_with_attributes<H>(
110 self,
111 path: &'a [&'a str],
112 attributes: &'a [Attribute],
113 handler: H,
114 ) -> ForkingHandler<'a, wkc::ConstantSingleRecordReport<'a, H>, Self>
115 where
116 H: Handler + Sized,
117 {
118 ForkingHandler {
119 h1: wkc::ConstantSingleRecordReport::new(handler, attributes),
120 h2: self,
121 h1_condition: path,
122 }
123 }
124
125 fn below<H>(self, path: &'a [&'a str], handler: H) -> ForkingTreeHandler<'a, H, Self> {
132 ForkingTreeHandler {
133 h1: handler,
134 h2: self,
135 h1_condition: path,
136 }
137 }
138}
139
140impl<OldRD, OldH> HandlerBuilder<'_, OldRD> for OldH
141where
142 Self: Handler<RequestData = OldRD> + Sized,
143{
144 }
146
147pub trait ReportingHandlerBuilder<'a, OldRD>: HandlerBuilder<'a, OldRD> + Reporting {
156 fn with_wkc(self) -> wkc_implementation::WellKnownCore<Self> {
159 wkc_implementation::WellKnownCore::new(self)
160 }
161}
162
163impl<OldRD, OldH> ReportingHandlerBuilder<'_, OldRD> for OldH
164where
165 OldH: Handler<RequestData = OldRD> + Reporting,
166{
167 }
169
170pub struct ForkingHandler<'a, H1, H2> {
171 h1: H1,
172 h2: H2,
173
174 h1_condition: &'a [&'a str],
178}
179
180#[derive(Debug)]
182pub enum ForkingRequestData<RD1, RD2> {
183 First(RD1),
184 Second(RD2),
185}
186
187impl<RE1, RE2> RenderableOnMinimal for ForkingRequestData<RE1, RE2>
188where
189 RE1: RenderableOnMinimal + core::fmt::Debug,
190 RE2: RenderableOnMinimal + core::fmt::Debug,
191{
192 type Error<IE: RenderableOnMinimal + core::fmt::Debug> = ForkingRequestData<
193 <RE1 as RenderableOnMinimal>::Error<IE>,
194 <RE2 as RenderableOnMinimal>::Error<IE>,
195 >;
196
197 fn render<M: MinimalWritableMessage>(
198 self,
199 message: &mut M,
200 ) -> Result<(), Self::Error<M::UnionError>> {
201 use ForkingRequestData::*;
202 match self {
203 First(e) => e.render(message).map_err(First),
204 Second(e) => e.render(message).map_err(Second),
205 }
206 }
207}
208
209impl<RD1, H1, RD2, H2> Handler for ForkingHandler<'_, H1, H2>
210where
211 H1: Handler<RequestData = RD1>,
212 H2: Handler<RequestData = RD2>,
213{
214 type RequestData = ForkingRequestData<RD1, RD2>;
215
216 type ExtractRequestError = ForkingRequestData<H1::ExtractRequestError, H2::ExtractRequestError>;
217 type BuildResponseError<M: MinimalWritableMessage> =
218 ForkingRequestData<H1::BuildResponseError<M>, H2::BuildResponseError<M>>;
219
220 fn extract_request_data<M: ReadableMessage>(
221 &mut self,
222 request: &M,
223 ) -> Result<Self::RequestData, Self::ExtractRequestError> {
224 let expected_path = self.h1_condition.iter().map(|s| s.as_bytes());
225 let actual_path = request.options().filter(|o| o.number() == option::URI_PATH);
226
227 Ok(
228 if IterOrderByBackport::cmp_by(expected_path, actual_path, |e, a| e.cmp(a.value()))
229 == core::cmp::Ordering::Equal
230 {
231 let masked = MaskingUriUpToPath(request);
232 ForkingRequestData::First(
233 self.h1
234 .extract_request_data(&masked)
235 .map_err(ForkingRequestData::First)?,
236 )
237 } else {
238 ForkingRequestData::Second(
239 self.h2
240 .extract_request_data(request)
241 .map_err(ForkingRequestData::Second)?,
242 )
243 },
244 )
245 }
246
247 fn estimate_length(&mut self, request: &Self::RequestData) -> usize {
248 match request {
249 ForkingRequestData::First(r) => self.h1.estimate_length(r),
250 ForkingRequestData::Second(r) => self.h2.estimate_length(r),
251 }
252 }
253
254 fn build_response<M: MutableWritableMessage>(
255 &mut self,
256 response: &mut M,
257 request: Self::RequestData,
258 ) -> Result<(), Self::BuildResponseError<M>> {
259 match request {
260 ForkingRequestData::First(r) => self
261 .h1
262 .build_response(response, r)
263 .map_err(ForkingRequestData::First)?,
264 ForkingRequestData::Second(r) => self
265 .h2
266 .build_response(response, r)
267 .map_err(ForkingRequestData::Second)?,
268 }
269 Ok(())
270 }
271}
272
273impl<RD1, H1, RD2, H2> Reporting for ForkingHandler<'_, H1, H2>
274where
275 H1: Handler<RequestData = RD1> + Reporting,
276 H2: Handler<RequestData = RD2> + Reporting,
277{
278 type Record<'b>
290 = ForkingRecord<PrefixedRecord<'b, H1::Record<'b>>, H2::Record<'b>>
291 where
292 Self: 'b;
293
294 type Reporter<'b>
295 = core::iter::Chain<
296 core::iter::Map<H2::Reporter<'b>, fn(H2::Record<'b>) -> Self::Record<'b>>,
297 core::iter::Map<
298 core::iter::Zip<H1::Reporter<'b>, core::iter::Repeat<&'b [&'b str]>>,
299 fn((H1::Record<'b>, &'b [&'b str])) -> Self::Record<'b>,
300 >,
301 >
302 where
303 Self: 'b;
304 fn report(&self) -> Self::Reporter<'_> {
305 fn first<'c, H1R, H2R>(
306 prefixed_prefix: (H1R, &'c [&'c str]),
307 ) -> ForkingRecord<PrefixedRecord<'c, H1R>, H2R> {
308 let (prefixed, prefix) = prefixed_prefix;
309 ForkingRecord::First(PrefixedRecord { prefix, prefixed })
310 }
311 self.h2
312 .report()
313 .map(ForkingRecord::Second as fn(_) -> _)
314 .chain(
315 self.h1
316 .report()
317 .zip(core::iter::repeat(self.h1_condition))
318 .map(first as fn(_) -> _),
319 )
320 }
321}
322
323pub struct ForkingTreeHandler<'a, H1, H2> {
327 h1: H1,
328 h2: H2,
329
330 h1_condition: &'a [&'a str],
331}
332
333impl<RD1, H1, RD2, H2> Handler for ForkingTreeHandler<'_, H1, H2>
334where
335 H1: Handler<RequestData = RD1>,
336 H2: Handler<RequestData = RD2>,
337{
338 type RequestData = ForkingRequestData<RD1, RD2>;
339
340 type ExtractRequestError = ForkingRequestData<H1::ExtractRequestError, H2::ExtractRequestError>;
341 type BuildResponseError<M: MinimalWritableMessage> =
342 ForkingRequestData<H1::BuildResponseError<M>, H2::BuildResponseError<M>>;
343
344 fn extract_request_data<M: ReadableMessage>(
345 &mut self,
346 request: &M,
347 ) -> Result<Self::RequestData, Self::ExtractRequestError> {
348 use ForkingRequestData::*;
349
350 let expected_path = self.h1_condition.iter().map(|s| s.as_bytes());
351 let actual_path = request
352 .options()
353 .filter(|o| o.number() == option::URI_PATH)
354 .take(self.h1_condition.len());
355
356 if IterOrderByBackport::cmp_by(expected_path, actual_path, |e, a| e.cmp(a.value()))
357 == core::cmp::Ordering::Equal
358 {
359 let masked = MaskingUriUpToPathN::new(request, self.h1_condition.len());
360 self.h1
361 .extract_request_data(&masked)
362 .map(First)
363 .map_err(First)
364 } else {
365 self.h2
366 .extract_request_data(request)
367 .map(Second)
368 .map_err(Second)
369 }
370 }
371
372 fn estimate_length(&mut self, request: &Self::RequestData) -> usize {
373 match request {
374 ForkingRequestData::First(r) => self.h1.estimate_length(r),
375 ForkingRequestData::Second(r) => self.h2.estimate_length(r),
376 }
377 }
378
379 fn build_response<M: MutableWritableMessage>(
380 &mut self,
381 response: &mut M,
382 request: Self::RequestData,
383 ) -> Result<(), Self::BuildResponseError<M>> {
384 use ForkingRequestData::*;
385 match request {
386 First(r) => self.h1.build_response(response, r).map_err(First),
387 Second(r) => self.h2.build_response(response, r).map_err(Second),
388 }
389 }
390}
391
392impl<RD1, H1, RD2, H2> Reporting for ForkingTreeHandler<'_, H1, H2>
393where
394 H1: Handler<RequestData = RD1> + Reporting,
395 H2: Handler<RequestData = RD2> + Reporting,
396{
397 type Record<'b>
398 = ForkingRecord<PrefixedRecord<'b, H1::Record<'b>>, H2::Record<'b>>
399 where
400 Self: 'b;
401
402 #[cfg(feature = "_nontrivial_option_processing")]
405 type Reporter<'b>
406 = impl Iterator<Item = Self::Record<'b>>
407 where
408 Self: 'b;
409
410 #[cfg(feature = "_nontrivial_option_processing")]
411 fn report(&self) -> Self::Reporter<'_> {
412 self.h2
413 .report()
414 .map(ForkingRecord::Second as fn(_) -> _)
415 .chain(self.h1.report().map(|f| {
416 ForkingRecord::First(PrefixedRecord {
417 prefix: self.h1_condition,
418 prefixed: f,
419 })
420 }))
421 }
422
423 #[cfg(not(feature = "_nontrivial_option_processing"))]
424 type Reporter<'b>
425 = core::iter::Chain<
426 core::iter::Map<H2::Reporter<'b>, fn(H2::Record<'b>) -> Self::Record<'b>>,
427 core::iter::Map<
428 core::iter::Zip<H1::Reporter<'b>, core::iter::Repeat<&'b [&'b str]>>,
429 fn((H1::Record<'b>, &'b [&'b str])) -> Self::Record<'b>,
430 >,
431 >
432 where
433 Self: 'b;
434 #[cfg(not(feature = "_nontrivial_option_processing"))]
435 fn report(&self) -> Self::Reporter<'_> {
436 fn first<'c, H1R, H2R>(
437 prefixed_prefix: (H1R, &'c [&'c str]),
438 ) -> ForkingRecord<PrefixedRecord<'c, H1R>, H2R> {
439 let (prefixed, prefix) = prefixed_prefix;
440 ForkingRecord::First(PrefixedRecord { prefix, prefixed })
441 }
442 self.h2
443 .report()
444 .map(ForkingRecord::Second as fn(_) -> _)
445 .chain(
446 self.h1
447 .report()
448 .zip(core::iter::repeat(self.h1_condition))
449 .map(first as fn(_) -> _),
450 )
451 }
452}