1use std::sync::Arc;
16
17use super::{Context, context::Extensions};
18use crate::Service;
19use rama_macros::paste;
20use rama_utils::macros::all_the_tuples_no_last_special_case;
21
22mod op_or;
23#[doc(inline)]
24pub use op_or::Or;
25
26mod op_and;
27#[doc(inline)]
28pub use op_and::And;
29
30mod op_not;
31#[doc(inline)]
32pub use op_not::Not;
33
34mod mfn;
35#[doc(inline)]
36pub use mfn::{MatchFn, match_fn};
37
38mod iter;
39#[doc(inline)]
40pub use iter::IteratorMatcherExt;
41
42mod ext;
43#[doc(inline)]
44pub use ext::ExtensionMatcher;
45
46pub trait Matcher<State, Request>: Send + Sync + 'static {
49 fn matches(&self, ext: Option<&mut Extensions>, ctx: &Context<State>, req: &Request) -> bool;
55
56 fn or<M>(self, other: M) -> impl Matcher<State, Request>
58 where
59 Self: Sized,
60 M: Matcher<State, Request>,
61 {
62 Or::new((self, other))
63 }
64
65 fn and<M>(self, other: M) -> impl Matcher<State, Request>
67 where
68 Self: Sized,
69 M: Matcher<State, Request>,
70 {
71 And::new((self, other))
72 }
73
74 fn not(self) -> impl Matcher<State, Request>
76 where
77 Self: Sized,
78 {
79 Not::new(self)
80 }
81}
82
83impl<State, Request, T> Matcher<State, Request> for Arc<T>
84where
85 T: Matcher<State, Request>,
86{
87 fn matches(&self, ext: Option<&mut Extensions>, ctx: &Context<State>, req: &Request) -> bool {
88 (**self).matches(ext, ctx, req)
89 }
90}
91
92impl<State, Request, T> Matcher<State, Request> for &'static T
93where
94 T: Matcher<State, Request>,
95{
96 fn matches(&self, ext: Option<&mut Extensions>, ctx: &Context<State>, req: &Request) -> bool {
97 (**self).matches(ext, ctx, req)
98 }
99}
100
101impl<State, Request, T> Matcher<State, Request> for Option<T>
102where
103 T: Matcher<State, Request>,
104{
105 fn matches(&self, ext: Option<&mut Extensions>, ctx: &Context<State>, req: &Request) -> bool {
106 match self {
107 Some(inner) => inner.matches(ext, ctx, req),
108 None => false,
109 }
110 }
111}
112
113impl<State, Request, T> Matcher<State, Request> for Box<T>
114where
115 T: Matcher<State, Request>,
116{
117 fn matches(&self, ext: Option<&mut Extensions>, ctx: &Context<State>, req: &Request) -> bool {
118 (**self).matches(ext, ctx, req)
119 }
120}
121
122impl<State, Request> Matcher<State, Request> for Box<(dyn Matcher<State, Request> + 'static)>
123where
124 State: Clone + Send + Sync + 'static,
125 Request: Send + 'static,
126{
127 fn matches(&self, ext: Option<&mut Extensions>, ctx: &Context<State>, req: &Request) -> bool {
128 (**self).matches(ext, ctx, req)
129 }
130}
131
132impl<State, Request> Matcher<State, Request> for bool {
133 fn matches(&self, _: Option<&mut Extensions>, _: &Context<State>, _: &Request) -> bool {
134 *self
135 }
136}
137
138macro_rules! impl_matcher_either {
139 ($id:ident, $($param:ident),+ $(,)?) => {
140 impl<$($param),+, State, Request> Matcher<State, Request> for crate::combinators::$id<$($param),+>
141 where
142 $($param: Matcher<State, Request>),+,
143 Request: Send + 'static,
144 State: Clone + Send + Sync + 'static,
145 {
146 fn matches(
147 &self,
148 ext: Option<&mut Extensions>,
149 ctx: &Context<State>,
150 req: &Request
151 ) -> bool{
152 match self {
153 $(
154 crate::combinators::$id::$param(layer) => layer.matches(ext, ctx, req),
155 )+
156 }
157 }
158 }
159 };
160}
161
162crate::combinators::impl_either!(impl_matcher_either);
163
164pub struct MatcherRouter<N>(pub N);
167
168impl<N: std::fmt::Debug> std::fmt::Debug for MatcherRouter<N> {
169 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
170 f.debug_tuple("MatcherRouter").field(&self.0).finish()
171 }
172}
173
174impl<N: Clone> Clone for MatcherRouter<N> {
175 fn clone(&self) -> Self {
176 Self(self.0.clone())
177 }
178}
179
180macro_rules! impl_matcher_service_tuple {
181 ($($T:ident),+ $(,)?) => {
182 paste!{
183 #[allow(non_camel_case_types)]
184 #[allow(non_snake_case)]
185 impl<State, $([<M_ $T>], $T),+, S, Request, Response, Error> Service<State, Request> for MatcherRouter<($(([<M_ $T>], $T)),+, S)>
186 where
187 State: Clone + Send + Sync + 'static,
188 Request: Send + 'static,
189 Response: Send + 'static,
190 $(
191 [<M_ $T>]: Matcher<State, Request>,
192 $T: Service<State, Request, Response = Response, Error = Error>,
193 )+
194 S: Service<State, Request, Response = Response, Error = Error>,
195 Error: Send + 'static,
196 {
197 type Response = Response;
198 type Error = Error;
199
200 async fn serve(
201 &self,
202 mut ctx: Context<State>,
203 req: Request,
204 ) -> Result<Self::Response, Self::Error> {
205 let ($(([<M_ $T>], $T)),+, S) = &self.0;
206 let mut ext = Extensions::new();
207 $(
208 if [<M_ $T>].matches(Some(&mut ext), &ctx, &req) {
209 ctx.extend(ext);
210 return $T.serve(ctx, req).await;
211 }
212 ext.clear();
213 )+
214 S.serve(ctx, req).await
215 }
216 }
217 }
218 };
219}
220
221all_the_tuples_no_last_special_case!(impl_matcher_service_tuple);
222
223#[cfg(test)]
224mod test;