1use std::convert::Infallible;
29use std::future::Future;
30use std::marker::PhantomData;
31use std::net::SocketAddr;
32use std::sync::Arc;
33
34use typeway_core::effects::{AllProvided, ECons, ENil, Effect};
35use typeway_core::ApiSpec;
36
37use crate::body::BoxBody;
38use crate::router::{Router, RouterService};
39use crate::server::LayeredServer;
40use crate::serves::Serves;
41
42pub struct EffectfulServer<A: ApiSpec, Provided = ENil> {
52 router: Arc<Router>,
53 _api: PhantomData<A>,
54 _provided: PhantomData<Provided>,
55}
56
57impl<A: ApiSpec> EffectfulServer<A, ENil> {
58 pub fn new<H: Serves<A>>(handlers: H) -> Self {
63 let mut router = Router::new();
64 handlers.register(&mut router);
65 EffectfulServer {
66 router: Arc::new(router),
67 _api: PhantomData,
68 _provided: PhantomData,
69 }
70 }
71}
72
73impl<A: ApiSpec, P> EffectfulServer<A, P> {
74 pub fn provide<E: Effect>(self) -> EffectfulServer<A, ECons<E, P>> {
88 EffectfulServer {
89 router: self.router,
90 _api: PhantomData,
91 _provided: PhantomData,
92 }
93 }
94
95 pub fn nest(self, prefix: &str) -> Self {
97 self.router.set_prefix(prefix);
98 self
99 }
100
101 pub fn max_body_size(self, max: usize) -> Self {
103 self.router.set_max_body_size(max);
104 self
105 }
106
107 pub fn with_state<T: Clone + Send + Sync + 'static>(self, state: T) -> Self {
109 self.router.set_state_injector(Arc::new(move |ext| {
110 ext.insert(state.clone());
111 }));
112 self
113 }
114
115 pub fn layer<L>(self, layer: L) -> EffectfulLayeredServer<A, P, L::Service>
128 where
129 L: tower_layer::Layer<RouterService>,
130 L::Service: tower_service::Service<
131 http::Request<hyper::body::Incoming>,
132 Response = http::Response<BoxBody>,
133 Error = Infallible,
134 > + Clone
135 + Send
136 + 'static,
137 <L::Service as tower_service::Service<http::Request<hyper::body::Incoming>>>::Future:
138 Send + 'static,
139 {
140 let router = self.router.clone();
141 let svc = RouterService::new(self.router);
142 let layered = layer.layer(svc);
143 EffectfulLayeredServer {
144 service: layered,
145 router,
146 _api: PhantomData,
147 _provided: PhantomData,
148 }
149 }
150
151 pub fn ready<Idx>(self) -> crate::server::Server<A>
155 where
156 A: AllProvided<P, Idx>,
157 {
158 crate::server::Server::from_router(self.router)
159 }
160
161 pub async fn serve<Idx>(
166 self,
167 addr: SocketAddr,
168 ) -> Result<(), Box<dyn std::error::Error + Send + Sync>>
169 where
170 A: AllProvided<P, Idx>,
171 {
172 self.ready::<Idx>().serve(addr).await
173 }
174
175 pub async fn serve_with_shutdown<Idx>(
179 self,
180 listener: tokio::net::TcpListener,
181 shutdown: impl Future<Output = ()> + Send,
182 ) -> Result<(), Box<dyn std::error::Error + Send + Sync>>
183 where
184 A: AllProvided<P, Idx>,
185 {
186 self.ready::<Idx>()
187 .serve_with_shutdown(listener, shutdown)
188 .await
189 }
190}
191
192pub struct EffectfulLayeredServer<A: ApiSpec, Provided, S> {
197 service: S,
198 router: Arc<Router>,
199 _api: PhantomData<A>,
200 _provided: PhantomData<Provided>,
201}
202
203impl<A: ApiSpec, P, S> EffectfulLayeredServer<A, P, S> {
204 pub fn provide<E: Effect>(self) -> EffectfulLayeredServer<A, ECons<E, P>, S> {
206 EffectfulLayeredServer {
207 service: self.service,
208 router: self.router,
209 _api: PhantomData,
210 _provided: PhantomData,
211 }
212 }
213
214 pub fn with_state<T: Clone + Send + Sync + 'static>(self, state: T) -> Self {
216 self.router.set_state_injector(Arc::new(move |ext| {
217 ext.insert(state.clone());
218 }));
219 self
220 }
221
222 pub fn max_body_size(self, max: usize) -> Self {
224 self.router.set_max_body_size(max);
225 self
226 }
227
228 pub fn nest(self, prefix: &str) -> Self {
230 self.router.set_prefix(prefix);
231 self
232 }
233}
234
235impl<A: ApiSpec, P, S> EffectfulLayeredServer<A, P, S>
236where
237 S: tower_service::Service<
238 http::Request<hyper::body::Incoming>,
239 Response = http::Response<BoxBody>,
240 Error = Infallible,
241 > + Clone
242 + Send
243 + 'static,
244 S::Future: Send + 'static,
245{
246 pub fn layer<L>(self, layer: L) -> EffectfulLayeredServer<A, P, L::Service>
248 where
249 L: tower_layer::Layer<S>,
250 L::Service: tower_service::Service<
251 http::Request<hyper::body::Incoming>,
252 Response = http::Response<BoxBody>,
253 Error = Infallible,
254 > + Clone
255 + Send
256 + 'static,
257 <L::Service as tower_service::Service<http::Request<hyper::body::Incoming>>>::Future:
258 Send + 'static,
259 {
260 EffectfulLayeredServer {
261 service: layer.layer(self.service),
262 router: self.router,
263 _api: PhantomData,
264 _provided: PhantomData,
265 }
266 }
267}
268
269impl<A: ApiSpec, P, S> EffectfulLayeredServer<A, P, S>
270where
271 S: tower_service::Service<
272 http::Request<hyper::body::Incoming>,
273 Response = http::Response<BoxBody>,
274 Error = Infallible,
275 > + Clone
276 + Send
277 + 'static,
278 S::Future: Send + 'static,
279{
280 pub fn ready<Idx>(self) -> LayeredServer<S>
284 where
285 A: AllProvided<P, Idx>,
286 {
287 LayeredServer {
288 service: self.service,
289 router: self.router,
290 }
291 }
292
293 pub async fn serve<Idx>(
297 self,
298 addr: SocketAddr,
299 ) -> Result<(), Box<dyn std::error::Error + Send + Sync>>
300 where
301 A: AllProvided<P, Idx>,
302 {
303 self.ready::<Idx>().serve(addr).await
304 }
305
306 pub async fn serve_with_shutdown<Idx>(
310 self,
311 listener: tokio::net::TcpListener,
312 shutdown: impl Future<Output = ()> + Send,
313 ) -> Result<(), Box<dyn std::error::Error + Send + Sync>>
314 where
315 A: AllProvided<P, Idx>,
316 {
317 self.ready::<Idx>()
318 .serve_with_shutdown(listener, shutdown)
319 .await
320 }
321}