1use crate::types::ExprType;
35use crate::value::ExprValue;
36use std::collections::HashMap;
37
38pub const MAX_SYMBOL_TABLE_ENTRIES: usize = 100_000;
57
58#[derive(Debug, Clone)]
62pub struct SymbolTableError {
63 pub key: String,
64 pub conflict: String,
65}
66
67impl std::fmt::Display for SymbolTableError {
68 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
69 write!(
70 f,
71 "Cannot set '{}': '{}' is not a table",
72 self.key, self.conflict
73 )
74 }
75}
76
77impl std::error::Error for SymbolTableError {}
78
79impl From<SymbolTableError> for crate::error::ExpressionError {
80 fn from(e: SymbolTableError) -> Self {
87 crate::error::ExpressionError::new(e.to_string())
88 }
89}
90
91#[derive(Debug, Clone)]
93pub enum SymbolTableEntry {
94 Table(SymbolTable),
95 Value(ExprValue),
96}
97
98#[derive(Debug, Clone, Default)]
103pub struct SymbolTable {
104 pub(crate) table: HashMap<String, SymbolTableEntry>,
105}
106
107impl SymbolTable {
108 pub fn new() -> Self {
109 Self {
110 table: HashMap::new(),
111 }
112 }
113
114 pub fn from_pairs<'a, I>(pairs: I) -> Result<Self, SymbolTableError>
120 where
121 I: IntoIterator<Item = (&'a str, ExprValue)>,
122 {
123 let mut st = Self::new();
124 for (k, v) in pairs {
125 st.set(k, v)?;
126 }
127 Ok(st)
128 }
129
130 pub fn set_table(&mut self, key: &str, subtable: SymbolTable) {
132 self.table
133 .insert(key.to_string(), SymbolTableEntry::Table(subtable));
134 }
135
136 pub fn get_table(&self, key: &str) -> Option<&SymbolTable> {
138 match self.get(key) {
139 Some(SymbolTableEntry::Table(t)) => Some(t),
140 _ => None,
141 }
142 }
143
144 pub fn set(&mut self, key: &str, value: impl Into<ExprValue>) -> Result<(), SymbolTableError> {
159 self.set_value(key, value.into())
160 }
161
162 fn set_value(&mut self, key: &str, value: ExprValue) -> Result<(), SymbolTableError> {
163 let parts: Vec<&str> = key.split('.').collect();
164 if parts.len() == 1 {
165 if matches!(self.table.get(key), Some(SymbolTableEntry::Table(_))) {
166 return Err(SymbolTableError {
167 key: key.to_string(),
168 conflict: key.to_string(),
169 });
170 }
171 self.table
172 .insert(key.to_string(), SymbolTableEntry::Value(value));
173 return Ok(());
174 }
175 let mut current = self;
176 for &part in &parts[..parts.len() - 1] {
177 let entry = current
178 .table
179 .entry(part.to_string())
180 .or_insert_with(|| SymbolTableEntry::Table(SymbolTable::new()));
181 current = match entry {
182 SymbolTableEntry::Table(t) => t,
183 _ => {
184 return Err(SymbolTableError {
185 key: key.to_string(),
186 conflict: part.to_string(),
187 })
188 }
189 };
190 }
191 let last = parts.last().unwrap().to_string();
192 if matches!(current.table.get(&last), Some(SymbolTableEntry::Table(_))) {
193 return Err(SymbolTableError {
194 key: key.to_string(),
195 conflict: last,
196 });
197 }
198 current.table.insert(last, SymbolTableEntry::Value(value));
199 Ok(())
200 }
201
202 pub fn set_string(&mut self, key: &str, value: &str) -> Result<(), SymbolTableError> {
204 self.set(key, ExprValue::String(value.to_string()))
205 }
206
207 pub fn get(&self, key: &str) -> Option<&SymbolTableEntry> {
209 let parts: Vec<&str> = key.split('.').collect();
210 let mut current = self;
211 for (i, &part) in parts.iter().enumerate() {
212 match current.table.get(part) {
213 Some(SymbolTableEntry::Table(t)) if i < parts.len() - 1 => current = t,
214 Some(entry) if i == parts.len() - 1 => return Some(entry),
215 _ => return None,
216 }
217 }
218 None
219 }
220
221 pub fn get_value(&self, key: &str) -> Option<&ExprValue> {
223 match self.get(key) {
224 Some(SymbolTableEntry::Value(v)) => Some(v),
225 _ => None,
226 }
227 }
228
229 pub fn get_string(&self, key: &str) -> Option<&str> {
231 match self.get_value(key) {
232 Some(ExprValue::String(s)) => Some(s),
233 Some(ExprValue::Path { value, .. }) => Some(value),
234 _ => None,
235 }
236 }
237
238 pub fn contains(&self, key: &str) -> bool {
239 self.get(key).is_some()
240 }
241
242 pub fn keys(&self) -> impl Iterator<Item = &str> {
244 self.table.keys().map(|s| s.as_str())
245 }
246
247 pub fn all_paths(&self, prefix: &str) -> Vec<String> {
252 let mut out = Vec::new();
253 self.collect_paths(prefix, &mut out);
254 out
255 }
256
257 fn collect_paths(&self, prefix: &str, out: &mut Vec<String>) {
258 for (key, entry) in &self.table {
259 let path = if prefix.is_empty() {
260 key.clone()
261 } else {
262 format!("{prefix}.{key}")
263 };
264 match entry {
265 SymbolTableEntry::Value(_) => out.push(path),
266 SymbolTableEntry::Table(sub) => sub.collect_paths(&path, out),
267 }
268 }
269 }
270
271 pub fn merge_from(&mut self, other: &SymbolTable) {
273 for (key, entry) in &other.table {
274 match entry {
275 SymbolTableEntry::Value(v) => {
276 self.table
277 .insert(key.clone(), SymbolTableEntry::Value(v.clone()));
278 }
279 SymbolTableEntry::Table(sub) => match self.table.get_mut(key) {
280 Some(SymbolTableEntry::Table(existing)) => existing.merge_from(sub),
281 _ => {
282 self.table
283 .insert(key.clone(), SymbolTableEntry::Table(sub.clone()));
284 }
285 },
286 }
287 }
288 }
289}
290
291impl serde::Serialize for SymbolTable {
292 fn serialize<S: serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
293 use serde::ser::SerializeSeq;
294 let paths = self.all_paths("");
295 let entries: Vec<_> = paths
297 .iter()
298 .filter_map(|p| {
299 self.get_value(p).and_then(|v| {
300 if matches!(v, ExprValue::Unresolved(_)) {
301 None
302 } else {
303 Some((p, v))
304 }
305 })
306 })
307 .collect();
308 let mut seq = s.serialize_seq(Some(entries.len()))?;
309 for (path, value) in entries {
310 seq.serialize_element(&serde_json::json!({
311 "name": path,
312 "value": value.transport_value(),
313 "type": value.expr_type().to_string(),
314 }))?;
315 }
316 seq.end()
317 }
318}
319
320impl<'de> serde::Deserialize<'de> for SymbolTable {
321 fn deserialize<D: serde::Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
322 let arr: Vec<serde_json::Value> = serde::Deserialize::deserialize(d)?;
323 if arr.len() > MAX_SYMBOL_TABLE_ENTRIES {
324 return Err(serde::de::Error::custom(format!(
325 "SymbolTable: too many entries ({}); maximum is {}",
326 arr.len(),
327 MAX_SYMBOL_TABLE_ENTRIES,
328 )));
329 }
330 let mut st = SymbolTable::new();
331 for entry in &arr {
332 let name = entry
333 .get("name")
334 .and_then(|n| n.as_str())
335 .ok_or_else(|| serde::de::Error::missing_field("name"))?;
336 let type_str = entry
337 .get("type")
338 .and_then(|t| t.as_str())
339 .ok_or_else(|| serde::de::Error::missing_field("type"))?;
340 let binding_type = ExprType::parse(type_str).map_err(serde::de::Error::custom)?;
341 let raw_value = entry
342 .get("value")
343 .ok_or_else(|| serde::de::Error::missing_field("value"))?;
344 let value = ExprValue::from_transport_value(
345 raw_value,
346 &binding_type,
347 crate::path_mapping::PathFormat::Posix,
348 )
349 .map_err(serde::de::Error::custom)?;
350 st.set(name, value).map_err(serde::de::Error::custom)?;
351 }
352 Ok(st)
353 }
354}
355
356impl<'a> FromIterator<(&'a str, ExprValue)> for SymbolTable {
363 fn from_iter<I: IntoIterator<Item = (&'a str, ExprValue)>>(iter: I) -> Self {
364 let mut st = Self::new();
365 for (k, v) in iter {
366 st.set(k, v)
367 .expect("SymbolTable path conflict in FromIterator");
368 }
369 st
370 }
371}
372
373#[derive(Debug, Clone, serde::Serialize)]
386#[serde(transparent)]
387pub struct SerializedSymbolTable(serde_json::Value);
388
389impl SerializedSymbolTable {
390 pub fn from_value(v: serde_json::Value) -> Self {
392 Self(v)
393 }
394
395 pub fn from_json_str(s: &str) -> Result<Self, serde_json::Error> {
397 Ok(Self(serde_json::from_str(s)?))
398 }
399
400 pub fn from_symtab(st: &SymbolTable) -> Self {
402 Self(serde_json::to_value(st).expect("SymbolTable serialization cannot fail"))
403 }
404
405 pub fn to_symtab(
414 &self,
415 path_format: crate::path_mapping::PathFormat,
416 ) -> Result<SymbolTable, String> {
417 let arr = self
418 .0
419 .as_array()
420 .ok_or("SerializedSymbolTable: expected JSON array")?;
421 if arr.len() > MAX_SYMBOL_TABLE_ENTRIES {
422 return Err(format!(
423 "SerializedSymbolTable: too many entries ({}); maximum is {}",
424 arr.len(),
425 MAX_SYMBOL_TABLE_ENTRIES,
426 ));
427 }
428 let mut st = SymbolTable::new();
429 for entry in arr {
430 let name = entry
431 .get("name")
432 .and_then(|n| n.as_str())
433 .ok_or("SerializedSymbolTable: missing 'name' field")?;
434 let type_str = entry
435 .get("type")
436 .and_then(|t| t.as_str())
437 .ok_or("SerializedSymbolTable: missing 'type' field")?;
438 let binding_type = ExprType::parse(type_str)
439 .map_err(|e| format!("SerializedSymbolTable: bad type '{type_str}': {e}"))?;
440 let raw_value = entry
441 .get("value")
442 .ok_or("SerializedSymbolTable: missing 'value' field")?;
443 let value = ExprValue::from_transport_value(raw_value, &binding_type, path_format)
444 .map_err(|e| format!("SerializedSymbolTable: {e}"))?;
445 st.set(name, value)
446 .map_err(|e| format!("SerializedSymbolTable: {e}"))?;
447 }
448 Ok(st)
449 }
450
451 pub fn as_value(&self) -> &serde_json::Value {
453 &self.0
454 }
455}
456
457impl<'de> serde::Deserialize<'de> for SerializedSymbolTable {
458 fn deserialize<D: serde::Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
459 let v: serde_json::Value = serde::Deserialize::deserialize(d)?;
460 Ok(Self(v))
461 }
462}
463
464#[macro_export]
484macro_rules! symtab {
485 ($($key:expr => $val:expr),* $(,)?) => {{
486 let mut st = $crate::SymbolTable::new();
487 $(st.set($key, $val).expect("symtab! path conflict");)*
488 st
489 }};
490}