1use std::borrow::Borrow;
2
3use parking_lot::Mutex;
4use std::collections::HashMap;
5use std::fmt;
6use std::ops::Deref;
7use std::sync::Arc;
8
9#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
10pub struct Name(pub usize);
11
12#[derive(Clone, PartialEq, Eq, Hash)]
13pub struct ArcStr(Arc<String>);
14
15impl fmt::Display for ArcStr {
16 fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
17 write!(f, "{}", &*self.0)
18 }
19}
20
21impl fmt::Debug for ArcStr {
22 fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
23 write!(f, "{}", &*self.0)
24 }
25}
26
27impl ArcStr {
28 fn new(value: String) -> ArcStr {
29 ArcStr(Arc::new(value))
30 }
31}
32
33impl Borrow<str> for ArcStr {
34 fn borrow(&self) -> &str {
35 &self.0[..]
36 }
37}
38
39impl Deref for ArcStr {
40 type Target = String;
41
42 fn deref<'a>(&'a self) -> &'a String {
43 &self.0
44 }
45}
46
47pub struct Interner {
48 data: Mutex<Internal>,
49}
50
51struct Internal {
52 map: HashMap<ArcStr, Name>,
53 vec: Vec<ArcStr>,
54}
55
56impl Interner {
57 pub fn new() -> Interner {
58 Interner {
59 data: Mutex::new(Internal {
60 map: HashMap::new(),
61 vec: Vec::new(),
62 }),
63 }
64 }
65
66 pub fn intern(&self, name: &str) -> Name {
67 let mut data = self.data.lock();
68
69 if let Some(&val) = data.map.get(name) {
70 return val;
71 }
72
73 let key = ArcStr::new(String::from(name));
74 let value = Name(data.vec.len());
75
76 data.vec.push(key.clone());
77 data.map.insert(key, value);
78
79 value
80 }
81
82 pub fn str(&self, name: Name) -> ArcStr {
83 let data = self.data.lock();
84 data.vec[name.0].clone()
85 }
86}
87
88#[test]
89fn interner() {
90 let interner = Interner::new();
91
92 assert_eq!(Name(0), interner.intern("hello"));
93 assert_eq!(Name(0), interner.intern("hello"));
94
95 assert_eq!(Name(1), interner.intern("world"));
96 assert_eq!(Name(1), interner.intern("world"));
97
98 assert_eq!("hello", *interner.str(Name(0)));
99 assert_eq!("world", *interner.str(Name(1)));
100
101 assert_eq!(Name(2), interner.intern("keyword"));
102 assert_eq!(Name(2), interner.intern("keyword"));
103
104 assert_eq!("keyword", *interner.str(Name(2)));
105}