From 158482cd2ff68f9a9c4f47b104e33db99a3968d6 Mon Sep 17 00:00:00 2001 From: Nikolay Kim Date: Thu, 6 Jun 2019 14:28:07 +0600 Subject: [PATCH] Add new_apply_cfg function --- actix-service/CHANGES.md | 6 ++ actix-service/Cargo.toml | 2 +- actix-service/src/apply_cfg.rs | 154 ++++++++++++++++++++++++++++++++- actix-service/src/cell.rs | 4 + actix-service/src/lib.rs | 2 +- 5 files changed, 163 insertions(+), 5 deletions(-) diff --git a/actix-service/CHANGES.md b/actix-service/CHANGES.md index 49722d4f..047de4e3 100644 --- a/actix-service/CHANGES.md +++ b/actix-service/CHANGES.md @@ -1,5 +1,11 @@ # Changes +## [0.4.1] - 2019-06-06 + +### Added + +* Add `new_apply_cfg` function + ## [0.4.0] - 2019-05-12 ### Changed diff --git a/actix-service/Cargo.toml b/actix-service/Cargo.toml index 026a0b33..7425902a 100644 --- a/actix-service/Cargo.toml +++ b/actix-service/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "actix-service" -version = "0.4.0" +version = "0.4.1" authors = ["Nikolay Kim "] description = "Actix Service" keywords = ["network", "framework", "async", "futures"] diff --git a/actix-service/src/apply_cfg.rs b/actix-service/src/apply_cfg.rs index 7924e716..66137eee 100644 --- a/actix-service/src/apply_cfg.rs +++ b/actix-service/src/apply_cfg.rs @@ -7,7 +7,17 @@ use crate::cell::Cell; use crate::{IntoService, NewService, Service}; /// Convert `Fn(&Config, &mut Service) -> Future` fn to a NewService -pub fn apply_cfg(srv: T, f: F) -> ApplyConfigService +pub fn apply_cfg( + srv: T, + f: F, +) -> impl NewService< + Config = C, + Request = S::Request, + Response = S::Response, + Error = S::Error, + Service = S, + InitError = R::Error, +> + Clone where F: FnMut(&C, &mut T) -> R, T: Service, @@ -22,8 +32,36 @@ where } } +/// Convert `Fn(&Config, &mut Service) -> Future` fn to a NewService +/// Service get constructor from NewService. +pub fn new_apply_cfg( + srv: T, + f: F, +) -> impl NewService< + Config = C, + Request = S::Request, + Response = S::Response, + Error = S::Error, + Service = S, + InitError = T::InitError, +> + Clone +where + C: Clone, + F: FnMut(&C, &mut T::Service) -> R, + T: NewService, + R: IntoFuture, + R::Item: IntoService, + S: Service, +{ + ApplyConfigNewService { + f: Cell::new(f), + srv: Cell::new(srv), + _t: PhantomData, + } +} + /// Convert `Fn(&Config) -> Future` fn to NewService -pub struct ApplyConfigService +struct ApplyConfigService where F: FnMut(&C, &mut T) -> R, T: Service, @@ -79,7 +117,7 @@ where } } -pub struct FnNewServiceConfigFut +struct FnNewServiceConfigFut where R: IntoFuture, R::Item: IntoService, @@ -102,3 +140,113 @@ where Ok(Async::Ready(try_ready!(self.fut.poll()).into_service())) } } + +/// Convert `Fn(&Config) -> Future` fn to NewService +struct ApplyConfigNewService +where + C: Clone, + F: FnMut(&C, &mut T::Service) -> R, + T: NewService, + R: IntoFuture, + R::Item: IntoService, + S: Service, +{ + f: Cell, + srv: Cell, + _t: PhantomData<(C, R, S)>, +} + +impl Clone for ApplyConfigNewService +where + C: Clone, + F: FnMut(&C, &mut T::Service) -> R, + T: NewService, + R: IntoFuture, + R::Item: IntoService, + S: Service, +{ + fn clone(&self) -> Self { + ApplyConfigNewService { + f: self.f.clone(), + srv: self.srv.clone(), + _t: PhantomData, + } + } +} + +impl NewService for ApplyConfigNewService +where + C: Clone, + F: FnMut(&C, &mut T::Service) -> R, + T: NewService, + R: IntoFuture, + R::Item: IntoService, + S: Service, +{ + type Config = C; + type Request = S::Request; + type Response = S::Response; + type Error = S::Error; + type Service = S; + + type InitError = R::Error; + type Future = ApplyConfigNewServiceFut; + + fn new_service(&self, cfg: &C) -> Self::Future { + ApplyConfigNewServiceFut { + f: self.f.clone(), + cfg: cfg.clone(), + srv: Some(self.srv.get_ref().new_service(&())), + fut: None, + _t: PhantomData, + } + } +} + +struct ApplyConfigNewServiceFut +where + C: Clone, + F: FnMut(&C, &mut T::Service) -> R, + T: NewService, + R: IntoFuture, + R::Item: IntoService, + S: Service, +{ + cfg: C, + f: Cell, + srv: Option, + fut: Option, + _t: PhantomData<(S,)>, +} + +impl Future for ApplyConfigNewServiceFut +where + C: Clone, + F: FnMut(&C, &mut T::Service) -> R, + T: NewService, + R: IntoFuture, + R::Item: IntoService, + S: Service, +{ + type Item = S; + type Error = R::Error; + + fn poll(&mut self) -> Poll { + if let Some(ref mut fut) = self.srv { + match fut.poll()? { + Async::NotReady => return Ok(Async::NotReady), + Async::Ready(mut srv) => { + let _ = self.srv.take(); + self.fut = Some(self.f.get_mut()(&self.cfg, &mut srv).into_future()); + return self.poll(); + } + } + } + + if let Some(ref mut fut) = self.fut { + Ok(Async::Ready(try_ready!(fut.poll()).into_service())) + } else { + Ok(Async::NotReady) + } + } +} diff --git a/actix-service/src/cell.rs b/actix-service/src/cell.rs index 33ecb97f..0dddefcc 100644 --- a/actix-service/src/cell.rs +++ b/actix-service/src/cell.rs @@ -26,6 +26,10 @@ impl Cell { } } + pub(crate) fn get_ref(&self) -> &T { + unsafe { &*self.inner.as_ref().get() } + } + pub(crate) fn get_mut(&mut self) -> &mut T { unsafe { &mut *self.inner.as_ref().get() } } diff --git a/actix-service/src/lib.rs b/actix-service/src/lib.rs index a973cc51..82e26677 100644 --- a/actix-service/src/lib.rs +++ b/actix-service/src/lib.rs @@ -25,7 +25,7 @@ mod transform_err; pub use self::and_then::{AndThen, AndThenNewService}; pub use self::apply::{apply_fn, new_apply_fn, Apply, ApplyNewService}; -pub use self::apply_cfg::apply_cfg; +pub use self::apply_cfg::{apply_cfg, new_apply_cfg}; pub use self::fn_service::{new_service_cfg, new_service_fn, service_fn, ServiceFn}; pub use self::fn_transform::transform_fn; pub use self::from_err::{FromErr, FromErrNewService};