diff --git a/tower/Cargo.toml b/tower/Cargo.toml index 3d5783d72..9a69b6b82 100644 --- a/tower/Cargo.toml +++ b/tower/Cargo.toml @@ -63,7 +63,7 @@ retry = ["__common", "tokio/time"] spawn-ready = ["__common", "futures-util", "tokio/sync", "tokio/rt", "util", "tracing"] steer = [] timeout = ["pin-project-lite", "tokio/time"] -util = ["__common", "futures-util", "pin-project"] +util = ["__common", "futures-util", "pin-project-lite"] [dependencies] tower-layer = { version = "0.3.1", path = "../tower-layer" } @@ -79,7 +79,6 @@ tokio = { version = "1.6", optional = true, features = ["sync"] } tokio-stream = { version = "0.1.0", optional = true } tokio-util = { version = "0.7.0", default-features = false, optional = true } tracing = { version = "0.1.2", default-features = false, features = ["std"], optional = true } -pin-project = { version = "1", optional = true } pin-project-lite = { version = "0.2.7", optional = true } [dev-dependencies] diff --git a/tower/src/util/either.rs b/tower/src/util/either.rs index 5933755ef..371abb4d7 100644 --- a/tower/src/util/either.rs +++ b/tower/src/util/either.rs @@ -2,8 +2,7 @@ //! //! See [`Either`] documentation for more details. -use futures_core::ready; -use pin_project::pin_project; +use pin_project_lite::pin_project; use std::{ future::Future, pin::Pin, @@ -17,58 +16,73 @@ use tower_service::Service; /// Both services must be of the same request, response, and error types. /// [`Either`] is useful for handling conditional branching in service middleware /// to different inner service types. -#[pin_project(project = EitherProj)] -#[derive(Clone, Debug)] +#[derive(Clone, Copy, Debug)] pub enum Either { - /// One type of backing [`Service`]. - A(#[pin] A), - /// The other type of backing [`Service`]. - B(#[pin] B), + #[allow(missing_docs)] + Left(A), + #[allow(missing_docs)] + Right(B), } impl Service for Either where A: Service, - A::Error: Into, - B: Service, - B::Error: Into, + B: Service, { type Response = A::Response; - type Error = crate::BoxError; - type Future = Either; + type Error = A::Error; + type Future = EitherResponseFuture; fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll> { - use self::Either::*; - match self { - A(service) => Poll::Ready(Ok(ready!(service.poll_ready(cx)).map_err(Into::into)?)), - B(service) => Poll::Ready(Ok(ready!(service.poll_ready(cx)).map_err(Into::into)?)), + Either::Left(service) => service.poll_ready(cx), + Either::Right(service) => service.poll_ready(cx), } } fn call(&mut self, request: Request) -> Self::Future { - use self::Either::*; - match self { - A(service) => A(service.call(request)), - B(service) => B(service.call(request)), + Either::Left(service) => EitherResponseFuture { + kind: Kind::Left { + inner: service.call(request), + }, + }, + Either::Right(service) => EitherResponseFuture { + kind: Kind::Right { + inner: service.call(request), + }, + }, } } } -impl Future for Either +pin_project! { + /// Response future for [`Either`]. + pub struct EitherResponseFuture { + #[pin] + kind: Kind + } +} + +pin_project! { + #[project = KindProj] + enum Kind { + Left { #[pin] inner: A }, + Right { #[pin] inner: B }, + } +} + +impl Future for EitherResponseFuture where - A: Future>, - AE: Into, - B: Future>, - BE: Into, + A: Future, + B: Future, { - type Output = Result; + type Output = A::Output; fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { - match self.project() { - EitherProj::A(fut) => Poll::Ready(Ok(ready!(fut.poll(cx)).map_err(Into::into)?)), - EitherProj::B(fut) => Poll::Ready(Ok(ready!(fut.poll(cx)).map_err(Into::into)?)), + match self.project().kind.project() { + KindProj::Left { inner } => inner.poll(cx), + KindProj::Right { inner } => inner.poll(cx), } } } @@ -82,8 +96,8 @@ where fn layer(&self, inner: S) -> Self::Service { match self { - Either::A(layer) => Either::A(layer.layer(inner)), - Either::B(layer) => Either::B(layer.layer(inner)), + Either::Left(layer) => Either::Left(layer.layer(inner)), + Either::Right(layer) => Either::Right(layer.layer(inner)), } } } diff --git a/tower/src/util/mod.rs b/tower/src/util/mod.rs index 129c9d7ab..3ca56ad26 100644 --- a/tower/src/util/mod.rs +++ b/tower/src/util/mod.rs @@ -53,6 +53,7 @@ pub mod future { //! Future types pub use super::and_then::AndThenFuture; + pub use super::either::EitherResponseFuture; pub use super::map_err::MapErrFuture; pub use super::map_response::MapResponseFuture; pub use super::map_result::MapResultFuture; @@ -1076,8 +1077,8 @@ impl ServiceExt for T where T: tower_service::Servi /// [`Layer`]: crate::layer::Layer pub fn option_layer(layer: Option) -> Either { if let Some(layer) = layer { - Either::A(layer) + Either::Left(layer) } else { - Either::B(Identity::new()) + Either::Right(Identity::new()) } }