diff --git a/service/src/factory/boxed.rs b/service/src/factory/boxed.rs new file mode 100644 index 00000000..a2f36850 --- /dev/null +++ b/service/src/factory/boxed.rs @@ -0,0 +1,32 @@ +use alloc::boxed::Box; + +use crate::BoxFuture; + +use super::ServiceFactory; + +pub struct BoxedServiceFactory { + factory: F, +} + +impl BoxedServiceFactory { + pub(super) fn new(factory: F) -> Self { + Self { factory } + } +} + +impl ServiceFactory for BoxedServiceFactory +where + F: ServiceFactory, + F::Future: 'static, +{ + type Response = F::Response; + type Error = F::Error; + type Config = F::Config; + type Service = F::Service; + type InitError = F::InitError; + type Future = BoxFuture<'static, Self::Service, Self::InitError>; + + fn new_service(&self, cfg: Self::Config) -> Self::Future { + Box::pin(self.factory.new_service(cfg)) + } +} diff --git a/service/src/factory/ext.rs b/service/src/factory/ext.rs index 5a414699..14b62abe 100644 --- a/service/src/factory/ext.rs +++ b/service/src/factory/ext.rs @@ -5,6 +5,7 @@ use alloc::boxed::Box; use crate::transform::Transform; use super::{ + boxed::BoxedServiceFactory, pipeline::{marker, PipelineServiceFactory}, ServiceFactory, ServiceFactoryObject, }; @@ -34,6 +35,16 @@ pub trait ServiceFactoryExt: ServiceFactory { PipelineServiceFactory::new(self, err) } + /// Box `>::Future` to reduce it's stack size. + /// + /// *. This combinator does not box `Self` or `Self::Service`. + fn boxed_future(self) -> BoxedServiceFactory + where + Self: Sized, + { + BoxedServiceFactory::new(self) + } + /// Chain another service factory who's service takes `Self`'s `Service::Future` output as /// `Service::Request`. /// @@ -48,6 +59,10 @@ pub trait ServiceFactoryExt: ServiceFactory { PipelineServiceFactory::new(self, factory) } + /// Chain another service factory who's service takes `Self`'s `Service::Response` output as + /// `Service::Request`. + /// + /// *. Unlike `then` combinator both `F` and `Self`'s readiness are checked beforehand. fn and_then(self, factory: F) -> PipelineServiceFactory where F: ServiceFactory, @@ -74,6 +89,11 @@ pub trait ServiceFactoryExt: ServiceFactory { PipelineServiceFactory::new(self, transform) } + /// Box self and cast it to a trait object. + /// + /// This would erase `Self::Service` type and it's GAT nature. + /// + /// See [crate::service::ServiceObject] for detail. fn into_object(self) -> ServiceFactoryObject where Self: Sized + 'static, diff --git a/service/src/factory/mod.rs b/service/src/factory/mod.rs index 5a77a703..8c48fc6f 100644 --- a/service/src/factory/mod.rs +++ b/service/src/factory/mod.rs @@ -1,6 +1,7 @@ pub(crate) mod pipeline; mod and_then; +mod boxed; mod ext; mod function; mod map;