dora_parser/
interner.rs

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}