composable_tower_http/extract/
any.rs

1use super::extractor::Extractor;
2
3#[derive(Debug, Clone)]
4pub struct Any<L, F> {
5    left: L,
6    right: F,
7}
8
9impl<L, F> Any<L, F> {
10    pub const fn new(left: L, right: F) -> Self {
11        Self { left, right }
12    }
13}
14
15impl<L, R> Extractor for Any<L, R>
16where
17    L: Extractor + Send + Sync,
18    R: Extractor + Send + Sync,
19    L::Extracted: From<R::Extracted>,
20    L::Error: Send,
21{
22    type Extracted = L::Extracted;
23
24    type Error = AnyError<L::Error, R::Error>;
25
26    async fn extract(&self, headers: &http::HeaderMap) -> Result<Self::Extracted, Self::Error> {
27        match self.left.extract(headers).await {
28            Ok(extracted) => Ok(extracted),
29            Err(left_error) => match self.right.extract(headers).await {
30                Ok(extracted) => Ok(extracted.into()),
31                Err(right_error) => Err(AnyError {
32                    left: left_error,
33                    right: right_error,
34                }),
35            },
36        }
37    }
38}
39
40#[derive(Debug, thiserror::Error)]
41#[error("Left: {left}, Right: {right}")]
42pub struct AnyError<L, R> {
43    pub left: L,
44    pub right: R,
45}
46
47#[cfg(feature = "axum")]
48mod axum {
49    use axum::response::{IntoResponse, Response};
50
51    use super::AnyError;
52
53    impl<L, R> IntoResponse for AnyError<L, R>
54    where
55        L: IntoResponse,
56    {
57        fn into_response(self) -> Response {
58            self.left.into_response()
59        }
60    }
61
62    impl<L, R> From<AnyError<L, R>> for Response
63    where
64        L: IntoResponse,
65    {
66        fn from(value: AnyError<L, R>) -> Self {
67            value.into_response()
68        }
69    }
70}