use super::family::FamilyId;
use alloc::sync::Arc;
use hashbrown::HashMap;
use smallvec::SmallVec;
#[derive(Clone, Debug)]
pub struct FamilyName {
id: FamilyId,
name: Arc<str>,
}
impl FamilyName {
pub fn id(&self) -> FamilyId {
self.id
}
pub fn name(&self) -> &str {
&self.name
}
}
impl From<&FamilyName> for FamilyId {
fn from(value: &FamilyName) -> Self {
value.id
}
}
#[derive(Clone, Default)]
pub struct FamilyNameMap {
name_map: HashMap<Arc<[u8]>, FamilyName>,
id_map: HashMap<FamilyId, FamilyName>,
}
impl FamilyNameMap {
pub fn get(&self, name: &str) -> Option<&FamilyName> {
let key = NameKey::from_str(name);
self.name_map.get(key.as_bytes())
}
pub fn get_by_id(&self, id: FamilyId) -> Option<&FamilyName> {
self.id_map.get(&id)
}
pub fn get_or_insert(&mut self, name: &str) -> FamilyName {
let key = NameKey::from_str(name);
if let Some(name) = self.name_map.get(key.as_bytes()) {
name.clone()
} else {
let new_name = FamilyName {
name: name.into(),
id: FamilyId::new(),
};
self.name_map
.insert(key.as_bytes().into(), new_name.clone());
self.id_map.insert(new_name.id, new_name.clone());
new_name
}
}
#[allow(unused)]
pub fn add_alias(&mut self, id: FamilyId, name: &str) {
if self.id_map.contains_key(&id) {
let key = NameKey::from_str(name);
if self.name_map.contains_key(key.as_bytes()) {
return;
}
let new_name = FamilyName {
name: name.into(),
id,
};
self.name_map.insert(key.as_bytes().into(), new_name);
}
}
pub fn iter(&self) -> impl Iterator<Item = &FamilyName> + Clone {
self.name_map.values()
}
}
#[derive(Default)]
struct NameKey {
data: SmallVec<[u8; 128]>,
}
impl NameKey {
fn from_str(s: &str) -> Self {
let mut res = Self::default();
let mut buf = [0_u8; 4];
for ch in s.chars() {
for ch in ch.to_lowercase() {
res.data
.extend_from_slice(ch.encode_utf8(&mut buf).as_bytes());
}
}
res
}
pub fn as_bytes(&self) -> &[u8] {
&self.data
}
}