use std::collections::HashMap;
use std::hash::BuildHasher;
use typed_arena::Arena;
pub struct Interner<'a, RS> {
map: HashMap<&'a str, u32, RS>,
vec: Vec<&'a str>,
arena: &'a Arena<u8>,
}
impl<RS: Default + BuildHasher> Interner<'_, RS> {
pub fn new(arena: &Arena<u8>) -> Interner<RS> {
Interner {
map: HashMap::with_capacity_and_hasher(1024, Default::default()),
vec: Vec::new(),
arena,
}
}
}
impl<RS> Interner<'_, RS> {
pub fn lookup(&self, idx: u32) -> &str {
self.vec[idx as usize]
}
}
impl<RS: Default + BuildHasher> Interner<'_, RS> {
pub fn intern(&mut self, name: &str) -> u32 {
if let Some(&idx) = self.map.get(name) {
return idx;
}
let idx = self.vec.len() as u32;
let name = self.arena.alloc_str(name);
self.map.insert(name, idx);
self.vec.push(name);
debug_assert!(self.lookup(idx) == name);
debug_assert!(self.intern(name) == idx);
idx
}
}