1use std::{
5 collections::HashMap,
6 sync::{PoisonError, RwLock, RwLockReadGuard, RwLockWriteGuard},
7};
8
9use sim_kernel::{
10 Cx, Error, Expr, Object, ObjectEncode, ObjectEncoding, Result, Symbol, Table, Value,
11 id::CORE_TABLE_CLASS_ID, object::ClassRef,
12};
13
14use crate::citizen::hash_table_class_symbol;
15
16pub struct HashTable {
25 inner: RwLock<HashMap<Symbol, Value>>,
26}
27
28impl Clone for HashTable {
29 fn clone(&self) -> Self {
30 Self {
31 inner: RwLock::new(
32 self.inner
33 .read()
34 .unwrap_or_else(PoisonError::into_inner)
35 .clone(),
36 ),
37 }
38 }
39}
40
41impl HashTable {
42 fn read(&self) -> Result<RwLockReadGuard<'_, HashMap<Symbol, Value>>> {
43 self.inner
44 .read()
45 .map_err(|_| Error::Eval("table/hash lock poisoned".into()))
46 }
47
48 fn write(&self) -> Result<RwLockWriteGuard<'_, HashMap<Symbol, Value>>> {
49 self.inner
50 .write()
51 .map_err(|_| Error::Eval("table/hash lock poisoned".into()))
52 }
53
54 pub fn new() -> Self {
56 Self {
57 inner: RwLock::new(HashMap::new()),
58 }
59 }
60
61 pub fn with_entries(entries: Vec<(Symbol, Value)>) -> Self {
81 Self {
82 inner: RwLock::new(entries.into_iter().collect()),
83 }
84 }
85
86 fn descriptor_entries(&self, cx: &mut Cx) -> Result<Vec<(Symbol, Expr)>> {
87 let mut entries = self
88 .read()?
89 .iter()
90 .map(|(key, value)| Ok((key.clone(), value.object().as_expr(cx)?)))
91 .collect::<Result<Vec<_>>>()?;
92 entries.sort_by(|left, right| left.0.cmp(&right.0));
93 Ok(entries)
94 }
95}
96
97impl Default for HashTable {
98 fn default() -> Self {
99 Self::new()
100 }
101}
102
103impl Object for HashTable {
104 fn display(&self, _cx: &mut Cx) -> Result<String> {
105 Ok(format!("table/hash[{}]", self.read()?.len()))
106 }
107
108 fn as_any(&self) -> &dyn std::any::Any {
109 self
110 }
111}
112
113impl sim_kernel::ObjectCompat for HashTable {
114 fn class(&self, cx: &mut Cx) -> Result<ClassRef> {
115 let symbol = hash_table_class_symbol();
116 if let Some(value) = cx.registry().class_by_symbol(&symbol) {
117 return Ok(value.clone());
118 }
119 let symbol = Symbol::qualified("core", "Table");
120 if let Some(value) = cx.registry().class_by_symbol(&symbol) {
121 return Ok(value.clone());
122 }
123 cx.factory().class_stub(CORE_TABLE_CLASS_ID, symbol)
124 }
125 fn as_expr(&self, cx: &mut Cx) -> Result<Expr> {
126 self.as_table_expr(cx)
127 }
128 fn truth(&self, _cx: &mut Cx) -> Result<bool> {
129 Ok(!self.read()?.is_empty())
130 }
131 fn as_table_impl(&self) -> Option<&dyn Table> {
132 Some(self)
133 }
134 fn as_object_encoder(&self) -> Option<&dyn ObjectEncode> {
135 Some(self)
136 }
137}
138
139impl ObjectEncode for HashTable {
140 fn object_encoding(&self, cx: &mut Cx) -> Result<ObjectEncoding> {
141 Ok(ObjectEncoding::Constructor {
142 class: hash_table_class_symbol(),
143 args: vec![
144 Expr::Symbol(Symbol::new("v0")),
145 sim_table_core::citizen_fields::entries::encode(&self.descriptor_entries(cx)?),
146 ],
147 })
148 }
149}
150
151impl sim_citizen::Citizen for HashTable {
152 fn citizen_symbol() -> Symbol {
153 hash_table_class_symbol()
154 }
155
156 fn citizen_version() -> u32 {
157 0
158 }
159
160 fn citizen_arity() -> usize {
161 1
162 }
163
164 fn citizen_fields() -> &'static [&'static str] {
165 &["entries"]
166 }
167}
168
169impl Table for HashTable {
170 fn backend_symbol(&self) -> Symbol {
171 Symbol::qualified("table", "hash")
172 }
173
174 fn get(&self, cx: &mut Cx, key: Symbol) -> Result<Value> {
175 match self.read()?.get(&key) {
176 Some(value) => Ok(value.clone()),
177 None => cx.factory().nil(),
178 }
179 }
180
181 fn set(&self, _cx: &mut Cx, key: Symbol, value: Value) -> Result<()> {
182 self.write()?.insert(key, value);
183 Ok(())
184 }
185
186 fn has(&self, _cx: &mut Cx, key: Symbol) -> Result<bool> {
187 Ok(self.read()?.contains_key(&key))
188 }
189
190 fn del(&self, cx: &mut Cx, key: Symbol) -> Result<Value> {
191 match self.write()?.remove(&key) {
192 Some(value) => Ok(value),
193 None => cx.factory().nil(),
194 }
195 }
196
197 fn keys(&self, _cx: &mut Cx) -> Result<Vec<Symbol>> {
198 Ok(self.read()?.keys().cloned().collect())
199 }
200
201 fn entries(&self, _cx: &mut Cx) -> Result<Vec<(Symbol, Value)>> {
202 Ok(self
203 .read()?
204 .iter()
205 .map(|(key, value)| (key.clone(), value.clone()))
206 .collect())
207 }
208
209 fn len(&self, _cx: &mut Cx) -> Result<usize> {
210 Ok(self.read()?.len())
211 }
212
213 fn clear(&self, _cx: &mut Cx) -> Result<()> {
214 self.write()?.clear();
215 Ok(())
216 }
217}