composable_tower_http/extract/
and.rs

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