use std::collections::HashMap;
pub struct SortedRegistry<T> {
entries: HashMap<String, T>,
sorted_keys: Vec<String>,
priority_fn: fn(&T) -> i32,
}
impl<T> SortedRegistry<T> {
pub fn new(priority_fn: fn(&T) -> i32) -> Self {
Self {
entries: HashMap::new(),
sorted_keys: Vec::new(),
priority_fn,
}
}
fn resort(&mut self) {
let pf = self.priority_fn;
let entries = &self.entries;
let mut keys: Vec<String> = entries.keys().cloned().collect();
keys.sort_by_key(|k| pf(entries.get(k).unwrap()));
self.sorted_keys = keys;
}
pub fn register(&mut self, name: String, entry: T) -> Result<(), String> {
if self.entries.contains_key(&name) {
return Err(format!("{name} already exists"));
}
self.entries.insert(name, entry);
self.resort();
Ok(())
}
pub fn deregister(&mut self, name: &str) -> bool {
if self.entries.remove(name).is_some() {
self.resort();
true
} else {
false
}
}
pub fn sorted_values(&self) -> Vec<&T> {
self.sorted_keys
.iter()
.filter_map(|k| self.entries.get(k))
.collect()
}
pub fn get(&self, name: &str) -> Option<&T> {
self.entries.get(name)
}
pub fn remove(&mut self, name: &str) -> Option<T> {
let removed = self.entries.remove(name);
if removed.is_some() {
self.resort();
}
removed
}
pub fn contains(&self, name: &str) -> bool {
self.entries.contains_key(name)
}
}
#[cfg(test)]
#[path = "../tests/unit/registry_tests.rs"]
mod tests;