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
31
32
33
34
35
36
37
use lasso::{Rodeo, Spur};

use std::cell::RefCell;
use std::fmt::{self, Display};

thread_local!(static STRINGS: RefCell<Rodeo<Spur>> = RefCell::new(Rodeo::default()));

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
pub(crate) struct InternedString(Spur);

impl InternedString {
    pub fn get_or_intern<T: AsRef<str>>(s: T) -> Self {
        Self(STRINGS.with(|interner| interner.borrow_mut().get_or_intern(s)))
    }

    #[allow(dead_code)]
    pub fn resolve(self) -> String {
        STRINGS.with(|interner| interner.borrow().resolve(&self.0).to_string())
    }

    #[allow(dead_code)]
    pub fn is_empty(self) -> bool {
        self.resolve_ref() == ""
    }

    pub fn resolve_ref<'a>(self) -> &'a str {
        unsafe {
            STRINGS.with(|interner| &(*(interner.as_ptr()).as_ref().unwrap().resolve(&self.0)))
        }
    }
}

impl Display for InternedString {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        STRINGS.with(|interner| write!(f, "{}", interner.borrow().resolve(&self.0)))
    }
}