xitca_server/server/
service.rs

1use 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
53/// helper trait for erase generic params of [Service]
54pub 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}