diff --git a/src/service/map_request.rs b/src/service/map_request.rs new file mode 100644 index 00000000..716fcf1f --- /dev/null +++ b/src/service/map_request.rs @@ -0,0 +1,141 @@ +use std::marker; + +use futures::{Async, Future, Poll}; +use {NewService, Service}; + +/// `MapReq` service combinator +pub struct MapReq { + a: A, + f: F, + r: marker::PhantomData, +} + +impl MapReq +where + A: Service, + F: Fn(R) -> A::Request, +{ + /// Create new `MapReq` combinator + pub fn new(a: A, f: F) -> Self { + Self { + a, + f, + r: marker::PhantomData, + } + } +} + +impl Service for MapReq +where + A: Service, + F: Fn(R) -> A::Request, + F: Clone, +{ + type Request = R; + type Response = A::Response; + type Error = A::Error; + type Future = A::Future; + + fn poll_ready(&mut self) -> Poll<(), Self::Error> { + self.a.poll_ready() + } + + fn call(&mut self, req: Self::Request) -> Self::Future { + self.a.call((self.f)(req)) + } +} + +/// `MapReqNewService` new service combinator +pub struct MapReqNewService { + a: A, + f: F, + r: marker::PhantomData, +} + +impl MapReqNewService +where + A: NewService, + F: Fn(R) -> A::Request, +{ + /// Create new `MapReq` new service instance + pub fn new(a: A, f: F) -> Self { + Self { + a, + f, + r: marker::PhantomData, + } + } +} + +impl Clone for MapReqNewService +where + A: NewService + Clone, + F: Fn(R) -> A::Request + Clone, +{ + fn clone(&self) -> Self { + Self { + a: self.a.clone(), + f: self.f.clone(), + r: marker::PhantomData, + } + } +} + +impl NewService for MapReqNewService +where + A: NewService, + F: Fn(R) -> A::Request + Clone, +{ + type Request = R; + type Response = A::Response; + type Error = A::Error; + type Service = MapReq; + + type InitError = A::InitError; + type Future = MapReqNewServiceFuture; + + fn new_service(&self) -> Self::Future { + MapReqNewServiceFuture::new(self.a.new_service(), self.f.clone()) + } +} + +pub struct MapReqNewServiceFuture +where + A: NewService, + F: Fn(R) -> A::Request, +{ + fut: A::Future, + f: Option, + r: marker::PhantomData, +} + +impl MapReqNewServiceFuture +where + A: NewService, + F: Fn(R) -> A::Request, +{ + fn new(fut: A::Future, f: F) -> Self { + MapReqNewServiceFuture { + f: Some(f), + fut, + r: marker::PhantomData, + } + } +} + +impl Future for MapReqNewServiceFuture +where + A: NewService, + F: Fn(R) -> A::Request, +{ + type Item = MapReq; + type Error = A::InitError; + + fn poll(&mut self) -> Poll { + if let Async::Ready(service) = self.fut.poll()? { + Ok(Async::Ready(MapReq::new(service, self.f.take().unwrap()))) + } else { + Ok(Async::NotReady) + } + } +} diff --git a/src/service/mod.rs b/src/service/mod.rs index 8c4e3666..f85dc600 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 map_request; mod partial; pub use self::and_then::{AndThen, AndThenNewService}; @@ -15,6 +16,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::map_request::{MapReq, MapReqNewService}; pub use self::partial::{Partial, PartialNewService}; pub trait ServiceExt: Service { @@ -74,6 +76,14 @@ pub trait NewServiceExt: NewService { MapErrNewService::new(self, f) } + fn map_request(self, f: F) -> MapReqNewService + where + Self: Sized, + F: Fn(R) -> Self::Request, + { + MapReqNewService::new(self, f) + } + fn map_init_err(self, f: F) -> MapInitErr where Self: Sized,