use std::rc::Rc; use std::sync::Arc; use futures::{Async, Future, IntoFuture, Poll}; use crate::transform_map_init_err::TransformMapInitErr; use crate::{NewService, Service}; /// `Transform` service factory. /// /// Transform factory creates service that wraps other services. /// /// * `S` is a wrapped service. /// * `R` requests handled by this transform service. pub trait Transform { /// Responses given by the service. type Response; /// Errors produced by the service. type Error; /// The `TransformService` value created by this factory type Transform: Service; /// Errors produced while building a service. type InitError; /// The future response value. type Future: Future; /// Create and return a new service value asynchronously. fn new_transform(&self, service: S) -> Self::Future; /// Map this service's factory init error to a different error, /// returning a new transform service factory. fn map_init_err(self, f: F) -> TransformMapInitErr where Self: Sized, F: Fn(Self::InitError) -> E, { TransformMapInitErr::new(self, f) } } impl Transform for Rc where T: Transform, { type Response = T::Response; type Error = T::Error; type InitError = T::InitError; type Transform = T::Transform; type Future = T::Future; fn new_transform(&self, service: S) -> T::Future { self.as_ref().new_transform(service) } } impl Transform for Arc where T: Transform, { type Response = T::Response; type Error = T::Error; type InitError = T::InitError; type Transform = T::Transform; type Future = T::Future; fn new_transform(&self, service: S) -> T::Future { self.as_ref().new_transform(service) } } /// Trait for types that can be converted to a *transform service* pub trait IntoTransform where T: Transform, { /// Convert to a `TransformService` fn into_transform(self) -> T; } impl IntoTransform for T where T: Transform, { fn into_transform(self) -> T { self } } /// `Apply` transform new service #[derive(Clone)] pub struct ApplyTransform { a: S, t: Rc, _t: std::marker::PhantomData<(R, Req, Cfg)>, } impl ApplyTransform where S: NewService, T: Transform, { /// Create new `ApplyNewService` new service instance pub fn new>(t: F, a: S) -> Self { Self { a, t: Rc::new(t.into_transform()), _t: std::marker::PhantomData, } } } impl NewService for ApplyTransform where S: NewService, T: Transform, { type Response = T::Response; type Error = T::Error; type Service = T::Transform; type InitError = T::InitError; type Future = ApplyTransformFuture; fn new_service(&self, cfg: &Cfg) -> Self::Future { ApplyTransformFuture { t_cell: self.t.clone(), fut_a: self.a.new_service(cfg).into_future(), fut_t: None, } } } pub struct ApplyTransformFuture where S: NewService, T: Transform, { fut_a: S::Future, fut_t: Option, t_cell: Rc, } impl Future for ApplyTransformFuture where S: NewService, T: Transform, { type Item = T::Transform; type Error = T::InitError; fn poll(&mut self) -> Poll { if self.fut_t.is_none() { if let Async::Ready(service) = self.fut_a.poll()? { self.fut_t = Some(self.t_cell.new_transform(service).into_future()); } } if let Some(ref mut fut) = self.fut_t { fut.poll() } else { Ok(Async::NotReady) } } }