/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 | | } |