diff --git a/src/connector.rs b/src/connector.rs index 27a2976a3..6458f803e 100644 --- a/src/connector.rs +++ b/src/connector.rs @@ -91,7 +91,7 @@ impl Connector { InitError = E, > + Clone { move || -> FutureResult, E> { - ok(Connector::new(cfg.clone(), opts.clone())) + ok(Connector::new(cfg.clone(), opts)) } } } diff --git a/src/service/apply.rs b/src/service/apply.rs new file mode 100644 index 000000000..15e31020b --- /dev/null +++ b/src/service/apply.rs @@ -0,0 +1,171 @@ +use std::marker::PhantomData; + +use futures::{Async, Future, Poll}; +use {NewService, Service}; + +/// `Apply` service combinator +pub struct Apply { + service: T, + f: F, + r: PhantomData, + r1: PhantomData, + r2: PhantomData, + e: PhantomData, +} + +impl Apply +where + T: Service, + F: Fn(Req, &mut T) -> R, + R: Future, +{ + /// Create new `Apply` combinator + pub fn new(f: F, service: T) -> Self { + Self { + service, + f, + r: PhantomData, + r1: PhantomData, + r2: PhantomData, + e: PhantomData, + } + } +} + +impl Service for Apply +where + T: Service, + T::Error: Into, + F: Fn(Req, &mut T) -> R, + R: Future, +{ + type Request = Req; + type Response = Resp; + type Error = Err; + type Future = R; + + fn poll_ready(&mut self) -> Poll<(), Self::Error> { + self.service.poll_ready().map_err(|e| e.into()) + } + + fn call(&mut self, req: Self::Request) -> Self::Future { + (self.f)(req, &mut self.service) + } +} + +/// `ApplyNewService` new service combinator +pub struct ApplyNewService { + service: T, + f: F, + r: PhantomData, + r1: PhantomData, + r2: PhantomData, + e: PhantomData, +} + +impl ApplyNewService +where + T: NewService, + F: Fn(Req, &mut T::Service) -> R, + R: Future, +{ + /// Create new `Partial` new service instance + pub fn new(f: F, service: T) -> Self { + Self { + service, + f, + r: PhantomData, + r1: PhantomData, + r2: PhantomData, + e: PhantomData, + } + } +} + +impl Clone for ApplyNewService +where + T: NewService + Clone, + F: Fn(Req, &mut T::Service) -> R + Clone, + R: Future, +{ + fn clone(&self) -> Self { + Self { + service: self.service.clone(), + f: self.f.clone(), + r: PhantomData, + r1: PhantomData, + r2: PhantomData, + e: PhantomData, + } + } +} + +impl NewService for ApplyNewService +where + T: NewService, + T::Error: Into, + F: Fn(Req, &mut T::Service) -> R + Clone, + R: Future, +{ + type Request = Req; + type Response = Resp; + type Error = Err; + type Service = Apply; + + type InitError = T::InitError; + type Future = ApplyNewServiceFuture; + + fn new_service(&self) -> Self::Future { + ApplyNewServiceFuture::new(self.service.new_service(), self.f.clone()) + } +} + +pub struct ApplyNewServiceFuture +where + T: NewService, + F: Fn(Req, &mut T::Service) -> R, + R: Future, +{ + fut: T::Future, + f: Option, + r: PhantomData, + r1: PhantomData, + r2: PhantomData, + e: PhantomData, +} + +impl ApplyNewServiceFuture +where + T: NewService, + F: Fn(Req, &mut T::Service) -> R, + R: Future, +{ + fn new(fut: T::Future, f: F) -> Self { + ApplyNewServiceFuture { + f: Some(f), + fut, + r: PhantomData, + r1: PhantomData, + r2: PhantomData, + e: PhantomData, + } + } +} + +impl Future for ApplyNewServiceFuture +where + T: NewService, + F: Fn(Req, &mut T::Service) -> R, + R: Future, +{ + type Item = Apply; + type Error = T::InitError; + + fn poll(&mut self) -> Poll { + if let Async::Ready(service) = self.fut.poll()? { + Ok(Async::Ready(Apply::new(self.f.take().unwrap(), service))) + } else { + Ok(Async::NotReady) + } + } +} diff --git a/src/service/mod.rs b/src/service/mod.rs index f85dc600b..2fdca0a61 100644 --- a/src/service/mod.rs +++ b/src/service/mod.rs @@ -1,23 +1,23 @@ -use futures::IntoFuture; -use tower_service::{NewService, Service}; +use futures::{Future, IntoFuture}; mod and_then; +mod apply; mod fn_service; mod fn_state_service; mod map; mod map_err; mod map_init_err; mod map_request; -mod partial; pub use self::and_then::{AndThen, AndThenNewService}; +pub use self::apply::{Apply, ApplyNewService}; pub use self::fn_service::{FnNewService, FnService}; pub use self::fn_state_service::{FnStateNewService, FnStateService}; pub use self::map::{Map, MapNewService}; pub use self::map_err::{MapErr, MapErrNewService}; pub use self::map_init_err::MapInitErr; pub use self::map_request::{MapReq, MapReqNewService}; -pub use self::partial::{Partial, PartialNewService}; +use {NewService, Service}; pub trait ServiceExt: Service { fn and_then(self, new_service: F) -> AndThen @@ -47,6 +47,18 @@ pub trait ServiceExt: Service { } pub trait NewServiceExt: NewService { + fn apply( + f: F, service: F2, + ) -> ApplyNewService + where + T: NewService, + F: Fn(Req, &mut T::Service) -> R + Clone, + R: Future, + F2: IntoNewService, + { + ApplyNewService::new(f, service.into_new_service()) + } + fn and_then(self, new_service: F) -> AndThenNewService where Self: Sized, @@ -91,14 +103,6 @@ pub trait NewServiceExt: NewService { { MapInitErr::new(self, f) } - - fn partial(self, f: F) -> PartialNewService - where - Self: Sized, - F: Fn(Req) -> (Self::Request, Resp), - { - PartialNewService::new(self, f) - } } impl ServiceExt for T {} diff --git a/src/service/partial.rs b/src/service/partial.rs deleted file mode 100644 index a0bdf2bf6..000000000 --- a/src/service/partial.rs +++ /dev/null @@ -1,183 +0,0 @@ -use std::marker::PhantomData; - -use futures::{Async, Future, Poll}; -use {NewService, Service}; - -/// `Partial` service combinator -pub struct Partial { - a: A, - f: F, - r1: PhantomData, - r2: PhantomData, -} - -impl Partial -where - A: Service, - F: Fn(Req) -> (A::Request, Resp), -{ - /// Create new `Partial` combinator - pub fn new(a: A, f: F) -> Self { - Self { - a, - f, - r1: PhantomData, - r2: PhantomData, - } - } -} - -impl Service for Partial -where - A: Service, - F: Fn(Req) -> (A::Request, Resp), -{ - type Request = Req; - type Response = (A::Response, Resp); - type Error = A::Error; - type Future = PartialFuture; - - fn poll_ready(&mut self) -> Poll<(), Self::Error> { - self.a.poll_ready() - } - - fn call(&mut self, req: Self::Request) -> Self::Future { - let (req, resp) = (self.f)(req); - PartialFuture::new(self.a.call(req), resp) - } -} - -pub struct PartialFuture -where - A: Service, -{ - fut: A::Future, - resp: Option, -} - -impl PartialFuture -where - A: Service, -{ - fn new(fut: A::Future, resp: Resp) -> Self { - PartialFuture { - fut, - resp: Some(resp), - } - } -} - -impl Future for PartialFuture -where - A: Service, -{ - type Item = (A::Response, Resp); - type Error = A::Error; - - fn poll(&mut self) -> Poll { - match self.fut.poll()? { - Async::Ready(resp) => Ok(Async::Ready((resp, self.resp.take().unwrap()))), - Async::NotReady => Ok(Async::NotReady), - } - } -} - -/// `PartialNewService` new service combinator -pub struct PartialNewService { - a: A, - f: F, - r1: PhantomData, - r2: PhantomData, -} - -impl PartialNewService -where - A: NewService, - F: Fn(Req) -> (A::Request, Resp), -{ - /// Create new `Partial` new service instance - pub fn new(a: A, f: F) -> Self { - Self { - a, - f, - r1: PhantomData, - r2: PhantomData, - } - } -} - -impl Clone for PartialNewService -where - A: NewService + Clone, - F: Fn(Req) -> (A::Request, Resp) + Clone, -{ - fn clone(&self) -> Self { - Self { - a: self.a.clone(), - f: self.f.clone(), - r1: PhantomData, - r2: PhantomData, - } - } -} - -impl NewService for PartialNewService -where - A: NewService, - F: Fn(Req) -> (A::Request, Resp) + Clone, -{ - type Request = Req; - type Response = (A::Response, Resp); - type Error = A::Error; - type Service = Partial; - - type InitError = A::InitError; - type Future = PartialNewServiceFuture; - - fn new_service(&self) -> Self::Future { - PartialNewServiceFuture::new(self.a.new_service(), self.f.clone()) - } -} - -pub struct PartialNewServiceFuture -where - A: NewService, - F: Fn(Req) -> (A::Request, Resp), -{ - fut: A::Future, - f: Option, - r1: PhantomData, - r2: PhantomData, -} - -impl PartialNewServiceFuture -where - A: NewService, - F: Fn(Req) -> (A::Request, Resp), -{ - fn new(fut: A::Future, f: F) -> Self { - PartialNewServiceFuture { - f: Some(f), - fut, - r1: PhantomData, - r2: PhantomData, - } - } -} - -impl Future for PartialNewServiceFuture -where - A: NewService, - F: Fn(Req) -> (A::Request, Resp), -{ - type Item = Partial; - type Error = A::InitError; - - fn poll(&mut self) -> Poll { - if let Async::Ready(service) = self.fut.poll()? { - Ok(Async::Ready(Partial::new(service, self.f.take().unwrap()))) - } else { - Ok(Async::NotReady) - } - } -}