1mod raw_route;
2pub use raw_route::{HyperBody, HyperRequest, RawRoute};
3
4mod route;
5pub use route::{Route, RoutePath};
6
7mod router;
8use router::Router;
9
10mod catcher;
11pub use catcher::Catcher;
12
13mod path_params;
14pub use path_params::{ParamsNames, PathParams};
15
16use crate::header::Method;
17
18use std::slice;
19
20type BoxedRawRoute = Box<dyn RawRoute>;
21type BoxedRoute = Box<dyn Route>;
22type BoxedCatcher = Box<dyn Catcher>;
23
24pub struct Routes {
25 raw: Router<BoxedRawRoute>,
26 basic: Router<BoxedRoute>,
27 catcher: Vec<BoxedCatcher>,
28}
29
30impl Routes {
31 pub fn new() -> Self {
32 Self {
33 raw: Router::new(),
34 basic: Router::new(),
35 catcher: vec![],
36 }
37 }
38
39 #[track_caller]
40 pub fn push_raw<R>(&mut self, path: RoutePath, route: R)
41 where
42 R: RawRoute + 'static,
43 {
44 self.raw
45 .insert(path.method.as_ref(), path.path, Box::new(route))
46 .unwrap();
47 }
48
49 #[track_caller]
50 pub fn push<R>(&mut self, path: RoutePath, route: R)
51 where
52 R: Route + 'static,
53 {
54 self.basic
55 .insert(path.method.as_ref(), path.path, Box::new(route))
56 .unwrap();
57 }
58
59 pub fn push_catcher<C>(&mut self, catcher: C)
60 where
61 C: Catcher + 'static,
62 {
63 self.catcher.push(Box::new(catcher))
64 }
65
66 pub fn route_raw<'a>(
67 &'a self,
68 method: &Method,
69 path: &str,
70 ) -> Option<(&'a BoxedRawRoute, PathParams)> {
71 let (route, params) = self
72 .raw
73 .at(Some(method), path)
75 .or_else(|| self.raw.at(None, path))?;
76
77 Some((route, PathParams::new(params)))
78 }
79
80 pub fn route<'a>(
81 &'a self,
82 method: &Method,
83 path: &str,
84 ) -> Option<(&'a BoxedRoute, PathParams)> {
85 let (route, params) = self
86 .basic
87 .at(Some(method), path)
89 .or_else(|| self.basic.at(None, path))?;
90
91 Some((route, PathParams::new(params)))
92 }
93
94 pub fn catchers(&self) -> slice::Iter<'_, BoxedCatcher> {
95 self.catcher.iter()
96 }
97}