Joel Galenson | 2370d12 | 2020-10-12 16:02:26 -0700 | [diff] [blame] | 1 | extern crate weak_table; |
| 2 | |
| 3 | use weak_table::WeakHashSet; |
| 4 | use std::ops::Deref; |
| 5 | use std::rc::{Rc, Weak}; |
| 6 | |
| 7 | #[derive(Clone, Debug)] |
| 8 | pub struct Symbol(Rc<str>); |
| 9 | |
| 10 | impl PartialEq for Symbol { |
| 11 | fn eq(&self, other: &Symbol) -> bool { |
| 12 | Rc::ptr_eq(&self.0, &other.0) |
| 13 | } |
| 14 | } |
| 15 | |
| 16 | impl Eq for Symbol {} |
| 17 | |
| 18 | impl Deref for Symbol { |
| 19 | type Target = str; |
| 20 | fn deref(&self) -> &str { |
| 21 | &self.0 |
| 22 | } |
| 23 | } |
| 24 | |
| 25 | #[derive(Debug, Default)] |
| 26 | pub struct SymbolTable(WeakHashSet<Weak<str>>); |
| 27 | |
| 28 | impl SymbolTable { |
| 29 | pub fn new() -> Self { |
| 30 | Self::default() |
| 31 | } |
| 32 | |
| 33 | pub fn intern(&mut self, name: &str) -> Symbol { |
| 34 | if let Some(rc) = self.0.get(name) { |
| 35 | Symbol(rc) |
| 36 | } else { |
| 37 | let rc = Rc::<str>::from(name); |
| 38 | self.0.insert(Rc::clone(&rc)); |
| 39 | Symbol(rc) |
| 40 | } |
| 41 | } |
| 42 | } |
| 43 | |
| 44 | #[test] |
| 45 | fn interning() { |
| 46 | let mut tab = SymbolTable::new(); |
| 47 | |
| 48 | let a0 = tab.intern("a"); |
| 49 | let a1 = tab.intern("a"); |
| 50 | let b = tab.intern("b"); |
| 51 | |
| 52 | assert_eq!(a0, a1); |
| 53 | assert_ne!(a0, b); |
| 54 | } |