Skip to main content

catallaxy_runtime/
symbol.rs

1//! Interned names (methods, fields). Symbols are process-wide and never freed.
2
3use std::sync::LazyLock;
4
5use parking_lot::RwLock;
6use rustc_hash::FxHashMap;
7
8#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)]
9pub struct Sym(pub u32);
10
11struct Interner {
12    map: FxHashMap<&'static str, Sym>,
13    names: Vec<&'static str>,
14}
15
16static INTERNER: LazyLock<RwLock<Interner>> =
17    LazyLock::new(|| RwLock::new(Interner { map: FxHashMap::default(), names: Vec::new() }));
18
19pub fn intern(s: &str) -> Sym {
20    if let Some(&sym) = INTERNER.read().map.get(s) {
21        return sym;
22    }
23    let mut w = INTERNER.write();
24    if let Some(&sym) = w.map.get(s) {
25        return sym;
26    }
27    let leaked: &'static str = Box::leak(s.to_string().into_boxed_str());
28    let sym = Sym(w.names.len() as u32);
29    w.names.push(leaked);
30    w.map.insert(leaked, sym);
31    sym
32}
33
34pub fn name(sym: Sym) -> &'static str {
35    INTERNER.read().names[sym.0 as usize]
36}
37
38impl std::fmt::Display for Sym {
39    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
40        f.write_str(name(*self))
41    }
42}