1
0
mirror of https://github.com/fafhrd91/actix-net synced 2025-02-26 02:22:50 +01:00
actix-net/actix-service/src/apply_cfg.rs

229 lines
6.1 KiB
Rust
Raw Normal View History

use std::cell::RefCell;
Migrate actix-net to std::future (#64) * Migrate actix-codec, actix-rt, and actix-threadpool to std::future * update to latest tokio alpha and futures-rs * Migrate actix-service to std::future, This is a squash of ~8 commits, since it included a lot of experimentation. To see the commits, look into the semtexzv/std-future-service-tmp branch. * update futures-rs and tokio * Migrate actix-threadpool to std::future (#59) * Migrate actix-threadpool to std::future * Cosmetic refactor - turn log::error! into log::warn! as it doesn't throw any error - add Clone and Copy impls for Cancelled making it cheap to operate with - apply rustfmt * Bump up crate version to 0.2.0 and pre-fill its changelog * Disable patching 'actix-threadpool' crate in global workspace as unnecessary * Revert patching and fix 'actix-rt' * Migrate actix-rt to std::future (#47) * remove Pin from Service::poll_ready(); simplify combinators api; make code compile * disable tests * update travis config * refactor naming * drop IntoFuture trait * Migrate actix-server to std::future (#50) Still not finished, this is more WIP, this is an aggregation of several commits, which can be found in semtexzv/std-future-server-tmp branch * update actix-server * rename Factor to ServiceFactory * start server worker in start mehtod * update actix-utils * remove IntoTransform trait * Migrate actix-server::ssl::nativetls to std futures (#61) * Refactor 'nativetls' module * Migrate 'actix-server-config' to std futures - remove "uds" feature - disable features by default * Switch NativeTlsAcceptor to use 'tokio-tls' crate * Bikeshed features names and remove unnecessary dependencies for 'actix-server-config' crate * update openssl impl * migrate actix-connect to std::future * migrate actix-ioframe to std::future * update version to alpha.1 * fix boxed service * migrate server rustls support * migratte openssl and rustls connecttors * store the thread's handle with arbiter (#62) * update ssl connect tests * restore service tests * update readme
2019-11-14 18:38:24 +06:00
use std::future::Future;
2019-03-09 09:01:02 -08:00
use std::marker::PhantomData;
Migrate actix-net to std::future (#64) * Migrate actix-codec, actix-rt, and actix-threadpool to std::future * update to latest tokio alpha and futures-rs * Migrate actix-service to std::future, This is a squash of ~8 commits, since it included a lot of experimentation. To see the commits, look into the semtexzv/std-future-service-tmp branch. * update futures-rs and tokio * Migrate actix-threadpool to std::future (#59) * Migrate actix-threadpool to std::future * Cosmetic refactor - turn log::error! into log::warn! as it doesn't throw any error - add Clone and Copy impls for Cancelled making it cheap to operate with - apply rustfmt * Bump up crate version to 0.2.0 and pre-fill its changelog * Disable patching 'actix-threadpool' crate in global workspace as unnecessary * Revert patching and fix 'actix-rt' * Migrate actix-rt to std::future (#47) * remove Pin from Service::poll_ready(); simplify combinators api; make code compile * disable tests * update travis config * refactor naming * drop IntoFuture trait * Migrate actix-server to std::future (#50) Still not finished, this is more WIP, this is an aggregation of several commits, which can be found in semtexzv/std-future-server-tmp branch * update actix-server * rename Factor to ServiceFactory * start server worker in start mehtod * update actix-utils * remove IntoTransform trait * Migrate actix-server::ssl::nativetls to std futures (#61) * Refactor 'nativetls' module * Migrate 'actix-server-config' to std futures - remove "uds" feature - disable features by default * Switch NativeTlsAcceptor to use 'tokio-tls' crate * Bikeshed features names and remove unnecessary dependencies for 'actix-server-config' crate * update openssl impl * migrate actix-connect to std::future * migrate actix-ioframe to std::future * update version to alpha.1 * fix boxed service * migrate server rustls support * migratte openssl and rustls connecttors * store the thread's handle with arbiter (#62) * update ssl connect tests * restore service tests * update readme
2019-11-14 18:38:24 +06:00
use std::pin::Pin;
2020-07-19 23:05:36 +02:00
use std::rc::Rc;
use std::task::{Context, Poll};
2019-03-09 09:01:02 -08:00
2019-11-18 14:30:04 +06:00
use crate::{Service, ServiceFactory};
/// Convert `Fn(Config, &mut 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-12 16:32:10 -07:00
where
S1: Service<Req>,
F: FnMut(Cfg, &mut S1) -> Fut,
Fut: Future<Output = Result<S2, Err>>,
S2: Service<Req>,
2019-03-12 16:32:10 -07:00
{
ApplyConfigService {
2020-07-19 23:05:36 +02:00
srv: Rc::new(RefCell::new((srv, f))),
_phantom: PhantomData,
}
2019-03-09 09:01:02 -08:00
}
/// Convert `Fn(Config, &mut ServiceFactory1) -> Future<ServiceFactory2>` fn to a service factory.
2019-12-10 21:34:51 +06:00
///
/// Service1 get constructed from `T` factory.
pub fn apply_cfg_factory<SF, Req, F, Cfg, Fut, S>(
factory: SF,
2019-06-06 14:28:07 +06:00
f: F,
) -> impl ServiceFactory<
Req,
Config = Cfg,
Response = S::Response,
Error = S::Error,
Service = S,
InitError = SF::InitError,
> + Clone
2019-06-06 14:28:07 +06:00
where
SF: ServiceFactory<Req, Config = ()>,
F: FnMut(Cfg, &mut SF::Service) -> Fut,
SF::InitError: From<SF::Error>,
Fut: Future<Output = Result<S, SF::InitError>>,
S: Service<Req>,
2019-06-06 14:28:07 +06:00
{
2019-11-18 14:30:04 +06:00
ApplyConfigServiceFactory {
2020-07-19 23:05:36 +02:00
srv: Rc::new(RefCell::new((factory, f))),
_phantom: PhantomData,
2019-06-06 14:28:07 +06:00
}
}
2019-12-10 21:34:51 +06:00
/// Convert `Fn(Config, &mut Server) -> Future<Service>` fn to NewService\
struct ApplyConfigService<S1, Req, F, Cfg, Fut, S2, Err>
2019-03-09 09:01:02 -08:00
where
S1: Service<Req>,
F: FnMut(Cfg, &mut S1) -> Fut,
Fut: Future<Output = Result<S2, Err>>,
S2: Service<Req>,
2019-03-09 09:01:02 -08:00
{
srv: Rc<RefCell<(S1, F)>>,
_phantom: PhantomData<(Cfg, Req, Fut, S2)>,
2019-03-09 09:01:02 -08:00
}
impl<S1, Req, F, Cfg, Fut, S2, Err> Clone for ApplyConfigService<S1, Req, F, Cfg, Fut, S2, Err>
2019-03-09 09:01:02 -08:00
where
S1: Service<Req>,
F: FnMut(Cfg, &mut S1) -> Fut,
Fut: Future<Output = Result<S2, Err>>,
S2: Service<Req>,
2019-03-09 09:01:02 -08:00
{
fn clone(&self) -> Self {
ApplyConfigService {
srv: self.srv.clone(),
_phantom: PhantomData,
2019-03-09 09:01:02 -08:00
}
}
}
impl<S1, Req, F, Cfg, Fut, S2, Err> ServiceFactory<Req>
for ApplyConfigService<S1, Req, F, Cfg, Fut, S2, Err>
2019-03-09 09:01:02 -08:00
where
S1: Service<Req>,
F: FnMut(Cfg, &mut S1) -> Fut,
Fut: Future<Output = Result<S2, Err>>,
S2: Service<Req>,
2019-03-09 09:01:02 -08:00
{
type Config = Cfg;
type Response = S2::Response;
type Error = S2::Error;
type Service = S2;
2019-03-09 09:01:02 -08:00
type InitError = Err;
type Future = Fut;
2019-03-09 09:01:02 -08:00
fn new_service(&self, cfg: Cfg) -> Self::Future {
2020-07-19 23:05:36 +02:00
let (t, f) = &mut *self.srv.borrow_mut();
f(cfg, t)
2019-03-09 09:01:02 -08:00
}
}
2019-06-06 14:28:07 +06:00
/// Convert `Fn(&Config) -> Future<Service>` fn to NewService
struct ApplyConfigServiceFactory<SF, Req, F, Cfg, Fut, S>
2019-06-06 14:28:07 +06:00
where
SF: ServiceFactory<Req, Config = ()>,
F: FnMut(Cfg, &mut SF::Service) -> Fut,
Fut: Future<Output = Result<S, SF::InitError>>,
S: Service<Req>,
2019-06-06 14:28:07 +06:00
{
srv: Rc<RefCell<(SF, F)>>,
_phantom: PhantomData<(Cfg, Req, Fut, S)>,
2019-06-06 14:28:07 +06:00
}
impl<SF, Req, F, Cfg, Fut, S> Clone for ApplyConfigServiceFactory<SF, Req, F, Cfg, Fut, S>
2019-06-06 14:28:07 +06:00
where
SF: ServiceFactory<Req, Config = ()>,
F: FnMut(Cfg, &mut SF::Service) -> Fut,
Fut: Future<Output = Result<S, SF::InitError>>,
S: Service<Req>,
2019-06-06 14:28:07 +06:00
{
fn clone(&self) -> Self {
2019-11-18 14:30:04 +06:00
Self {
2019-06-06 14:28:07 +06:00
srv: self.srv.clone(),
_phantom: PhantomData,
2019-06-06 14:28:07 +06:00
}
}
}
impl<SF, Req, F, Cfg, Fut, S> ServiceFactory<Req>
for ApplyConfigServiceFactory<SF, Req, F, Cfg, Fut, S>
2019-06-06 14:28:07 +06:00
where
SF: ServiceFactory<Req, Config = ()>,
SF::InitError: From<SF::Error>,
F: FnMut(Cfg, &mut SF::Service) -> Fut,
Fut: Future<Output = Result<S, SF::InitError>>,
S: Service<Req>,
2019-06-06 14:28:07 +06:00
{
type Config = Cfg;
2019-06-06 14:28:07 +06:00
type Response = S::Response;
type Error = S::Error;
type Service = S;
type InitError = SF::InitError;
type Future = ApplyConfigServiceFactoryResponse<SF, Req, F, Cfg, Fut, S>;
2019-06-06 14:28:07 +06:00
fn new_service(&self, cfg: Cfg) -> Self::Future {
2019-11-18 14:30:04 +06:00
ApplyConfigServiceFactoryResponse {
cfg: Some(cfg),
store: self.srv.clone(),
2020-07-19 23:05:36 +02:00
state: State::A(self.srv.borrow().0.new_service(())),
2019-06-06 14:28:07 +06:00
}
}
}
#[pin_project::pin_project]
struct ApplyConfigServiceFactoryResponse<SF, Req, F, Cfg, Fut, S>
where
SF: ServiceFactory<Req, Config = ()>,
SF::InitError: From<SF::Error>,
F: FnMut(Cfg, &mut SF::Service) -> Fut,
Fut: Future<Output = Result<S, SF::InitError>>,
S: Service<Req>,
{
cfg: Option<Cfg>,
store: Rc<RefCell<(SF, F)>>,
#[pin]
state: State<SF, Fut, S, Req>,
}
#[pin_project::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] SF::Future),
B(SF::Service),
C(#[pin] Fut),
2019-06-06 14:28:07 +06:00
}
impl<SF, Req, F, Cfg, Fut, S> Future
for ApplyConfigServiceFactoryResponse<SF, Req, F, Cfg, Fut, S>
2019-11-18 14:30:04 +06:00
where
SF: ServiceFactory<Req, Config = ()>,
SF::InitError: From<SF::Error>,
F: FnMut(Cfg, &mut SF::Service) -> Fut,
Fut: Future<Output = Result<S, SF::InitError>>,
S: Service<Req>,
2019-06-06 14:28:07 +06:00
{
type Output = Result<S, SF::InitError>;
2019-06-06 14:28:07 +06:00
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
let mut this = self.as_mut().project();
2019-11-18 14:30:04 +06:00
match this.state.as_mut().project() {
StateProj::A(fut) => match fut.poll(cx)? {
Poll::Pending => Poll::Pending,
Poll::Ready(srv) => {
this.state.set(State::B(srv));
self.poll(cx)
2019-06-06 14:28:07 +06:00
}
},
StateProj::B(srv) => match srv.poll_ready(cx)? {
Poll::Ready(_) => {
2020-07-19 23:05:36 +02:00
{
let (_, f) = &mut *this.store.borrow_mut();
let fut = f(this.cfg.take().unwrap(), srv);
this.state.set(State::C(fut));
}
self.poll(cx)
}
Poll::Pending => Poll::Pending,
},
StateProj::C(fut) => fut.poll(cx),
2019-06-06 14:28:07 +06:00
}
}
}