blob: aa519d682b202634ab2de5e52574f769294dd67f [file] [log] [blame]
//! 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<Target, Request>: Sealed<(Target, Request)> {
/// Responses given by the service
type Response;
/// Errors produced by the service
type Error;
/// The [`Service`] value created by this factory
type Service: Service<Request, Response = Self::Response, Error = Self::Error>;
/// Errors produced while building a service.
type MakeError;
/// The future of the [`Service`] instance.
type Future: Future<Output = Result<Self::Service, Self::MakeError>>;
/// Returns [`Poll::Ready`] when the factory is able to create more services.
///
/// If the service is at capacity, then [`Poll::Pending`] is returned and the task
/// is notified when the service becomes ready again. This function is
/// expected to be called while on a task.
///
/// [`Poll::Ready`]: std::task::Poll::Ready
/// [`Poll::Pending`]: std::task::Poll::Pending
fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::MakeError>>;
/// Create and return a new service value asynchronously.
fn make_service(&mut self, target: Target) -> Self::Future;
/// Consume this [`MakeService`] and convert it into a [`Service`].
///
/// # Example
/// ```
/// use std::convert::Infallible;
/// use tower::Service;
/// use tower::make::MakeService;
/// use tower::service_fn;
///
/// # fn main() {
/// # async {
/// // A `MakeService`
/// let make_service = service_fn(|make_req: ()| async {
/// Ok::<_, Infallible>(service_fn(|req: String| async {
/// Ok::<_, Infallible>(req)
/// }))
/// });
///
/// // Convert the `MakeService` into a `Service`
/// let mut svc = make_service.into_service();
///
/// // Make a new service
/// let mut new_svc = svc.call(()).await.unwrap();
///
/// // Call the service
/// let res = new_svc.call("foo".to_string()).await.unwrap();
/// # };
/// # }
/// ```
fn into_service(self) -> IntoService<Self, Request>
where
Self: Sized,
{
IntoService {
make: self,
_marker: PhantomData,
}
}
/// Convert this [`MakeService`] into a [`Service`] without consuming the original [`MakeService`].
///
/// # Example
/// ```
/// use std::convert::Infallible;
/// use tower::Service;
/// use tower::make::MakeService;
/// use tower::service_fn;
///
/// # fn main() {
/// # async {
/// // A `MakeService`
/// let mut make_service = service_fn(|make_req: ()| async {
/// Ok::<_, Infallible>(service_fn(|req: String| async {
/// Ok::<_, Infallible>(req)
/// }))
/// });
///
/// // Convert the `MakeService` into a `Service`
/// let mut svc = make_service.as_service();
///
/// // Make a new service
/// let mut new_svc = svc.call(()).await.unwrap();
///
/// // Call the service
/// let res = new_svc.call("foo".to_string()).await.unwrap();
///
/// // The original `MakeService` is still accessible
/// let new_svc = make_service.make_service(()).await.unwrap();
/// # };
/// # }
/// ```
fn as_service(&mut self) -> AsService<Self, Request>
where
Self: Sized,
{
AsService {
make: self,
_marker: PhantomData,
}
}
}
impl<M, S, Target, Request> Sealed<(Target, Request)> for M
where
M: Service<Target, Response = S>,
S: Service<Request>,
{
}
impl<M, S, Target, Request> MakeService<Target, Request> for M
where
M: Service<Target, Response = S>,
S: Service<Request>,
{
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<Result<(), Self::MakeError>> {
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<M, Request> {
make: M,
_marker: PhantomData<Request>,
}
impl<M, Request> Clone for IntoService<M, Request>
where
M: Clone,
{
fn clone(&self) -> Self {
Self {
make: self.make.clone(),
_marker: PhantomData,
}
}
}
impl<M, Request> fmt::Debug for IntoService<M, Request>
where
M: fmt::Debug,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("IntoService")
.field("make", &self.make)
.finish()
}
}
impl<M, S, Target, Request> Service<Target> for IntoService<M, Request>
where
M: Service<Target, Response = S>,
S: Service<Request>,
{
type Response = M::Response;
type Error = M::Error;
type Future = M::Future;
#[inline]
fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
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<Request>,
}
impl<M, Request> 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<M, S, Target, Request> Service<Target> for AsService<'_, M, Request>
where
M: Service<Target, Response = S>,
S: Service<Request>,
{
type Response = M::Response;
type Error = M::Error;
type Future = M::Future;
#[inline]
fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
self.make.poll_ready(cx)
}
#[inline]
fn call(&mut self, target: Target) -> Self::Future {
self.make.make_service(target)
}
}