use std::collections::HashMap;
pub const KEY_NONE: u32 = u32::MAX;
#[derive(Default, Debug)]
pub struct NameTable {
name_to_key: HashMap<String, u32>,
names: Vec<String>,
node_key: Vec<u32>,
}
impl NameTable {
pub fn new() -> Self {
Self::default()
}
pub fn intern(&mut self, name: &str) -> u32 {
if let Some(&k) = self.name_to_key.get(name) {
return k;
}
let k = self.names.len() as u32;
self.name_to_key.insert(name.to_string(), k);
self.names.push(name.to_string());
k
}
pub fn name(&self, key: u32) -> &str {
self.names.get(key as usize).map(|s| s.as_str()).unwrap_or("")
}
pub fn var_key(&self, idx: usize) -> Option<u32> {
match self.node_key.get(idx) {
Some(&k) if k != KEY_NONE => Some(k),
_ => None,
}
}
pub fn raw_key(&self, idx: usize) -> u32 {
self.node_key.get(idx).copied().unwrap_or(KEY_NONE)
}
pub fn key_slots(&self) -> usize {
self.node_key.len()
}
pub fn extend_owned(&mut self, base: usize, names: &[Option<String>]) {
if self.node_key.len() < base + names.len() {
self.node_key.resize(base + names.len(), KEY_NONE);
}
for (i, name) in names.iter().enumerate() {
if let Some(n) = name {
self.node_key[base + i] = self.intern(n);
}
}
}
}