1use crate::extract::{FromRequest, FromRequestParts, Request};
13use crate::response::{IntoResponse, Response};
14use siderite_openapi::{Operation, SchemaRegistry};
15use std::future::Future;
16
17pub trait Handler<T>: Clone + Send + Sync + Sized + 'static {
19 const BACKGROUND_TASKS: bool = false;
21
22 fn call(self, req: Request) -> impl Future<Output = Response> + Send;
24
25 fn describe(op: &mut Operation, registry: &mut SchemaRegistry);
27}
28
29#[allow(clippy::manual_async_fn)]
30impl<F, Fut, R> Handler<(R,)> for F
31where
32 F: FnOnce() -> Fut + Clone + Send + Sync + 'static,
33 Fut: Future<Output = R> + Send,
34 R: IntoResponse,
35{
36 fn call(self, _req: Request) -> impl Future<Output = Response> + Send {
37 async move { self().await.into_response() }
38 }
39
40 fn describe(op: &mut Operation, registry: &mut SchemaRegistry) {
41 R::describe(op, registry);
42 }
43}
44
45macro_rules! impl_handler {
46 ($($p:ident),* ; $last:ident) => {
47 #[allow(non_snake_case, unused_mut)]
48 impl<F, Fut, R, $($p,)* $last> Handler<(R, $($p,)* $last)> for F
49 where
50 F: FnOnce($($p,)* $last) -> Fut + Clone + Send + Sync + 'static,
51 Fut: Future<Output = R> + Send,
52 R: IntoResponse,
53 $($p: FromRequestParts,)*
54 $last: FromRequest,
55 {
56 const BACKGROUND_TASKS: bool =
57 false $(|| <$p as FromRequestParts>::BACKGROUND_TASKS)*
58 || <$last as FromRequest>::BACKGROUND_TASKS;
59
60 fn call(self, req: Request) -> impl Future<Output = Response> + Send {
61 async move {
62 let (mut parts, body) = req.into_parts();
63 $(
64 let $p = match $p::from_request_parts(&mut parts).await {
65 Ok(value) => value,
66 Err(err) => return err.into_response(),
67 };
68 )*
69 let req = Request::from_parts(parts, body);
70 let $last = match $last::from_request(req).await {
71 Ok(value) => value,
72 Err(err) => return err.into_response(),
73 };
74 self($($p,)* $last).await.into_response()
75 }
76 }
77
78 fn describe(op: &mut Operation, registry: &mut SchemaRegistry) {
79 $(<$p as FromRequestParts>::describe(op, registry);)*
80 <$last as FromRequest>::describe(op, registry);
81 R::describe(op, registry);
82 }
83 }
84 };
85}
86
87impl_handler!(; A1);
88impl_handler!(A1; A2);
89impl_handler!(A1, A2; A3);
90impl_handler!(A1, A2, A3; A4);
91impl_handler!(A1, A2, A3, A4; A5);
92impl_handler!(A1, A2, A3, A4, A5; A6);
93impl_handler!(A1, A2, A3, A4, A5, A6; A7);
94impl_handler!(A1, A2, A3, A4, A5, A6, A7; A8);
95impl_handler!(A1, A2, A3, A4, A5, A6, A7, A8; A9);
96impl_handler!(A1, A2, A3, A4, A5, A6, A7, A8, A9; A10);
97impl_handler!(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10; A11);
98impl_handler!(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11; A12);