diff --git a/tower/tower/src/make.rs b/tower/tower/src/make.rs new file mode 100644 index 0000000..dfb99eb --- /dev/null +++ b/tower/tower/src/make.rs @@ -0,0 +1,90 @@ +//! Trait aliases for Services that produce specific types of Responses. + +pub use self::make_service::shared::Shared; +pub use self::make_service::MakeService; + +pub mod future { + //! Future types + + pub use super::make_service::shared::SharedFuture; +} + +mod make_service { + //! Contains [`MakeService`] which is a trait alias for a [`Service`] of [`Service`]s. + + use crate::sealed::Sealed; + use std::fmt; + use std::future::Future; + use std::marker::PhantomData; + use std::task::{Context, Poll}; + use tower_service::Service; + + pub mod shared { + use std::convert::Infallible; + use std::task::{Context, Poll}; + use tower_service::Service; + + pub struct Shared { + service: S, + } + + impl Service for Shared + where + S: Clone, + { + type Response = S; + type Error = Infallible; + type Future = SharedFuture; + + fn poll_ready(&mut self, _cx: &mut Context<'_>) -> Poll> { + todo!() + } + + fn call(&mut self, _target: T) -> Self::Future { + todo!() + } + } + + opaque_future! { + /// Response future from [`Shared`] services. + pub type SharedFuture = futures_util::future::Ready>; + } + } + + pub trait MakeService { + type Response; + type Error; + type Service: Service; + type MakeError; + type Future; + fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll>; + fn make_service(&mut self, target: Target) -> Self::Future; + } + + impl Sealed<(Target, Request)> for M + where + M: Service, + S: Service, + { + } + + impl MakeService for M + where + M: Service, + S: Service, + { + type Response = S::Response; + type Error = S::Error; + type Service = S; + type MakeError = M::Error; + type Future = M::Future; + + fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll> { + Service::poll_ready(self, cx) + } + + fn make_service(&mut self, target: Target) -> Self::Future { + Service::call(self, target) + } + } +} diff --git a/tower/tower/src/make/make_service.rs b/tower/tower/src/make/make_service.rs deleted file mode 100644 index 3a1503e..0000000 --- a/tower/tower/src/make/make_service.rs +++ /dev/null @@ -1,150 +0,0 @@ -//! Contains [`MakeService`] which is a trait alias for a [`Service`] of [`Service`]s. - -use crate::sealed::Sealed; -use std::fmt; -use std::future::Future; -use std::marker::PhantomData; -use std::task::{Context, Poll}; -use tower_service::Service; - -pub(crate) mod shared; - -/// Creates new [`Service`] values. -/// -/// Acts as a service factory. This is useful for cases where new [`Service`] -/// values must be produced. One case is a TCP server listener. The listener -/// accepts new TCP streams, obtains a new [`Service`] value using the -/// [`MakeService`] trait, and uses that new [`Service`] value to process inbound -/// requests on that new TCP stream. -/// -/// This is essentially a trait alias for a [`Service`] of [`Service`]s. -pub trait MakeService { - type Response; - type Error; - type Service: Service; - type MakeError; - type Future; - fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll>; - fn make_service(&mut self, target: Target) -> Self::Future; -} - -impl Sealed<(Target, Request)> for M -where - M: Service, - S: Service, -{ -} - -impl MakeService for M -where - M: Service, - S: Service, -{ - type Response = S::Response; - type Error = S::Error; - type Service = S; - type MakeError = M::Error; - type Future = M::Future; - - fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll> { - Service::poll_ready(self, cx) - } - - fn make_service(&mut self, target: Target) -> Self::Future { - Service::call(self, target) - } -} - -/// Service returned by [`MakeService::into_service`][into]. -/// -/// See the documentation on [`into_service`][into] for details. -/// -/// [into]: MakeService::into_service -pub struct IntoService { - make: M, - _marker: PhantomData, -} - -impl Clone for IntoService -where - M: Clone, -{ - fn clone(&self) -> Self { - Self { - make: self.make.clone(), - _marker: PhantomData, - } - } -} - -impl fmt::Debug for IntoService -where - M: fmt::Debug, -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("IntoService") - .field("make", &self.make) - .finish() - } -} - -impl Service for IntoService -where - M: Service, - S: Service, -{ - type Response = M::Response; - type Error = M::Error; - type Future = M::Future; - - #[inline] - fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll> { - self.make.poll_ready(cx) - } - - #[inline] - fn call(&mut self, target: Target) -> Self::Future { - self.make.make_service(target) - } -} - -/// Service returned by [`MakeService::as_service`][as]. -/// -/// See the documentation on [`as_service`][as] for details. -/// -/// [as]: MakeService::as_service -pub struct AsService<'a, M, Request> { - make: &'a mut M, - _marker: PhantomData, -} - -impl fmt::Debug for AsService<'_, M, Request> -where - M: fmt::Debug, -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("AsService") - .field("make", &self.make) - .finish() - } -} - -impl Service for AsService<'_, M, Request> -where - M: Service, - S: Service, -{ - type Response = M::Response; - type Error = M::Error; - type Future = M::Future; - - #[inline] - fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll> { - self.make.poll_ready(cx) - } - - #[inline] - fn call(&mut self, target: Target) -> Self::Future { - self.make.make_service(target) - } -} diff --git a/tower/tower/src/make/make_service/shared.rs b/tower/tower/src/make/make_service/shared.rs deleted file mode 100644 index fd308a0..0000000 --- a/tower/tower/src/make/make_service/shared.rs +++ /dev/null @@ -1,146 +0,0 @@ -use std::convert::Infallible; -use std::task::{Context, Poll}; -use tower_service::Service; - -/// A [`MakeService`] that produces services by cloning an inner service. -/// -/// [`MakeService`]: super::MakeService -/// -/// # Example -/// -/// ``` -/// # use std::task::{Context, Poll}; -/// # use std::pin::Pin; -/// # use std::convert::Infallible; -/// use tower::make::{MakeService, Shared}; -/// use tower::buffer::Buffer; -/// use tower::Service; -/// use futures::future::{Ready, ready}; -/// -/// // An example connection type -/// struct Connection {} -/// -/// // An example request type -/// struct Request {} -/// -/// // An example response type -/// struct Response {} -/// -/// // Some service that doesn't implement `Clone` -/// struct MyService; -/// -/// impl Service for MyService { -/// type Response = Response; -/// type Error = Infallible; -/// type Future = Ready>; -/// -/// fn poll_ready(&mut self, _cx: &mut Context<'_>) -> Poll> { -/// Poll::Ready(Ok(())) -/// } -/// -/// fn call(&mut self, req: Request) -> Self::Future { -/// ready(Ok(Response {})) -/// } -/// } -/// -/// // Example function that runs a service by accepting new connections and using -/// // `Make` to create new services that might be bound to the connection. -/// // -/// // This is similar to what you might find in hyper. -/// async fn serve_make_service(make: Make) -/// where -/// Make: MakeService -/// { -/// // ... -/// } -/// -/// # async { -/// // Our service -/// let svc = MyService; -/// -/// // Make it `Clone` by putting a channel in front -/// let buffered = Buffer::new(svc, 1024); -/// -/// // Convert it into a `MakeService` -/// let make = Shared::new(buffered); -/// -/// // Run the service and just ignore the `Connection`s as `MyService` doesn't need them -/// serve_make_service(make).await; -/// # }; -/// ``` -#[derive(Debug, Clone, Copy)] -pub struct Shared { - service: S, -} - -impl Shared { - /// Create a new [`Shared`] from a service. - pub fn new(service: S) -> Self { - Self { service } - } -} - -impl Service for Shared -where - S: Clone, -{ - type Response = S; - type Error = Infallible; - type Future = SharedFuture; - - fn poll_ready(&mut self, _cx: &mut Context<'_>) -> Poll> { - Poll::Ready(Ok(())) - } - - fn call(&mut self, _target: T) -> Self::Future { - SharedFuture::new(futures_util::future::ready(Ok(self.service.clone()))) - } -} - -opaque_future! { - /// Response future from [`Shared`] services. - pub type SharedFuture = futures_util::future::Ready>; -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::make::MakeService; - use crate::service_fn; - use futures::future::poll_fn; - - async fn echo(req: R) -> Result { - Ok(req) - } - - #[tokio::test] - async fn as_make_service() { - let mut shared = Shared::new(service_fn(echo::<&'static str>)); - - poll_fn(|cx| MakeService::<(), _>::poll_ready(&mut shared, cx)) - .await - .unwrap(); - let mut svc = shared.make_service(()).await.unwrap(); - - poll_fn(|cx| svc.poll_ready(cx)).await.unwrap(); - let res = svc.call("foo").await.unwrap(); - - assert_eq!(res, "foo"); - } - - #[tokio::test] - async fn as_make_service_into_service() { - let shared = Shared::new(service_fn(echo::<&'static str>)); - let mut shared = MakeService::<(), _>::into_service(shared); - - poll_fn(|cx| Service::<()>::poll_ready(&mut shared, cx)) - .await - .unwrap(); - let mut svc = shared.call(()).await.unwrap(); - - poll_fn(|cx| svc.poll_ready(cx)).await.unwrap(); - let res = svc.call("foo").await.unwrap(); - - assert_eq!(res, "foo"); - } -} diff --git a/tower/tower/src/make/mod.rs b/tower/tower/src/make/mod.rs deleted file mode 100644 index 41b20c7..0000000 --- a/tower/tower/src/make/mod.rs +++ /dev/null @@ -1,12 +0,0 @@ -//! Trait aliases for Services that produce specific types of Responses. - -mod make_service; - -pub use self::make_service::shared::Shared; -pub use self::make_service::{AsService, IntoService, MakeService}; - -pub mod future { - //! Future types - - pub use super::make_service::shared::SharedFuture; -}