use futures::{try_ready, Async, Future, IntoFuture, Poll}; use super::{FnNewTransform, FnTransform}; use super::{ IntoNewService, IntoNewTransform, IntoService, IntoTransform, NewService, NewTransform, Service, Transform, }; /// `Apply` service combinator pub struct Apply where T: Transform, T::Error: From, S: Service, { transform: T, service: S, } impl Apply where T: Transform, T::Error: From, S: Service, { /// Create new `Apply` combinator pub fn new, S1: IntoService>( transform: T1, service: S1, ) -> Self { Self { transform: transform.into_transform(), service: service.into_service(), } } } impl Apply, S> where F: FnMut(Req, &mut S) -> Out, Out: IntoFuture, Out::Error: From, S: Service, { /// Create new `Apply` combinator pub fn new_fn>(service: S1, transform: F) -> Self { Self { service: service.into_service(), transform: transform.into_transform(), } } } impl Clone for Apply where S: Service + Clone, T::Error: From, T: Transform + Clone, { fn clone(&self) -> Self { Apply { service: self.service.clone(), transform: self.transform.clone(), } } } impl Service for Apply where T: Transform, T::Error: From, S: Service, { type Request = T::Request; type Response = T::Response; type Error = T::Error; type Future = T::Future; fn poll_ready(&mut self) -> Poll<(), Self::Error> { try_ready!(self.service.poll_ready()); self.transform.poll_ready() } fn call(&mut self, req: Self::Request) -> Self::Future { self.transform.call(req, &mut self.service).into_future() } } /// `ApplyNewService` new service combinator pub struct ApplyNewService where T: NewTransform, T::Error: From, S: NewService, { transform: T, service: S, } impl ApplyNewService where T: NewTransform, T::Error: From, S: NewService, { /// Create new `ApplyNewService` new service instance pub fn new, S1: IntoNewService>( transform: T1, service: S1, ) -> Self { Self { transform: transform.into_new_transform(), service: service.into_new_service(), } } } impl ApplyNewService, S> where F: FnMut(In, &mut S::Service) -> Out + Clone, Out: IntoFuture, Out::Error: From, S: NewService, { /// Create new `Apply` combinator factory pub fn new_fn>(service: S1, transform: F) -> Self { Self { service: service.into_new_service(), transform: FnNewTransform::new(transform), } } } impl Clone for ApplyNewService where T: NewTransform + Clone, T::Error: From, S: NewService + Clone, { fn clone(&self) -> Self { Self { service: self.service.clone(), transform: self.transform.clone(), } } } impl NewService for ApplyNewService where T: NewTransform, T::Error: From, S: NewService, { type Request = T::Request; type Response = T::Response; type Error = T::Error; type Service = Apply; type InitError = T::InitError; type Future = ApplyNewServiceFuture; fn new_service(&self) -> Self::Future { ApplyNewServiceFuture { fut_t: self.transform.new_transform(), fut_s: self.service.new_service(), service: None, transform: None, } } } pub struct ApplyNewServiceFuture where T: NewTransform, T::Error: From, S: NewService, { fut_s: S::Future, fut_t: T::Future, service: Option, transform: Option, } impl Future for ApplyNewServiceFuture where T: NewTransform, T::Error: From, S: NewService, { type Item = Apply; type Error = T::InitError; fn poll(&mut self) -> Poll { if self.transform.is_none() { if let Async::Ready(transform) = self.fut_t.poll()? { self.transform = Some(transform); } } if self.service.is_none() { if let Async::Ready(service) = self.fut_s.poll()? { self.service = Some(service); } } if self.transform.is_some() && self.service.is_some() { Ok(Async::Ready(Apply { service: self.service.take().unwrap(), transform: self.transform.take().unwrap(), })) } else { Ok(Async::NotReady) } } } #[cfg(test)] mod tests { use futures::future::{ok, FutureResult}; use futures::{Async, Future, Poll}; use super::*; use crate::{NewService, Service}; #[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_apply() { let mut srv = Apply::new_fn(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", ()))); } #[test] fn test_new_service() { let new_srv = ApplyNewService::new( |req: &'static str, srv: &mut Srv| srv.call(()).map(move |res| (req, res)), || Ok::<_, ()>(Srv), ); if let Async::Ready(mut srv) = new_srv.new_service().poll().unwrap() { assert!(srv.poll_ready().is_ok()); let res = srv.call("srv").poll(); assert!(res.is_ok()); assert_eq!(res.unwrap(), Async::Ready(("srv", ()))); } else { panic!() } } #[test] fn test_new_service_fn() { let new_srv = ApplyNewService::new_fn( || Ok::<_, ()>(Srv), |req: &'static str, srv| srv.call(()).map(move |res| (req, res)), ); if let Async::Ready(mut srv) = new_srv.new_service().poll().unwrap() { assert!(srv.poll_ready().is_ok()); let res = srv.call("srv").poll(); assert!(res.is_ok()); assert_eq!(res.unwrap(), Async::Ready(("srv", ()))); } else { panic!() } } }