Skip to main content

veryl_parser/
resource_table.rs

1use bimap::BiMap;
2use std::borrow::Borrow;
3use std::cell::RefCell;
4use std::fmt;
5use std::hash::Hash;
6use std::path::{Path, PathBuf};
7
8#[derive(Default)]
9pub struct GlobalTable<T, U>
10where
11    T: Hash + Eq,
12    U: Hash + Eq,
13{
14    table: BiMap<T, U>,
15    last: U,
16}
17
18impl<T, U> Clone for GlobalTable<T, U>
19where
20    T: Hash + Eq + Clone,
21    U: Hash + Eq + Clone,
22{
23    fn clone(&self) -> Self {
24        Self {
25            table: self.table.clone(),
26            last: self.last.clone(),
27        }
28    }
29}
30
31impl<T, U> GlobalTable<T, U>
32where
33    T: Hash + Eq,
34    U: Hash + Eq + Copy + Incrementable,
35{
36    pub fn insert(&mut self, value: T) -> U {
37        if let Some(id) = self.table.get_by_left(&value) {
38            *id
39        } else {
40            let id = self.last;
41            self.table.insert(value, id);
42            self.last.inc();
43            id
44        }
45    }
46
47    pub fn get_value(&self, id: U) -> Option<&T> {
48        self.table.get_by_right(&id)
49    }
50
51    pub fn get_id<V: Borrow<T>>(&self, value: V) -> Option<U> {
52        self.table.get_by_left(value.borrow()).copied()
53    }
54}
55
56#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
57pub struct StrId(pub usize);
58#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
59pub struct PathId(pub usize);
60#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
61pub struct TokenId(pub usize);
62
63pub trait Incrementable {
64    fn inc(&mut self);
65}
66
67impl Incrementable for StrId {
68    fn inc(&mut self) {
69        self.0 += 1;
70    }
71}
72
73impl Incrementable for PathId {
74    fn inc(&mut self) {
75        self.0 += 1;
76    }
77}
78
79impl fmt::Display for StrId {
80    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
81        let text = get_str_value(*self).unwrap();
82        text.fmt(f)
83    }
84}
85
86impl fmt::Display for PathId {
87    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
88        let text = format!("{}", get_path_value(*self).unwrap().to_string_lossy());
89        text.fmt(f)
90    }
91}
92
93impl fmt::Display for TokenId {
94    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
95        self.0.fmt(f)
96    }
97}
98
99impl From<&str> for StrId {
100    fn from(x: &str) -> Self {
101        insert_str(x)
102    }
103}
104
105thread_local!(static STRING_TABLE: RefCell<GlobalTable<String, StrId>> = RefCell::new(GlobalTable::default()));
106thread_local!(static PATHBUF_TABLE: RefCell<GlobalTable<PathBuf, PathId>> = RefCell::new(GlobalTable::default()));
107thread_local!(static TOKEN_ID: RefCell<usize> = const { RefCell::new(0) });
108
109pub fn insert_str(value: &str) -> StrId {
110    STRING_TABLE.with(|f| f.borrow_mut().insert(value.to_owned()))
111}
112
113pub fn insert_path(value: &Path) -> PathId {
114    PATHBUF_TABLE.with(|f| f.borrow_mut().insert(value.to_owned()))
115}
116
117pub fn get_str_value(id: StrId) -> Option<String> {
118    STRING_TABLE.with(|f| f.borrow().get_value(id).map(|x| x.to_owned()))
119}
120
121pub fn get_path_value(id: PathId) -> Option<PathBuf> {
122    PATHBUF_TABLE.with(|f| f.borrow().get_value(id).map(|x| x.to_owned()))
123}
124
125pub fn get_str_id<T: Borrow<String>>(value: T) -> Option<StrId> {
126    STRING_TABLE.with(|f| f.borrow().get_id(value).map(|x| x.to_owned()))
127}
128
129pub fn get_path_id<T: Borrow<PathBuf>>(value: T) -> Option<PathId> {
130    PATHBUF_TABLE.with(|f| f.borrow().get_id(value).map(|x| x.to_owned()))
131}
132
133pub struct ResourceTableSnapshot {
134    string_table: GlobalTable<String, StrId>,
135    pathbuf_table: GlobalTable<PathBuf, PathId>,
136}
137
138pub fn export_tables() -> ResourceTableSnapshot {
139    ResourceTableSnapshot {
140        string_table: STRING_TABLE.with(|f| f.borrow().clone()),
141        pathbuf_table: PATHBUF_TABLE.with(|f| f.borrow().clone()),
142    }
143}
144
145pub fn import_tables(snapshot: &ResourceTableSnapshot) {
146    STRING_TABLE.with(|f| *f.borrow_mut() = snapshot.string_table.clone());
147    PATHBUF_TABLE.with(|f| *f.borrow_mut() = snapshot.pathbuf_table.clone());
148}
149
150pub fn new_token_id() -> TokenId {
151    TOKEN_ID.with(|f| {
152        let mut ret = f.borrow_mut();
153        *ret += 1;
154        TokenId(*ret)
155    })
156}