use std::marker::PhantomData; use futures::{Async, Future, IntoFuture, Poll}; use super::{IntoNewService, IntoService, NewService, Service}; /// `Apply` service combinator pub struct Apply { service: T, f: F, r: PhantomData<(Req, R)>, } impl Apply where T: Service, T::Error: Into<::Error>, F: Fn(Req, &mut T) -> R, R: IntoFuture, { /// Create new `Apply` combinator pub fn new>(service: I, f: F) -> Self { Self { service: service.into_service(), f, r: PhantomData, } } } impl Clone for Apply where T: Service + Clone, T::Error: Into<::Error>, F: Fn(Req, &mut T) -> R + Clone, R: IntoFuture, { fn clone(&self) -> Self { Apply { service: self.service.clone(), f: self.f.clone(), r: PhantomData, } } } impl Service for Apply where T: Service, T::Error: Into<::Error>, F: Fn(Req, &mut T) -> R, R: IntoFuture, { type Request = Req; type Response = ::Item; type Error = ::Error; type Future = R::Future; 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).into_future() } } /// `ApplyNewService` new service combinator pub struct ApplyNewService { service: T, f: F, r: PhantomData R>, } impl ApplyNewService where T: NewService, F: Fn(Req, &mut T::Service) -> R, R: IntoFuture, { /// Create new `ApplyNewService` new service instance pub fn new>(service: F1, f: F) -> Self { Self { f, service: service.into_new_service(), r: PhantomData, } } } impl Clone for ApplyNewService where T: NewService + Clone, F: Fn(Req, &mut T::Service) -> R + Clone, R: IntoFuture, { fn clone(&self) -> Self { Self { service: self.service.clone(), f: self.f.clone(), r: PhantomData, } } } impl NewService for ApplyNewService where T: NewService, T::Error: Into<::Error>, F: Fn(Req, &mut T::Service) -> R + Clone, R: IntoFuture, { type Request = Req; type Response = ::Item; type Error = ::Error; 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: IntoFuture, { fut: T::Future, f: Option, r: PhantomData R>, } impl ApplyNewServiceFuture where T: NewService, F: Fn(Req, &mut T::Service) -> R, R: IntoFuture, { fn new(fut: T::Future, f: F) -> Self { ApplyNewServiceFuture { f: Some(f), fut, r: PhantomData, } } } impl Future for ApplyNewServiceFuture where T: NewService, T::Error: Into<::Error>, F: Fn(Req, &mut T::Service) -> R, R: IntoFuture, { 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(service, self.f.take().unwrap()))) } else { Ok(Async::NotReady) } } } #[cfg(test)] mod tests { use futures::future::{ok, FutureResult}; use futures::{Async, Future, Poll}; use service::{IntoService, Service, ServiceExt}; #[derive(Clone)] 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_call() { let blank = |req| Ok(req); let mut srv = blank.into_service().apply(Srv, |req: &'static str, srv| { srv.call(()).map(move |res| (req, res)) }); assert!(srv.poll_ready().is_ok()); let res = srv.call("srv").poll(); assert!(res.is_ok()); assert_eq!(res.unwrap(), Async::Ready(("srv", ()))); } }