Skip to main content

sark_core/decode/request/admit/
mod.rs

1use core::{convert::Infallible, ops::ControlFlow};
2
3use crate::decode::{self, Encode, dispatch, request, state};
4
5mod stop;
6pub use stop::Stop;
7
8/// Consumes the selected route's admission contract without erasing its guard capability.
9pub trait Start<R: decode::Decode>: Sized {
10    type Stop<T, E>: Stop<T, E>;
11
12    fn admit<'req, 'd: 'req, E: Encode<'req, 'd>, T, F>(
13        self,
14        router: &R,
15        encode: impl FnOnce() -> E,
16        stop: impl FnOnce(Encoded<'req, 'd, E>) -> Result<T, F>,
17    ) -> ControlFlow<Self::Stop<T, F>, Admitted<R::Prepared>>;
18}
19
20impl<R, U> Start<R> for request::Plain<U>
21where
22    R: decode::Decode,
23    U: state::Admission<R::Prepared, state::Routed, state::Admitted,
24        Output = <<R::Prepared as request::Prepared>::Family as state::Family<R::Prepared>>::State<state::Admitted>>,
25{
26    type Stop<T, E> = Infallible;
27
28    fn admit<'req, 'd: 'req, E: Encode<'req, 'd>, T, F>(
29        self,
30        _: &R,
31        _: impl FnOnce() -> E,
32        _: impl FnOnce(Encoded<'req, 'd, E>) -> Result<T, F>,
33    ) -> ControlFlow<Infallible,
34        <<R::Prepared as request::Prepared>::Family as state::Family<R::Prepared>>::State<state::Admitted>,
35    > {
36        state::Admission::admit(self.into_state(), &mut state::Pass)
37    }
38}
39
40impl<R: decode::Guarded> Start<R>
41    for request::Guarded<<R::Routes as state::Family<R::Prepared>>::State<state::Routed>>
42{
43    type Stop<T, E> = Result<T, E>;
44
45    fn admit<'req, 'd: 'req, E: Encode<'req, 'd>, T, F>(
46        self,
47        router: &R,
48        encode: impl FnOnce() -> E,
49        stop: impl FnOnce(Encoded<'req, 'd, E>) -> Result<T, F>,
50    ) -> ControlFlow<Result<T, F>, Admitted<R::Prepared>> {
51        decode::Guarded::try_admit(router, self, encode(), &mut state::Pass).map_break(stop)
52    }
53}
54
55impl<R, U> Start<R>
56    for request::Start<U, <R::Routes as state::Family<R::Prepared>>::State<state::Routed>>
57where
58    R: decode::Guarded,
59    U: state::Admission<R::Prepared, state::Routed, state::Admitted,
60        Output = <<R::Prepared as request::Prepared>::Family as state::Family<R::Prepared>>::State<state::Admitted>>,
61{
62    type Stop<T, E> = Result<T, E>;
63
64    fn admit<'req, 'd: 'req, E: Encode<'req, 'd>, T, F>(
65        self,
66        router: &R,
67        encode: impl FnOnce() -> E,
68        stop: impl FnOnce(Encoded<'req, 'd, E>) -> Result<T, F>,
69    ) -> ControlFlow<
70        Result<T, F>,
71        <<R::Prepared as request::Prepared>::Family as state::Family<R::Prepared>>::State<state::Admitted>,
72    > {
73        match self {
74            Self::Plain(request) => match request.admit(router, encode, stop) {
75                ControlFlow::Continue(request) => ControlFlow::Continue(request),
76                ControlFlow::Break(never) => match never {},
77            },
78            Self::Guarded(request) => request.admit(router, encode, stop),
79        }
80    }
81}
82
83type Admitted<P> = <<P as request::Prepared>::Family as state::Family<P>>::State<state::Admitted>;
84
85type Encoded<'req, 'd, E> = Result<
86    <E as Encode<'req, 'd>>::Prepared,
87    (
88        dispatch::Error<<E as Encode<'req, 'd>>::Error, Infallible, Infallible>,
89        <E as decode::Cancel>::Target,
90    ),
91>;