#![allow(clippy::type_complexity)]
use std::{fmt, marker::PhantomData};
use crate::and_then::{AndThen, AndThenFactory};
use crate::apply::{Apply, ApplyCtx, ApplyFactory};
use crate::ctx::ServiceCtx;
use crate::inspect::{Inspect, InspectErr, InspectErrFactory, InspectFactory};
use crate::map::{Map, MapFactory};
use crate::map_err::{MapErr, MapErrFactory};
use crate::map_init_err::MapInitErr;
use crate::middleware::{ApplyMiddleware, Middleware};
use crate::then::{Then, ThenFactory};
use crate::{IntoService, IntoServiceFactory, Pipeline, Service, ServiceFactory};
pub fn chain<Svc, Req, F>(service: F) -> ServiceChain<Svc, Req>
where
Svc: Service<Req>,
F: IntoService<Svc, Req>,
{
ServiceChain {
service: service.into_service(),
_t: PhantomData,
}
}
pub fn chain_factory<Fac, Req, C, F>(factory: F) -> ServiceChainFactory<Fac, Req, C>
where
Fac: ServiceFactory<Req, C>,
F: IntoServiceFactory<Fac, Req, C>,
{
ServiceChainFactory {
factory: factory.into_factory(),
_t: PhantomData,
}
}
pub struct ServiceChain<Svc, Req> {
service: Svc,
_t: PhantomData<Req>,
}
impl<Svc: Service<Req>, Req> ServiceChain<Svc, Req> {
pub fn and_then<Next, F>(self, service: F) -> ServiceChain<AndThen<Svc, Next>, Req>
where
Self: Sized,
F: IntoService<Next, Svc::Response>,
Next: Service<Svc::Response, Error = Svc::Error>,
{
ServiceChain {
service: AndThen::new(self.service, service.into_service()),
_t: PhantomData,
}
}
pub fn then<Next, F>(self, service: F) -> ServiceChain<Then<Svc, Next>, Req>
where
Self: Sized,
F: IntoService<Next, Result<Svc::Response, Svc::Error>>,
Next: Service<Result<Svc::Response, Svc::Error>, Error = Svc::Error>,
{
ServiceChain {
service: Then::new(self.service, service.into_service()),
_t: PhantomData,
}
}
pub fn map<F, Res>(self, f: F) -> ServiceChain<Map<Svc, F, Req, Res>, Req>
where
Self: Sized,
F: Fn(Svc::Response) -> Res,
{
ServiceChain {
service: Map::new(self.service, f),
_t: PhantomData,
}
}
pub fn map_err<F, Err>(self, f: F) -> ServiceChain<MapErr<Svc, F, Err>, Req>
where
Self: Sized,
F: Fn(Svc::Error) -> Err,
{
ServiceChain {
service: MapErr::new(self.service, f),
_t: PhantomData,
}
}
pub fn inspect<F>(self, f: F) -> ServiceChain<Inspect<Svc, F>, Req>
where
Self: Sized,
F: Fn(&Svc::Response),
{
ServiceChain {
service: Inspect::new(self.service, f),
_t: PhantomData,
}
}
pub fn inspect_err<F>(self, f: F) -> ServiceChain<InspectErr<Svc, F>, Req>
where
Self: Sized,
F: Fn(&Svc::Error),
{
ServiceChain {
service: InspectErr::new(self.service, f),
_t: PhantomData,
}
}
pub fn apply_fn<F, In, Out, Err>(
self,
f: F,
) -> ServiceChain<Apply<Svc, Req, F, In, Out, Err>, In>
where
F: AsyncFn(In, &ApplyCtx<'_, Svc>) -> Result<Out, Err>,
Svc: Service<Req>,
Err: From<Svc::Error>,
{
crate::apply_fn(self.service, f)
}
pub fn into_pipeline(self) -> Pipeline<Svc> {
Pipeline::new(self.service)
}
}
impl<Svc, Req> Clone for ServiceChain<Svc, Req>
where
Svc: Clone,
{
fn clone(&self) -> Self {
ServiceChain {
service: self.service.clone(),
_t: PhantomData,
}
}
}
impl<Svc, Req> fmt::Debug for ServiceChain<Svc, Req>
where
Svc: fmt::Debug,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("ServiceChain")
.field("service", &self.service)
.finish()
}
}
impl<Svc: Service<Req>, Req> Service<Req> for ServiceChain<Svc, Req> {
type Response = Svc::Response;
type Error = Svc::Error;
crate::forward_poll!(service);
crate::forward_ready!(service);
crate::forward_shutdown!(service);
#[inline]
async fn call(
&self,
req: Req,
ctx: ServiceCtx<'_, Self>,
) -> Result<Self::Response, Self::Error> {
ctx.call(&self.service, req).await
}
}
pub struct ServiceChainFactory<Fac, Req, C = ()> {
pub(crate) factory: Fac,
pub(crate) _t: PhantomData<(Req, C)>,
}
impl<Fac: ServiceFactory<Req, C>, Req, C> ServiceChainFactory<Fac, Req, C> {
pub fn and_then<F, U>(
self,
factory: F,
) -> ServiceChainFactory<AndThenFactory<Fac, U>, Req, C>
where
Self: Sized,
F: IntoServiceFactory<U, Fac::Response, C>,
U: ServiceFactory<Fac::Response, C, Error = Fac::Error, InitError = Fac::InitError>,
{
ServiceChainFactory {
factory: AndThenFactory::new(self.factory, factory.into_factory()),
_t: PhantomData,
}
}
pub fn apply<U>(self, tr: U) -> ServiceChainFactory<ApplyMiddleware<U, Fac, C>, Req, C>
where
U: Middleware<Fac::Service, C>,
{
crate::apply(tr, self.factory)
}
pub fn apply_fn<F, In, Out, Err>(
self,
f: F,
) -> ServiceChainFactory<ApplyFactory<Fac, Req, C, F, In, Out, Err>, In, C>
where
F: AsyncFn(In, &ApplyCtx<'_, Fac::Service>) -> Result<Out, Err> + Clone,
Fac: ServiceFactory<Req, C>,
Err: From<Fac::Error>,
{
crate::apply_fn_factory(self.factory, f)
}
pub fn then<F, U>(self, factory: F) -> ServiceChainFactory<ThenFactory<Fac, U>, Req, C>
where
Self: Sized,
C: Clone,
F: IntoServiceFactory<U, Result<Fac::Response, Fac::Error>, C>,
U: ServiceFactory<
Result<Fac::Response, Fac::Error>,
C,
Error = Fac::Error,
InitError = Fac::InitError,
>,
{
ServiceChainFactory {
factory: ThenFactory::new(self.factory, factory.into_factory()),
_t: PhantomData,
}
}
pub fn map<F, Res>(
self,
f: F,
) -> ServiceChainFactory<MapFactory<Fac, F, Req, Res, C>, Req, C>
where
Self: Sized,
F: Fn(Fac::Response) -> Res + Clone,
{
ServiceChainFactory {
factory: MapFactory::new(self.factory, f),
_t: PhantomData,
}
}
pub fn map_err<F, E>(
self,
f: F,
) -> ServiceChainFactory<MapErrFactory<Fac, Req, C, F, E>, Req, C>
where
Self: Sized,
F: Fn(Fac::Error) -> E + Clone,
{
ServiceChainFactory {
factory: MapErrFactory::new(self.factory, f),
_t: PhantomData,
}
}
pub fn map_init_err<F, E>(
self,
f: F,
) -> ServiceChainFactory<MapInitErr<Fac, Req, C, F, E>, Req, C>
where
Self: Sized,
F: Fn(Fac::InitError) -> E + Clone,
{
ServiceChainFactory {
factory: MapInitErr::new(self.factory, f),
_t: PhantomData,
}
}
pub fn inspect<F>(self, f: F) -> ServiceChainFactory<InspectFactory<Fac, F>, Req, C>
where
Self: Sized,
F: Fn(&Fac::Response) + Clone,
{
ServiceChainFactory {
factory: InspectFactory::new(self.factory, f),
_t: PhantomData,
}
}
pub fn inspect_err<F>(
self,
f: F,
) -> ServiceChainFactory<InspectErrFactory<Fac, F>, Req, C>
where
Self: Sized,
F: Fn(&Fac::Error) + Clone,
{
ServiceChainFactory {
factory: InspectErrFactory::new(self.factory, f),
_t: PhantomData,
}
}
pub async fn pipeline(&self, cfg: C) -> Result<Pipeline<Fac::Service>, Fac::InitError>
where
Self: Sized,
{
Ok(Pipeline::new(self.factory.create(cfg).await?))
}
}
impl<Fac, R, C> Clone for ServiceChainFactory<Fac, R, C>
where
Fac: Clone,
{
fn clone(&self) -> Self {
ServiceChainFactory {
factory: self.factory.clone(),
_t: PhantomData,
}
}
}
impl<Fac, R, C> fmt::Debug for ServiceChainFactory<Fac, R, C>
where
Fac: fmt::Debug,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("ServiceChainFactory")
.field("factory", &self.factory)
.finish()
}
}
impl<Fac: ServiceFactory<Req, C>, Req, C> ServiceFactory<Req, C>
for ServiceChainFactory<Fac, Req, C>
{
type Response = Fac::Response;
type Error = Fac::Error;
type Service = Fac::Service;
type InitError = Fac::InitError;
#[inline]
async fn create(&self, cfg: C) -> Result<Self::Service, Self::InitError> {
self.factory.create(cfg).await
}
}