mincat_core/
router.rs

1use std::{borrow::BorrowMut, collections::HashMap, fmt::Debug};
2
3use http::Method;
4
5use crate::{handler::Handler, middleware::Middleware, route::Route};
6
7#[derive(Clone, Debug, Default)]
8pub struct Endpoint {
9    path: String,
10    method_handler: HashMap<Method, Handler>,
11}
12
13impl Endpoint {
14    fn new() -> Self {
15        Self::default()
16    }
17
18    fn path(&mut self, path: &str) -> Self {
19        self.path = path.to_owned();
20        self.clone()
21    }
22
23    fn method_handler(&mut self, method: &Method, handler: &Handler) -> Self {
24        self.method_handler.insert(method.clone(), handler.clone());
25        self.clone()
26    }
27}
28
29#[derive(Clone, Default)]
30pub struct Router {
31    index: usize,
32    index_endpoint: HashMap<usize, Endpoint>,
33    path_index: matchit::Router<usize>,
34}
35
36impl Debug for Router {
37    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
38        f.debug_struct("Router")
39            .field("index", &self.index)
40            .field("index_endpoint", &self.index_endpoint)
41            .finish()
42    }
43}
44
45impl Router {
46    pub fn new() -> Self {
47        Self::default()
48    }
49
50    pub fn group(&mut self, path: &str, router: Router) -> Self {
51        if !path.starts_with('/') {
52            panic!("group routes must start with '/'");
53        }
54
55        for (_, endpoint) in router.index_endpoint {
56            let path = format!("{}{}", path, endpoint.path);
57            for (method, hadnler) in endpoint.method_handler {
58                self.route((method, path.clone(), hadnler));
59            }
60        }
61
62        self.clone()
63    }
64
65    pub fn route<T>(&mut self, route: T) -> Self
66    where
67        T: Into<Route>,
68    {
69        let Route {
70            method,
71            path,
72            handler,
73        } = route.into();
74
75        if let Ok(matched) = self.path_index.at(&path) {
76            if let Some(endpoint) = self.index_endpoint.get_mut(matched.value) {
77                endpoint.method_handler.insert(method, handler);
78            }
79        } else {
80            let index = self.index;
81            self.path_index
82                .insert(&path, index)
83                .expect("path_index insert failed");
84            let endpoint = Endpoint::new()
85                .path(&path)
86                .method_handler(&method, &handler);
87            self.index_endpoint.insert(index, endpoint);
88            self.index += 1;
89        };
90
91        self.clone()
92    }
93
94    pub fn merge(&mut self, router: Router) -> Self {
95        for (_, endpoint) in router.index_endpoint {
96            for (method, hadnler) in endpoint.method_handler {
97                self.route((method, endpoint.path.clone(), hadnler));
98            }
99        }
100
101        self.clone()
102    }
103
104    pub fn get_handler(&self, method: &Method, path: &str) -> Option<(String, Handler)> {
105        if let Ok(matchit) = self.path_index.at(path) {
106            if let Some(endpoint) = self.index_endpoint.get(matchit.value) {
107                if let Some(handler) = endpoint.method_handler.get(method) {
108                    return Some((endpoint.path.clone(), handler.clone()));
109                }
110            }
111        }
112
113        None
114    }
115
116    pub fn middleware<T>(&mut self, middleware: T) -> Self
117    where
118        T: Into<Box<dyn Middleware>>,
119    {
120        let middleware = middleware.into();
121        for endpoint in self.index_endpoint.borrow_mut().values_mut() {
122            for handler in endpoint.method_handler.borrow_mut().values_mut() {
123                handler.middleware(middleware.clone());
124            }
125        }
126
127        self.clone()
128    }
129}