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 {
eq(&self, other: &Symbol) -> bool11     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;
deref(&self) -> &str20     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 {
new() -> Self29     pub fn new() -> Self {
30         Self::default()
31     }
32 
intern(&mut self, name: &str) -> Symbol33     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]
interning()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 }
55