1use std::{collections::VecDeque, fmt::Debug, future::Future, marker::PhantomData};
2
3use mincat_macro::repeat_macro_max_generics_param;
4
5use crate::{
6 middleware::Middleware,
7 next::Next,
8 request::{FromRequest, FromRequestParts, Request},
9 response::{IntoResponse, Response},
10};
11
12#[derive(Clone)]
13pub struct Handler {
14 pub func: Box<dyn HandlerFunc>,
15 pub middleware: Option<VecDeque<Box<dyn Middleware>>>,
16}
17
18impl Debug for Handler {
19 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
20 let mut middleware_len = 0;
21 if let Some(middleware) = &self.middleware {
22 middleware_len = middleware.len();
23 }
24
25 f.debug_struct("Handler")
26 .field("func", &"func")
27 .field("middleware", &middleware_len)
28 .finish()
29 }
30}
31
32impl Handler {
33 pub fn middleware<T>(&mut self, middleware: T) -> Self
34 where
35 T: Into<Box<dyn Middleware>>,
36 {
37 self.middleware
38 .get_or_insert(VecDeque::new())
39 .push_back(middleware.into());
40
41 self.clone()
42 }
43
44 pub async fn exectue(self, request: Request) -> Response {
45 Next::new(self).run(request).await
46 }
47}
48
49#[async_trait::async_trait]
50pub trait HandlerFunc: Send + Sync {
51 async fn call(self: Box<Self>, request: Request) -> Response;
52
53 fn clone_box(&self) -> Box<dyn HandlerFunc>;
54}
55
56impl Clone for Box<dyn HandlerFunc> {
57 fn clone(&self) -> Self {
58 self.clone_box()
59 }
60}
61
62#[async_trait::async_trait]
63pub trait HandlerFuncParam<Param>: Send {
64 async fn call(self, request: Request) -> Response;
65}
66
67#[derive(Clone)]
68pub struct FuncParamHandler<Func, Param>
69where
70 Func: HandlerFuncParam<Param>,
71{
72 func: Func,
73 _mark: PhantomData<Param>,
74}
75
76impl<Func, Param> From<Func> for FuncParamHandler<Func, Param>
77where
78 Func: HandlerFuncParam<Param>,
79{
80 fn from(value: Func) -> Self {
81 Self {
82 func: value,
83 _mark: PhantomData,
84 }
85 }
86}
87
88impl<Func, Param> From<FuncParamHandler<Func, Param>> for Handler
89where
90 Func: HandlerFuncParam<Param> + Clone + Sync + 'static,
91 Param: Send + Sync + 'static,
92{
93 fn from(value: FuncParamHandler<Func, Param>) -> Self {
94 Handler {
95 func: Box::new(value),
96 middleware: None,
97 }
98 }
99}
100
101#[async_trait::async_trait]
102impl<Func, Param> HandlerFunc for FuncParamHandler<Func, Param>
103where
104 Func: HandlerFuncParam<Param> + Clone + Sync + 'static,
105 Param: Send + Sync + 'static,
106{
107 async fn call(self: Box<Self>, request: Request) -> Response {
108 self.func.call(request).await
109 }
110
111 fn clone_box(&self) -> Box<dyn HandlerFunc> {
112 Box::new(Self {
113 func: self.func.clone(),
114 _mark: PhantomData,
115 })
116 }
117}
118
119#[async_trait::async_trait]
120impl<Func, Fut, Res> HandlerFuncParam<((),)> for Func
121where
122 Func: FnOnce() -> Fut,
123 Func: Clone + Send + Sync + 'static,
124 Fut: Future<Output = Res> + Send,
125 Res: IntoResponse,
126{
127 async fn call(self, _: Request) -> Response {
128 self().await.into_response()
129 }
130}
131
132macro_rules! handle_func_param {
133 ([$($param: ident),*], $lastparam:ident) => {
134 #[allow(non_snake_case)]
135 #[async_trait::async_trait]
136 impl<Func, Fut, Res, $($param,)* $lastparam> HandlerFuncParam<($($param,)* $lastparam,)> for Func
137 where
138 Func: FnOnce($($param,)* $lastparam,) -> Fut,
139 Func: Clone + Send + Sync + 'static,
140 Fut: Future<Output = Res> + Send,
141 Res: IntoResponse,
142 $($param: FromRequestParts + Send,)*
143 $lastparam: FromRequest + Send
144 {
145 async fn call(self, request: Request) -> Response {
146 #[allow(unused_mut)]
147 let (mut parts, body) = request.into_parts();
148
149 $(
150 let $param = match $param::from_request_parts(&mut parts).await {
151 Ok(v) => v,
152 Err(e) => return e.into_response(),
153 };
154 )*
155
156 let request = Request::from_parts(parts, body);
157
158 let $lastparam = match $lastparam::from_request(request).await {
159 Ok(v) => v,
160 Err(e) => return e.into_response(),
161 };
162
163 let res = self($($param,)* $lastparam,).await;
164
165 res.into_response()
166 }
167
168 }
169 }
170}
171
172macro_rules! handle_func_param_pre {
173 ($($param: ident),*) => {
174 handle_func_param!([$($param),*], T);
175 }
176}
177
178repeat_macro_max_generics_param!(handle_func_param_pre, 0, 17, P);