use std::collections::HashMap;
use std::sync::{Arc, OnceLock, RwLock};
use std::time::SystemTime;
pub type TimeStampSource = Arc<dyn Fn() -> SystemTime + Send + Sync>;
fn registry() -> &'static RwLock<HashMap<String, TimeStampSource>> {
static REGISTRY: OnceLock<RwLock<HashMap<String, TimeStampSource>>> = OnceLock::new();
REGISTRY.get_or_init(|| RwLock::new(HashMap::new()))
}
pub fn register_time_stamp_source<F>(name: &str, source: F)
where
F: Fn() -> SystemTime + Send + Sync + 'static,
{
if let Ok(mut reg) = registry().write() {
reg.insert(name.to_string(), Arc::new(source));
}
}
pub fn find_time_stamp_source(name: &str) -> Option<TimeStampSource> {
registry().read().ok()?.get(name).cloned()
}
#[cfg(test)]
mod tests {
use super::*;
use std::time::{Duration, UNIX_EPOCH};
#[test]
fn an_unregistered_name_does_not_resolve() {
assert!(find_time_stamp_source("nothing_registered_under_this").is_none());
}
#[test]
fn a_registered_name_resolves_to_its_source() {
let fixed = UNIX_EPOCH + Duration::from_secs(1_000_000);
register_time_stamp_source("fixed_ts_for_test", move || fixed);
let f = find_time_stamp_source("fixed_ts_for_test").expect("registered name must resolve");
assert_eq!(f(), fixed);
}
}