summaryrefslogtreecommitdiffstats
path: root/src/tools/rust-analyzer/crates/proc-macro-srv/src/server/symbol.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/tools/rust-analyzer/crates/proc-macro-srv/src/server/symbol.rs')
-rw-r--r--src/tools/rust-analyzer/crates/proc-macro-srv/src/server/symbol.rs48
1 files changed, 48 insertions, 0 deletions
diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/server/symbol.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/server/symbol.rs
new file mode 100644
index 000000000..540d06457
--- /dev/null
+++ b/src/tools/rust-analyzer/crates/proc-macro-srv/src/server/symbol.rs
@@ -0,0 +1,48 @@
+//! Symbol interner for proc-macro-srv
+
+use std::{cell::RefCell, collections::HashMap, thread::LocalKey};
+use tt::SmolStr;
+
+thread_local! {
+ pub(crate) static SYMBOL_INTERNER: RefCell<SymbolInterner> = Default::default();
+}
+
+// ID for an interned symbol.
+#[derive(Hash, Eq, PartialEq, Copy, Clone)]
+pub struct Symbol(u32);
+
+pub(crate) type SymbolInternerRef = &'static LocalKey<RefCell<SymbolInterner>>;
+
+impl Symbol {
+ pub(super) fn intern(interner: SymbolInternerRef, data: &str) -> Symbol {
+ interner.with(|i| i.borrow_mut().intern(data))
+ }
+
+ pub(super) fn text(&self, interner: SymbolInternerRef) -> SmolStr {
+ interner.with(|i| i.borrow().get(self).clone())
+ }
+}
+
+#[derive(Default)]
+pub(crate) struct SymbolInterner {
+ idents: HashMap<SmolStr, u32>,
+ ident_data: Vec<SmolStr>,
+}
+
+impl SymbolInterner {
+ fn intern(&mut self, data: &str) -> Symbol {
+ if let Some(index) = self.idents.get(data) {
+ return Symbol(*index);
+ }
+
+ let index = self.idents.len() as u32;
+ let data = SmolStr::from(data);
+ self.ident_data.push(data.clone());
+ self.idents.insert(data, index);
+ Symbol(index)
+ }
+
+ fn get(&self, sym: &Symbol) -> &SmolStr {
+ &self.ident_data[sym.0 as usize]
+ }
+}