Skip to main content

latexml_core/common/arena/
data.rs

1use std::{
2  any::type_name,
3  collections::hash_map::{Entry, IntoIter, Iter, IterMut, Keys},
4  fmt,
5  iter::IntoIterator,
6  ops::Index,
7};
8
9use rustc_hash::FxHashMap as HashMap;
10use string_interner::{Symbol, symbol::SymbolU32};
11
12use crate::common::arena;
13
14pub type SymStr = SymbolU32;
15
16// TODO: Are we heading in the right direction with this interface...
17// is there performance overhead from the extra wrap? It seems borderline usable...
18
19/// A convenience abstraction over a String-keyed HashMap
20///
21/// typically used for `HashMap<String,Stored>` states.
22/// The goal is to support both a string interface, as well as the interned tickets interface,
23/// while avoiding String allocations internally.
24#[derive(Clone)]
25pub struct SymHashMap<T>(pub HashMap<SymStr, T>);
26
27impl<T> Default for SymHashMap<T> {
28  fn default() -> Self { SymHashMap(HashMap::default()) }
29}
30
31impl<T> SymHashMap<T> {
32  #[inline]
33  pub fn len(&self) -> usize { self.0.len() }
34  #[inline]
35  pub fn is_empty(&self) -> bool { self.0.is_empty() }
36  #[inline]
37  pub fn get(&self, key: &str) -> Option<&T> { self.0.get(&arena::pin(key)) }
38  #[inline]
39  pub fn get_sym(&self, key: SymStr) -> Option<&T> { self.0.get(&key) }
40  #[inline]
41  pub fn get_mut(&mut self, key: &str) -> Option<&mut T> { self.0.get_mut(&arena::pin(key)) }
42  #[inline]
43  pub fn get_mut_sym(&mut self, key: SymStr) -> Option<&mut T> { self.0.get_mut(&key) }
44  #[inline]
45  pub fn contains_key(&self, key: &str) -> bool { self.0.contains_key(&arena::pin(key)) }
46  #[inline]
47  pub fn contains_key_sym(&self, key: &SymStr) -> bool { self.0.contains_key(key) }
48  #[inline]
49  pub fn insert(&mut self, key: &str, value: T) { self.0.insert(arena::pin(key), value); }
50  #[inline]
51  pub fn insert_sym(&mut self, key: SymStr, value: T) { self.0.insert(key, value); }
52  #[inline]
53  pub fn remove(&mut self, key: &str) { self.0.remove(&arena::pin(key)); }
54  #[inline]
55  pub fn remove_sym(&mut self, key: SymStr) { self.0.remove(&key); }
56  #[inline]
57  pub fn keys(&self) -> Keys<'_, SymStr, T> { self.0.keys() }
58  #[inline]
59  pub fn entry(&mut self, key: &str) -> Entry<'_, SymStr, T> { self.0.entry(arena::pin(key)) }
60  #[inline]
61  pub fn entry_sym(&mut self, key: SymStr) -> Entry<'_, SymStr, T> { self.0.entry(key) }
62  #[inline]
63  pub fn iter(&self) -> Iter<'_, SymStr, T> { self.0.iter() }
64}
65
66impl<'a, T> IntoIterator for &'a SymHashMap<T> {
67  type Item = (&'a SymStr, &'a T);
68  type IntoIter = Iter<'a, SymStr, T>;
69
70  #[inline]
71  fn into_iter(self) -> Iter<'a, SymStr, T> { self.0.iter() }
72}
73
74impl<'a, T> IntoIterator for &'a mut SymHashMap<T> {
75  type Item = (&'a SymStr, &'a mut T);
76  type IntoIter = IterMut<'a, SymStr, T>;
77
78  #[inline]
79  fn into_iter(self) -> IterMut<'a, SymStr, T> { self.0.iter_mut() }
80}
81impl<T> IntoIterator for SymHashMap<T> {
82  type Item = (SymStr, T);
83  type IntoIter = IntoIter<SymStr, T>;
84  #[inline]
85  fn into_iter(self) -> Self::IntoIter { self.0.into_iter() }
86}
87
88impl<T: fmt::Debug> fmt::Debug for SymHashMap<T> {
89  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
90    write!(f, "SymHashMap[")?;
91    let mut init = true;
92    for (k, v) in self {
93      if init {
94        init = false;
95      } else {
96        write!(f, ", ")?;
97      }
98      arena::with(*k, |key| write!(f, "{key}"))?;
99      // very temporary hack to get the full trace
100      if type_name::<T>() == "string_interner::symbol::SymbolU32" {
101        let symstr = format!("{:?}", v);
102        // "SymbolU32 { value: 28104 }"
103        let mut symiter = symstr.split(' ');
104        symiter.next();
105        symiter.next();
106        symiter.next();
107        let sym_v_str = symiter.next().unwrap();
108        let sym_val = sym_v_str.parse::<usize>().unwrap();
109        let sym = Symbol::try_from_usize(sym_val - 1).unwrap();
110        let vstr = arena::to_string(sym);
111        write!(f, ": {vstr}")?;
112      } else {
113        write!(f, ": [{:?}]", v)?;
114      }
115      // write!(f,": {:?}",v)?;
116    }
117    write!(f, "]")
118  }
119}
120
121impl<T> Index<&SymStr> for SymHashMap<T> {
122  type Output = T;
123  /// Returns a reference to the value corresponding to the supplied key.
124  ///
125  /// # Panics
126  ///
127  /// Panics if the key is not present in the `HashMap`.
128  #[inline]
129  fn index(&self, key: &SymStr) -> &T { &self.0[key] }
130}