Skip to main content

delhi_syntax/
symbol.rs

1//! Interning of agent and predicate names to dense `u32` ids.
2
3use std::collections::HashMap;
4
5/// Maps names to dense `u32` ids and back.
6#[derive(Default, Debug, Clone)]
7pub struct Interner {
8    names: Vec<String>,
9    map: HashMap<String, u32>,
10}
11
12impl Interner {
13    /// Returns the id for `s`, assigning a fresh one if unseen.
14    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    /// The name behind an id.
25    ///
26    /// # Panics
27    /// If `i` was not produced by this interner.
28    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    /// How many distinct names have been interned.
34    pub fn len(&self) -> usize {
35        self.names.len()
36    }
37
38    /// Whether nothing has been interned yet.
39    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}