1use std::task::{Context, Poll};
94
95use axum::{
96    extract::FromRequestParts,
97    response::{IntoResponse, Response},
98};
99use http::request::Parts;
100use tower_layer::Layer;
101use tower_service::Service;
102
103#[derive(Debug, Clone)]
107#[must_use]
108pub enum Either<E1, E2> {
109    #[allow(missing_docs)]
110    E1(E1),
111    #[allow(missing_docs)]
112    E2(E2),
113}
114
115#[derive(Debug, Clone)]
119#[must_use]
120pub enum Either3<E1, E2, E3> {
121    #[allow(missing_docs)]
122    E1(E1),
123    #[allow(missing_docs)]
124    E2(E2),
125    #[allow(missing_docs)]
126    E3(E3),
127}
128
129#[derive(Debug, Clone)]
133#[must_use]
134pub enum Either4<E1, E2, E3, E4> {
135    #[allow(missing_docs)]
136    E1(E1),
137    #[allow(missing_docs)]
138    E2(E2),
139    #[allow(missing_docs)]
140    E3(E3),
141    #[allow(missing_docs)]
142    E4(E4),
143}
144
145#[derive(Debug, Clone)]
149#[must_use]
150pub enum Either5<E1, E2, E3, E4, E5> {
151    #[allow(missing_docs)]
152    E1(E1),
153    #[allow(missing_docs)]
154    E2(E2),
155    #[allow(missing_docs)]
156    E3(E3),
157    #[allow(missing_docs)]
158    E4(E4),
159    #[allow(missing_docs)]
160    E5(E5),
161}
162
163#[derive(Debug, Clone)]
167#[must_use]
168pub enum Either6<E1, E2, E3, E4, E5, E6> {
169    #[allow(missing_docs)]
170    E1(E1),
171    #[allow(missing_docs)]
172    E2(E2),
173    #[allow(missing_docs)]
174    E3(E3),
175    #[allow(missing_docs)]
176    E4(E4),
177    #[allow(missing_docs)]
178    E5(E5),
179    #[allow(missing_docs)]
180    E6(E6),
181}
182
183#[derive(Debug, Clone)]
187#[must_use]
188pub enum Either7<E1, E2, E3, E4, E5, E6, E7> {
189    #[allow(missing_docs)]
190    E1(E1),
191    #[allow(missing_docs)]
192    E2(E2),
193    #[allow(missing_docs)]
194    E3(E3),
195    #[allow(missing_docs)]
196    E4(E4),
197    #[allow(missing_docs)]
198    E5(E5),
199    #[allow(missing_docs)]
200    E6(E6),
201    #[allow(missing_docs)]
202    E7(E7),
203}
204
205#[derive(Debug, Clone)]
209#[must_use]
210pub enum Either8<E1, E2, E3, E4, E5, E6, E7, E8> {
211    #[allow(missing_docs)]
212    E1(E1),
213    #[allow(missing_docs)]
214    E2(E2),
215    #[allow(missing_docs)]
216    E3(E3),
217    #[allow(missing_docs)]
218    E4(E4),
219    #[allow(missing_docs)]
220    E5(E5),
221    #[allow(missing_docs)]
222    E6(E6),
223    #[allow(missing_docs)]
224    E7(E7),
225    #[allow(missing_docs)]
226    E8(E8),
227}
228
229macro_rules! impl_traits_for_either {
230    (
231        $either:ident =>
232        [$($ident:ident),* $(,)?],
233        $last:ident $(,)?
234    ) => {
235        impl<S, $($ident),*, $last> FromRequestParts<S> for $either<$($ident),*, $last>
236        where
237            $($ident: FromRequestParts<S>),*,
238            $last: FromRequestParts<S>,
239            S: Send + Sync,
240        {
241            type Rejection = $last::Rejection;
242
243            async fn from_request_parts(parts: &mut Parts, state: &S) -> Result<Self, Self::Rejection> {
244                $(
245                    if let Ok(value) = <$ident as FromRequestParts<S>>::from_request_parts(parts, state).await {
246                        return Ok(Self::$ident(value));
247                    }
248                )*
249
250                <$last as FromRequestParts<S>>::from_request_parts(parts, state).await.map(Self::$last)
251            }
252        }
253
254        impl<$($ident),*, $last> IntoResponse for $either<$($ident),*, $last>
255        where
256            $($ident: IntoResponse),*,
257            $last: IntoResponse,
258        {
259            fn into_response(self) -> Response {
260                match self {
261                    $( Self::$ident(value) => value.into_response(), )*
262                    Self::$last(value) => value.into_response(),
263                }
264            }
265        }
266    };
267}
268
269impl_traits_for_either!(Either => [E1], E2);
270impl_traits_for_either!(Either3 => [E1, E2], E3);
271impl_traits_for_either!(Either4 => [E1, E2, E3], E4);
272impl_traits_for_either!(Either5 => [E1, E2, E3, E4], E5);
273impl_traits_for_either!(Either6 => [E1, E2, E3, E4, E5], E6);
274impl_traits_for_either!(Either7 => [E1, E2, E3, E4, E5, E6], E7);
275impl_traits_for_either!(Either8 => [E1, E2, E3, E4, E5, E6, E7], E8);
276
277impl<E1, E2, S> Layer<S> for Either<E1, E2>
278where
279    E1: Layer<S>,
280    E2: Layer<S>,
281{
282    type Service = Either<E1::Service, E2::Service>;
283
284    fn layer(&self, inner: S) -> Self::Service {
285        match self {
286            Either::E1(layer) => Either::E1(layer.layer(inner)),
287            Either::E2(layer) => Either::E2(layer.layer(inner)),
288        }
289    }
290}
291
292impl<R, E1, E2> Service<R> for Either<E1, E2>
293where
294    E1: Service<R>,
295    E2: Service<R, Response = E1::Response, Error = E1::Error>,
296{
297    type Response = E1::Response;
298    type Error = E1::Error;
299    type Future = futures_util::future::Either<E1::Future, E2::Future>;
300
301    fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
302        match self {
303            Either::E1(inner) => inner.poll_ready(cx),
304            Either::E2(inner) => inner.poll_ready(cx),
305        }
306    }
307
308    fn call(&mut self, req: R) -> Self::Future {
309        match self {
310            Either::E1(inner) => futures_util::future::Either::Left(inner.call(req)),
311            Either::E2(inner) => futures_util::future::Either::Right(inner.call(req)),
312        }
313    }
314}