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