use std::collections::HashMap;
#[derive(Debug, Default, Clone)]
pub struct EntityAliases {
stored_by_alias: HashMap<String, String>,
}
impl EntityAliases {
pub fn record(&mut self, alias: &str, stored: &str) {
self.stored_by_alias.insert(fold(alias), stored.to_string());
self.stored_by_alias
.entry(fold(stored))
.or_insert_with(|| stored.to_string());
}
#[must_use]
pub fn resolve(&self, name: &str) -> Option<&str> {
self.stored_by_alias.get(&fold(name)).map(String::as_str)
}
}
#[must_use]
pub fn fold(name: &str) -> String {
name.split_whitespace()
.collect::<Vec<_>>()
.join(" ")
.to_lowercase()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn a_case_variant_resolves_to_the_stored_name() {
let mut aliases = EntityAliases::default();
aliases.record("Synth", "Synth");
assert_eq!(aliases.resolve("synth"), Some("Synth"));
assert_eq!(aliases.resolve(" SYNTH "), Some("Synth"));
}
#[test]
fn a_duplicate_resolves_to_the_entity_it_duplicates() {
let mut aliases = EntityAliases::default();
aliases.record("Synth pulse", "Synth");
assert_eq!(aliases.resolve("synth pulse"), Some("Synth"));
assert_eq!(aliases.resolve("Synth"), Some("Synth"));
}
#[test]
fn a_target_name_does_not_redirect_an_earlier_alias() {
let mut aliases = EntityAliases::default();
aliases.record("Synth pulse", "Synth");
aliases.record("The Synth pulse", "Synth pulse");
assert_eq!(aliases.resolve("synth pulse"), Some("Synth"));
assert_eq!(aliases.resolve("the synth pulse"), Some("Synth pulse"));
}
#[test]
fn an_unknown_name_resolves_to_nothing() {
assert_eq!(EntityAliases::default().resolve("User"), None);
}
}