monolake_services/common/
context.rs1use std::marker::PhantomData;
42
43use certain_map::Handler;
44use monolake_core::{context::PeerAddr, listener::AcceptedAddr};
45use service_async::{
46 layer::{layer_fn, FactoryLayer},
47 AsyncMakeService, MakeService, ParamSet, Service,
48};
49
50#[derive(Debug)]
52pub struct ContextService<CXStore, T> {
53 pub inner: T,
54 pub ctx: PhantomData<CXStore>,
55}
56
57unsafe impl<CXStore, T: Send> Send for ContextService<CXStore, T> {}
58unsafe impl<CXStore, T: Sync> Sync for ContextService<CXStore, T> {}
59
60impl<CXStore, T> Clone for ContextService<CXStore, T>
62where
63 T: Clone,
64{
65 fn clone(&self) -> Self {
66 Self {
67 inner: self.inner.clone(),
68 ctx: PhantomData,
69 }
70 }
71}
72
73impl<CXStore, T> Copy for ContextService<CXStore, T> where T: Copy {}
75
76impl<R, T, CXStore, Resp, Err> Service<(R, AcceptedAddr)> for ContextService<CXStore, T>
77where
78 CXStore: Default + Handler,
79 for<'a> CXStore::Hdr<'a>: ParamSet<PeerAddr>,
83 for<'a> T: Service<
84 (R, <CXStore::Hdr<'a> as ParamSet<PeerAddr>>::Transformed),
85 Response = Resp,
86 Error = Err,
87 >,
88{
89 type Response = Resp;
90 type Error = Err;
91
92 async fn call(&self, (req, addr): (R, AcceptedAddr)) -> Result<Self::Response, Self::Error> {
93 let mut store = CXStore::default();
94 let hdr = store.handler();
95 let hdr = hdr.param_set(PeerAddr(addr));
96 self.inner.call((req, hdr)).await
97 }
98}
99
100impl<CX, F> ContextService<CX, F> {
101 pub fn layer<C>() -> impl FactoryLayer<C, F, Factory = Self> {
102 layer_fn(|_: &C, inner| ContextService {
103 inner,
104 ctx: PhantomData,
105 })
106 }
107}
108
109impl<CXStore, F: MakeService> MakeService for ContextService<CXStore, F> {
110 type Service = ContextService<CXStore, F::Service>;
111 type Error = F::Error;
112
113 fn make_via_ref(&self, old: Option<&Self::Service>) -> Result<Self::Service, Self::Error> {
114 Ok(ContextService {
115 ctx: PhantomData,
116 inner: self
117 .inner
118 .make_via_ref(old.map(|o| &o.inner))
119 .map_err(Into::into)?,
120 })
121 }
122}
123
124impl<CXStore, F: AsyncMakeService> AsyncMakeService for ContextService<CXStore, F> {
125 type Service = ContextService<CXStore, F::Service>;
126 type Error = F::Error;
127
128 async fn make_via_ref(
129 &self,
130 old: Option<&Self::Service>,
131 ) -> Result<Self::Service, Self::Error> {
132 Ok(ContextService {
133 ctx: PhantomData,
134 inner: self
135 .inner
136 .make_via_ref(old.map(|o| &o.inner))
137 .await
138 .map_err(Into::into)?,
139 })
140 }
141}