composable_tower_http/extract/
and.rs1use 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}