xitca_server/server/
service.rs1use core::marker::PhantomData;
2
3use std::rc::Rc;
4
5use tokio::task::JoinHandle;
6use xitca_io::net::Stream;
7use xitca_service::{Service, ready::ReadyService};
8
9use crate::{
10 net::ListenerDyn,
11 worker::{self, ServiceAny},
12};
13
14pub type ServiceObj = Box<
15 dyn for<'a> xitca_service::object::ServiceObject<
16 (&'a str, &'a [(String, ListenerDyn)]),
17 Response = (Vec<JoinHandle<()>>, ServiceAny),
18 Error = (),
19 > + Send
20 + Sync,
21>;
22
23struct Container<F, Req> {
24 inner: F,
25 _t: PhantomData<fn(Req)>,
26}
27
28impl<'a, F, Req> Service<(&'a str, &'a [(String, ListenerDyn)])> for Container<F, Req>
29where
30 F: IntoServiceObj<Req>,
31 Req: TryFrom<Stream> + 'static,
32{
33 type Response = (Vec<JoinHandle<()>>, ServiceAny);
34 type Error = ();
35
36 async fn call(
37 &self,
38 (name, listeners): (&'a str, &'a [(String, ListenerDyn)]),
39 ) -> Result<Self::Response, Self::Error> {
40 let service = self.inner.call(()).await.map_err(|_| ())?;
41 let service = Rc::new(service);
42
43 let handles = listeners
44 .iter()
45 .filter(|(n, _)| n == name)
46 .map(|(_, listener)| worker::start(listener, &service))
47 .collect::<Vec<_>>();
48
49 Ok((handles, service as _))
50 }
51}
52
53pub trait IntoServiceObj<Req>: Send + Sync + 'static
55where
56 Self: Service<Response = Self::Service> + Send + Sync + 'static,
57 Req: TryFrom<Stream> + 'static,
58{
59 type Service: ReadyService + Service<Req>;
60
61 fn into_object(self) -> ServiceObj;
62}
63
64impl<T, Req> IntoServiceObj<Req> for T
65where
66 T: Service + Send + Sync + 'static,
67 T::Response: ReadyService + Service<Req>,
68 Req: TryFrom<Stream> + 'static,
69{
70 type Service = T::Response;
71
72 fn into_object(self) -> ServiceObj {
73 Box::new(Container {
74 inner: self,
75 _t: PhantomData,
76 })
77 }
78}