use std::marker; use futures::{Async, Future, Poll}; use super::{NewService, Service}; /// Service for the `map` combinator, changing the type of a service's response. /// /// This is created by the `ServiceExt::map` method. pub struct Map where A: Service, F: Fn(A::Response) -> R, { service: A, f: F, } impl Map where A: Service, F: Fn(A::Response) -> R, { /// Create new `Map` combinator pub fn new(service: A, f: F) -> Self { Self { service, f } } } impl Clone for Map where A: Service + Clone, F: Fn(A::Response) -> R + Clone, { fn clone(&self) -> Self { Map { service: self.service.clone(), f: self.f.clone(), } } } impl Service for Map where A: Service, F: Fn(A::Response) -> R + Clone, { type Request = A::Request; type Response = R; type Error = A::Error; type Future = MapFuture; fn poll_ready(&mut self) -> Poll<(), Self::Error> { self.service.poll_ready() } fn call(&mut self, req: Self::Request) -> Self::Future { MapFuture::new(self.service.call(req), self.f.clone()) } } pub struct MapFuture where A: Service, F: Fn(A::Response) -> R, { f: F, fut: A::Future, } impl MapFuture where A: Service, F: Fn(A::Response) -> R, { fn new(fut: A::Future, f: F) -> Self { MapFuture { f, fut } } } impl Future for MapFuture where A: Service, F: Fn(A::Response) -> R, { type Item = R; type Error = A::Error; fn poll(&mut self) -> Poll { match self.fut.poll()? { Async::Ready(resp) => Ok(Async::Ready((self.f)(resp))), Async::NotReady => Ok(Async::NotReady), } } } /// `MapNewService` new service combinator pub struct MapNewService { a: A, f: F, r: marker::PhantomData, } impl MapNewService where A: NewService, F: Fn(A::Response) -> R, { /// Create new `Map` new service instance pub fn new(a: A, f: F) -> Self { Self { a, f, r: marker::PhantomData, } } } impl Clone for MapNewService where A: NewService + Clone, F: Fn(A::Response) -> R + Clone, { fn clone(&self) -> Self { Self { a: self.a.clone(), f: self.f.clone(), r: marker::PhantomData, } } } impl NewService for MapNewService where A: NewService, F: Fn(A::Response) -> R + Clone, { type Request = A::Request; type Response = R; type Error = A::Error; type Service = Map; type InitError = A::InitError; type Future = MapNewServiceFuture; fn new_service(&self) -> Self::Future { MapNewServiceFuture::new(self.a.new_service(), self.f.clone()) } } pub struct MapNewServiceFuture where A: NewService, F: Fn(A::Response) -> R, { fut: A::Future, f: Option, } impl MapNewServiceFuture where A: NewService, F: Fn(A::Response) -> R, { fn new(fut: A::Future, f: F) -> Self { MapNewServiceFuture { f: Some(f), fut } } } impl Future for MapNewServiceFuture where A: NewService, F: Fn(A::Response) -> R, { type Item = Map; type Error = A::InitError; fn poll(&mut self) -> Poll { if let Async::Ready(service) = self.fut.poll()? { Ok(Async::Ready(Map::new(service, self.f.take().unwrap()))) } else { Ok(Async::NotReady) } } } #[cfg(test)] mod tests { use futures::future::{ok, FutureResult}; use super::*; use service::{Service, ServiceExt}; struct Srv; impl Service for Srv { type Request = (); type Response = (); type Error = (); type Future = FutureResult<(), ()>; fn poll_ready(&mut self) -> Poll<(), Self::Error> { Ok(Async::Ready(())) } fn call(&mut self, _: ()) -> Self::Future { ok(()) } } #[test] fn test_poll_ready() { let mut srv = Srv.map(|_| "ok"); let res = srv.poll_ready(); assert!(res.is_ok()); assert_eq!(res.unwrap(), Async::Ready(())); } #[test] fn test_call() { let mut srv = Srv.map(|_| "ok"); let res = srv.call(()).poll(); assert!(res.is_ok()); assert_eq!(res.unwrap(), Async::Ready("ok")); } }