use std::sync::Mutex;
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct RouteEntry {
pub method: String,
pub path: String,
}
static ROUTES: Mutex<Vec<RouteEntry>> = Mutex::new(Vec::new());
pub fn register_routes(entries: Vec<RouteEntry>) {
if let Ok(mut guard) = ROUTES.lock() {
*guard = entries;
}
}
pub fn all_routes() -> Vec<RouteEntry> {
ROUTES.lock().map(|g| g.clone()).unwrap_or_default()
}
pub fn format_routes() -> String {
let routes = all_routes();
if routes.is_empty() {
return "No routes defined.".to_string();
}
let width = routes.iter().map(|r| r.method.len()).max().unwrap_or(0);
let mut out = String::new();
out.push_str(&format!(
"{:<width$} {}\n",
"METHOD",
"PATH",
width = width
));
for r in &routes {
out.push_str(&format!(
"{:<width$} {}\n",
r.method,
r.path,
width = width
));
}
out
}
pub fn print_routes() {
print!("{}", format_routes());
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn register_and_format_round_trip() {
register_routes(vec![
RouteEntry {
method: "GET".to_string(),
path: "/".to_string(),
},
RouteEntry {
method: "PUT|PATCH".to_string(),
path: "/posts/{id}".to_string(),
},
]);
let entries = all_routes();
assert_eq!(entries.len(), 2);
assert_eq!(entries[0].path, "/");
let table = format_routes();
assert!(table.contains("METHOD"));
assert!(table.contains("GET /")); assert!(table.contains("PUT|PATCH /posts/{id}"));
}
}