1use core::marker::PhantomData;
2
3use xitca_http::util::service::router::{IntoObject, PathGen, RouteGen, RouteObject};
4use xitca_service::{Service, object::ServiceObject};
5
6use crate::context::WebContext;
7
8pub type WebObject<C, B, Res, Err> = Box<dyn for<'r> ServiceObject<WebContext<'r, C, B>, Response = Res, Error = Err>>;
9
10impl<C, B, I, Res, Err> IntoObject<I, ()> for WebContext<'_, C, B>
11where
12 C: 'static,
13 B: 'static,
14 I: Service + RouteGen + Send + Sync + 'static,
15 I::Response: for<'r> Service<WebContext<'r, C, B>, Response = Res, Error = Err> + 'static,
16{
17 type Object = RouteObject<(), WebObject<C, B, Res, Err>, I::Error>;
18
19 fn into_object(inner: I) -> Self::Object {
20 struct Builder<I, C, B>(I, PhantomData<fn(C, B)>);
21
22 impl<I, C, B> PathGen for Builder<I, C, B>
23 where
24 I: PathGen,
25 {
26 fn path_gen(&mut self, prefix: &str) -> String {
27 self.0.path_gen(prefix)
28 }
29 }
30
31 impl<I, C, B> RouteGen for Builder<I, C, B>
32 where
33 I: RouteGen,
34 {
35 type Route<R> = I::Route<R>;
36
37 fn route_gen<R>(route: R) -> Self::Route<R> {
38 I::route_gen(route)
39 }
40 }
41
42 impl<C, I, B, Res, Err> Service for Builder<I, C, B>
43 where
44 I: Service + RouteGen + 'static,
45 I::Response: for<'r> Service<WebContext<'r, C, B>, Response = Res, Error = Err> + 'static,
46 {
47 type Response = WebObject<C, B, Res, Err>;
48 type Error = I::Error;
49
50 async fn call(&self, arg: ()) -> Result<Self::Response, Self::Error> {
51 self.0.call(arg).await.map(|s| Box::new(s) as _)
52 }
53 }
54
55 RouteObject(Box::new(Builder(inner, PhantomData)))
56 }
57}