aboutsummaryrefslogtreecommitdiff
path: root/gen/build/src/intern.rs
blob: c8b57d89c734cb7e87a15acced5d67692d575fc9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
use crate::syntax::set::UnorderedSet as Set;
use once_cell::sync::OnceCell;
use std::sync::{Mutex, PoisonError};

#[derive(Copy, Clone, Default)]
pub struct InternedString(&'static str);

impl InternedString {
    pub fn str(self) -> &'static str {
        self.0
    }
}

pub fn intern(s: &str) -> InternedString {
    static INTERN: OnceCell<Mutex<Set<&'static str>>> = OnceCell::new();

    let mut set = INTERN
        .get_or_init(|| Mutex::new(Set::new()))
        .lock()
        .unwrap_or_else(PoisonError::into_inner);

    InternedString(match set.get(s) {
        Some(interned) => *interned,
        None => {
            let interned = Box::leak(Box::from(s));
            set.insert(interned);
            interned
        }
    })
}