1use std::convert::Infallible;
27use std::marker::PhantomData;
28use std::sync::Arc;
29
30use typeway_core::effects::{AllProvided, ECons, ENil, Effect};
31use typeway_core::ApiSpec;
32
33use crate::body::BoxBody;
34use crate::router::{Router, RouterService};
35use crate::serves::Serves;
36
37pub struct MNil;
43
44pub struct MCons<A, Tail>(PhantomData<(A, Tail)>);
46
47pub struct MHere;
51
52pub struct MThere<T>(PhantomData<T>);
54
55pub trait HasMount<A, Idx> {}
57
58impl<A, Tail> HasMount<A, MHere> for MCons<A, Tail> {}
59
60impl<A, Head, Tail, Idx> HasMount<A, MThere<Idx>> for MCons<Head, Tail> where Tail: HasMount<A, Idx> {}
61
62#[diagnostic::on_unimplemented(
67 message = "not all sub-APIs have been mounted for `{Self}`",
68 label = "some sub-APIs are missing — add more .mount() calls",
69 note = "each sub-API in the API type must have a corresponding .mount() call"
70)]
71pub trait AllMounted<M, Idx> {}
72
73impl<M> AllMounted<M, ()> for () {}
75
76macro_rules! impl_all_mounted_for_tuple {
78 ($($T:ident, $I:ident);+) => {
79 impl<Mounted, $($T: ApiSpec, $I,)+> AllMounted<Mounted, ($($I,)+)> for ($($T,)+)
80 where $(Mounted: HasMount<$T, $I>,)+ {}
81 };
82}
83
84impl_all_mounted_for_tuple!(A, IA);
85impl_all_mounted_for_tuple!(A, IA; B, IB);
86impl_all_mounted_for_tuple!(A, IA; B, IB; C, IC);
87impl_all_mounted_for_tuple!(A, IA; B, IB; C, IC; D, ID);
88impl_all_mounted_for_tuple!(A, IA; B, IB; C, IC; D, ID; E, IE);
89impl_all_mounted_for_tuple!(A, IA; B, IB; C, IC; D, ID; E, IE; F, IF);
90impl_all_mounted_for_tuple!(A, IA; B, IB; C, IC; D, ID; E, IE; F, IF; G, IG);
91impl_all_mounted_for_tuple!(A, IA; B, IB; C, IC; D, ID; E, IE; F, IF; G, IG; H, IH);
92impl_all_mounted_for_tuple!(A, IA; B, IB; C, IC; D, ID; E, IE; F, IF; G, IG; H, IH; I, II);
93impl_all_mounted_for_tuple!(A, IA; B, IB; C, IC; D, ID; E, IE; F, IF; G, IG; H, IH; I, II; J, IJ);
94
95pub struct ServerBuilder<A: ApiSpec, Mounted = MNil, Provided = ENil> {
122 router: Router,
123 _api: PhantomData<A>,
124 _mounted: PhantomData<Mounted>,
125 _provided: PhantomData<Provided>,
126}
127
128impl<A: ApiSpec> ServerBuilder<A, MNil, ENil> {
129 pub fn new() -> Self {
131 ServerBuilder {
132 router: Router::new(),
133 _api: PhantomData,
134 _mounted: PhantomData,
135 _provided: PhantomData,
136 }
137 }
138}
139
140impl<A: ApiSpec, M, P> ServerBuilder<A, M, P> {
141 pub fn mount<Sub: ApiSpec, H: Serves<Sub>>(
145 mut self,
146 handlers: H,
147 ) -> ServerBuilder<A, MCons<Sub, M>, P> {
148 handlers.register(&mut self.router);
149 ServerBuilder {
150 router: self.router,
151 _api: PhantomData,
152 _mounted: PhantomData,
153 _provided: PhantomData,
154 }
155 }
156
157 pub fn provide<E: Effect>(self) -> ServerBuilder<A, M, ECons<E, P>> {
162 ServerBuilder {
163 router: self.router,
164 _api: PhantomData,
165 _mounted: PhantomData,
166 _provided: PhantomData,
167 }
168 }
169
170 pub fn layer<L>(self, layer: L) -> LayeredServerBuilder<A, M, P, L::Service>
176 where
177 L: tower_layer::Layer<RouterService>,
178 L::Service: tower_service::Service<
179 http::Request<hyper::body::Incoming>,
180 Response = http::Response<BoxBody>,
181 Error = Infallible,
182 > + Clone
183 + Send
184 + 'static,
185 <L::Service as tower_service::Service<http::Request<hyper::body::Incoming>>>::Future:
186 Send + 'static,
187 {
188 let router = Arc::new(self.router);
189 let svc = RouterService::new(router.clone());
190 let layered = layer.layer(svc);
191 LayeredServerBuilder {
192 service: layered,
193 router,
194 _api: PhantomData,
195 _mounted: PhantomData,
196 _provided: PhantomData,
197 }
198 }
199
200 pub fn with_state<T: Clone + Send + Sync + 'static>(self, state: T) -> Self {
202 self.router.set_state_injector(Arc::new(move |ext| {
203 ext.insert(state.clone());
204 }));
205 self
206 }
207
208 pub fn max_body_size(self, max: usize) -> Self {
210 self.router.set_max_body_size(max);
211 self
212 }
213
214 pub fn build<MIdx, PIdx>(self) -> crate::server::Server<A>
220 where
221 A: AllMounted<M, MIdx>,
222 A: AllProvided<P, PIdx>,
223 {
224 crate::server::Server::from_router(Arc::new(self.router))
225 }
226}
227
228pub struct LayeredServerBuilder<A: ApiSpec, Mounted, Provided, S> {
233 service: S,
234 router: Arc<Router>,
235 _api: PhantomData<A>,
236 _mounted: PhantomData<Mounted>,
237 _provided: PhantomData<Provided>,
238}
239
240impl<A: ApiSpec, M, P, S> LayeredServerBuilder<A, M, P, S> {
241 pub fn provide<E: Effect>(self) -> LayeredServerBuilder<A, M, ECons<E, P>, S> {
243 LayeredServerBuilder {
244 service: self.service,
245 router: self.router,
246 _api: PhantomData,
247 _mounted: PhantomData,
248 _provided: PhantomData,
249 }
250 }
251}
252
253impl<A: ApiSpec, M, P, S> LayeredServerBuilder<A, M, P, S>
254where
255 S: tower_service::Service<
256 http::Request<hyper::body::Incoming>,
257 Response = http::Response<BoxBody>,
258 Error = Infallible,
259 > + Clone
260 + Send
261 + 'static,
262 S::Future: Send + 'static,
263{
264 pub fn build<MIdx, PIdx>(self) -> crate::server::LayeredServer<S>
268 where
269 A: AllMounted<M, MIdx>,
270 A: AllProvided<P, PIdx>,
271 {
272 crate::server::LayeredServer {
273 service: self.service,
274 router: self.router,
275 }
276 }
277
278 pub fn layer<L>(self, layer: L) -> LayeredServerBuilder<A, M, P, L::Service>
280 where
281 L: tower_layer::Layer<S>,
282 L::Service: tower_service::Service<
283 http::Request<hyper::body::Incoming>,
284 Response = http::Response<BoxBody>,
285 Error = Infallible,
286 > + Clone
287 + Send
288 + 'static,
289 <L::Service as tower_service::Service<http::Request<hyper::body::Incoming>>>::Future:
290 Send + 'static,
291 {
292 LayeredServerBuilder {
293 service: layer.layer(self.service),
294 router: self.router,
295 _api: PhantomData,
296 _mounted: PhantomData,
297 _provided: PhantomData,
298 }
299 }
300}
301
302impl<A: ApiSpec> Default for ServerBuilder<A, MNil, ENil> {
303 fn default() -> Self {
304 Self::new()
305 }
306}