use alloc::{boxed::Box, rc::Rc}; use core::{ future::Future, pin::Pin, task::{Context, Poll}, }; use crate::{Service, ServiceFactory}; pub type BoxFuture = Pin>>; macro_rules! service_object { ($name: ident, $type: tt, $fn_name: ident) => { /// Type alias for service trait object. pub type $name = $type< dyn Service>>, >; /// Create service trait object. pub fn $fn_name(service: S) -> $name where S: Service + 'static, Req: 'static, S::Future: 'static, { $type::new(ServiceWrapper(service)) } }; } service_object!(BoxService, Box, service); service_object!(RcService, Rc, rc_service); /// Type alias for service factory trait object that would produce a trait object service /// (`BoxService`, `RcService`, etc.) pub struct BoxServiceFactory(Inner); /// Create service factory trait object. pub fn factory( factory: SF, ) -> BoxServiceFactory where SF: ServiceFactory + 'static, Req: 'static, SF::Response: 'static, SF::Service: 'static, SF::Future: 'static, SF::Error: 'static, SF::InitError: 'static, { BoxServiceFactory(Box::new(FactoryWrapper(factory))) } type Inner = Box< dyn ServiceFactory< Req, Config = C, Response = Res, Error = Err, InitError = InitErr, Service = BoxService, Future = BoxFuture, InitErr>>, >, >; impl ServiceFactory for BoxServiceFactory where Req: 'static, Res: 'static, Err: 'static, InitErr: 'static, { type Response = Res; type Error = Err; type Config = C; type Service = BoxService; type InitError = InitErr; type Future = BoxFuture>; fn new_service(&self, cfg: C) -> Self::Future { self.0.new_service(cfg) } } struct FactoryWrapper(SF); impl ServiceFactory for FactoryWrapper where Req: 'static, Res: 'static, Err: 'static, InitErr: 'static, SF: ServiceFactory, SF::Future: 'static, SF::Service: 'static, >::Future: 'static, { type Response = Res; type Error = Err; type Config = Cfg; type Service = BoxService; type InitError = InitErr; type Future = BoxFuture>; fn new_service(&self, cfg: Cfg) -> Self::Future { let f = self.0.new_service(cfg); Box::pin(async { f.await.map(|s| Box::new(ServiceWrapper(s)) as _) }) } } struct ServiceWrapper(S); impl Service for ServiceWrapper where S: Service, S::Future: 'static, { type Response = Res; type Error = Err; type Future = BoxFuture>; fn poll_ready(&self, ctx: &mut Context<'_>) -> Poll> { self.0.poll_ready(ctx) } fn call(&self, req: Req) -> Self::Future { Box::pin(self.0.call(req)) } }