use std::marker::PhantomData; 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 { service: A, f: F, _t: PhantomData, } impl Map { /// Create new `Map` combinator pub fn new(service: A, f: F) -> Self where A: Service, F: Fn(A::Response) -> Response, { Self { service, f, _t: PhantomData, } } } impl Clone for Map where A: Clone, F: Clone, { fn clone(&self) -> Self { Map { service: self.service.clone(), f: self.f.clone(), _t: PhantomData, } } } impl Service for Map where A: Service, F: Fn(A::Response) -> Response + Clone, { type Response = Response; type Error = A::Error; type Future = MapFuture; fn poll_ready(&mut self) -> Poll<(), Self::Error> { self.service.poll_ready() } fn call(&mut self, req: Request) -> Self::Future { MapFuture::new(self.service.call(req), self.f.clone()) } } pub struct MapFuture where A: Service, F: Fn(A::Response) -> Response, { f: F, fut: A::Future, } impl MapFuture where A: Service, F: Fn(A::Response) -> Response, { fn new(fut: A::Future, f: F) -> Self { MapFuture { f, fut } } } impl Future for MapFuture where A: Service, F: Fn(A::Response) -> Response, { type Item = Response; 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: PhantomData, } impl MapNewService { /// Create new `Map` new service instance pub fn new(a: A, f: F) -> Self where A: NewService, F: Fn(A::Response) -> Response, { Self { a, f, r: PhantomData, } } } impl Clone for MapNewService where A: Clone, F: Clone, { fn clone(&self) -> Self { Self { a: self.a.clone(), f: self.f.clone(), r: PhantomData, } } } impl NewService for MapNewService where A: NewService, F: Fn(A::Response) -> Response + Clone, { type Response = Response; 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) -> Response, { fut: A::Future, f: Option, } impl MapNewServiceFuture where A: NewService, F: Fn(A::Response) -> Response, { fn new(fut: A::Future, f: F) -> Self { MapNewServiceFuture { f: Some(f), fut } } } impl Future for MapNewServiceFuture where A: NewService, F: Fn(A::Response) -> Response, { 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 crate::service::{IntoNewService, NewServiceExt, Service, ServiceExt}; struct Srv; impl Service<()> for Srv { 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")); } #[test] fn test_new_service() { let blank = || Ok::<_, ()>(Srv); let new_srv = blank.into_new_service().map(|_| "ok"); if let Async::Ready(mut srv) = new_srv.new_service().poll().unwrap() { let res = srv.call(()).poll(); assert!(res.is_ok()); assert_eq!(res.unwrap(), Async::Ready("ok")); } else { panic!() } } }