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. /// `Config` is a service factory configuration type. pub trait Transform { /// Requests handled by the service. type Request; /// Responses given by the service. type Response; /// Errors produced by the service. type Error; /// The `TransformService` value created by this factory type Transform: Service< Request = Self::Request, Response = Self::Response, Error = Self::Error, >; /// Errors produced while building a service. type InitError; /// The future response value. type Future: IntoFuture; /// 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 Request = T::Request; 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 Request = T::Request; 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: A, t: Rc, _t: std::marker::PhantomData, } impl ApplyTransform where A: NewService, T: Transform, { /// Create new `ApplyNewService` new service instance pub fn new>(t: F, a: A) -> Self { Self { a, t: Rc::new(t.into_transform()), _t: std::marker::PhantomData, } } } impl NewService for ApplyTransform where A: NewService, T: Transform, { type Request = T::Request; type Response = T::Response; type Error = T::Error; type Service = T::Transform; type InitError = T::InitError; type Future = ApplyTransformFuture; fn new_service(&self, cfg: &C) -> Self::Future { ApplyTransformFuture { t_cell: self.t.clone(), fut_a: self.a.new_service(cfg).into_future(), fut_t: None, } } } pub struct ApplyTransformFuture where A: NewService, T: Transform, { fut_a: ::Future, fut_t: Option<::Future>, t_cell: Rc, } impl Future for ApplyTransformFuture where A: 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) } } }