2021-03-10 04:18:09 +01:00
|
|
|
//! Trait object forms of services and service factories.
|
|
|
|
|
2021-03-01 00:01:05 +01:00
|
|
|
use alloc::{boxed::Box, rc::Rc};
|
2021-03-10 04:18:09 +01:00
|
|
|
use core::{future::Future, pin::Pin};
|
2019-04-08 05:48:40 +02:00
|
|
|
|
2021-04-15 21:43:02 +02:00
|
|
|
use paste::paste;
|
|
|
|
|
2019-11-27 15:59:36 +01:00
|
|
|
use crate::{Service, ServiceFactory};
|
|
|
|
|
2021-04-15 21:43:02 +02:00
|
|
|
/// A boxed future with no send bound or lifetime parameters.
|
2020-12-27 05:28:00 +01:00
|
|
|
pub type BoxFuture<T> = Pin<Box<dyn Future<Output = T>>>;
|
2019-02-21 19:41:39 +01:00
|
|
|
|
2021-03-01 00:01:05 +01:00
|
|
|
macro_rules! service_object {
|
|
|
|
($name: ident, $type: tt, $fn_name: ident) => {
|
2021-04-15 21:43:02 +02:00
|
|
|
paste! {
|
|
|
|
#[doc = "Type alias for service trait object using `" $type "`."]
|
|
|
|
pub type $name<Req, Res, Err> = $type<
|
|
|
|
dyn Service<Req, Response = Res, Error = Err, Future = BoxFuture<Result<Res, Err>>>,
|
|
|
|
>;
|
|
|
|
|
|
|
|
#[doc = "Wraps service as a trait object using [`" $name "`]."]
|
|
|
|
pub fn $fn_name<S, Req>(service: S) -> $name<Req, S::Response, S::Error>
|
|
|
|
where
|
|
|
|
S: Service<Req> + 'static,
|
|
|
|
Req: 'static,
|
|
|
|
S::Future: 'static,
|
|
|
|
{
|
|
|
|
$type::new(ServiceWrapper::new(service))
|
|
|
|
}
|
2021-03-01 00:01:05 +01:00
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
service_object!(BoxService, Box, service);
|
|
|
|
service_object!(RcService, Rc, rc_service);
|
2019-04-20 02:43:52 +02:00
|
|
|
|
2021-03-10 04:18:09 +01:00
|
|
|
struct ServiceWrapper<S> {
|
|
|
|
inner: S,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<S> ServiceWrapper<S> {
|
|
|
|
fn new(inner: S) -> Self {
|
|
|
|
Self { inner }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<S, Req, Res, Err> Service<Req> for ServiceWrapper<S>
|
|
|
|
where
|
|
|
|
S: Service<Req, Response = Res, Error = Err>,
|
|
|
|
S::Future: 'static,
|
|
|
|
{
|
|
|
|
type Response = Res;
|
|
|
|
type Error = Err;
|
|
|
|
type Future = BoxFuture<Result<Res, Err>>;
|
|
|
|
|
|
|
|
crate::forward_ready!(inner);
|
|
|
|
|
|
|
|
fn call(&self, req: Req) -> Self::Future {
|
|
|
|
Box::pin(self.inner.call(req))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-04-15 21:43:02 +02:00
|
|
|
/// Wrapper for a service factory that will map it's services to boxed trait object services.
|
2020-12-27 05:28:00 +01:00
|
|
|
pub struct BoxServiceFactory<Cfg, Req, Res, Err, InitErr>(Inner<Cfg, Req, Res, Err, InitErr>);
|
2019-05-12 15:03:50 +02:00
|
|
|
|
2021-04-15 21:43:02 +02:00
|
|
|
/// Wraps a service factory that returns service trait objects.
|
2020-12-27 05:28:00 +01:00
|
|
|
pub fn factory<SF, Req>(
|
|
|
|
factory: SF,
|
|
|
|
) -> BoxServiceFactory<SF::Config, Req, SF::Response, SF::Error, SF::InitError>
|
2019-02-21 19:41:39 +01:00
|
|
|
where
|
2020-12-27 05:28:00 +01:00
|
|
|
SF: ServiceFactory<Req> + 'static,
|
|
|
|
Req: 'static,
|
|
|
|
SF::Response: 'static,
|
|
|
|
SF::Service: 'static,
|
|
|
|
SF::Future: 'static,
|
|
|
|
SF::Error: 'static,
|
|
|
|
SF::InitError: 'static,
|
2019-02-21 19:41:39 +01:00
|
|
|
{
|
2021-03-01 00:01:05 +01:00
|
|
|
BoxServiceFactory(Box::new(FactoryWrapper(factory)))
|
2019-02-21 19:41:39 +01:00
|
|
|
}
|
|
|
|
|
2019-02-22 21:44:37 +01:00
|
|
|
type Inner<C, Req, Res, Err, InitErr> = Box<
|
2019-11-14 13:38:24 +01:00
|
|
|
dyn ServiceFactory<
|
2020-12-27 05:28:00 +01:00
|
|
|
Req,
|
2019-05-12 15:03:50 +02:00
|
|
|
Config = C,
|
2019-02-21 20:19:16 +01:00
|
|
|
Response = Res,
|
|
|
|
Error = Err,
|
|
|
|
InitError = InitErr,
|
2019-11-25 13:18:00 +01:00
|
|
|
Service = BoxService<Req, Res, Err>,
|
2020-12-27 05:28:00 +01:00
|
|
|
Future = BoxFuture<Result<BoxService<Req, Res, Err>, InitErr>>,
|
2019-02-21 20:19:16 +01:00
|
|
|
>,
|
|
|
|
>;
|
|
|
|
|
2020-12-27 05:28:00 +01:00
|
|
|
impl<C, Req, Res, Err, InitErr> ServiceFactory<Req>
|
|
|
|
for BoxServiceFactory<C, Req, Res, Err, InitErr>
|
2019-02-21 20:19:16 +01:00
|
|
|
where
|
|
|
|
Req: 'static,
|
|
|
|
Res: 'static,
|
|
|
|
Err: 'static,
|
|
|
|
InitErr: 'static,
|
|
|
|
{
|
|
|
|
type Response = Res;
|
|
|
|
type Error = Err;
|
2019-05-12 15:03:50 +02:00
|
|
|
type Config = C;
|
2019-11-25 13:18:00 +01:00
|
|
|
type Service = BoxService<Req, Res, Err>;
|
2021-03-01 00:01:05 +01:00
|
|
|
type InitError = InitErr;
|
2019-11-14 13:38:24 +01:00
|
|
|
|
2020-12-27 05:28:00 +01:00
|
|
|
type Future = BoxFuture<Result<Self::Service, InitErr>>;
|
2019-02-21 20:19:16 +01:00
|
|
|
|
2019-12-02 16:27:48 +01:00
|
|
|
fn new_service(&self, cfg: C) -> Self::Future {
|
2019-02-22 21:44:37 +01:00
|
|
|
self.0.new_service(cfg)
|
2019-02-21 20:19:16 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-01 00:01:05 +01:00
|
|
|
struct FactoryWrapper<SF>(SF);
|
2019-02-21 19:41:39 +01:00
|
|
|
|
2021-03-01 00:01:05 +01:00
|
|
|
impl<SF, Req, Cfg, Res, Err, InitErr> ServiceFactory<Req> for FactoryWrapper<SF>
|
2019-02-21 19:41:39 +01:00
|
|
|
where
|
|
|
|
Req: 'static,
|
|
|
|
Res: 'static,
|
|
|
|
Err: 'static,
|
|
|
|
InitErr: 'static,
|
2020-12-27 05:28:00 +01:00
|
|
|
SF: ServiceFactory<Req, Config = Cfg, Response = Res, Error = Err, InitError = InitErr>,
|
|
|
|
SF::Future: 'static,
|
|
|
|
SF::Service: 'static,
|
|
|
|
<SF::Service as Service<Req>>::Future: 'static,
|
2019-02-21 19:41:39 +01:00
|
|
|
{
|
|
|
|
type Response = Res;
|
|
|
|
type Error = Err;
|
2020-12-27 05:28:00 +01:00
|
|
|
type Config = Cfg;
|
2019-11-25 13:18:00 +01:00
|
|
|
type Service = BoxService<Req, Res, Err>;
|
2021-03-01 00:01:05 +01:00
|
|
|
type InitError = InitErr;
|
2020-12-27 05:28:00 +01:00
|
|
|
type Future = BoxFuture<Result<Self::Service, Self::InitError>>;
|
2019-02-21 19:41:39 +01:00
|
|
|
|
2020-12-27 05:28:00 +01:00
|
|
|
fn new_service(&self, cfg: Cfg) -> Self::Future {
|
2021-03-01 00:01:05 +01:00
|
|
|
let f = self.0.new_service(cfg);
|
2021-03-10 04:18:09 +01:00
|
|
|
Box::pin(async { f.await.map(|s| Box::new(ServiceWrapper::new(s)) as _) })
|
2019-02-21 19:41:39 +01:00
|
|
|
}
|
|
|
|
}
|