1use serde::{Deserialize, Serialize};
2use std::collections::HashMap;
3
4#[derive(Debug, Default, Clone, Serialize, Deserialize)]
7pub struct Interner {
8 to_sym: HashMap<String, u32>,
9 to_str: Vec<String>,
10}
11
12impl Interner {
13 pub fn new() -> Self {
14 Self::default()
15 }
16
17 pub fn intern(&mut self, s: &str) -> u32 {
18 if let Some(&sym) = self.to_sym.get(s) {
19 return sym;
20 }
21 let sym = self.to_str.len() as u32;
22 self.to_sym.insert(s.to_string(), sym);
23 self.to_str.push(s.to_string());
24 sym
25 }
26
27 pub fn resolve(&self, sym: u32) -> Option<&str> {
28 self.to_str.get(sym as usize).map(|s| s.as_str())
29 }
30
31 pub fn get(&self, s: &str) -> Option<u32> {
32 self.to_sym.get(s).copied()
33 }
34
35 pub fn len(&self) -> usize {
37 self.to_str.len()
38 }
39
40 pub fn is_empty(&self) -> bool {
41 self.to_str.is_empty()
42 }
43
44 pub fn truncate(&mut self, len: usize) {
49 if len >= self.to_str.len() {
50 return;
51 }
52 for s in self.to_str.drain(len..) {
53 self.to_sym.remove(&s);
54 }
55 }
56}
57
58#[cfg(test)]
59mod tests {
60 use super::*;
61
62 #[test]
63 fn interning_is_idempotent_and_resolvable() {
64 let mut i = Interner::new();
65 let a = i.intern("Person");
66 let b = i.intern("Company");
67 assert_eq!(i.intern("Person"), a);
68 assert_ne!(a, b);
69 assert_eq!(i.resolve(b), Some("Company"));
70 assert_eq!(i.get("Person"), Some(a));
71 assert_eq!(i.get("Nope"), None);
72 }
73}