1use std::collections::HashMap;
4
5#[derive(Default, Debug, Clone)]
7pub struct Interner {
8 names: Vec<String>,
9 map: HashMap<String, u32>,
10}
11
12impl Interner {
13 pub fn intern(&mut self, s: &str) -> u32 {
15 if let Some(&i) = self.map.get(s) {
16 return i;
17 }
18 let i = self.names.len() as u32;
19 self.names.push(s.to_owned());
20 self.map.insert(s.to_owned(), i);
21 i
22 }
23
24 pub fn name(&self, i: u32) -> &str {
29 debug_assert!((i as usize) < self.names.len(), "id not produced by this interner");
30 &self.names[i as usize]
31 }
32
33 pub fn len(&self) -> usize {
35 self.names.len()
36 }
37
38 pub fn is_empty(&self) -> bool {
40 self.names.is_empty()
41 }
42}
43
44#[cfg(test)]
45mod tests {
46 use super::*;
47
48 #[test]
49 fn interning_is_stable_and_deduplicates() {
50 let mut i = Interner::default();
51 let alice = i.intern("alice");
52 let bob = i.intern("bob");
53 assert_ne!(alice, bob);
54 assert_eq!(i.intern("alice"), alice, "re-interning must return the same id");
55 assert_eq!(i.name(alice), "alice");
56 assert_eq!(i.len(), 2);
57 }
58}