veryl_parser/
resource_table.rs1use 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}