1use crate::extract::FromRequest;
58use crate::request::Request;
59use crate::response::{IntoResponse, Response};
60use rustapi_openapi::{Operation, OperationModifier, ResponseModifier};
61use std::future::Future;
62use std::marker::PhantomData;
63use std::pin::Pin;
64
65mod sealed {
66 pub trait Sealed {}
67
68 impl<T> Sealed for T where T: Clone + Send + Sync + Sized + 'static {}
69}
70
71pub trait Handler<T>: sealed::Sealed + Clone + Send + Sync + Sized + 'static {
73 type Future: Future<Output = Response> + Send + 'static;
75
76 fn call(self, req: Request) -> Self::Future;
78
79 fn update_operation(op: &mut Operation);
81}
82
83pub struct HandlerService<H, T> {
85 handler: H,
86 _marker: PhantomData<fn() -> T>,
87}
88
89impl<H, T> HandlerService<H, T> {
90 pub fn new(handler: H) -> Self {
91 Self {
92 handler,
93 _marker: PhantomData,
94 }
95 }
96}
97
98impl<H: Clone, T> Clone for HandlerService<H, T> {
99 fn clone(&self) -> Self {
100 Self {
101 handler: self.handler.clone(),
102 _marker: PhantomData,
103 }
104 }
105}
106
107impl<F, Fut, Res> Handler<()> for F
111where
112 F: FnOnce() -> Fut + Clone + Send + Sync + 'static,
113 Fut: Future<Output = Res> + Send + 'static,
114 Res: IntoResponse + ResponseModifier,
115{
116 type Future = Pin<Box<dyn Future<Output = Response> + Send>>;
117
118 fn call(self, _req: Request) -> Self::Future {
119 Box::pin(async move { self().await.into_response() })
120 }
121
122 fn update_operation(op: &mut Operation) {
123 Res::update_response(op);
124 }
125}
126
127impl<F, Fut, Res, T1> Handler<(T1,)> for F
129where
130 F: FnOnce(T1) -> Fut + Clone + Send + Sync + 'static,
131 Fut: Future<Output = Res> + Send + 'static,
132 Res: IntoResponse + ResponseModifier,
133 T1: FromRequest + OperationModifier + Send + 'static,
134{
135 type Future = Pin<Box<dyn Future<Output = Response> + Send>>;
136
137 fn call(self, mut req: Request) -> Self::Future {
138 Box::pin(async move {
139 let t1 = match T1::from_request(&mut req).await {
140 Ok(v) => v,
141 Err(e) => return e.into_response(),
142 };
143 self(t1).await.into_response()
144 })
145 }
146
147 fn update_operation(op: &mut Operation) {
148 T1::update_operation(op);
149 Res::update_response(op);
150 }
151}
152
153impl<F, Fut, Res, T1, T2> Handler<(T1, T2)> for F
155where
156 F: FnOnce(T1, T2) -> Fut + Clone + Send + Sync + 'static,
157 Fut: Future<Output = Res> + Send + 'static,
158 Res: IntoResponse + ResponseModifier,
159 T1: FromRequest + OperationModifier + Send + 'static,
160 T2: FromRequest + OperationModifier + Send + 'static,
161{
162 type Future = Pin<Box<dyn Future<Output = Response> + Send>>;
163
164 fn call(self, mut req: Request) -> Self::Future {
165 Box::pin(async move {
166 let t1 = match T1::from_request(&mut req).await {
167 Ok(v) => v,
168 Err(e) => return e.into_response(),
169 };
170 let t2 = match T2::from_request(&mut req).await {
171 Ok(v) => v,
172 Err(e) => return e.into_response(),
173 };
174 self(t1, t2).await.into_response()
175 })
176 }
177
178 fn update_operation(op: &mut Operation) {
179 T1::update_operation(op);
180 T2::update_operation(op);
181 Res::update_response(op);
182 }
183}
184
185impl<F, Fut, Res, T1, T2, T3> Handler<(T1, T2, T3)> for F
187where
188 F: FnOnce(T1, T2, T3) -> Fut + Clone + Send + Sync + 'static,
189 Fut: Future<Output = Res> + Send + 'static,
190 Res: IntoResponse + ResponseModifier,
191 T1: FromRequest + OperationModifier + Send + 'static,
192 T2: FromRequest + OperationModifier + Send + 'static,
193 T3: FromRequest + OperationModifier + Send + 'static,
194{
195 type Future = Pin<Box<dyn Future<Output = Response> + Send>>;
196
197 fn call(self, mut req: Request) -> Self::Future {
198 Box::pin(async move {
199 let t1 = match T1::from_request(&mut req).await {
200 Ok(v) => v,
201 Err(e) => return e.into_response(),
202 };
203 let t2 = match T2::from_request(&mut req).await {
204 Ok(v) => v,
205 Err(e) => return e.into_response(),
206 };
207 let t3 = match T3::from_request(&mut req).await {
208 Ok(v) => v,
209 Err(e) => return e.into_response(),
210 };
211 self(t1, t2, t3).await.into_response()
212 })
213 }
214
215 fn update_operation(op: &mut Operation) {
216 T1::update_operation(op);
217 T2::update_operation(op);
218 T3::update_operation(op);
219 Res::update_response(op);
220 }
221}
222
223impl<F, Fut, Res, T1, T2, T3, T4> Handler<(T1, T2, T3, T4)> for F
225where
226 F: FnOnce(T1, T2, T3, T4) -> Fut + Clone + Send + Sync + 'static,
227 Fut: Future<Output = Res> + Send + 'static,
228 Res: IntoResponse + ResponseModifier,
229 T1: FromRequest + OperationModifier + Send + 'static,
230 T2: FromRequest + OperationModifier + Send + 'static,
231 T3: FromRequest + OperationModifier + Send + 'static,
232 T4: FromRequest + OperationModifier + Send + 'static,
233{
234 type Future = Pin<Box<dyn Future<Output = Response> + Send>>;
235
236 fn call(self, mut req: Request) -> Self::Future {
237 Box::pin(async move {
238 let t1 = match T1::from_request(&mut req).await {
239 Ok(v) => v,
240 Err(e) => return e.into_response(),
241 };
242 let t2 = match T2::from_request(&mut req).await {
243 Ok(v) => v,
244 Err(e) => return e.into_response(),
245 };
246 let t3 = match T3::from_request(&mut req).await {
247 Ok(v) => v,
248 Err(e) => return e.into_response(),
249 };
250 let t4 = match T4::from_request(&mut req).await {
251 Ok(v) => v,
252 Err(e) => return e.into_response(),
253 };
254 self(t1, t2, t3, t4).await.into_response()
255 })
256 }
257
258 fn update_operation(op: &mut Operation) {
259 T1::update_operation(op);
260 T2::update_operation(op);
261 T3::update_operation(op);
262 T4::update_operation(op);
263 Res::update_response(op);
264 }
265}
266
267impl<F, Fut, Res, T1, T2, T3, T4, T5> Handler<(T1, T2, T3, T4, T5)> for F
269where
270 F: FnOnce(T1, T2, T3, T4, T5) -> Fut + Clone + Send + Sync + 'static,
271 Fut: Future<Output = Res> + Send + 'static,
272 Res: IntoResponse + ResponseModifier,
273 T1: FromRequest + OperationModifier + Send + 'static,
274 T2: FromRequest + OperationModifier + Send + 'static,
275 T3: FromRequest + OperationModifier + Send + 'static,
276 T4: FromRequest + OperationModifier + Send + 'static,
277 T5: FromRequest + OperationModifier + Send + 'static,
278{
279 type Future = Pin<Box<dyn Future<Output = Response> + Send>>;
280
281 fn call(self, mut req: Request) -> Self::Future {
282 Box::pin(async move {
283 let t1 = match T1::from_request(&mut req).await {
284 Ok(v) => v,
285 Err(e) => return e.into_response(),
286 };
287 let t2 = match T2::from_request(&mut req).await {
288 Ok(v) => v,
289 Err(e) => return e.into_response(),
290 };
291 let t3 = match T3::from_request(&mut req).await {
292 Ok(v) => v,
293 Err(e) => return e.into_response(),
294 };
295 let t4 = match T4::from_request(&mut req).await {
296 Ok(v) => v,
297 Err(e) => return e.into_response(),
298 };
299 let t5 = match T5::from_request(&mut req).await {
300 Ok(v) => v,
301 Err(e) => return e.into_response(),
302 };
303 self(t1, t2, t3, t4, t5).await.into_response()
304 })
305 }
306
307 fn update_operation(op: &mut Operation) {
308 T1::update_operation(op);
309 T2::update_operation(op);
310 T3::update_operation(op);
311 T4::update_operation(op);
312 T5::update_operation(op);
313 Res::update_response(op);
314 }
315}
316
317pub(crate) type BoxedHandler =
319 std::sync::Arc<dyn Fn(Request) -> Pin<Box<dyn Future<Output = Response> + Send>> + Send + Sync>;
320
321pub(crate) fn into_boxed_handler<H, T>(handler: H) -> BoxedHandler
323where
324 H: Handler<T>,
325 T: 'static,
326{
327 std::sync::Arc::new(move |req| {
328 let handler = handler.clone();
329 Box::pin(async move { handler.call(req).await })
330 })
331}
332
333pub trait RouteHandler<T>: Handler<T> {
338 const PATH: &'static str;
340 const METHOD: &'static str;
342}
343
344pub struct Route {
346 pub(crate) path: &'static str,
347 pub(crate) method: &'static str,
348 pub(crate) handler: BoxedHandler,
349 pub(crate) operation: Operation,
350 pub(crate) param_schemas: std::collections::BTreeMap<String, String>,
353 pub(crate) error_responses: Vec<(u16, String)>,
355}
356
357impl Route {
358 pub fn new<H, T>(path: &'static str, method: &'static str, handler: H) -> Self
360 where
361 H: Handler<T>,
362 T: 'static,
363 {
364 let mut operation = Operation::new();
365 H::update_operation(&mut operation);
366
367 Self {
368 path,
369 method,
370 handler: into_boxed_handler(handler),
371 operation,
372 param_schemas: std::collections::BTreeMap::new(),
373 error_responses: Vec::new(),
374 }
375 }
376 pub fn summary(mut self, summary: impl Into<String>) -> Self {
378 self.operation = self.operation.summary(summary);
379 self
380 }
381
382 pub fn description(mut self, description: impl Into<String>) -> Self {
384 self.operation = self.operation.description(description);
385 self
386 }
387
388 pub fn tag(mut self, tag: impl Into<String>) -> Self {
390 self.operation.tags.push(tag.into());
391 self
392 }
393
394 pub fn path(&self) -> &str {
396 self.path
397 }
398
399 pub fn method(&self) -> &str {
401 self.method
402 }
403
404 pub fn param(mut self, name: impl Into<String>, schema_type: impl Into<String>) -> Self {
428 self.param_schemas.insert(name.into(), schema_type.into());
429 self
430 }
431
432 pub fn param_schemas(&self) -> &std::collections::BTreeMap<String, String> {
434 &self.param_schemas
435 }
436
437 pub fn error_response(mut self, status: u16, description: impl Into<String>) -> Self {
455 let desc = description.into();
456 self.error_responses.push((status, desc.clone()));
457
458 let mut content = std::collections::BTreeMap::new();
460 content.insert(
461 "application/json".to_string(),
462 rustapi_openapi::MediaType {
463 schema: Some(rustapi_openapi::SchemaRef::Ref {
464 reference: "#/components/schemas/ErrorSchema".to_string(),
465 }),
466 example: None,
467 },
468 );
469
470 self.operation.responses.insert(
471 status.to_string(),
472 rustapi_openapi::ResponseSpec {
473 description: desc,
474 content,
475 headers: std::collections::BTreeMap::new(),
476 },
477 );
478
479 self
480 }
481
482 pub fn error_responses(&self) -> &[(u16, String)] {
484 &self.error_responses
485 }
486}
487
488#[macro_export]
490macro_rules! route {
491 ($handler:ident) => {{
492 $crate::Route::new($handler::PATH, $handler::METHOD, $handler)
493 }};
494}
495
496pub fn get_route<H, T>(path: &'static str, handler: H) -> Route
498where
499 H: Handler<T>,
500 T: 'static,
501{
502 Route::new(path, "GET", handler)
503}
504
505pub fn post_route<H, T>(path: &'static str, handler: H) -> Route
507where
508 H: Handler<T>,
509 T: 'static,
510{
511 Route::new(path, "POST", handler)
512}
513
514pub fn put_route<H, T>(path: &'static str, handler: H) -> Route
516where
517 H: Handler<T>,
518 T: 'static,
519{
520 Route::new(path, "PUT", handler)
521}
522
523pub fn patch_route<H, T>(path: &'static str, handler: H) -> Route
525where
526 H: Handler<T>,
527 T: 'static,
528{
529 Route::new(path, "PATCH", handler)
530}
531
532pub fn delete_route<H, T>(path: &'static str, handler: H) -> Route
534where
535 H: Handler<T>,
536 T: 'static,
537{
538 Route::new(path, "DELETE", handler)
539}