1use coap_handler::{Attribute, Handler, Reporting};
4use coap_message::{
5 MessageOption, MinimalWritableMessage, MutableWritableMessage, ReadableMessage,
6 error::RenderableOnMinimal,
7};
8use coap_numbers::option;
9
10use crate::forking_helpers::{ForkingRecord, PrefixedRecord};
11use crate::helpers::{MaskingUriUpToPath, MaskingUriUpToPathN};
12use crate::{NeverFound, wkc, wkc_implementation};
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 fn with_extra_record(
163 self,
164 target: &'a str,
165 attributes: &'a [Attribute],
166 ) -> WithExtraRecord<'a, Self> {
167 WithExtraRecord::new(self, target, attributes)
168 }
169}
170
171impl<OldRD, OldH> ReportingHandlerBuilder<'_, OldRD> for OldH
172where
173 OldH: Handler<RequestData = OldRD> + Reporting,
174{
175 }
177
178pub struct ForkingHandler<'a, H1, H2> {
179 h1: H1,
180 h2: H2,
181
182 h1_condition: &'a [&'a str],
186}
187
188#[derive(Debug)]
190pub enum ForkingRequestData<RD1, RD2> {
191 First(RD1),
192 Second(RD2),
193}
194
195impl<RE1, RE2> RenderableOnMinimal for ForkingRequestData<RE1, RE2>
196where
197 RE1: RenderableOnMinimal + core::fmt::Debug,
198 RE2: RenderableOnMinimal + core::fmt::Debug,
199{
200 type Error<IE: RenderableOnMinimal + core::fmt::Debug> = ForkingRequestData<
201 <RE1 as RenderableOnMinimal>::Error<IE>,
202 <RE2 as RenderableOnMinimal>::Error<IE>,
203 >;
204
205 fn render<M: MinimalWritableMessage>(
206 self,
207 message: &mut M,
208 ) -> Result<(), Self::Error<M::UnionError>> {
209 use ForkingRequestData::*;
210 match self {
211 First(e) => e.render(message).map_err(First),
212 Second(e) => e.render(message).map_err(Second),
213 }
214 }
215}
216
217impl<RD1, H1, RD2, H2> Handler for ForkingHandler<'_, H1, H2>
218where
219 H1: Handler<RequestData = RD1>,
220 H2: Handler<RequestData = RD2>,
221{
222 type RequestData = ForkingRequestData<RD1, RD2>;
223
224 type ExtractRequestError = ForkingRequestData<H1::ExtractRequestError, H2::ExtractRequestError>;
225 type BuildResponseError<M: MinimalWritableMessage> =
226 ForkingRequestData<H1::BuildResponseError<M>, H2::BuildResponseError<M>>;
227
228 fn extract_request_data<M: ReadableMessage>(
229 &mut self,
230 request: &M,
231 ) -> Result<Self::RequestData, Self::ExtractRequestError> {
232 let expected_path = self.h1_condition.iter().map(|s| s.as_bytes());
233 let actual_path = request.options().filter(|o| o.number() == option::URI_PATH);
234
235 Ok(
236 if IterOrderByBackport::cmp_by(expected_path, actual_path, |e, a| e.cmp(a.value()))
237 == core::cmp::Ordering::Equal
238 {
239 let masked = MaskingUriUpToPath(request);
240 ForkingRequestData::First(
241 self.h1
242 .extract_request_data(&masked)
243 .map_err(ForkingRequestData::First)?,
244 )
245 } else {
246 ForkingRequestData::Second(
247 self.h2
248 .extract_request_data(request)
249 .map_err(ForkingRequestData::Second)?,
250 )
251 },
252 )
253 }
254
255 fn estimate_length(&mut self, request: &Self::RequestData) -> usize {
256 match request {
257 ForkingRequestData::First(r) => self.h1.estimate_length(r),
258 ForkingRequestData::Second(r) => self.h2.estimate_length(r),
259 }
260 }
261
262 fn build_response<M: MutableWritableMessage>(
263 &mut self,
264 response: &mut M,
265 request: Self::RequestData,
266 ) -> Result<(), Self::BuildResponseError<M>> {
267 match request {
268 ForkingRequestData::First(r) => self
269 .h1
270 .build_response(response, r)
271 .map_err(ForkingRequestData::First)?,
272 ForkingRequestData::Second(r) => self
273 .h2
274 .build_response(response, r)
275 .map_err(ForkingRequestData::Second)?,
276 }
277 Ok(())
278 }
279}
280
281impl<RD1, H1, RD2, H2> Reporting for ForkingHandler<'_, H1, H2>
282where
283 H1: Handler<RequestData = RD1> + Reporting,
284 H2: Handler<RequestData = RD2> + Reporting,
285{
286 type Record<'b>
298 = ForkingRecord<PrefixedRecord<'b, H1::Record<'b>>, H2::Record<'b>>
299 where
300 Self: 'b;
301
302 type Reporter<'b>
303 = core::iter::Chain<
304 core::iter::Map<H2::Reporter<'b>, fn(H2::Record<'b>) -> Self::Record<'b>>,
305 core::iter::Map<
306 core::iter::Zip<H1::Reporter<'b>, core::iter::Repeat<&'b [&'b str]>>,
307 fn((H1::Record<'b>, &'b [&'b str])) -> Self::Record<'b>,
308 >,
309 >
310 where
311 Self: 'b;
312 fn report(&self) -> Self::Reporter<'_> {
313 fn first<'c, H1R, H2R>(
314 prefixed_prefix: (H1R, &'c [&'c str]),
315 ) -> ForkingRecord<PrefixedRecord<'c, H1R>, H2R> {
316 let (prefixed, prefix) = prefixed_prefix;
317 ForkingRecord::First(PrefixedRecord { prefix, prefixed })
318 }
319 self.h2
320 .report()
321 .map(ForkingRecord::Second as fn(_) -> _)
322 .chain(
323 self.h1
324 .report()
325 .zip(core::iter::repeat(self.h1_condition))
326 .map(first as fn(_) -> _),
327 )
328 }
329
330 fn write_extra_link_format(
331 &self,
332 writer: &mut impl core::fmt::Write,
333 is_first: &mut bool,
334 ) -> core::fmt::Result {
335 self.h1.write_extra_link_format(writer, is_first)?;
336 self.h2.write_extra_link_format(writer, is_first)?;
337 Ok(())
338 }
339}
340
341pub struct ForkingTreeHandler<'a, H1, H2> {
345 h1: H1,
346 h2: H2,
347
348 h1_condition: &'a [&'a str],
349}
350
351impl<RD1, H1, RD2, H2> Handler for ForkingTreeHandler<'_, H1, H2>
352where
353 H1: Handler<RequestData = RD1>,
354 H2: Handler<RequestData = RD2>,
355{
356 type RequestData = ForkingRequestData<RD1, RD2>;
357
358 type ExtractRequestError = ForkingRequestData<H1::ExtractRequestError, H2::ExtractRequestError>;
359 type BuildResponseError<M: MinimalWritableMessage> =
360 ForkingRequestData<H1::BuildResponseError<M>, H2::BuildResponseError<M>>;
361
362 fn extract_request_data<M: ReadableMessage>(
363 &mut self,
364 request: &M,
365 ) -> Result<Self::RequestData, Self::ExtractRequestError> {
366 use ForkingRequestData::*;
367
368 let expected_path = self.h1_condition.iter().map(|s| s.as_bytes());
369 let actual_path = request
370 .options()
371 .filter(|o| o.number() == option::URI_PATH)
372 .take(self.h1_condition.len());
373
374 if IterOrderByBackport::cmp_by(expected_path, actual_path, |e, a| e.cmp(a.value()))
375 == core::cmp::Ordering::Equal
376 {
377 let masked = MaskingUriUpToPathN::new(request, self.h1_condition.len());
378 self.h1
379 .extract_request_data(&masked)
380 .map(First)
381 .map_err(First)
382 } else {
383 self.h2
384 .extract_request_data(request)
385 .map(Second)
386 .map_err(Second)
387 }
388 }
389
390 fn estimate_length(&mut self, request: &Self::RequestData) -> usize {
391 match request {
392 ForkingRequestData::First(r) => self.h1.estimate_length(r),
393 ForkingRequestData::Second(r) => self.h2.estimate_length(r),
394 }
395 }
396
397 fn build_response<M: MutableWritableMessage>(
398 &mut self,
399 response: &mut M,
400 request: Self::RequestData,
401 ) -> Result<(), Self::BuildResponseError<M>> {
402 use ForkingRequestData::*;
403 match request {
404 First(r) => self.h1.build_response(response, r).map_err(First),
405 Second(r) => self.h2.build_response(response, r).map_err(Second),
406 }
407 }
408}
409
410impl<RD1, H1, RD2, H2> Reporting for ForkingTreeHandler<'_, H1, H2>
411where
412 H1: Handler<RequestData = RD1> + Reporting,
413 H2: Handler<RequestData = RD2> + Reporting,
414{
415 type Record<'b>
416 = ForkingRecord<PrefixedRecord<'b, H1::Record<'b>>, H2::Record<'b>>
417 where
418 Self: 'b;
419
420 #[cfg(feature = "_nontrivial_option_processing")]
423 type Reporter<'b>
424 = impl Iterator<Item = Self::Record<'b>>
425 where
426 Self: 'b;
427
428 #[cfg(feature = "_nontrivial_option_processing")]
429 fn report(&self) -> Self::Reporter<'_> {
430 self.h2
431 .report()
432 .map(ForkingRecord::Second as fn(_) -> _)
433 .chain(self.h1.report().map(|f| {
434 ForkingRecord::First(PrefixedRecord {
435 prefix: self.h1_condition,
436 prefixed: f,
437 })
438 }))
439 }
440
441 #[cfg(not(feature = "_nontrivial_option_processing"))]
442 type Reporter<'b>
443 = core::iter::Chain<
444 core::iter::Map<H2::Reporter<'b>, fn(H2::Record<'b>) -> Self::Record<'b>>,
445 core::iter::Map<
446 core::iter::Zip<H1::Reporter<'b>, core::iter::Repeat<&'b [&'b str]>>,
447 fn((H1::Record<'b>, &'b [&'b str])) -> Self::Record<'b>,
448 >,
449 >
450 where
451 Self: 'b;
452 #[cfg(not(feature = "_nontrivial_option_processing"))]
453 fn report(&self) -> Self::Reporter<'_> {
454 fn first<'c, H1R, H2R>(
455 prefixed_prefix: (H1R, &'c [&'c str]),
456 ) -> ForkingRecord<PrefixedRecord<'c, H1R>, H2R> {
457 let (prefixed, prefix) = prefixed_prefix;
458 ForkingRecord::First(PrefixedRecord { prefix, prefixed })
459 }
460 self.h2
461 .report()
462 .map(ForkingRecord::Second as fn(_) -> _)
463 .chain(
464 self.h1
465 .report()
466 .zip(core::iter::repeat(self.h1_condition))
467 .map(first as fn(_) -> _),
468 )
469 }
470}
471
472pub struct WithExtraRecord<'a, H> {
473 handler: H,
474 target: &'a str,
475 attributes: &'a [Attribute],
476}
477
478impl<'a, H> WithExtraRecord<'a, H> {
479 pub fn new(handler: H, target: &'a str, attributes: &'a [Attribute]) -> Self {
480 Self {
481 handler,
482 target,
483 attributes,
484 }
485 }
486}
487
488impl<H: Handler> Handler for WithExtraRecord<'_, H> {
490 type RequestData = H::RequestData;
491 type ExtractRequestError = H::ExtractRequestError;
492 type BuildResponseError<M: MinimalWritableMessage> = H::BuildResponseError<M>;
493
494 fn extract_request_data<M: ReadableMessage>(
495 &mut self,
496 request: &M,
497 ) -> Result<Self::RequestData, Self::ExtractRequestError> {
498 self.handler.extract_request_data(request)
499 }
500
501 fn estimate_length(&mut self, request: &Self::RequestData) -> usize {
502 self.handler.estimate_length(request)
503 }
504
505 fn build_response<M: MutableWritableMessage>(
506 &mut self,
507 response: &mut M,
508 request: Self::RequestData,
509 ) -> Result<(), Self::BuildResponseError<M>> {
510 self.handler.build_response(response, request)
511 }
512}
513
514impl<'a, H: Reporting> Reporting for WithExtraRecord<'a, H> {
515 type Record<'b>
516 = H::Record<'b>
517 where
518 Self: 'b;
519
520 type Reporter<'b>
521 = H::Reporter<'b>
522 where
523 Self: 'b;
524 fn report(&self) -> Self::Reporter<'_> {
525 self.handler.report()
526 }
527
528 fn write_extra_link_format(
529 &self,
530 writer: &mut impl core::fmt::Write,
531 is_first: &mut bool,
532 ) -> core::fmt::Result {
533 self.handler.write_extra_link_format(writer, is_first)?;
534
535 if !*is_first {
536 write!(writer, ",")?;
537 } else {
538 *is_first = false;
539 }
540
541 write!(writer, "<{}>", self.target)?;
542 for a in self.attributes {
543 a.write_link_format(writer)?;
544 }
545
546 Ok(())
547 }
548}