tower/util/
either.rs
1use pin_project_lite::pin_project;
6use std::{
7 future::Future,
8 pin::Pin,
9 task::{Context, Poll},
10};
11use tower_layer::Layer;
12use tower_service::Service;
13
14#[derive(Clone, Copy, Debug)]
20pub enum Either<A, B> {
21 #[allow(missing_docs)]
22 Left(A),
23 #[allow(missing_docs)]
24 Right(B),
25}
26
27impl<A, B, Request> Service<Request> for Either<A, B>
28where
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 fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
37 match self {
38 Either::Left(service) => service.poll_ready(cx),
39 Either::Right(service) => service.poll_ready(cx),
40 }
41 }
42
43 fn call(&mut self, request: Request) -> Self::Future {
44 match self {
45 Either::Left(service) => EitherResponseFuture {
46 kind: Kind::Left {
47 inner: service.call(request),
48 },
49 },
50 Either::Right(service) => EitherResponseFuture {
51 kind: Kind::Right {
52 inner: service.call(request),
53 },
54 },
55 }
56 }
57}
58
59pin_project! {
60 pub struct EitherResponseFuture<A, B> {
62 #[pin]
63 kind: Kind<A, B>
64 }
65}
66
67pin_project! {
68 #[project = KindProj]
69 enum Kind<A, B> {
70 Left { #[pin] inner: A },
71 Right { #[pin] inner: B },
72 }
73}
74
75impl<A, B> Future for EitherResponseFuture<A, B>
76where
77 A: Future,
78 B: Future<Output = A::Output>,
79{
80 type Output = A::Output;
81
82 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
83 match self.project().kind.project() {
84 KindProj::Left { inner } => inner.poll(cx),
85 KindProj::Right { inner } => inner.poll(cx),
86 }
87 }
88}
89
90impl<S, A, B> Layer<S> for Either<A, B>
91where
92 A: Layer<S>,
93 B: Layer<S>,
94{
95 type Service = Either<A::Service, B::Service>;
96
97 fn layer(&self, inner: S) -> Self::Service {
98 match self {
99 Either::Left(layer) => Either::Left(layer.layer(inner)),
100 Either::Right(layer) => Either::Right(layer.layer(inner)),
101 }
102 }
103}