Skip to main content

typeway_server/
serves.rs

1//! The [`Serves`] trait — compile-time check that a handler tuple covers an API.
2//!
3//! `Serves<A>` is implemented for tuples of [`BoundHandler`]
4//! that cover every endpoint in the API type `A`.
5
6use typeway_core::ApiSpec;
7
8use crate::handler_for::BoundHandler;
9use crate::router::Router;
10
11/// A tuple of bound handlers that fully covers an API specification.
12///
13/// If your API has 3 endpoints and you provide only 2 handlers, the compiler
14/// will reject it because `Serves<API>` won't be satisfied.
15#[diagnostic::on_unimplemented(
16    message = "the handler tuple does not match the API specification `{A}`",
17    label = "handler tuple does not implement `Serves<{A}>`",
18    note = "each endpoint in the API type needs a corresponding `BoundHandler` created via `bind!(handler)`",
19    note = "the handler tuple must have exactly one `bind!(handler)` for each endpoint"
20)]
21pub trait Serves<A: ApiSpec> {
22    /// Register all handlers into the router.
23    fn register(self, router: &mut Router);
24}
25
26// Generate Serves impls for tuples of BoundHandler matching tuples of endpoints.
27macro_rules! impl_serves_for_tuple {
28    ($(($E:ident, $idx:tt)),+) => {
29        impl<$($E: ApiSpec,)+> Serves<($($E,)+)> for ($(BoundHandler<$E>,)+) {
30            fn register(self, router: &mut Router) {
31                $(self.$idx.register_into(router);)+
32            }
33        }
34    };
35}
36
37impl_serves_for_tuple!((E0, 0));
38impl_serves_for_tuple!((E0, 0), (E1, 1));
39impl_serves_for_tuple!((E0, 0), (E1, 1), (E2, 2));
40impl_serves_for_tuple!((E0, 0), (E1, 1), (E2, 2), (E3, 3));
41impl_serves_for_tuple!((E0, 0), (E1, 1), (E2, 2), (E3, 3), (E4, 4));
42impl_serves_for_tuple!((E0, 0), (E1, 1), (E2, 2), (E3, 3), (E4, 4), (E5, 5));
43impl_serves_for_tuple!(
44    (E0, 0),
45    (E1, 1),
46    (E2, 2),
47    (E3, 3),
48    (E4, 4),
49    (E5, 5),
50    (E6, 6)
51);
52impl_serves_for_tuple!(
53    (E0, 0),
54    (E1, 1),
55    (E2, 2),
56    (E3, 3),
57    (E4, 4),
58    (E5, 5),
59    (E6, 6),
60    (E7, 7)
61);
62impl_serves_for_tuple!(
63    (E0, 0),
64    (E1, 1),
65    (E2, 2),
66    (E3, 3),
67    (E4, 4),
68    (E5, 5),
69    (E6, 6),
70    (E7, 7),
71    (E8, 8)
72);
73impl_serves_for_tuple!(
74    (E0, 0),
75    (E1, 1),
76    (E2, 2),
77    (E3, 3),
78    (E4, 4),
79    (E5, 5),
80    (E6, 6),
81    (E7, 7),
82    (E8, 8),
83    (E9, 9)
84);
85impl_serves_for_tuple!(
86    (E0, 0),
87    (E1, 1),
88    (E2, 2),
89    (E3, 3),
90    (E4, 4),
91    (E5, 5),
92    (E6, 6),
93    (E7, 7),
94    (E8, 8),
95    (E9, 9),
96    (E10, 10)
97);
98impl_serves_for_tuple!(
99    (E0, 0),
100    (E1, 1),
101    (E2, 2),
102    (E3, 3),
103    (E4, 4),
104    (E5, 5),
105    (E6, 6),
106    (E7, 7),
107    (E8, 8),
108    (E9, 9),
109    (E10, 10),
110    (E11, 11)
111);
112impl_serves_for_tuple!(
113    (E0, 0),
114    (E1, 1),
115    (E2, 2),
116    (E3, 3),
117    (E4, 4),
118    (E5, 5),
119    (E6, 6),
120    (E7, 7),
121    (E8, 8),
122    (E9, 9),
123    (E10, 10),
124    (E11, 11),
125    (E12, 12)
126);
127impl_serves_for_tuple!(
128    (E0, 0),
129    (E1, 1),
130    (E2, 2),
131    (E3, 3),
132    (E4, 4),
133    (E5, 5),
134    (E6, 6),
135    (E7, 7),
136    (E8, 8),
137    (E9, 9),
138    (E10, 10),
139    (E11, 11),
140    (E12, 12),
141    (E13, 13)
142);
143impl_serves_for_tuple!(
144    (E0, 0),
145    (E1, 1),
146    (E2, 2),
147    (E3, 3),
148    (E4, 4),
149    (E5, 5),
150    (E6, 6),
151    (E7, 7),
152    (E8, 8),
153    (E9, 9),
154    (E10, 10),
155    (E11, 11),
156    (E12, 12),
157    (E13, 13),
158    (E14, 14)
159);
160impl_serves_for_tuple!(
161    (E0, 0),
162    (E1, 1),
163    (E2, 2),
164    (E3, 3),
165    (E4, 4),
166    (E5, 5),
167    (E6, 6),
168    (E7, 7),
169    (E8, 8),
170    (E9, 9),
171    (E10, 10),
172    (E11, 11),
173    (E12, 12),
174    (E13, 13),
175    (E14, 14),
176    (E15, 15)
177);
178
179// Extended to arity 20 for large APIs.
180impl_serves_for_tuple!(
181    (E0, 0),
182    (E1, 1),
183    (E2, 2),
184    (E3, 3),
185    (E4, 4),
186    (E5, 5),
187    (E6, 6),
188    (E7, 7),
189    (E8, 8),
190    (E9, 9),
191    (E10, 10),
192    (E11, 11),
193    (E12, 12),
194    (E13, 13),
195    (E14, 14),
196    (E15, 15),
197    (E16, 16)
198);
199impl_serves_for_tuple!(
200    (E0, 0),
201    (E1, 1),
202    (E2, 2),
203    (E3, 3),
204    (E4, 4),
205    (E5, 5),
206    (E6, 6),
207    (E7, 7),
208    (E8, 8),
209    (E9, 9),
210    (E10, 10),
211    (E11, 11),
212    (E12, 12),
213    (E13, 13),
214    (E14, 14),
215    (E15, 15),
216    (E16, 16),
217    (E17, 17)
218);
219impl_serves_for_tuple!(
220    (E0, 0),
221    (E1, 1),
222    (E2, 2),
223    (E3, 3),
224    (E4, 4),
225    (E5, 5),
226    (E6, 6),
227    (E7, 7),
228    (E8, 8),
229    (E9, 9),
230    (E10, 10),
231    (E11, 11),
232    (E12, 12),
233    (E13, 13),
234    (E14, 14),
235    (E15, 15),
236    (E16, 16),
237    (E17, 17),
238    (E18, 18)
239);
240impl_serves_for_tuple!(
241    (E0, 0),
242    (E1, 1),
243    (E2, 2),
244    (E3, 3),
245    (E4, 4),
246    (E5, 5),
247    (E6, 6),
248    (E7, 7),
249    (E8, 8),
250    (E9, 9),
251    (E10, 10),
252    (E11, 11),
253    (E12, 12),
254    (E13, 13),
255    (E14, 14),
256    (E15, 15),
257    (E16, 16),
258    (E17, 17),
259    (E18, 18),
260    (E19, 19)
261);
262impl_serves_for_tuple!(
263    (E0, 0),
264    (E1, 1),
265    (E2, 2),
266    (E3, 3),
267    (E4, 4),
268    (E5, 5),
269    (E6, 6),
270    (E7, 7),
271    (E8, 8),
272    (E9, 9),
273    (E10, 10),
274    (E11, 11),
275    (E12, 12),
276    (E13, 13),
277    (E14, 14),
278    (E15, 15),
279    (E16, 16),
280    (E17, 17),
281    (E18, 18),
282    (E19, 19),
283    (E20, 20)
284);
285impl_serves_for_tuple!(
286    (E0, 0),
287    (E1, 1),
288    (E2, 2),
289    (E3, 3),
290    (E4, 4),
291    (E5, 5),
292    (E6, 6),
293    (E7, 7),
294    (E8, 8),
295    (E9, 9),
296    (E10, 10),
297    (E11, 11),
298    (E12, 12),
299    (E13, 13),
300    (E14, 14),
301    (E15, 15),
302    (E16, 16),
303    (E17, 17),
304    (E18, 18),
305    (E19, 19),
306    (E20, 20),
307    (E21, 21)
308);
309impl_serves_for_tuple!(
310    (E0, 0),
311    (E1, 1),
312    (E2, 2),
313    (E3, 3),
314    (E4, 4),
315    (E5, 5),
316    (E6, 6),
317    (E7, 7),
318    (E8, 8),
319    (E9, 9),
320    (E10, 10),
321    (E11, 11),
322    (E12, 12),
323    (E13, 13),
324    (E14, 14),
325    (E15, 15),
326    (E16, 16),
327    (E17, 17),
328    (E18, 18),
329    (E19, 19),
330    (E20, 20),
331    (E21, 21),
332    (E22, 22)
333);
334impl_serves_for_tuple!(
335    (E0, 0),
336    (E1, 1),
337    (E2, 2),
338    (E3, 3),
339    (E4, 4),
340    (E5, 5),
341    (E6, 6),
342    (E7, 7),
343    (E8, 8),
344    (E9, 9),
345    (E10, 10),
346    (E11, 11),
347    (E12, 12),
348    (E13, 13),
349    (E14, 14),
350    (E15, 15),
351    (E16, 16),
352    (E17, 17),
353    (E18, 18),
354    (E19, 19),
355    (E20, 20),
356    (E21, 21),
357    (E22, 22),
358    (E23, 23)
359);
360impl_serves_for_tuple!(
361    (E0, 0),
362    (E1, 1),
363    (E2, 2),
364    (E3, 3),
365    (E4, 4),
366    (E5, 5),
367    (E6, 6),
368    (E7, 7),
369    (E8, 8),
370    (E9, 9),
371    (E10, 10),
372    (E11, 11),
373    (E12, 12),
374    (E13, 13),
375    (E14, 14),
376    (E15, 15),
377    (E16, 16),
378    (E17, 17),
379    (E18, 18),
380    (E19, 19),
381    (E20, 20),
382    (E21, 21),
383    (E22, 22),
384    (E23, 23),
385    (E24, 24)
386);
387
388// VersionedApi<Base, Changes, Resolved> delegates Serves to the resolved API type.
389// This allows EffectfulServer::<VersionedApi<V1, Changes, V2Resolved>>::new(handlers)
390// where handlers: Serves<V2Resolved>.
391impl<B, C, R: ApiSpec, H: Serves<R>> Serves<typeway_core::versioning::VersionedApi<B, C, R>> for H {
392    fn register(self, router: &mut Router) {
393        <H as Serves<R>>::register(self, router)
394    }
395}
396
397// ---------------------------------------------------------------------------
398// Nested API composition — for APIs with more than 22 endpoints.
399//
400// Use `SubApi<A, H>` to compose sub-APIs with their handlers:
401//
402//   type FullAPI = (UsersAPI, OrdersAPI);
403//   Server::<FullAPI>::new((
404//       SubApi::<UsersAPI, _>::new((bind!(get_users), bind!(create_user))),
405//       SubApi::<OrdersAPI, _>::new((bind!(get_orders),)),
406//   ))
407// ---------------------------------------------------------------------------
408
409/// A wrapper that pairs a sub-API with its handler tuple.
410///
411/// Allows composing APIs larger than 22 endpoints by nesting sub-APIs.
412///
413/// # Example
414///
415/// ```ignore
416/// type UsersAPI = (GetEndpoint<UsersPath, Vec<User>>, PostEndpoint<UsersPath, CreateUser, User>);
417/// type OrdersAPI = (GetEndpoint<OrdersPath, Vec<Order>>,);
418/// type FullAPI = (UsersAPI, OrdersAPI);
419///
420/// Server::<FullAPI>::new((
421///     SubApi::<UsersAPI, _>::new((bind!(list_users), bind!(create_user))),
422///     SubApi::<OrdersAPI, _>::new((bind!(list_orders),)),
423/// ))
424/// ```
425/// A wrapper that pairs a sub-API type with its handler tuple for
426/// nested API composition.
427pub struct SubApi<A: ApiSpec, H> {
428    handlers: H,
429    _api: std::marker::PhantomData<A>,
430}
431
432impl<A: ApiSpec, H> SubApi<A, H> {
433    pub fn new(handlers: H) -> Self {
434        SubApi {
435            handlers,
436            _api: std::marker::PhantomData,
437        }
438    }
439}
440
441impl<A: ApiSpec, H: Serves<A>> SubApi<A, H> {
442    /// Register all handlers from this sub-API into the router.
443    pub fn register_into(self, router: &mut Router) {
444        self.handlers.register(router);
445    }
446}
447
448// SubApi<A, H> implements Serves<A> — but we need to avoid the VersionedApi conflict.
449// Instead, we generate Serves impls for tuples of SubApi via a macro:
450
451macro_rules! impl_serves_for_subapi_tuple {
452    ($(($A:ident, $H:ident, $idx:tt)),+) => {
453        impl<$($A: ApiSpec, $H: Serves<$A>,)+> Serves<($($A,)+)> for ($(SubApi<$A, $H>,)+) {
454            fn register(self, router: &mut Router) {
455                $(self.$idx.register_into(router);)+
456            }
457        }
458    };
459}
460
461impl_serves_for_subapi_tuple!((A0, H0, 0), (A1, H1, 1));
462impl_serves_for_subapi_tuple!((A0, H0, 0), (A1, H1, 1), (A2, H2, 2));
463impl_serves_for_subapi_tuple!((A0, H0, 0), (A1, H1, 1), (A2, H2, 2), (A3, H3, 3));
464impl_serves_for_subapi_tuple!(
465    (A0, H0, 0),
466    (A1, H1, 1),
467    (A2, H2, 2),
468    (A3, H3, 3),
469    (A4, H4, 4)
470);
471impl_serves_for_subapi_tuple!(
472    (A0, H0, 0),
473    (A1, H1, 1),
474    (A2, H2, 2),
475    (A3, H3, 3),
476    (A4, H4, 4),
477    (A5, H5, 5)
478);
479impl_serves_for_subapi_tuple!(
480    (A0, H0, 0),
481    (A1, H1, 1),
482    (A2, H2, 2),
483    (A3, H3, 3),
484    (A4, H4, 4),
485    (A5, H5, 5),
486    (A6, H6, 6)
487);
488impl_serves_for_subapi_tuple!(
489    (A0, H0, 0),
490    (A1, H1, 1),
491    (A2, H2, 2),
492    (A3, H3, 3),
493    (A4, H4, 4),
494    (A5, H5, 5),
495    (A6, H6, 6),
496    (A7, H7, 7)
497);
498impl_serves_for_subapi_tuple!(
499    (A0, H0, 0),
500    (A1, H1, 1),
501    (A2, H2, 2),
502    (A3, H3, 3),
503    (A4, H4, 4),
504    (A5, H5, 5),
505    (A6, H6, 6),
506    (A7, H7, 7),
507    (A8, H8, 8)
508);
509impl_serves_for_subapi_tuple!(
510    (A0, H0, 0),
511    (A1, H1, 1),
512    (A2, H2, 2),
513    (A3, H3, 3),
514    (A4, H4, 4),
515    (A5, H5, 5),
516    (A6, H6, 6),
517    (A7, H7, 7),
518    (A8, H8, 8),
519    (A9, H9, 9)
520);