From ef9bfb8981a5a51b03a7a2c704b192dc560f0457 Mon Sep 17 00:00:00 2001 From: Nikolay Kim Date: Tue, 12 Mar 2019 12:53:08 -0700 Subject: [PATCH] add helpers --- actix-service/CHANGES.md | 11 ++ actix-service/src/apply.rs | 28 ++++ actix-service/src/fn_transform.rs | 13 ++ actix-service/src/lib.rs | 21 ++- actix-service/src/transform.rs | 108 ++++++++++--- actix-service/src/transform_err.rs | 162 ++++++++++++++++++++ actix-service/src/transform_map_init_err.rs | 94 ------------ 7 files changed, 314 insertions(+), 123 deletions(-) create mode 100644 actix-service/src/transform_err.rs delete mode 100644 actix-service/src/transform_map_init_err.rs diff --git a/actix-service/CHANGES.md b/actix-service/CHANGES.md index 3cf8fc4c..e8f3df6c 100644 --- a/actix-service/CHANGES.md +++ b/actix-service/CHANGES.md @@ -1,5 +1,16 @@ # Changes +## [0.3.4] - 2019-03-12 + +### Added + +* Add `Transform::from_err()` combinator + +* Add `apply_fn` and `apply_fn_factory` helpers + +* Add `apply_transform` helper + + ## [0.3.3] - 2019-03-09 ### Added diff --git a/actix-service/src/apply.rs b/actix-service/src/apply.rs index d5dda2d4..9719e087 100644 --- a/actix-service/src/apply.rs +++ b/actix-service/src/apply.rs @@ -4,6 +4,34 @@ use futures::{Async, Future, IntoFuture, Poll}; use super::{IntoNewService, IntoService, NewService, Service}; +/// Apply tranform function to a service +pub fn apply_fn(service: U, f: F) -> Apply +where + T: Service, + F: FnMut(In, &mut T) -> Out, + Out: IntoFuture, + Out::Error: From, + U: IntoService, +{ + Apply::new(service.into_service(), f) +} + +/// Create fractory for `apply_fn` service. +pub fn apply_fn_factory( + service: U, + f: F, +) -> ApplyNewService +where + T: NewService, + F: FnMut(In, &mut T::Service) -> Out + Clone, + Out: IntoFuture, + Out::Error: From, + U: IntoNewService, +{ + ApplyNewService::new(service.into_new_service(), f) +} + +#[doc(hidden)] /// `Apply` service combinator pub struct Apply where diff --git a/actix-service/src/fn_transform.rs b/actix-service/src/fn_transform.rs index 7c3773ba..f7d708f7 100644 --- a/actix-service/src/fn_transform.rs +++ b/actix-service/src/fn_transform.rs @@ -5,6 +5,19 @@ use futures::IntoFuture; use crate::{Apply, IntoTransform, Service, Transform}; +/// Use function as transform service +pub fn fn_transform( + f: F, +) -> impl Transform +where + S: Service, + F: FnMut(In, &mut S) -> Out + Clone, + Out: IntoFuture, + Out::Error: From, +{ + FnTransform::new(f) +} + pub struct FnTransform where F: FnMut(In, &mut S) -> Out + Clone, diff --git a/actix-service/src/lib.rs b/actix-service/src/lib.rs index 4e46da7b..38e220af 100644 --- a/actix-service/src/lib.rs +++ b/actix-service/src/lib.rs @@ -21,21 +21,34 @@ mod map_err; mod map_init_err; mod then; mod transform; -mod transform_map_init_err; +mod transform_err; + +#[doc(hidden)] +#[deprecated(since = "0.3.4", note = "please use `apply_fn` instead")] +pub use self::apply::Apply; +#[doc(hidden)] +#[deprecated(since = "0.3.4", note = "please use `apply_fn_factory` instead")] +pub use self::apply::ApplyNewService; +#[doc(hidden)] +#[deprecated(since = "0.3.4", note = "please use `fn_transform` instead")] +pub use self::fn_transform::FnTransform; +#[doc(hidden)] +#[deprecated(since = "0.3.4", note = "please use `apply_transform` instead")] +pub use self::transform::ApplyTransform; pub use self::and_then::{AndThen, AndThenNewService}; use self::and_then_apply::AndThenTransform; use self::and_then_apply_fn::{AndThenApply, AndThenApplyNewService}; -pub use self::apply::{Apply, ApplyNewService}; +pub use self::apply::{apply_fn, apply_fn_factory}; pub use self::apply_cfg::ApplyConfig; pub use self::fn_service::{fn_cfg_factory, fn_factory, fn_service, FnService}; -pub use self::fn_transform::FnTransform; +pub use self::fn_transform::fn_transform; pub use self::from_err::{FromErr, FromErrNewService}; 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::{ApplyTransform, IntoTransform, Transform}; +pub use self::transform::{apply_transform, 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 3e8a693e..b511b67a 100644 --- a/actix-service/src/transform.rs +++ b/actix-service/src/transform.rs @@ -3,8 +3,8 @@ use std::sync::Arc; use futures::{Async, Future, IntoFuture, Poll}; -use crate::transform_map_init_err::TransformMapInitErr; -use crate::{NewService, Service}; +use crate::transform_err::{TransformFromErr, TransformMapInitErr}; +use crate::{IntoNewService, NewService, Service}; /// `Transform` service factory. /// @@ -36,7 +36,7 @@ pub trait Transform { /// Create and return a new service value asynchronously. fn new_transform(&self, service: S) -> Self::Future; - /// Map this service's factory init error to a different error, + /// Map this service's factory error to a different error, /// returning a new transform service factory. fn map_init_err(self, f: F) -> TransformMapInitErr where @@ -45,6 +45,32 @@ pub trait Transform { { TransformMapInitErr::new(self, f) } + + /// Map this service's init error to any error implementing `From` for + /// this service`s `Error`. + /// + /// Note that this function consumes the receiving transform and returns a + /// wrapped version of it. + fn from_err(self) -> TransformFromErr + where + Self: Sized, + E: From, + { + TransformFromErr::new(self) + } + + // /// Map this service's init error to service's init error + // /// if it is implementing `Into` to this service`s `InitError`. + // /// + // /// Note that this function consumes the receiving transform and returns a + // /// wrapped version of it. + // fn into_err(self) -> TransformIntoErr + // where + // Self: Sized, + // Self::InitError: From, + // { + // TransformFromErr::new(self) + // } } impl Transform for Rc @@ -97,33 +123,65 @@ where } } -/// `Apply` transform new service -#[derive(Clone)] -pub struct ApplyTransform { - a: A, +/// Apply transform to service factory. Function returns +/// services factory that in initialization creates +/// service and applies transform to this service. +pub fn apply_transform( + t: F, + service: U, +) -> impl NewService< + C, + Request = T::Request, + Response = T::Response, + Error = T::Error, + Service = T::Transform, + InitError = S::InitError, +> + Clone +where + S: NewService, + T: Transform, + F: IntoTransform, + U: IntoNewService, +{ + ApplyTransform::new(t.into_transform(), service.into_new_service()) +} + +/// `Apply` transform to new service +pub struct ApplyTransform { + s: Rc, t: Rc, _t: std::marker::PhantomData, } -impl ApplyTransform +impl ApplyTransform where - A: NewService, - T: Transform, + S: NewService, + T: Transform, { - /// Create new `ApplyNewService` new service instance - pub fn new>(t: F, a: A) -> Self { + /// Create new `ApplyTransform` new service instance + pub fn new>(t: F, service: S) -> Self { Self { - a, + s: Rc::new(service), t: Rc::new(t.into_transform()), _t: std::marker::PhantomData, } } } -impl NewService for ApplyTransform +impl Clone for ApplyTransform { + fn clone(&self) -> Self { + ApplyTransform { + s: self.s.clone(), + t: self.t.clone(), + _t: std::marker::PhantomData, + } + } +} + +impl NewService for ApplyTransform where - A: NewService, - T: Transform, + S: NewService, + T: Transform, { type Request = T::Request; type Response = T::Response; @@ -131,31 +189,31 @@ where type Service = T::Transform; type InitError = T::InitError; - type Future = ApplyTransformFuture; + 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_a: self.s.new_service(cfg).into_future(), fut_t: None, } } } -pub struct ApplyTransformFuture +pub struct ApplyTransformFuture where - A: NewService, - T: Transform, + S: NewService, + T: Transform, { - fut_a: A::Future, + fut_a: S::Future, fut_t: Option<::Future>, t_cell: Rc, } -impl Future for ApplyTransformFuture +impl Future for ApplyTransformFuture where - A: NewService, - T: Transform, + S: NewService, + T: Transform, { type Item = T::Transform; type Error = T::InitError; diff --git a/actix-service/src/transform_err.rs b/actix-service/src/transform_err.rs new file mode 100644 index 00000000..dcc3c245 --- /dev/null +++ b/actix-service/src/transform_err.rs @@ -0,0 +1,162 @@ +use std::marker::PhantomData; + +use futures::{Future, Poll}; + +use super::Transform; + +/// Transform for the `map_err` combinator, changing the type of a new +/// transform's init error. +/// +/// This is created by the `Transform::map_err` method. +pub struct TransformMapInitErr { + t: T, + f: F, + e: PhantomData<(S, E)>, +} + +impl TransformMapInitErr { + /// Create new `TransformMapErr` new transform instance + pub fn new(t: T, f: F) -> Self + where + T: Transform, + F: Fn(T::InitError) -> E, + { + Self { + t, + f, + e: PhantomData, + } + } +} + +impl Clone for TransformMapInitErr +where + T: Clone, + F: Clone, +{ + fn clone(&self) -> Self { + Self { + t: self.t.clone(), + f: self.f.clone(), + e: PhantomData, + } + } +} + +impl Transform for TransformMapInitErr +where + T: Transform, + F: Fn(T::InitError) -> E + Clone, +{ + type Request = T::Request; + type Response = T::Response; + type Error = T::Error; + type Transform = T::Transform; + + type InitError = E; + type Future = TransformMapInitErrFuture; + + fn new_transform(&self, service: S) -> Self::Future { + TransformMapInitErrFuture { + fut: self.t.new_transform(service), + f: self.f.clone(), + } + } +} + +pub struct TransformMapInitErrFuture +where + T: Transform, + F: Fn(T::InitError) -> E, +{ + fut: T::Future, + f: F, +} + +impl Future for TransformMapInitErrFuture +where + T: Transform, + F: Fn(T::InitError) -> E + Clone, +{ + type Item = T::Transform; + type Error = E; + + fn poll(&mut self) -> Poll { + self.fut.poll().map_err(&self.f) + } +} + +/// Transform for the `from_err` combinator, changing the type of a new +/// transform's init error. +/// +/// This is created by the `Transform::from_err` method. +pub struct TransformFromErr { + t: T, + e: PhantomData<(S, E)>, +} + +impl TransformFromErr +where + T: Transform, + E: From, +{ + /// Create new `TransformFromErr` new transform instance + pub fn new(t: T) -> Self { + Self { t, e: PhantomData } + } +} + +impl Clone for TransformFromErr +where + T: Clone, +{ + fn clone(&self) -> Self { + Self { + t: self.t.clone(), + e: PhantomData, + } + } +} + +impl Transform for TransformFromErr +where + T: Transform, + E: From, +{ + type Request = T::Request; + type Response = T::Response; + type Error = T::Error; + type Transform = T::Transform; + + type InitError = E; + type Future = TransformFromErrFuture; + + fn new_transform(&self, service: S) -> Self::Future { + TransformFromErrFuture { + fut: self.t.new_transform(service), + _t: PhantomData, + } + } +} + +pub struct TransformFromErrFuture +where + T: Transform, + E: From, +{ + fut: T::Future, + _t: PhantomData, +} + +impl Future for TransformFromErrFuture +where + T: Transform, + E: From, +{ + type Item = T::Transform; + type Error = E; + + fn poll(&mut self) -> Poll { + self.fut.poll().map_err(E::from) + } +} diff --git a/actix-service/src/transform_map_init_err.rs b/actix-service/src/transform_map_init_err.rs deleted file mode 100644 index 0b0dd9b9..00000000 --- a/actix-service/src/transform_map_init_err.rs +++ /dev/null @@ -1,94 +0,0 @@ -use std::marker::PhantomData; - -use futures::{Future, Poll}; - -use super::Transform; - -/// NewTransform for the `map_init_err` combinator, changing the type of a new -/// transform's error. -/// -/// This is created by the `NewTransform::map_init_err` method. -pub struct TransformMapInitErr { - t: T, - f: F, - e: PhantomData<(S, E)>, -} - -impl TransformMapInitErr { - /// Create new `MapInitErr` new transform instance - pub fn new(t: T, f: F) -> Self - where - T: Transform, - F: Fn(T::InitError) -> E, - { - Self { - t, - f, - e: PhantomData, - } - } -} - -impl Clone for TransformMapInitErr -where - T: Clone, - F: Clone, -{ - fn clone(&self) -> Self { - Self { - t: self.t.clone(), - f: self.f.clone(), - e: PhantomData, - } - } -} - -impl Transform for TransformMapInitErr -where - T: Transform, - F: Fn(T::InitError) -> E + Clone, -{ - type Request = T::Request; - type Response = T::Response; - type Error = T::Error; - type Transform = T::Transform; - - type InitError = E; - type Future = TransformMapInitErrFuture; - - fn new_transform(&self, service: S) -> Self::Future { - TransformMapInitErrFuture::new(self.t.new_transform(service), self.f.clone()) - } -} - -pub struct TransformMapInitErrFuture -where - T: Transform, - F: Fn(T::InitError) -> E, -{ - fut: T::Future, - f: F, -} - -impl TransformMapInitErrFuture -where - T: Transform, - F: Fn(T::InitError) -> E, -{ - fn new(fut: T::Future, f: F) -> Self { - TransformMapInitErrFuture { f, fut } - } -} - -impl Future for TransformMapInitErrFuture -where - T: Transform, - F: Fn(T::InitError) -> E + Clone, -{ - type Item = T::Transform; - type Error = E; - - fn poll(&mut self) -> Poll { - self.fut.poll().map_err(&self.f) - } -}