1use std::borrow::Borrow;
8use std::cell::RefCell;
9use std::cmp::Ordering;
10use std::collections::HashMap;
11use std::fmt;
12use std::hash::Hash;
13use std::ops::Deref;
14use std::rc::Rc;
15
16#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
22pub struct Name(pub u32);
23
24impl Name {
25 pub fn is_case_sensitive(&self) -> bool {
27 self.0 & 1 == 1
28 }
29
30 pub fn as_str(self) -> RcStr {
32 get_name_table().get(self)
33 }
34}
35
36impl fmt::Debug for Name {
37 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
38 write!(f, "{}({})", self, self.0)
39 }
40}
41
42impl fmt::Display for Name {
43 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
44 fmt::Display::fmt(&self.as_str(), f)
45 }
46}
47
48impl Into<String> for Name {
65 fn into(self) -> String {
66 self.as_str().into()
67 }
68}
69
70impl<'a> From<&'a str> for Name {
71 fn from(s: &'a str) -> Name {
72 get_name_table().intern(s, true)
73 }
74}
75
76#[derive(Clone, PartialEq, Hash, PartialOrd)]
79pub struct RcStr(Rc<String>);
80
81impl RcStr {
82 pub fn new(value: &str) -> RcStr {
84 RcStr(Rc::new(value.to_string()))
85 }
86
87 pub fn from(value: String) -> RcStr {
90 RcStr(Rc::new(value))
91 }
92}
93
94impl Eq for RcStr {}
95
96impl Ord for RcStr {
97 fn cmp(&self, other: &RcStr) -> Ordering {
98 self[..].cmp(&other[..])
99 }
100}
101
102impl fmt::Debug for RcStr {
103 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
104 self[..].fmt(f)
105 }
106}
107
108impl fmt::Display for RcStr {
109 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
110 self[..].fmt(f)
111 }
112}
113
114impl Borrow<str> for RcStr {
115 fn borrow(&self) -> &str {
116 &self.0[..]
117 }
118}
119
120impl Deref for RcStr {
121 type Target = str;
122 fn deref(&self) -> &str {
123 &self.0[..]
124 }
125}
126
127impl Into<String> for RcStr {
128 fn into(self) -> String {
129 (*self.0).clone()
130 }
131}
132
133impl AsRef<str> for RcStr {
134 fn as_ref(&self) -> &str {
135 self.0.as_ref()
136 }
137}
138
139pub struct NameTable {
143 map: RefCell<HashMap<RcStr, Name>>,
144 vect: RefCell<Vec<RcStr>>,
145}
146
147impl NameTable {
148 pub fn new() -> NameTable {
150 NameTable {
151 map: RefCell::new(HashMap::new()),
152 vect: RefCell::new(Vec::new()),
153 }
154 }
155
156 pub fn intern(&self, value: &str, case_sensitive: bool) -> Name {
160 let mut map = self.map.borrow_mut();
161 if let Some(&idx) = map.get(value) {
162 return idx;
163 }
164
165 let mut vect = self.vect.borrow_mut();
169 if case_sensitive {
170 let new_idx = Name((vect.len() as u32) << 1 | 1);
171 let v = RcStr::new(value);
172 map.insert(v.clone(), new_idx);
173 vect.push(v);
174 new_idx
175 } else {
176 let new_idx = Name((vect.len() as u32) << 1 | 0);
177 let lower = value.to_lowercase();
178 if let Some(&idx) = map.get(lower.as_str()) {
179 return idx;
180 }
181 let v = RcStr::new(value);
182 map.insert(RcStr::from(lower), new_idx);
183 map.insert(v.clone(), new_idx);
184 vect.push(v);
185 new_idx
186 }
187 }
188
189 pub fn get(&self, idx: Name) -> RcStr {
191 (*self.vect.borrow())[(idx.0 >> 1) as usize].clone()
192 }
193
194 pub fn find<Q: ?Sized>(&self, value: &Q) -> Option<Name>
196 where
197 RcStr: Borrow<Q>,
198 Q: Eq + Hash,
199 {
200 (*self.map.borrow()).get(value).map(|v| *v)
201 }
202}
203
204pub fn get_name_table() -> Rc<NameTable> {
206 thread_local!(static TBL: Rc<NameTable> = {
207 let nt = NameTable::new();
208 Rc::new(nt)
210 });
211 TBL.with(|x| x.clone())
212}