Coverage Report

Created: 2025-10-29 07:05

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/tower-0.5.2/src/util/either.rs
Line
Count
Source
1
//! Contains [`Either`] and related types and functions.
2
//!
3
//! See [`Either`] documentation for more details.
4
5
use pin_project_lite::pin_project;
6
use std::{
7
    future::Future,
8
    pin::Pin,
9
    task::{Context, Poll},
10
};
11
use tower_layer::Layer;
12
use tower_service::Service;
13
14
/// Combine two different service types into a single type.
15
///
16
/// Both services must be of the same request, response, and error types.
17
/// [`Either`] is useful for handling conditional branching in service middleware
18
/// to different inner service types.
19
#[derive(Clone, Copy, Debug)]
20
pub enum Either<A, B> {
21
    #[allow(missing_docs)]
22
    Left(A),
23
    #[allow(missing_docs)]
24
    Right(B),
25
}
26
27
impl<A, B, Request> Service<Request> for Either<A, B>
28
where
29
    A: Service<Request>,
30
    B: Service<Request, Response = A::Response, Error = A::Error>,
31
{
32
    type Response = A::Response;
33
    type Error = A::Error;
34
    type Future = EitherResponseFuture<A::Future, B::Future>;
35
36
0
    fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
37
0
        match self {
38
0
            Either::Left(service) => service.poll_ready(cx),
39
0
            Either::Right(service) => service.poll_ready(cx),
40
        }
41
0
    }
42
43
0
    fn call(&mut self, request: Request) -> Self::Future {
44
0
        match self {
45
0
            Either::Left(service) => EitherResponseFuture {
46
0
                kind: Kind::Left {
47
0
                    inner: service.call(request),
48
0
                },
49
0
            },
50
0
            Either::Right(service) => EitherResponseFuture {
51
0
                kind: Kind::Right {
52
0
                    inner: service.call(request),
53
0
                },
54
0
            },
55
        }
56
0
    }
57
}
58
59
pin_project! {
60
    /// Response future for [`Either`].
61
    pub struct EitherResponseFuture<A, B> {
62
        #[pin]
63
        kind: Kind<A, B>
64
    }
65
}
66
67
pin_project! {
68
    #[project = KindProj]
69
    enum Kind<A, B> {
70
        Left { #[pin] inner: A },
71
        Right { #[pin] inner: B },
72
    }
73
}
74
75
impl<A, B> Future for EitherResponseFuture<A, B>
76
where
77
    A: Future,
78
    B: Future<Output = A::Output>,
79
{
80
    type Output = A::Output;
81
82
0
    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
83
0
        match self.project().kind.project() {
84
0
            KindProj::Left { inner } => inner.poll(cx),
85
0
            KindProj::Right { inner } => inner.poll(cx),
86
        }
87
0
    }
88
}
89
90
impl<S, A, B> Layer<S> for Either<A, B>
91
where
92
    A: Layer<S>,
93
    B: Layer<S>,
94
{
95
    type Service = Either<A::Service, B::Service>;
96
97
0
    fn layer(&self, inner: S) -> Self::Service {
98
0
        match self {
99
0
            Either::Left(layer) => Either::Left(layer.layer(inner)),
100
0
            Either::Right(layer) => Either::Right(layer.layer(inner)),
101
        }
102
0
    }
103
}