use std::{ collections::HashMap, future::IntoFuture, sync::{LazyLock, Mutex}, }; #[cfg(debug_assertions)] pub const CACHE_RATE: u64 = 1; #[cfg(not(debug_assertions))] pub const CACHE_RATE: u64 = 60 * 5; pub static ROUTES: LazyLock>> = LazyLock::new(|| Mutex::new(HashMap::new())); #[derive(Debug)] pub struct Route { pub description: String, pub text_cache: String, } impl Route { pub fn new(description: &str) -> Self { Self { description: description.to_string(), text_cache: String::new() } } } pub fn hits_from(route: &str) -> i32 { crate::DATABASE.lock().map_or(0, |database| { (*database) .get::(if route.is_empty() { "/" } else { route }) .unwrap_or(0) }) } pub fn track_mount( router: &mut windmark::router::Router, route: &str, description: &str, handler: F, ) where F: FnMut(windmark::context::RouteContext) -> R + Send + Sync + 'static, R: IntoFuture + Send + 'static, ::IntoFuture: Send, { if !description.starts_with('-') { (*ROUTES.lock().unwrap()) .insert(route.to_string(), Route::new(description)); } router.mount(route, handler); } #[cfg(test)] mod tests { use super::{ROUTES, track_mount}; #[test] fn track_mount_preserves_internal_hyphens_in_public_descriptions() { let mut router = windmark::router::Router::new(); ROUTES.lock().unwrap().clear(); track_mount( &mut router, "/finger", "Finger-to-Gemini Gateway", |_context| async { windmark::response::Response::success("ok".to_string()) }, ); let stored_description = ROUTES .lock() .unwrap() .get("/finger") .map(|route| route.description.clone()); assert_eq!( stored_description, Some("Finger-to-Gemini Gateway".to_string()) ); } }