|
1 | 1 | use std::fmt;
|
2 | 2 | use std::sync::RwLock;
|
3 |
| -use std::collections::HashMap; |
| 3 | +use std::collections::HashSet; |
| 4 | +use std::slice; |
| 5 | +use std::str; |
| 6 | +use std::mem; |
| 7 | + |
| 8 | +pub fn leek(s: String) -> &'static str { |
| 9 | + let ptr = s.as_ptr(); |
| 10 | + let len = s.len(); |
| 11 | + mem::forget(s); |
| 12 | + unsafe { |
| 13 | + let slice = slice::from_raw_parts(ptr, len); |
| 14 | + str::from_utf8_unchecked(slice) |
| 15 | + } |
| 16 | +} |
4 | 17 |
|
5 | 18 | lazy_static! {
|
6 |
| - static ref STRING_CASHE: RwLock<(Vec<String>, HashMap<String, usize>)> = |
7 |
| - RwLock::new((Vec::new(), HashMap::new())); |
| 19 | + static ref STRING_CASHE: RwLock<HashSet<&'static str>> = |
| 20 | + RwLock::new(HashSet::new()); |
8 | 21 | }
|
9 | 22 |
|
10 | 23 | #[derive(Eq, PartialEq, Hash, Clone, Copy)]
|
11 | 24 | pub struct InternedString {
|
12 |
| - id: usize |
| 25 | + ptr: *const u8, |
| 26 | + len: usize, |
13 | 27 | }
|
14 | 28 |
|
15 | 29 | impl InternedString {
|
16 | 30 | pub fn new(str: &str) -> InternedString {
|
17 |
| - let (ref mut str_from_id, ref mut id_from_str) = *STRING_CASHE.write().unwrap(); |
18 |
| - if let Some(&id) = id_from_str.get(str) { |
19 |
| - return InternedString { id }; |
| 31 | + let mut cache = STRING_CASHE.write().unwrap(); |
| 32 | + if let Some(&s) = cache.get(str) { |
| 33 | + return InternedString { ptr: s.as_ptr(), len: s.len() }; |
20 | 34 | }
|
21 |
| - str_from_id.push(str.to_string()); |
22 |
| - id_from_str.insert(str.to_string(), str_from_id.len() - 1); |
23 |
| - return InternedString { id: str_from_id.len() - 1 } |
| 35 | + let s = leek(str.to_string()); |
| 36 | + cache.insert(s); |
| 37 | + InternedString { ptr: s.as_ptr(), len: s.len() } |
24 | 38 | }
|
25 |
| - pub fn to_inner(&self) -> String { |
26 |
| - STRING_CASHE.read().unwrap().0[self.id].to_string() |
| 39 | + pub fn to_inner(&self) -> &'static str { |
| 40 | + unsafe { |
| 41 | + let slice = slice::from_raw_parts(self.ptr, self.len); |
| 42 | + str::from_utf8_unchecked(slice) |
| 43 | + } |
27 | 44 | }
|
28 | 45 | }
|
29 | 46 |
|
30 | 47 | impl fmt::Debug for InternedString {
|
31 | 48 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
32 |
| - write!(f, "InternedString {{ {} }}", STRING_CASHE.read().unwrap().0[self.id]) |
| 49 | + write!(f, "InternedString {{ {} }}", self.to_inner()) |
33 | 50 | }
|
34 | 51 | }
|
0 commit comments