From db0bc1e156ea0c83a2147c531deb6e9beebbf879 Mon Sep 17 00:00:00 2001 From: Nikolay Kim Date: Tue, 3 Dec 2019 18:32:02 +0600 Subject: [PATCH] Restore Transform::map_init_err() combinator --- actix-service/CHANGES.md | 3 + actix-service/src/and_then.rs | 16 ++++- actix-service/src/apply.rs | 2 + actix-service/src/lib.rs | 2 + actix-service/src/transform.rs | 11 ++++ actix-service/src/transform_err.rs | 94 ++++++++++++++++++++++++++++++ 6 files changed, 126 insertions(+), 2 deletions(-) create mode 100644 actix-service/src/transform_err.rs diff --git a/actix-service/CHANGES.md b/actix-service/CHANGES.md index ca18613d..0c85bd13 100644 --- a/actix-service/CHANGES.md +++ b/actix-service/CHANGES.md @@ -4,6 +4,9 @@ ### Add missing Clone impls +### Restore `Transform::map_init_err()` combinator + + ## [1.0.0-alpha.2] - 2019-12-02 ### Use owned config value for service factory diff --git a/actix-service/src/and_then.rs b/actix-service/src/and_then.rs index 6f631b96..14bfcac7 100644 --- a/actix-service/src/and_then.rs +++ b/actix-service/src/and_then.rs @@ -126,7 +126,13 @@ where pub struct AndThenServiceFactory where A: ServiceFactory, - B: ServiceFactory, + A::Config: Clone, + B: ServiceFactory< + Config = A::Config, + Request = A::Response, + Error = A::Error, + InitError = A::InitError, + >, { a: A, b: B, @@ -180,7 +186,13 @@ where impl Clone for AndThenServiceFactory where A: ServiceFactory + Clone, - B: ServiceFactory + Clone, + A::Config: Clone, + B: ServiceFactory< + Config = A::Config, + Request = A::Response, + Error = A::Error, + InitError = A::InitError, + > + Clone, { fn clone(&self) -> Self { Self { diff --git a/actix-service/src/apply.rs b/actix-service/src/apply.rs index 5fb984d4..ae498160 100644 --- a/actix-service/src/apply.rs +++ b/actix-service/src/apply.rs @@ -80,6 +80,8 @@ where pub struct ApplyServiceFactory where T: ServiceFactory, + F: FnMut(In, &mut T::Service) -> R + Clone, + R: Future>, { service: T, f: F, diff --git a/actix-service/src/lib.rs b/actix-service/src/lib.rs index d3138d62..f0cd60e3 100644 --- a/actix-service/src/lib.rs +++ b/actix-service/src/lib.rs @@ -23,6 +23,7 @@ mod map_init_err; mod pipeline; mod then; mod transform; +mod transform_err; pub use self::apply::{apply_fn, apply_fn_factory}; pub use self::apply_cfg::{apply_cfg, apply_cfg_factory}; @@ -323,4 +324,5 @@ pub mod dev { pub use crate::map_init_err::MapInitErr; pub use crate::then::{ThenService, ThenServiceFactory}; pub use crate::transform::ApplyTransform; + pub use crate::transform_err::TransformMapInitErr; } diff --git a/actix-service/src/transform.rs b/actix-service/src/transform.rs index f1e4ee41..08d325d1 100644 --- a/actix-service/src/transform.rs +++ b/actix-service/src/transform.rs @@ -4,6 +4,7 @@ use std::rc::Rc; use std::sync::Arc; use std::task::{Context, Poll}; +use crate::transform_err::TransformMapInitErr; use crate::{IntoServiceFactory, Service, ServiceFactory}; /// Apply transform to a service. Function returns @@ -48,6 +49,16 @@ pub trait Transform { /// Creates and returns a new Service component, asynchronously fn new_transform(&self, service: S) -> Self::Future; + + /// Map this transforms's factory error to a different error, + /// returning a new transform service factory. + fn map_init_err(self, f: F) -> TransformMapInitErr + where + Self: Sized, + F: Fn(Self::InitError) -> E + Clone, + { + TransformMapInitErr::new(self, f) + } } impl Transform for Rc diff --git a/actix-service/src/transform_err.rs b/actix-service/src/transform_err.rs new file mode 100644 index 00000000..c3a71ab6 --- /dev/null +++ b/actix-service/src/transform_err.rs @@ -0,0 +1,94 @@ +use std::future::Future; +use std::marker::PhantomData; +use std::pin::Pin; +use std::task::{Context, Poll}; + +use super::Transform; + +/// Transform for the `map_init_err` combinator, changing the type of a new +/// transform's init error. +/// +/// This is created by the `Transform::map_init_err` method. +pub struct TransformMapInitErr { + t: T, + f: F, + e: PhantomData<(S, E)>, +} + +impl TransformMapInitErr { + pub(crate) 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(), + } + } +} + +pin_project! { + pub struct TransformMapInitErrFuture + where + T: Transform, + F: Fn(T::InitError) -> E, + { + #[pin] + fut: T::Future, + f: F, + } +} + +impl Future for TransformMapInitErrFuture +where + T: Transform, + F: Fn(T::InitError) -> E + Clone, +{ + type Output = Result; + + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + let this = self.project(); + if let Poll::Ready(res) = this.fut.poll(cx) { + Poll::Ready(res.map_err(this.f)) + } else { + Poll::Pending + } + } +}