Skip to main content

ion_core/
intern.rs

1//! String interner for fast variable name lookups.
2//!
3//! Symbols are u32 indices into a global pool. Equality is O(1).
4
5use std::collections::HashMap;
6
7/// An interned string identifier.
8#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
9pub struct Symbol(pub u32);
10
11/// A string interner that maps strings to unique `Symbol` IDs.
12#[derive(Debug, Clone)]
13pub struct StringPool {
14    map: HashMap<String, Symbol>,
15    strings: Vec<String>,
16}
17
18impl Default for StringPool {
19    fn default() -> Self {
20        Self::new()
21    }
22}
23
24impl StringPool {
25    pub fn new() -> Self {
26        Self {
27            map: HashMap::new(),
28            strings: Vec::new(),
29        }
30    }
31
32    /// Intern a string, returning its symbol. If already interned, returns the existing symbol.
33    pub fn intern(&mut self, s: &str) -> Symbol {
34        if let Some(&sym) = self.map.get(s) {
35            return sym;
36        }
37        let sym = Symbol(self.strings.len() as u32);
38        self.strings.push(s.to_string());
39        self.map.insert(s.to_string(), sym);
40        sym
41    }
42
43    /// Resolve a symbol back to its string.
44    pub fn resolve(&self, sym: Symbol) -> &str {
45        &self.strings[sym.0 as usize]
46    }
47
48    /// Look up a string without interning it. Returns None if not yet interned.
49    pub fn map_get(&self, s: &str) -> Option<Symbol> {
50        self.map.get(s).copied()
51    }
52}