use std::future::Future; use std::pin::Pin; use std::task::{Context, Poll}; use futures_util::future::FutureExt; use crate::{Service, ServiceFactory}; pub type BoxFuture = Pin>>>; pub type BoxService = Box>>; pub struct BoxServiceFactory(Inner); /// Create boxed new service pub fn factory( factory: T, ) -> BoxServiceFactory where T: ServiceFactory + 'static, T::Request: 'static, T::Response: 'static, T::Service: 'static, T::Future: 'static, T::Error: 'static, T::InitError: 'static, { BoxServiceFactory(Box::new(FactoryWrapper { factory, _t: std::marker::PhantomData, })) } /// Create boxed service pub fn service(service: T) -> BoxService where T: Service + 'static, T::Future: 'static, { Box::new(ServiceWrapper(service)) } type Inner = Box< dyn ServiceFactory< Config = C, Request = Req, 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 Request = Req; 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: T, _t: std::marker::PhantomData, } impl ServiceFactory for FactoryWrapper where Req: 'static, Res: 'static, Err: 'static, InitErr: 'static, T: ServiceFactory< Config = C, Request = Req, Response = Res, Error = Err, InitError = InitErr, >, T::Future: 'static, T::Service: 'static, ::Future: 'static, { type Request = Req; 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 { Box::pin( self.factory .new_service(cfg) .map(|res| res.map(ServiceWrapper::boxed)), ) } } struct ServiceWrapper(T); impl ServiceWrapper where T: Service + 'static, T::Future: 'static, { fn boxed(service: T) -> BoxService { Box::new(ServiceWrapper(service)) } } impl Service for ServiceWrapper where T: Service, T::Future: 'static, { type Request = Req; type Response = Res; type Error = Err; type Future = BoxFuture; fn poll_ready(&mut self, ctx: &mut Context<'_>) -> Poll> { self.0.poll_ready(ctx) } fn call(&mut self, req: Self::Request) -> Self::Future { Box::pin(self.0.call(req)) } }