use std::task::{Context, Poll}; use crate::map::{Map, MapNewService}; use crate::map_err::{MapErr, MapErrNewService}; use crate::map_init_err::MapInitErr; use crate::{IntoService, IntoServiceFactory, Service, ServiceFactory}; #[inline] /// Convert object of type `U` to a service `T` pub fn into_service(service: U) -> ServiceMapper where U: IntoService, T: Service, { ServiceMapper { service: service.into_service(), } } pub fn into_factory(factory: F) -> ServiceFactoryMapper where T: ServiceFactory, F: IntoServiceFactory, { ServiceFactoryMapper { factory: factory.into_factory(), } } pub struct ServiceMapper { service: T, } pub struct ServiceFactoryMapper { factory: T, } impl ServiceMapper { /// Map this service's output to a different type, returning a new service /// of the resulting type. /// /// This function is similar to the `Option::map` or `Iterator::map` where /// it will change the type of the underlying service. /// /// Note that this function consumes the receiving service and returns a /// wrapped version of it, similar to the existing `map` methods in the /// standard library. pub fn map( self, f: F, ) -> ServiceMapper> where Self: Sized, F: FnMut(T::Response) -> R + Clone, { ServiceMapper { service: Map::new(self.service, f), } } /// Map this service's error to a different error, returning a new service. /// /// This function is similar to the `Result::map_err` where it will change /// the error type of the underlying service. This is useful for example to /// ensure that services have the same error type. /// /// Note that this function consumes the receiving service and returns a /// wrapped version of it. pub fn map_err( self, f: F, ) -> ServiceMapper> where Self: Sized, F: Fn(T::Error) -> E + Clone, { ServiceMapper { service: MapErr::new(self, f), } } } impl Clone for ServiceMapper where T: Clone, { fn clone(&self) -> Self { ServiceMapper { service: self.service.clone(), } } } impl Service for ServiceMapper { type Request = T::Request; type Response = T::Response; type Error = T::Error; type Future = T::Future; #[inline] fn poll_ready(&mut self, ctx: &mut Context<'_>) -> Poll> { self.service.poll_ready(ctx) } #[inline] fn call(&mut self, req: T::Request) -> Self::Future { self.service.call(req) } } impl ServiceFactoryMapper { /// Map this service's output to a different type, returning a new service /// of the resulting type. pub fn map( self, f: F, ) -> ServiceFactoryMapper< impl ServiceFactory< Config = T::Config, Request = T::Request, Response = R, Error = T::Error, InitError = T::InitError, >, > where Self: Sized, F: FnMut(T::Response) -> R + Clone, { ServiceFactoryMapper { factory: MapNewService::new(self.factory, f), } } /// Map this service's error to a different error, returning a new service. pub fn map_err( self, f: F, ) -> ServiceFactoryMapper< impl ServiceFactory< Config = T::Config, Request = T::Request, Response = T::Response, Error = E, InitError = T::InitError, >, > where Self: Sized, F: Fn(T::Error) -> E + Clone, { ServiceFactoryMapper { factory: MapErrNewService::new(self.factory, f), } } /// Map this factory's init error to a different error, returning a new service. pub fn map_init_err( self, f: F, ) -> ServiceFactoryMapper< impl ServiceFactory< Config = T::Config, Request = T::Request, Response = T::Response, Error = T::Error, InitError = E, >, > where Self: Sized, F: Fn(T::InitError) -> E + Clone, { ServiceFactoryMapper { factory: MapInitErr::new(self.factory, f), } } } impl Clone for ServiceFactoryMapper where T: Clone, { fn clone(&self) -> Self { ServiceFactoryMapper { factory: self.factory.clone(), } } } impl ServiceFactory for ServiceFactoryMapper { type Config = T::Config; type Request = T::Request; type Response = T::Response; type Error = T::Error; type Service = T::Service; type InitError = T::InitError; type Future = T::Future; #[inline] fn new_service(&self, cfg: &T::Config) -> Self::Future { self.factory.new_service(cfg) } }