#![deny(clippy::pedantic)]
#![allow(
clippy::cast_possible_truncation,
clippy::missing_fields_in_debug,
clippy::missing_errors_doc,
clippy::missing_panics_doc,
clippy::must_use_candidate,
clippy::type_complexity,
clippy::unused_async,
clippy::unused_async_trait_impl
)]
use std::rc::Rc;
mod and_then;
mod apply;
pub mod boxed;
pub mod cfg;
mod chain;
mod ctx;
mod fn_ready;
mod fn_service;
mod fn_shutdown;
mod macros;
mod map;
mod map_err;
mod map_init_err;
mod map_state;
mod middleware;
pub mod state;
mod then;
mod util;
pub mod pipeline;
mod pl_factory;
mod pl_inner;
mod pl_state;
pub use crate::apply::{apply_fn, apply_fn_factory};
pub use crate::chain::{ServiceChain, ServiceChainFactory, factory, service};
pub use crate::ctx::Ctx;
pub use crate::fn_service::{fn_factory, fn_service, fn_service_st};
pub use crate::map_state::{map_state, map_state_factory};
pub use crate::middleware::{Identity, Middleware, Stack, apply, fn_layer};
pub use crate::pipeline::Pipeline;
pub use crate::state::{RequestState, State};
#[allow(unused_variables)]
pub trait Service<St, Req> {
type Res;
type Error;
async fn call(&self, req: Req, ctx: Ctx<'_, Self, St>) -> Result<Self::Res, Self::Error>;
#[inline]
async fn ready(&self, ctx: Ctx<'_, Self, St>) -> Result<(), Self::Error> {
Ok(())
}
#[inline]
async fn shutdown(&self, cfg: Ctx<'_, Self, St>) {}
#[inline]
fn map<F, Res>(self, f: F) -> ServiceChain<dev::Map<F, Self, Res>, St, Req>
where
Self: Sized,
F: Fn(Self::Res) -> Res,
{
service(dev::Map::new(f, self))
}
#[inline]
fn map_err<F, E>(self, f: F) -> ServiceChain<dev::MapErr<F, Self, E>, St, Req>
where
Self: Sized,
F: Fn(Self::Error) -> E,
{
service(dev::MapErr::new(f, self))
}
#[inline]
fn and_then<Next, F>(self, f: F) -> ServiceChain<dev::AndThen<Self, Next>, St, Req>
where
Self: Sized,
Next: Service<St, Self::Res, Error = Self::Error>,
F: IntoService<Next, St, Self::Res>,
{
service(dev::AndThen::new(self, f.into_service()))
}
#[inline]
fn pipeline(self, st: St) -> Pipeline<Req, Self::Res, Self::Error>
where
Self: Sized + 'static,
St: 'static,
Req: 'static,
{
Pipeline::new(st, self)
}
}
pub trait ServiceFactory<St, Req> {
type Res;
type Error;
type Service: Service<St, Req, Res = Self::Res, Error = Self::Error>;
type InitError;
async fn create(&self, cfg: &St) -> Result<Self::Service, Self::InitError>;
#[inline]
async fn pipeline(
&self,
st: St,
) -> Result<Pipeline<Req, Self::Res, Self::Error>, Self::InitError>
where
Self: 'static,
St: 'static,
Req: 'static,
{
let svc = self.create(&st).await?;
Ok(Pipeline::new(st, svc))
}
#[inline]
fn map<F, Res>(self, f: F) -> ServiceChainFactory<dev::MapFactory<F, Self, Res>, St, Req>
where
Self: Sized,
F: Fn(Self::Res) -> Res + Clone,
{
factory(dev::MapFactory::new(f, self))
}
#[inline]
fn map_err<F, E>(self, f: F) -> ServiceChainFactory<dev::MapErrFactory<F, Self, E>, St, Req>
where
Self: Sized,
F: Fn(Self::Error) -> E + Clone,
{
factory(dev::MapErrFactory::new(f, self))
}
#[inline]
fn map_init_err<F, E>(self, f: F) -> ServiceChainFactory<dev::MapInitErr<F, Self, E>, St, Req>
where
Self: Sized,
F: Fn(Self::InitError) -> E + Clone,
{
factory(dev::MapInitErr::new(f, self))
}
fn and_then<U, F>(self, f: F) -> ServiceChainFactory<dev::AndThenFactory<Self, U>, St, Req>
where
Self: Sized,
U: ServiceFactory<St, Self::Res, Error = Self::Error, InitError = Self::InitError>,
F: IntoServiceFactory<U, St, Self::Res>,
{
factory(dev::AndThenFactory::new(self, f.into_factory()))
}
fn boxed(self) -> boxed::BoxServiceFactory<St, Req, Self::Res, Self::Error, Self::InitError>
where
St: 'static,
Req: 'static,
Self: Sized + 'static,
{
boxed::factory(self)
}
}
impl<S, St, Req> Service<St, Req> for &S
where
S: Service<St, Req>,
{
type Res = S::Res;
type Error = S::Error;
#[inline]
async fn ready(&self, ctx: Ctx<'_, Self, St>) -> Result<(), S::Error> {
ctx.ready(&**self).await
}
#[inline]
async fn call(&self, req: Req, ctx: Ctx<'_, Self, St>) -> Result<S::Res, S::Error> {
ctx.call_nowait(&**self, req).await
}
#[inline]
async fn shutdown(&self, ctx: Ctx<'_, Self, St>) {
ctx.shutdown(&**self).await;
}
}
impl<S, St, Req> Service<St, Req> for Box<S>
where
S: Service<St, Req>,
{
type Res = S::Res;
type Error = S::Error;
#[inline]
async fn ready(&self, ctx: Ctx<'_, Self, St>) -> Result<(), S::Error> {
ctx.ready(&**self).await
}
#[inline]
async fn call(&self, req: Req, ctx: Ctx<'_, Self, St>) -> Result<S::Res, S::Error> {
ctx.call_nowait(&**self, req).await
}
#[inline]
async fn shutdown(&self, ctx: Ctx<'_, Self, St>) {
ctx.shutdown(&**self).await;
}
}
impl<S, St, Req> Service<St, Req> for Rc<S>
where
S: Service<St, Req>,
{
type Res = S::Res;
type Error = S::Error;
#[inline]
async fn ready(&self, ctx: Ctx<'_, Self, St>) -> Result<(), S::Error> {
ctx.ready(&**self).await
}
#[inline]
async fn call(&self, req: Req, ctx: Ctx<'_, Self, St>) -> Result<S::Res, S::Error> {
ctx.call_nowait(&**self, req).await
}
#[inline]
async fn shutdown(&self, ctx: Ctx<'_, Self, St>) {
ctx.shutdown(&**self).await;
}
}
impl<Sf, St, Req> ServiceFactory<St, Req> for Rc<Sf>
where
Sf: ServiceFactory<St, Req>,
{
type Res = Sf::Res;
type Error = Sf::Error;
type Service = Sf::Service;
type InitError = Sf::InitError;
async fn create(&self, cfg: &St) -> Result<Self::Service, Self::InitError> {
self.as_ref().create(cfg).await
}
}
pub trait ServiceCaller<Req, Res, Err> {
async fn call_service(&self, req: Req) -> Result<Res, Err>;
}
pub trait IntoService<S, St, Req>
where
S: Service<St, Req>,
{
fn into_service(self) -> S;
}
pub trait IntoServiceFactory<Sf, St, Req>
where
Sf: ServiceFactory<St, Req>,
{
fn into_factory(self) -> Sf;
}
impl<S, St, Req> IntoService<S, St, Req> for S
where
S: Service<St, Req>,
{
#[inline]
fn into_service(self) -> S {
self
}
}
impl<Sf, St, Req> IntoServiceFactory<Sf, St, Req> for Sf
where
Sf: ServiceFactory<St, Req>,
{
#[inline]
fn into_factory(self) -> Sf {
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_ready::FnReadiness;
pub use crate::fn_service::{FnFactory, FnService, FnServiceSt, FnServiceStFactory};
pub use crate::fn_shutdown::FnShutdown;
pub use crate::map::{Map, MapFactory};
pub use crate::map_err::{MapErr, MapErrFactory};
pub use crate::map_init_err::MapInitErr;
pub use crate::map_state::{MapState, MapStateFactory};
pub use crate::middleware::{ApplyMiddleware, FnMiddleware};
pub use crate::then::{Then, ThenFactory};
}