diff --git a/actix-service/CHANGES.md b/actix-service/CHANGES.md index 57f37154..f28218e6 100644 --- a/actix-service/CHANGES.md +++ b/actix-service/CHANGES.md @@ -1,5 +1,12 @@ # Changes +## [0.3.2] - 2019-03-xx + +### Added + +* Add `ApplyTransform` new service for transform and new service. + + ## [0.3.2] - 2019-03-04 ### Changed diff --git a/actix-service/src/lib.rs b/actix-service/src/lib.rs index 7c14cf0a..4b58c231 100644 --- a/actix-service/src/lib.rs +++ b/actix-service/src/lib.rs @@ -23,7 +23,7 @@ mod transform; mod transform_map_init_err; pub use self::and_then::{AndThen, AndThenNewService}; -pub use self::and_then_apply::AndThenTransform; +use self::and_then_apply::AndThenTransform; use self::and_then_apply_fn::{AndThenApply, AndThenApplyNewService}; pub use self::apply::{Apply, ApplyNewService}; pub use self::fn_service::{fn_cfg_factory, fn_factory, fn_service, FnService}; @@ -33,7 +33,7 @@ pub use self::map::{Map, MapNewService}; pub use self::map_err::{MapErr, MapErrNewService}; pub use self::map_init_err::MapInitErr; pub use self::then::{Then, ThenNewService}; -pub use self::transform::{IntoTransform, Transform}; +pub use self::transform::{ApplyTransform, IntoTransform, Transform}; /// An asynchronous function from `Request` to a `Response`. pub trait Service { diff --git a/actix-service/src/transform.rs b/actix-service/src/transform.rs index 7e5ba920..741d91a6 100644 --- a/actix-service/src/transform.rs +++ b/actix-service/src/transform.rs @@ -1,10 +1,10 @@ use std::rc::Rc; use std::sync::Arc; -use futures::IntoFuture; +use futures::{Async, Future, IntoFuture, Poll}; use crate::transform_map_init_err::TransformMapInitErr; -use crate::Service; +use crate::{NewService, Service}; /// `Transform` service factory. /// @@ -96,3 +96,80 @@ where self } } + +/// `Apply` transform new service +#[derive(Clone)] +pub struct ApplyTransform { + a: A, + t: Rc, + _t: std::marker::PhantomData, +} + +impl ApplyTransform +where + A: NewService, + T: Transform, +{ + /// Create new `ApplyNewService` new service instance + pub fn new>(t: F, a: A) -> Self { + Self { + a, + t: Rc::new(t.into_transform()), + _t: std::marker::PhantomData, + } + } +} + +impl NewService for ApplyTransform +where + A: NewService, + T: Transform, +{ + type Request = T::Request; + type Response = T::Response; + type Error = T::Error; + + type Service = T::Transform; + type InitError = T::InitError; + type Future = ApplyTransformFuture; + + fn new_service(&self, cfg: &C) -> Self::Future { + ApplyTransformFuture { + t_cell: self.t.clone(), + fut_a: self.a.new_service(cfg).into_future(), + fut_t: None, + } + } +} + +pub struct ApplyTransformFuture +where + A: NewService, + T: Transform, +{ + fut_a: ::Future, + fut_t: Option<::Future>, + t_cell: Rc, +} + +impl Future for ApplyTransformFuture +where + A: NewService, + T: Transform, +{ + type Item = T::Transform; + type Error = T::InitError; + + fn poll(&mut self) -> Poll { + if self.fut_t.is_none() { + if let Async::Ready(service) = self.fut_a.poll()? { + self.fut_t = Some(self.t_cell.new_transform(service).into_future()); + } + } + if let Some(ref mut fut) = self.fut_t { + fut.poll() + } else { + Ok(Async::NotReady) + } + } +}