1use std::ops::{Index, IndexMut};
13use std::sync::RwLock;
14
15use jstd::registry::{Identified, Identifier, Registry};
16use rustc_hash::FxHashMap as HashMap;
17use serde::{Deserialize, Deserializer, Serialize, Serializer};
18
19use crate::{
20 types::TypeId,
21 value::literal::{Literal, LiteralId},
22};
23
24fn mask_to_size(value: u64, size: usize) -> u64 {
27 if size >= 8 {
28 value
29 } else {
30 value & ((1u64 << (size * 8)) - 1)
31 }
32}
33
34pub struct Interner<Id: Identifier, T> {
38 inner: RwLock<Registry<Id, T>>,
39}
40
41impl<Id: Identifier, T> Default for Interner<Id, T> {
42 fn default() -> Self {
43 Self {
44 inner: RwLock::new(Registry::default()),
45 }
46 }
47}
48
49impl<Id: Identifier, T: Clone> Clone for Interner<Id, T> {
50 fn clone(&self) -> Self {
51 Self {
52 inner: RwLock::new(self.read().clone()),
53 }
54 }
55}
56
57impl<Id: Identifier, T> Interner<Id, T> {
58 fn read(&self) -> std::sync::RwLockReadGuard<'_, Registry<Id, T>> {
59 self.inner.read().expect("interner RwLock poisoned")
60 }
61
62 pub fn push(&self, value: T) -> Id {
64 self.inner
65 .write()
66 .expect("interner RwLock poisoned")
67 .push(value)
68 }
69
70 pub fn len(&self) -> usize {
72 self.read().len()
73 }
74
75 pub fn is_empty(&self) -> bool {
77 self.read().is_empty()
78 }
79}
80
81impl<Id: Identifier, T: Clone> Interner<Id, T> {
82 pub fn iter(&self) -> impl Iterator<Item = Identified<Id, T>> {
86 self.read()
87 .iter()
88 .map(|item| Identified::new(item.id, item.inner.clone()))
89 .collect::<Vec<_>>()
90 .into_iter()
91 }
92}
93
94impl<Id: Identifier, T> Index<Id> for Interner<Id, T> {
95 type Output = T;
96
97 fn index(&self, id: Id) -> &T {
98 let ptr: *const T = {
99 let reg = self.read();
100 ®[id] as *const T
101 };
102 unsafe { &*ptr }
106 }
107}
108
109impl<Id: Identifier, T> IndexMut<Id> for Interner<Id, T> {
110 fn index_mut(&mut self, id: Id) -> &mut T {
111 &mut self.inner.get_mut().expect("interner RwLock poisoned")[id]
115 }
116}
117
118impl<Id: Identifier, T: Serialize> Serialize for Interner<Id, T> {
119 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
120 self.read().serialize(serializer)
121 }
122}
123
124impl<'de, Id: Identifier, T: Deserialize<'de>> Deserialize<'de> for Interner<Id, T> {
125 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
126 Ok(Self {
127 inner: RwLock::new(Registry::deserialize(deserializer)?),
128 })
129 }
130}
131
132#[derive(Default)]
136pub struct LiteralInterner {
137 inner: RwLock<LiteralPool>,
138}
139
140#[derive(Default, Clone)]
141struct LiteralPool {
142 literals: Registry<LiteralId, Literal>,
143 cache: HashMap<(u64, TypeId), LiteralId>,
146}
147
148impl Clone for LiteralInterner {
149 fn clone(&self) -> Self {
150 Self {
151 inner: RwLock::new(self.read().clone()),
152 }
153 }
154}
155
156impl LiteralInterner {
157 fn read(&self) -> std::sync::RwLockReadGuard<'_, LiteralPool> {
158 self.inner.read().expect("literal interner RwLock poisoned")
159 }
160
161 pub fn get_or_make_typed_literal(&self, value: u64, type_id: TypeId, size: usize) -> LiteralId {
166 let value = mask_to_size(value, size);
167 if let Some(&id) = self.read().cache.get(&(value, type_id)) {
169 return id;
170 }
171 let mut pool = self
173 .inner
174 .write()
175 .expect("literal interner RwLock poisoned");
176 if let Some(&id) = pool.cache.get(&(value, type_id)) {
177 return id;
178 }
179 let id = pool.literals.push(Literal {
180 value,
181 type_id,
182 symbolic: None,
183 });
184 pool.cache.insert((value, type_id), id);
185 id
186 }
187
188 pub fn push_literal(&self, literal: Literal) -> LiteralId {
191 self.inner
192 .write()
193 .expect("literal interner RwLock poisoned")
194 .literals
195 .push(literal)
196 }
197
198 pub fn len(&self) -> usize {
200 self.read().literals.len()
201 }
202
203 pub fn is_empty(&self) -> bool {
205 self.read().literals.is_empty()
206 }
207
208 pub fn iter(&self) -> impl Iterator<Item = Identified<LiteralId, Literal>> {
212 self.read()
213 .literals
214 .iter()
215 .map(|item| Identified::new(item.id, item.inner.clone()))
216 .collect::<Vec<_>>()
217 .into_iter()
218 }
219}
220
221impl Index<LiteralId> for LiteralInterner {
222 type Output = Literal;
223
224 fn index(&self, id: LiteralId) -> &Literal {
225 let ptr: *const Literal = {
226 let pool = self.read();
227 &pool.literals[id] as *const Literal
228 };
229 unsafe { &*ptr }
231 }
232}
233
234impl IndexMut<LiteralId> for LiteralInterner {
235 fn index_mut(&mut self, id: LiteralId) -> &mut Literal {
236 &mut self
241 .inner
242 .get_mut()
243 .expect("literal interner RwLock poisoned")
244 .literals[id]
245 }
246}
247
248impl Serialize for LiteralInterner {
249 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
250 self.read().literals.serialize(serializer)
253 }
254}
255
256impl<'de> Deserialize<'de> for LiteralInterner {
257 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
258 let literals = Registry::<LiteralId, Literal>::deserialize(deserializer)?;
259 let mut cache: HashMap<(u64, TypeId), LiteralId> = HashMap::default();
262 for item in literals.iter() {
263 if item.inner.symbolic.is_none() {
264 cache
265 .entry((item.inner.value, item.inner.type_id))
266 .or_insert(item.id);
267 }
268 }
269 Ok(Self {
270 inner: RwLock::new(LiteralPool { literals, cache }),
271 })
272 }
273}