doido_controller/
route_table.rs1use std::sync::Mutex;
10
11#[derive(Clone, Debug, PartialEq, Eq)]
13pub struct RouteEntry {
14 pub method: String,
16 pub path: String,
18}
19
20static ROUTES: Mutex<Vec<RouteEntry>> = Mutex::new(Vec::new());
21
22pub fn register_routes(entries: Vec<RouteEntry>) {
25 if let Ok(mut guard) = ROUTES.lock() {
26 *guard = entries;
27 }
28}
29
30pub fn all_routes() -> Vec<RouteEntry> {
32 ROUTES.lock().map(|g| g.clone()).unwrap_or_default()
33}
34
35pub fn format_routes() -> String {
37 let routes = all_routes();
38 if routes.is_empty() {
39 return "No routes defined.".to_string();
40 }
41 let width = routes.iter().map(|r| r.method.len()).max().unwrap_or(0);
42 let mut out = String::new();
43 out.push_str(&format!(
44 "{:<width$} {}\n",
45 "METHOD",
46 "PATH",
47 width = width
48 ));
49 for r in &routes {
50 out.push_str(&format!(
51 "{:<width$} {}\n",
52 r.method,
53 r.path,
54 width = width
55 ));
56 }
57 out
58}
59
60pub fn print_routes() {
65 print!("{}", format_routes());
66}
67
68#[cfg(test)]
69mod tests {
70 use super::*;
71
72 #[test]
73 fn register_and_format_round_trip() {
74 register_routes(vec![
75 RouteEntry {
76 method: "GET".to_string(),
77 path: "/".to_string(),
78 },
79 RouteEntry {
80 method: "PUT|PATCH".to_string(),
81 path: "/posts/{id}".to_string(),
82 },
83 ]);
84
85 let entries = all_routes();
86 assert_eq!(entries.len(), 2);
87 assert_eq!(entries[0].path, "/");
88
89 let table = format_routes();
90 assert!(table.contains("METHOD"));
91 assert!(table.contains("GET /")); assert!(table.contains("PUT|PATCH /posts/{id}"));
93 }
94}