use alloc::boxed::Box; use core::{ future::Future, marker::PhantomData, pin::Pin, task::{Context, Poll}, }; use crate::{Service, ServiceFactory}; pub type BoxFuture = Pin>>; pub type BoxService = Box>>>; pub struct BoxServiceFactory(Inner); /// Create boxed service factory 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, _t: PhantomData, })) } /// Create boxed service pub fn service(service: S) -> BoxService where S: Service + 'static, Req: 'static, S::Future: 'static, { Box::new(ServiceWrapper(service, PhantomData)) } 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 InitError = InitErr; type Config = C; type Service = BoxService; type Future = BoxFuture>; fn new_service(&self, cfg: C) -> Self::Future { self.0.new_service(cfg) } } struct FactoryWrapper { factory: SF, _t: PhantomData<(Req, Cfg)>, } 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 InitError = InitErr; type Config = Cfg; type Service = BoxService; type Future = BoxFuture>; fn new_service(&self, cfg: Cfg) -> Self::Future { let fut = self.factory.new_service(cfg); Box::pin(async { let res = fut.await; res.map(ServiceWrapper::boxed) }) } } struct ServiceWrapper, Req>(S, PhantomData); impl ServiceWrapper where S: Service + 'static, Req: 'static, S::Future: 'static, { fn boxed(service: S) -> BoxService { Box::new(ServiceWrapper(service, PhantomData)) } } 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)) } }