1use futures_core::ready;
6use pin_project::pin_project;
7use std::{
8 future::Future,
9 pin::Pin,
10 task::{Context, Poll},
11};
12use tower_layer::Layer;
13use tower_service::Service;
14
15#[pin_project(project = EitherProj)]
21#[derive(Clone, Debug)]
22pub enum Either<A, B> {
23 A(#[pin] A),
25 B(#[pin] B),
27}
28
29impl<A, B, Request> Service<Request> for Either<A, B>
30where
31 A: Service<Request>,
32 A::Error: Into<crate::BoxError>,
33 B: Service<Request, Response = A::Response>,
34 B::Error: Into<crate::BoxError>,
35{
36 type Response = A::Response;
37 type Error = crate::BoxError;
38 type Future = Either<A::Future, B::Future>;
39
40 fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
41 use self::Either::*;
42
43 match self {
44 A(service) => Poll::Ready(Ok(ready!(service.poll_ready(cx)).map_err(Into::into)?)),
45 B(service) => Poll::Ready(Ok(ready!(service.poll_ready(cx)).map_err(Into::into)?)),
46 }
47 }
48
49 fn call(&mut self, request: Request) -> Self::Future {
50 use self::Either::*;
51
52 match self {
53 A(service) => A(service.call(request)),
54 B(service) => B(service.call(request)),
55 }
56 }
57}
58
59impl<A, B, T, AE, BE> Future for Either<A, B>
60where
61 A: Future<Output = Result<T, AE>>,
62 AE: Into<crate::BoxError>,
63 B: Future<Output = Result<T, BE>>,
64 BE: Into<crate::BoxError>,
65{
66 type Output = Result<T, crate::BoxError>;
67
68 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
69 match self.project() {
70 EitherProj::A(fut) => Poll::Ready(Ok(ready!(fut.poll(cx)).map_err(Into::into)?)),
71 EitherProj::B(fut) => Poll::Ready(Ok(ready!(fut.poll(cx)).map_err(Into::into)?)),
72 }
73 }
74}
75
76impl<S, A, B> Layer<S> for Either<A, B>
77where
78 A: Layer<S>,
79 B: Layer<S>,
80{
81 type Service = Either<A::Service, B::Service>;
82
83 fn layer(&self, inner: S) -> Self::Service {
84 match self {
85 Either::A(layer) => Either::A(layer.layer(inner)),
86 Either::B(layer) => Either::B(layer.layer(inner)),
87 }
88 }
89}