use std::collections::HashMap;
pub(crate) trait RegistryEntry {
fn name(&self) -> &str;
fn priority(&self) -> i32;
}
pub(crate) struct SortedRegistry<T: RegistryEntry> {
entries: HashMap<String, T>,
sorted_keys: Vec<String>,
}
impl<T: RegistryEntry> SortedRegistry<T> {
pub(crate) fn new() -> Self {
Self {
entries: HashMap::new(),
sorted_keys: Vec::new(),
}
}
fn resort(&mut self) {
let entries = &self.entries;
let mut keys: Vec<String> = entries.keys().cloned().collect();
keys.sort_by(|left, right| {
let left_entry = entries.get(left).unwrap();
let right_entry = entries.get(right).unwrap();
left_entry
.priority()
.cmp(&right_entry.priority())
.then_with(|| left.cmp(right))
});
self.sorted_keys = keys;
}
pub(crate) fn register(&mut self, entry: T) -> Result<(), String> {
let name = entry.name().to_string();
if self.entries.contains_key(&name) {
return Err(format!("{name} already exists"));
}
self.entries.insert(name, entry);
self.resort();
Ok(())
}
pub(crate) fn deregister(&mut self, name: &str) -> bool {
if self.entries.remove(name).is_some() {
self.resort();
true
} else {
false
}
}
pub(crate) fn sorted_values(&self) -> Vec<&T> {
self.sorted_keys
.iter()
.filter_map(|k| self.entries.get(k))
.collect()
}
}
impl<T: RegistryEntry> Default for SortedRegistry<T> {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
#[path = "../tests/unit/registry_tests.rs"]
mod tests;