Skip to main content

rama_core/matcher/service/
tuples.rs

1use rama_error::{BoxError, ErrorContext};
2
3use crate::extensions::ExtensionsRef;
4
5use super::{ServiceMatch, ServiceMatcher};
6
7macro_rules! impl_service_matcher_tuple {
8    ($either:ident, $first_variant:ident => $first_ty:ident : $first_var:ident, $($variant:ident => $rest_ty:ident : $rest_var:ident),+ $(,)?) => {
9        impl<Input, ModifiedInput, $first_ty, $($rest_ty),+> ServiceMatcher<Input>
10            for ($first_ty, $($rest_ty),+)
11        where
12            Input: Send + ExtensionsRef + 'static,
13            ModifiedInput: Send + 'static,
14            $first_ty: ServiceMatcher<Input, Error: Into<BoxError>, ModifiedInput = ModifiedInput>,
15            $(
16                $rest_ty: ServiceMatcher<
17                    ModifiedInput,
18                    Error: Into<BoxError>,
19                    ModifiedInput = ModifiedInput,
20                >,
21            )+
22        {
23            type Service = crate::combinators::$either<$first_ty::Service, $($rest_ty::Service),+>;
24            type Error = BoxError;
25            type ModifiedInput = ModifiedInput;
26
27            async fn match_service(
28                &self,
29                input: Input,
30            ) -> Result<ServiceMatch<Self::ModifiedInput, Self::Service>, Self::Error> {
31                let ($first_var, $($rest_var),+) = self;
32
33                let ServiceMatch { input, service } = $first_var.match_service(input).await.into_box_error()?;
34                if let Some(service) = service {
35                    return Ok(ServiceMatch {
36                        input,
37                        service: Some(crate::combinators::$either::$first_variant(service)),
38                    });
39                }
40
41                $(
42                    let ServiceMatch { input, service } = $rest_var.match_service(input).await.into_box_error()?;
43                    if let Some(service) = service {
44                        return Ok(ServiceMatch {
45                            input,
46                            service: Some(crate::combinators::$either::$variant(service)),
47                        });
48                    }
49                )+
50
51                Ok(ServiceMatch {
52                    input,
53                    service: None,
54                })
55            }
56
57            async fn into_match_service(
58                self,
59                input: Input,
60            ) -> Result<ServiceMatch<Self::ModifiedInput, Self::Service>, Self::Error>
61            where
62                Input: Send,
63            {
64                let ($first_var, $($rest_var),+) = self;
65
66                let ServiceMatch { input, service } = $first_var.into_match_service(input).await.into_box_error()?;
67                if let Some(service) = service {
68                    return Ok(ServiceMatch {
69                        input,
70                        service: Some(crate::combinators::$either::$first_variant(service)),
71                    });
72                }
73
74                $(
75                    let ServiceMatch { input, service } = $rest_var.into_match_service(input).await.into_box_error()?;
76                    if let Some(service) = service {
77                        return Ok(ServiceMatch {
78                            input,
79                            service: Some(crate::combinators::$either::$variant(service)),
80                        });
81                    }
82                )+
83
84                Ok(ServiceMatch {
85                    input,
86                    service: None,
87                })
88            }
89        }
90    };
91}
92
93impl_service_matcher_tuple!(Either, A => SM1: sm1, B => SM2: sm2);
94impl_service_matcher_tuple!(Either3, A => SM1: sm1, B => SM2: sm2, C => SM3: sm3);
95impl_service_matcher_tuple!(Either4, A => SM1: sm1, B => SM2: sm2, C => SM3: sm3, D => SM4: sm4);
96impl_service_matcher_tuple!(Either5, A => SM1: sm1, B => SM2: sm2, C => SM3: sm3, D => SM4: sm4, E => SM5: sm5);
97impl_service_matcher_tuple!(Either6, A => SM1: sm1, B => SM2: sm2, C => SM3: sm3, D => SM4: sm4, E => SM5: sm5, F => SM6: sm6);
98impl_service_matcher_tuple!(Either7, A => SM1: sm1, B => SM2: sm2, C => SM3: sm3, D => SM4: sm4, E => SM5: sm5, F => SM6: sm6, G => SM7: sm7);
99impl_service_matcher_tuple!(Either8, A => SM1: sm1, B => SM2: sm2, C => SM3: sm3, D => SM4: sm4, E => SM5: sm5, F => SM6: sm6, G => SM7: sm7, H => SM8: sm8);
100impl_service_matcher_tuple!(Either9, A => SM1: sm1, B => SM2: sm2, C => SM3: sm3, D => SM4: sm4, E => SM5: sm5, F => SM6: sm6, G => SM7: sm7, H => SM8: sm8, I => SM9: sm9);
101
102macro_rules! impl_service_matcher_either {
103    ($either:ident, $first:ident $(, $rest:ident)* $(,)?) => {
104        impl<Input, ModifiedInput, $first, $($rest,)*> ServiceMatcher<Input>
105            for crate::combinators::$either<$first $(, $rest)*>
106        where
107            Input: Send + 'static,
108            ModifiedInput: Send + 'static,
109            $first: ServiceMatcher<Input, ModifiedInput = ModifiedInput>,
110            $(
111                $rest: ServiceMatcher<
112                    Input,
113                    ModifiedInput = ModifiedInput,
114                    Error: Into<$first::Error>,
115                >,
116            )*
117        {
118            type Service = crate::combinators::$either<$first::Service $(, $rest::Service)*>;
119            type Error = $first::Error;
120            type ModifiedInput = ModifiedInput;
121
122            async fn match_service(
123                &self,
124                input: Input,
125            ) -> Result<ServiceMatch<Self::ModifiedInput, Self::Service>, Self::Error> {
126                match self {
127                    crate::combinators::$either::$first(matcher) => {
128                        matcher.match_service(input).await.map(|sm| ServiceMatch {
129                            input: sm.input,
130                            service: sm.service.map(crate::combinators::$either::$first),
131                        })
132                    }
133                    $(
134                        crate::combinators::$either::$rest(matcher) => {
135                            matcher.match_service(input).await.map_err(Into::into).map(|sm| ServiceMatch {
136                                input: sm.input,
137                                service: sm.service.map(crate::combinators::$either::$rest),
138                            })
139                        }
140                    )*
141                }
142            }
143
144            async fn into_match_service(
145                self,
146                input: Input,
147            ) -> Result<ServiceMatch<Self::ModifiedInput, Self::Service>, Self::Error>
148            where
149                Input: Send,
150            {
151                match self {
152                    crate::combinators::$either::$first(matcher) => {
153                        matcher.into_match_service(input).await.map(|sm| ServiceMatch {
154                            input: sm.input,
155                            service: sm.service.map(crate::combinators::$either::$first),
156                        })
157                    }
158                    $(
159                        crate::combinators::$either::$rest(matcher) => {
160                            matcher.into_match_service(input).await.map_err(Into::into).map(|sm| ServiceMatch {
161                                input: sm.input,
162                                service: sm.service.map(crate::combinators::$either::$rest),
163                            })
164                        }
165                    )*
166                }
167            }
168        }
169    };
170}
171
172crate::combinators::impl_either!(impl_service_matcher_either);