1
0
mirror of https://github.com/fafhrd91/actix-net synced 2024-11-30 22:14:35 +01:00
actix-net/actix-service/src/apply_cfg.rs

234 lines
5.9 KiB
Rust
Raw Normal View History

2020-12-27 15:15:42 +01:00
use core::{
future::Future,
marker::PhantomData,
pin::Pin,
task::{Context, Poll},
};
use alloc::rc::Rc;
use futures_core::ready;
2020-12-27 15:15:42 +01:00
use pin_project_lite::pin_project;
2019-03-09 18:01:02 +01:00
2019-11-18 09:30:04 +01:00
use crate::{Service, ServiceFactory};
/// Convert `Fn(Config, &Service1) -> Future<Service2>` fn to a service factory.
pub fn apply_cfg<S1, Req, F, Cfg, Fut, S2, Err>(
srv: S1,
f: F,
) -> impl ServiceFactory<
Req,
Config = Cfg,
Response = S2::Response,
Error = S2::Error,
Service = S2,
InitError = Err,
Future = Fut,
> + Clone
2019-03-13 00:32:10 +01:00
where
S1: Service<Req>,
F: Fn(Cfg, &S1) -> Fut,
Fut: Future<Output = Result<S2, Err>>,
S2: Service<Req>,
2019-03-13 00:32:10 +01:00
{
ApplyConfigService {
srv: Rc::new((srv, f)),
_phantom: PhantomData,
}
2019-03-09 18:01:02 +01:00
}
/// Convert `Fn(Config, &ServiceFactory1) -> Future<ServiceFactory2>` fn to a service factory.
2019-12-10 16:34:51 +01:00
///
/// Service1 get constructed from `T` factory.
pub fn apply_cfg_factory<SF, Req, F, Cfg, Fut, S>(
factory: SF,
2019-06-06 10:28:07 +02:00
f: F,
) -> impl ServiceFactory<
Req,
Config = Cfg,
Response = S::Response,
Error = S::Error,
Service = S,
InitError = SF::InitError,
> + Clone
2019-06-06 10:28:07 +02:00
where
SF: ServiceFactory<Req, Config = ()>,
F: Fn(Cfg, &SF::Service) -> Fut,
SF::InitError: From<SF::Error>,
Fut: Future<Output = Result<S, SF::InitError>>,
S: Service<Req>,
2019-06-06 10:28:07 +02:00
{
2019-11-18 09:30:04 +01:00
ApplyConfigServiceFactory {
srv: Rc::new((factory, f)),
_phantom: PhantomData,
2019-06-06 10:28:07 +02:00
}
}
/// Convert `Fn(Config, &Server) -> Future<Service>` fn to NewService\
struct ApplyConfigService<S1, Req, F, Cfg, Fut, S2, Err>
2019-03-09 18:01:02 +01:00
where
S1: Service<Req>,
F: Fn(Cfg, &S1) -> Fut,
Fut: Future<Output = Result<S2, Err>>,
S2: Service<Req>,
2019-03-09 18:01:02 +01:00
{
srv: Rc<(S1, F)>,
_phantom: PhantomData<(Cfg, Req, Fut, S2)>,
2019-03-09 18:01:02 +01:00
}
impl<S1, Req, F, Cfg, Fut, S2, Err> Clone for ApplyConfigService<S1, Req, F, Cfg, Fut, S2, Err>
2019-03-09 18:01:02 +01:00
where
S1: Service<Req>,
F: Fn(Cfg, &S1) -> Fut,
Fut: Future<Output = Result<S2, Err>>,
S2: Service<Req>,
2019-03-09 18:01:02 +01:00
{
fn clone(&self) -> Self {
ApplyConfigService {
srv: self.srv.clone(),
_phantom: PhantomData,
2019-03-09 18:01:02 +01:00
}
}
}
impl<S1, Req, F, Cfg, Fut, S2, Err> ServiceFactory<Req>
for ApplyConfigService<S1, Req, F, Cfg, Fut, S2, Err>
2019-03-09 18:01:02 +01:00
where
S1: Service<Req>,
F: Fn(Cfg, &S1) -> Fut,
Fut: Future<Output = Result<S2, Err>>,
S2: Service<Req>,
2019-03-09 18:01:02 +01:00
{
type Response = S2::Response;
type Error = S2::Error;
type Config = Cfg;
type Service = S2;
2019-03-09 18:01:02 +01:00
type InitError = Err;
type Future = Fut;
2019-03-09 18:01:02 +01:00
fn new_service(&self, cfg: Cfg) -> Self::Future {
let (t, f) = &*self.srv;
2020-07-19 23:05:36 +02:00
f(cfg, t)
2019-03-09 18:01:02 +01:00
}
}
2019-06-06 10:28:07 +02:00
/// Convert `Fn(&Config) -> Future<Service>` fn to NewService
struct ApplyConfigServiceFactory<SF, Req, F, Cfg, Fut, S>
2019-06-06 10:28:07 +02:00
where
SF: ServiceFactory<Req, Config = ()>,
F: Fn(Cfg, &SF::Service) -> Fut,
Fut: Future<Output = Result<S, SF::InitError>>,
S: Service<Req>,
2019-06-06 10:28:07 +02:00
{
srv: Rc<(SF, F)>,
_phantom: PhantomData<(Cfg, Req, Fut, S)>,
2019-06-06 10:28:07 +02:00
}
impl<SF, Req, F, Cfg, Fut, S> Clone for ApplyConfigServiceFactory<SF, Req, F, Cfg, Fut, S>
2019-06-06 10:28:07 +02:00
where
SF: ServiceFactory<Req, Config = ()>,
F: Fn(Cfg, &SF::Service) -> Fut,
Fut: Future<Output = Result<S, SF::InitError>>,
S: Service<Req>,
2019-06-06 10:28:07 +02:00
{
fn clone(&self) -> Self {
2019-11-18 09:30:04 +01:00
Self {
2019-06-06 10:28:07 +02:00
srv: self.srv.clone(),
_phantom: PhantomData,
2019-06-06 10:28:07 +02:00
}
}
}
impl<SF, Req, F, Cfg, Fut, S> ServiceFactory<Req>
for ApplyConfigServiceFactory<SF, Req, F, Cfg, Fut, S>
2019-06-06 10:28:07 +02:00
where
SF: ServiceFactory<Req, Config = ()>,
SF::InitError: From<SF::Error>,
F: Fn(Cfg, &SF::Service) -> Fut,
Fut: Future<Output = Result<S, SF::InitError>>,
S: Service<Req>,
2019-06-06 10:28:07 +02:00
{
type Response = S::Response;
type Error = S::Error;
type Config = Cfg;
2019-06-06 10:28:07 +02:00
type Service = S;
type InitError = SF::InitError;
type Future = ApplyConfigServiceFactoryResponse<SF, Req, F, Cfg, Fut, S>;
2019-06-06 10:28:07 +02:00
fn new_service(&self, cfg: Cfg) -> Self::Future {
2019-11-18 09:30:04 +01:00
ApplyConfigServiceFactoryResponse {
cfg: Some(cfg),
store: self.srv.clone(),
2020-12-27 15:15:42 +01:00
state: State::A {
fut: self.srv.0.new_service(()),
2020-12-27 15:15:42 +01:00
},
2019-06-06 10:28:07 +02:00
}
}
}
2020-12-27 15:15:42 +01:00
pin_project! {
struct ApplyConfigServiceFactoryResponse<SF, Req, F, Cfg, Fut, S>
where
SF: ServiceFactory<Req, Config = ()>,
SF::InitError: From<SF::Error>,
F: Fn(Cfg, &SF::Service) -> Fut,
2020-12-27 15:15:42 +01:00
Fut: Future<Output = Result<S, SF::InitError>>,
S: Service<Req>,
{
cfg: Option<Cfg>,
store: Rc<(SF, F)>,
2020-12-27 15:15:42 +01:00
#[pin]
state: State<SF, Fut, S, Req>,
}
}
2020-12-27 15:15:42 +01:00
pin_project! {
#[project = StateProj]
enum State<SF, Fut, S, Req>
where
SF: ServiceFactory<Req, Config = ()>,
SF::InitError: From<SF::Error>,
Fut: Future<Output = Result<S, SF::InitError>>,
S: Service<Req>,
{
A { #[pin] fut: SF::Future },
B { svc: SF::Service },
C { #[pin] fut: Fut },
}
2019-06-06 10:28:07 +02:00
}
impl<SF, Req, F, Cfg, Fut, S> Future
for ApplyConfigServiceFactoryResponse<SF, Req, F, Cfg, Fut, S>
2019-11-18 09:30:04 +01:00
where
SF: ServiceFactory<Req, Config = ()>,
SF::InitError: From<SF::Error>,
F: Fn(Cfg, &SF::Service) -> Fut,
Fut: Future<Output = Result<S, SF::InitError>>,
S: Service<Req>,
2019-06-06 10:28:07 +02:00
{
type Output = Result<S, SF::InitError>;
2019-06-06 10:28:07 +02:00
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
let mut this = self.as_mut().project();
2019-11-18 09:30:04 +01:00
match this.state.as_mut().project() {
StateProj::A { fut } => {
let svc = ready!(fut.poll(cx))?;
this.state.set(State::B { svc });
self.poll(cx)
}
StateProj::B { svc } => {
ready!(svc.poll_ready(cx))?;
{
let (_, f) = &**this.store;
let fut = f(this.cfg.take().unwrap(), svc);
this.state.set(State::C { fut });
}
self.poll(cx)
}
2020-12-27 15:15:42 +01:00
StateProj::C { fut } => fut.poll(cx),
2019-06-06 10:28:07 +02:00
}
}
}