use std::marker::PhantomData; use super::ServiceFactory; pub enum MappedConfig<'a, T> { Ref(&'a T), Owned(T), } /// Adapt external config to a config for provided new service pub fn map_config( factory: T, f: F, ) -> impl ServiceFactory< Config = C, Request = T::Request, Response = T::Response, Error = T::Error, InitError = T::InitError, > where T: ServiceFactory, F: Fn(&C) -> MappedConfig, { MapConfig::new(factory, f) } /// Replace config with unit pub fn unit_config( new_service: T, ) -> impl ServiceFactory< Config = C, Request = T::Request, Response = T::Response, Error = T::Error, InitError = T::InitError, > where T: ServiceFactory, { UnitConfig::new(new_service) } /// `MapInitErr` service combinator pub(crate) struct MapConfig { a: A, f: F, e: PhantomData, } impl MapConfig { /// Create new `MapConfig` combinator pub fn new(a: A, f: F) -> Self where A: ServiceFactory, F: Fn(&C) -> MappedConfig, { Self { a, f, e: PhantomData, } } } impl Clone for MapConfig where A: Clone, F: Clone, { fn clone(&self) -> Self { Self { a: self.a.clone(), f: self.f.clone(), e: PhantomData, } } } impl ServiceFactory for MapConfig where A: ServiceFactory, F: Fn(&C) -> MappedConfig, { type Request = A::Request; type Response = A::Response; type Error = A::Error; type Config = C; type Service = A::Service; type InitError = A::InitError; type Future = A::Future; fn new_service(&self, cfg: &C) -> Self::Future { match (self.f)(cfg) { MappedConfig::Ref(cfg) => self.a.new_service(cfg), MappedConfig::Owned(cfg) => self.a.new_service(&cfg), } } } /// `MapInitErr` service combinator pub(crate) struct UnitConfig { a: A, e: PhantomData, } impl UnitConfig where A: ServiceFactory, { /// Create new `UnitConfig` combinator pub(crate) fn new(a: A) -> Self { Self { a, e: PhantomData } } } impl Clone for UnitConfig where A: Clone, { fn clone(&self) -> Self { Self { a: self.a.clone(), e: PhantomData, } } } impl ServiceFactory for UnitConfig where A: ServiceFactory, { type Request = A::Request; type Response = A::Response; type Error = A::Error; type Config = C; type Service = A::Service; type InitError = A::InitError; type Future = A::Future; fn new_service(&self, _: &C) -> Self::Future { self.a.new_service(&()) } }