diff --git a/src/connector.rs b/src/connector.rs index d6e9a9c6..27a2976a 100644 --- a/src/connector.rs +++ b/src/connector.rs @@ -46,7 +46,7 @@ pub struct ConnectionInfo { pub addr: SocketAddr, } -pub struct Connector { +pub struct Connector { resolver: AsyncResolver, req: PhantomData, } diff --git a/src/service/map.rs b/src/service/map.rs index 865b2e23..ac2cb480 100644 --- a/src/service/map.rs +++ b/src/service/map.rs @@ -1,7 +1,7 @@ use std::marker; use futures::{Async, Future, Poll}; -use tower_service::{NewService, Service}; +use {NewService, Service}; /// `Map` service combinator pub struct Map { diff --git a/src/service/mod.rs b/src/service/mod.rs index 553f35e8..8c4e3666 100644 --- a/src/service/mod.rs +++ b/src/service/mod.rs @@ -7,6 +7,7 @@ mod fn_state_service; mod map; mod map_err; mod map_init_err; +mod partial; pub use self::and_then::{AndThen, AndThenNewService}; pub use self::fn_service::{FnNewService, FnService}; @@ -14,6 +15,7 @@ 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::partial::{Partial, PartialNewService}; pub trait ServiceExt: Service { fn and_then(self, new_service: F) -> AndThen @@ -79,6 +81,14 @@ 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 new file mode 100644 index 00000000..a0bdf2bf --- /dev/null +++ b/src/service/partial.rs @@ -0,0 +1,183 @@ +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) + } + } +}