chateau 0.3.2

Tower primitives for Servers and Clients with ergonomic APIs
Documentation
use std::error::Error as StdError;
use std::fmt;
use std::future::Future;
use std::pin::Pin;
use std::sync::Arc;
use std::task::{Context, Poll};

use tower::BoxError;
use tower::Service;
use tower::{Layer, ServiceExt, layer::layer_fn};

pub trait Sealed<Conn> {}

/// A trait for types that can be used to make HTTP services, by recieving references to connections.
pub trait MakeServiceRef<Target, Request>: Sealed<(Target, Request)> {
    /// The `HttpBody` body of the `http::Response`.
    type Response;

    /// The error type that can occur within this `Service`.
    type Error: Into<BoxError>;

    /// The Service type produced to handle requests.
    type Service: tower::Service<Request, Response = Self::Response, Error = Self::Error>;

    /// The error type that occurs if we can't create the service.
    type MakeError: Into<BoxError>;

    /// The `Future` returned by this `MakeService`.
    type Future: Future<Output = Result<Self::Service, Self::MakeError>>;

    /// Poll the readiness of the make_serivce.
    fn poll_ready_ref(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::MakeError>>;

    /// Create a new service.
    fn make_service_ref(&mut self, target: &Target) -> Self::Future;
}

impl<T, Target, ME, S, F, IB> Sealed<(Target, IB)> for T where
    T: for<'a> Service<&'a Target, Error = ME, Response = S, Future = F>
{
}

impl<T, Target, E, ME, S, F, Request, Response> MakeServiceRef<Target, Request> for T
where
    T: for<'a> Service<&'a Target, Error = ME, Response = S, Future = F>,
    E: Into<Box<dyn StdError + Send + Sync>>,
    ME: Into<Box<dyn StdError + Send + Sync>>,
    S: tower::Service<Request, Response = Response, Error = E>,
    F: Future<Output = Result<S, ME>>,
{
    type Error = E;
    type Service = S;
    type Response = Response;
    type MakeError = ME;
    type Future = F;

    fn poll_ready_ref(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::MakeError>> {
        self.poll_ready(cx)
    }

    fn make_service_ref(&mut self, target: &Target) -> Self::Future {
        self.call(target)
    }
}

/// Create a `MakeService` from a function.
pub fn make_service_fn<F, Target, Ret>(f: F) -> MakeServiceFn<F>
where
    F: FnMut(&Target) -> Ret,
    Ret: Future,
{
    MakeServiceFn { f }
}

/// `MakeService` returned from [`make_service_fn`]
#[derive(Clone, Copy)]
pub struct MakeServiceFn<F> {
    f: F,
}

impl<'t, F, Ret, Target, Svc, MkErr> Service<&'t Target> for MakeServiceFn<F>
where
    F: FnMut(&Target) -> Ret,
    Ret: Future<Output = Result<Svc, MkErr>>,
    MkErr: Into<Box<dyn StdError + Send + Sync>>,
{
    type Error = MkErr;
    type Response = Svc;
    type Future = Ret;

    fn poll_ready(&mut self, _cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
        Poll::Ready(Ok(()))
    }

    fn call(&mut self, target: &'t Target) -> Self::Future {
        (self.f)(target)
    }
}

impl<F> fmt::Debug for MakeServiceFn<F> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("MakeServiceFn").finish()
    }
}

//TODO: Should this really be 'static?
type BoxFuture<T, E> = Pin<Box<dyn Future<Output = Result<T, E>> + Send + 'static>>;
type ServiceRef<T, S, E> =
    dyn for<'a> tower::Service<&'a T, Response = S, Error = E, Future = BoxFuture<S, E>> + Send;

/// A boxed `ServiceRef`.
pub struct BoxMakeServiceRef<Target, Service, MakeServiceError> {
    inner: Box<ServiceRef<Target, Service, MakeServiceError>>,
}

impl<T, S, E> fmt::Debug for BoxMakeServiceRef<T, S, E> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("BoxMakeServiceRef").finish()
    }
}

impl<T, S, E> BoxMakeServiceRef<T, S, E> {
    /// Create a new `BoxMakeServiceRef`.
    pub fn new<U, F>(inner: U) -> Self
    where
        U: for<'a> Service<&'a T, Response = S, Error = E, Future = F> + Send + 'static,
        F: Future<Output = Result<S, E>> + Send + 'static,
        T: 'static,
    {
        let inner = Box::new(inner.map_future(|f| Box::pin(f) as _));
        Self { inner }
    }
}

impl<T, S, E> Service<&T> for BoxMakeServiceRef<T, S, E> {
    type Response = S;
    type Error = E;
    type Future = BoxFuture<S, E>;

    fn poll_ready(
        &mut self,
        cx: &mut std::task::Context<'_>,
    ) -> std::task::Poll<Result<(), Self::Error>> {
        self.inner.poll_ready(cx)
    }

    fn call(&mut self, target: &T) -> Self::Future {
        self.inner.call(target)
    }
}

/// A [`Layer`] that wraps an inner [`MakeServiceRef`] and returns a boxed [`MakeServiceRef`].
pub struct BoxMakeServiceLayer<InnerMakeService, Target, InnerService, MakeServiceError> {
    boxed: Arc<
        dyn Layer<
                InnerMakeService,
                Service = BoxMakeServiceRef<Target, InnerService, MakeServiceError>,
            > + Send
            + Sync
            + 'static,
    >,
}

impl<In, T, U, E> BoxMakeServiceLayer<In, T, U, E> {
    /// Create a new [`BoxMakeServiceLayer`].
    pub fn new<L, F>(inner_layer: L) -> Self
    where
        L: Layer<In> + Send + Sync + 'static,
        L::Service: for<'a> Service<&'a T, Response = U, Error = E, Future = F> + Send + 'static,
        F: Future<Output = Result<U, E>> + Send + 'static,
        T: 'static,
    {
        let layer = layer_fn(move |inner: In| {
            let out = inner_layer.layer(inner);
            BoxMakeServiceRef::new(out)
        });

        Self {
            boxed: Arc::new(layer),
        }
    }
}

impl<In, T, U, E> Layer<In> for BoxMakeServiceLayer<In, T, U, E> {
    type Service = BoxMakeServiceRef<T, U, E>;

    fn layer(&self, inner: In) -> Self::Service {
        self.boxed.layer(inner)
    }
}

impl<In, T, U, E> Clone for BoxMakeServiceLayer<In, T, U, E> {
    fn clone(&self) -> Self {
        Self {
            boxed: Arc::clone(&self.boxed),
        }
    }
}

impl<In, T, U, E> fmt::Debug for BoxMakeServiceLayer<In, T, U, E> {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt.debug_struct("BoxMakeServiceLayer").finish()
    }
}

#[cfg(test)]
mod tests {

    use super::*;

    use static_assertions::assert_impl_all;

    assert_impl_all!(BoxMakeServiceLayer<(), (), (), ()>: Clone, Send, Sync);
    assert_impl_all!(BoxMakeServiceRef<(), (), ()>: Send);
}