spade_common/
interning.rs1use std::{
2 ops::DerefMut,
3 sync::{LazyLock, Mutex},
4};
5
6use bumpalo::Bump;
7use rustc_hash::{FxBuildHasher, FxHashSet};
8
9pub static INTERNER: LazyLock<Interner> = LazyLock::new(|| Interner::new());
10
11pub struct Interner {
12 inner: Mutex<(FxHashSet<&'static str>, Bump)>,
13}
14
15impl Interner {
16 pub fn new() -> Self {
17 Self {
18 inner: Mutex::new((
19 FxHashSet::with_capacity_and_hasher(256, FxBuildHasher::default()),
20 Bump::new(),
21 )),
22 }
23 }
24
25 pub fn intern(&self, string: &str) -> &'static str {
26 let mut guard = self.inner.lock().unwrap();
27 let (lookup, arena) = DerefMut::deref_mut(&mut guard);
28
29 if let Some(prev) = lookup.get(string) {
30 return prev;
31 }
32
33 let ptr = arena.alloc_str(string);
34 let ptr = unsafe {
35 ::core::mem::transmute::<&'_ str, &'static str>(ptr)
37 };
38 lookup.insert(ptr);
39 ptr
40 }
41}