#![deny(clippy::pedantic)]
#![allow(
clippy::missing_fields_in_debug,
clippy::must_use_candidate,
clippy::missing_errors_doc
)]
use std::{rc::Rc, task::Context};
mod and_then;
mod apply;
pub mod boxed;
pub mod cfg;
mod chain;
mod ctx;
mod fn_service;
mod fn_shutdown;
mod inspect;
mod macros;
mod map;
mod map_config;
mod map_err;
mod map_init_err;
mod middleware;
mod pipeline;
mod then;
mod util;
pub use self::apply::{apply_fn, apply_fn_factory};
pub use self::chain::{chain, chain_factory};
pub use self::ctx::ServiceCtx;
pub use self::fn_service::{fn_factory, fn_factory_with_config, fn_service};
pub use self::fn_shutdown::fn_shutdown;
pub use self::map_config::{map_config, unit_config};
pub use self::middleware::{Identity, Middleware, Stack, apply, fn_layer};
pub use self::pipeline::{Pipeline, PipelineBinding, PipelineCall, PipelineSvc};
#[allow(unused_variables)]
pub trait Service<Req> {
type Response;
type Error;
async fn call(
&self,
req: Req,
ctx: ServiceCtx<'_, Self>,
) -> Result<Self::Response, Self::Error>;
#[inline]
async fn ready(&self, ctx: ServiceCtx<'_, Self>) -> Result<(), Self::Error> {
Ok(())
}
#[inline]
async fn shutdown(&self) {}
#[inline]
fn poll(&self, cx: &mut Context<'_>) -> Result<(), Self::Error> {
Ok(())
}
#[inline]
fn map<F, Res>(self, f: F) -> dev::ServiceChain<dev::Map<Self, F, Req, Res>, Req>
where
Self: Sized,
F: Fn(Self::Response) -> Res,
{
chain(dev::Map::new(self, f))
}
#[inline]
fn map_err<F, E>(self, f: F) -> dev::ServiceChain<dev::MapErr<Self, F, E>, Req>
where
Self: Sized,
F: Fn(Self::Error) -> E,
{
chain(dev::MapErr::new(self, f))
}
}
pub trait ServiceFactory<Req, Cfg = ()> {
type Response;
type Error;
type Service: Service<Req, Response = Self::Response, Error = Self::Error>;
type InitError;
async fn create(&self, cfg: Cfg) -> Result<Self::Service, Self::InitError>;
#[inline]
async fn pipeline(&self, cfg: Cfg) -> Result<Pipeline<Self::Service>, Self::InitError>
where
Self: Sized,
{
Ok(Pipeline::new(self.create(cfg).await?))
}
#[inline]
fn map<F, Res>(
self,
f: F,
) -> dev::ServiceChainFactory<dev::MapFactory<Self, F, Req, Res, Cfg>, Req, Cfg>
where
Self: Sized,
F: Fn(Self::Response) -> Res + Clone,
{
chain_factory(dev::MapFactory::new(self, f))
}
#[inline]
fn map_err<F, E>(
self,
f: F,
) -> dev::ServiceChainFactory<dev::MapErrFactory<Self, Req, Cfg, F, E>, Req, Cfg>
where
Self: Sized,
F: Fn(Self::Error) -> E + Clone,
{
chain_factory(dev::MapErrFactory::new(self, f))
}
#[inline]
fn map_init_err<F, E>(
self,
f: F,
) -> dev::ServiceChainFactory<dev::MapInitErr<Self, Req, Cfg, F, E>, Req, Cfg>
where
Self: Sized,
F: Fn(Self::InitError) -> E + Clone,
{
chain_factory(dev::MapInitErr::new(self, f))
}
fn boxed(
self,
) -> boxed::BoxServiceFactory<Cfg, Req, Self::Response, Self::Error, Self::InitError>
where
Cfg: 'static,
Req: 'static,
Self: 'static + Sized,
{
boxed::factory(self)
}
}
impl<S, Req> Service<Req> for &S
where
S: Service<Req>,
{
type Response = S::Response;
type Error = S::Error;
#[inline]
async fn ready(&self, ctx: ServiceCtx<'_, Self>) -> Result<(), S::Error> {
ctx.ready(&**self).await
}
#[inline]
fn poll(&self, cx: &mut Context<'_>) -> Result<(), S::Error> {
(**self).poll(cx)
}
#[inline]
async fn shutdown(&self) {
(**self).shutdown().await;
}
#[inline]
async fn call(
&self,
request: Req,
ctx: ServiceCtx<'_, Self>,
) -> Result<Self::Response, Self::Error> {
ctx.call_nowait(&**self, request).await
}
}
impl<S, Req> Service<Req> for Box<S>
where
S: Service<Req>,
{
type Response = S::Response;
type Error = S::Error;
#[inline]
async fn ready(&self, ctx: ServiceCtx<'_, Self>) -> Result<(), S::Error> {
ctx.ready(&**self).await
}
#[inline]
async fn shutdown(&self) {
(**self).shutdown().await;
}
#[inline]
async fn call(
&self,
request: Req,
ctx: ServiceCtx<'_, Self>,
) -> Result<Self::Response, Self::Error> {
ctx.call_nowait(&**self, request).await
}
#[inline]
fn poll(&self, cx: &mut Context<'_>) -> Result<(), S::Error> {
(**self).poll(cx)
}
}
impl<S, Req, Cfg> ServiceFactory<Req, Cfg> for Rc<S>
where
S: ServiceFactory<Req, Cfg>,
{
type Response = S::Response;
type Error = S::Error;
type Service = S::Service;
type InitError = S::InitError;
async fn create(&self, cfg: Cfg) -> Result<Self::Service, Self::InitError> {
self.as_ref().create(cfg).await
}
}
pub trait IntoService<Svc, Req>
where
Svc: Service<Req>,
{
fn into_service(self) -> Svc;
}
pub trait IntoServiceFactory<T, Req, Cfg = ()>
where
T: ServiceFactory<Req, Cfg>,
{
fn into_factory(self) -> T;
}
impl<Svc, Req> IntoService<Svc, Req> for Svc
where
Svc: Service<Req>,
{
#[inline]
fn into_service(self) -> Svc {
self
}
}
impl<T, Req, Cfg> IntoServiceFactory<T, Req, Cfg> for T
where
T: ServiceFactory<Req, Cfg>,
{
#[inline]
fn into_factory(self) -> T {
self
}
}
pub mod dev {
pub use crate::and_then::{AndThen, AndThenFactory};
pub use crate::apply::{Apply, ApplyCtx, ApplyFactory};
pub use crate::chain::{ServiceChain, ServiceChainFactory};
pub use crate::fn_service::{
FnService, FnServiceConfig, FnServiceFactory, FnServiceNoConfig,
};
pub use crate::fn_shutdown::FnShutdown;
pub use crate::inspect::{InspectErr, InspectErrFactory};
pub use crate::map::{Map, MapFactory};
pub use crate::map_config::{MapConfig, UnitConfig};
pub use crate::map_err::{MapErr, MapErrFactory};
pub use crate::map_init_err::MapInitErr;
pub use crate::middleware::{ApplyMiddleware, FnMiddleware};
pub use crate::then::{Then, ThenFactory};
}