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