state_engine/common/pool.rs
1use std::collections::HashMap;
2
3/// Interns unique strings and assigns each a u16 index.
4/// Index 0 is reserved as null.
5pub struct DynamicPool {
6 slots: Vec<String>,
7 forward: HashMap<String, u16>,
8}
9
10impl DynamicPool {
11 pub fn new() -> Self {
12 let mut pool = Self {
13 slots: Vec::new(),
14 forward: HashMap::new(),
15 };
16 pool.slots.push(String::new()); // index 0 = null
17 pool
18 }
19
20 /// Interns a string and returns its index.
21 ///
22 /// # Examples
23 ///
24 /// ```
25 /// use state_engine::common::pool::DynamicPool;
26 ///
27 /// let mut pool = DynamicPool::new();
28 /// let i0 = pool.intern("foo");
29 /// let i1 = pool.intern("bar");
30 ///
31 /// // same string returns same index
32 /// assert_eq!(pool.intern("foo"), i0);
33 /// assert_ne!(i0, i1);
34 ///
35 /// // index 0 is reserved as null
36 /// assert_ne!(i0, 0);
37 /// ```
38 pub fn intern(&mut self, s: &str) -> u16 {
39 if let Some(&idx) = self.forward.get(s) {
40 return idx;
41 }
42 let idx = self.slots.len() as u16;
43 self.slots.push(s.to_string());
44 self.forward.insert(s.to_string(), idx);
45 idx
46 }
47
48 /// Returns the string at the given index, or None if out of range.
49 ///
50 /// # Examples
51 ///
52 /// ```
53 /// use state_engine::common::pool::DynamicPool;
54 ///
55 /// let mut pool = DynamicPool::new();
56 /// let i0 = pool.intern("foo");
57 /// assert_eq!(pool.get(i0), Some("foo"));
58 /// assert_eq!(pool.get(0), Some("")); // null slot
59 /// assert_eq!(pool.get(999), None);
60 /// ```
61 pub fn get(&self, index: u16) -> Option<&str> {
62 self.slots.get(index as usize).map(|s| s.as_str())
63 }
64}
65
66impl Default for DynamicPool {
67 fn default() -> Self {
68 Self::new()
69 }
70}
71
72/// Stores path sequences as lists of dynamic pool indices.
73/// Index 0 is reserved as null.
74pub struct PathMap {
75 slots: Vec<Vec<u16>>,
76}
77
78impl PathMap {
79 pub fn new() -> Self {
80 let mut map = Self { slots: Vec::new() };
81 map.slots.push(Vec::new()); // index 0 = null
82 map
83 }
84
85 /// Appends a path (as dynamic pool indices) and returns its index.
86 ///
87 /// # Examples
88 ///
89 /// ```
90 /// use state_engine::common::pool::PathMap;
91 ///
92 /// let mut map = PathMap::new();
93 /// let idx = map.push(vec![1, 2, 3]);
94 ///
95 /// assert_ne!(idx, 0);
96 /// assert_eq!(map.get(idx), Some([1u16, 2, 3].as_slice()));
97 /// assert_eq!(map.get(0), Some([].as_slice())); // null slot
98 /// assert_eq!(map.get(999), None);
99 /// ```
100 pub fn push(&mut self, indices: Vec<u16>) -> u16 {
101 let idx = self.slots.len() as u16;
102 self.slots.push(indices);
103 idx
104 }
105
106 /// Returns the path indices at the given index.
107 pub fn get(&self, index: u16) -> Option<&[u16]> {
108 self.slots.get(index as usize).map(|v| v.as_slice())
109 }
110}
111
112impl Default for PathMap {
113 fn default() -> Self {
114 Self::new()
115 }
116}
117
118/// Stores child key index lists for nodes with multiple children.
119/// Index 0 is reserved as null.
120pub struct ChildrenMap {
121 slots: Vec<Vec<u16>>,
122}
123
124impl ChildrenMap {
125 pub fn new() -> Self {
126 let mut map = Self { slots: Vec::new() };
127 map.slots.push(Vec::new()); // index 0 = null
128 map
129 }
130
131 /// Appends a children list (as key list indices) and returns its index.
132 ///
133 /// # Examples
134 ///
135 /// ```
136 /// use state_engine::common::pool::ChildrenMap;
137 ///
138 /// let mut map = ChildrenMap::new();
139 /// let idx = map.push(vec![2, 3, 4]);
140 ///
141 /// assert_ne!(idx, 0);
142 /// assert_eq!(map.get(idx), Some([2u16, 3, 4].as_slice()));
143 /// assert_eq!(map.get(0), Some([].as_slice())); // null slot
144 /// assert_eq!(map.get(999), None);
145 /// ```
146 pub fn push(&mut self, indices: Vec<u16>) -> u16 {
147 let idx = self.slots.len() as u16;
148 self.slots.push(indices);
149 idx
150 }
151
152 /// Returns the child indices at the given index.
153 pub fn get(&self, index: u16) -> Option<&[u16]> {
154 self.slots.get(index as usize).map(|v| v.as_slice())
155 }
156}
157
158impl Default for ChildrenMap {
159 fn default() -> Self {
160 Self::new()
161 }
162}
163
164/// Stores key records (u64) forming the Trie structure.
165/// Index 0 is reserved as null.
166pub struct KeyList {
167 slots: Vec<u64>,
168}
169
170impl KeyList {
171 pub fn new() -> Self {
172 let mut list = Self { slots: Vec::new() };
173 list.slots.push(0u64); // index 0 = null
174 list
175 }
176
177 /// Appends a key record and returns its index.
178 ///
179 /// # Examples
180 ///
181 /// ```
182 /// use state_engine::common::pool::KeyList;
183 ///
184 /// let mut list = KeyList::new();
185 /// let idx = list.push(0xDEAD_BEEF_u64);
186 ///
187 /// assert_ne!(idx, 0);
188 /// assert_eq!(list.get(idx), Some(0xDEAD_BEEF_u64));
189 /// assert_eq!(list.get(0), Some(0u64)); // null slot
190 /// assert_eq!(list.get(999), None);
191 ///
192 /// // set overwrites in place
193 /// list.set(idx, 0xCAFE);
194 /// assert_eq!(list.get(idx), Some(0xCAFE));
195 /// ```
196 pub fn push(&mut self, record: u64) -> u16 {
197 let idx = self.slots.len() as u16;
198 self.slots.push(record);
199 idx
200 }
201
202 /// Returns the key record at the given index.
203 pub fn get(&self, index: u16) -> Option<u64> {
204 self.slots.get(index as usize).copied()
205 }
206
207 /// Updates the key record at the given index.
208 pub fn set(&mut self, index: u16, record: u64) {
209 if let Some(slot) = self.slots.get_mut(index as usize) {
210 *slot = record;
211 }
212 }
213}
214
215impl Default for KeyList {
216 fn default() -> Self {
217 Self::new()
218 }
219}
220
221/// Stores YAML value records ([u64; 2]) for leaf values.
222/// Index 0 is reserved as null.
223pub struct YamlValueList {
224 slots: Vec<[u64; 2]>,
225}
226
227impl YamlValueList {
228 pub fn new() -> Self {
229 let mut list = Self { slots: Vec::new() };
230 list.slots.push([0u64; 2]); // index 0 = null
231 list
232 }
233
234 /// Appends a value record and returns its index.
235 ///
236 /// # Examples
237 ///
238 /// ```
239 /// use state_engine::common::pool::YamlValueList;
240 ///
241 /// let mut list = YamlValueList::new();
242 /// let record = [0xABCD_u64, 0x1234_u64];
243 /// let idx = list.push(record);
244 ///
245 /// assert_ne!(idx, 0);
246 /// assert_eq!(list.get(idx), Some([0xABCD_u64, 0x1234_u64]));
247 /// assert_eq!(list.get(0), Some([0u64, 0u64])); // null slot
248 /// assert_eq!(list.get(999), None);
249 /// ```
250 pub fn push(&mut self, record: [u64; 2]) -> u16 {
251 let idx = self.slots.len() as u16;
252 self.slots.push(record);
253 idx
254 }
255
256 /// Returns the value record at the given index.
257 pub fn get(&self, index: u16) -> Option<[u64; 2]> {
258 self.slots.get(index as usize).copied()
259 }
260}
261
262impl Default for YamlValueList {
263 fn default() -> Self {
264 Self::new()
265 }
266}
267
268/// State value record: 32-bit fixed-length record.
269///
270/// Layout:
271/// | field | bit |
272/// |-------------|-----|
273/// | key_index | 16 |
274/// | value_index | 16 |
275///
276/// - key_index: index into KeyList (for type info via key record's type index)
277/// - value_index: index into StateValueList's value buffer (serde_json::Value)
278pub type StateRecord = u32;
279
280pub const STATE_OFFSET_KEY: u32 = 16;
281pub const STATE_OFFSET_VALUE: u32 = 0;
282pub const STATE_MASK_KEY: u32 = 0xFFFF;
283pub const STATE_MASK_VALUE: u32 = 0xFFFF;
284
285pub fn state_new() -> StateRecord { 0 }
286
287pub fn state_get(record: StateRecord, offset: u32, mask: u32) -> u16 {
288 ((record >> offset) & mask) as u16
289}
290
291pub fn state_set(record: StateRecord, offset: u32, mask: u32, value: u16) -> StateRecord {
292 (record & !(mask << offset)) | (((value as u32) & mask) << offset)
293}
294
295/// Stores state value records (u32) and their associated serde_json::Value payloads.
296/// Index 0 is reserved as null.
297pub struct StateValueList {
298 records: Vec<StateRecord>,
299 values: Vec<serde_json::Value>,
300}
301
302impl StateValueList {
303 pub fn new() -> Self {
304 let mut list = Self {
305 records: Vec::new(),
306 values: Vec::new(),
307 };
308 list.records.push(0);
309 list.values.push(serde_json::Value::Null);
310 list
311 }
312
313 /// Appends a state record and its value, returning the record index.
314 ///
315 /// # Examples
316 ///
317 /// ```
318 /// use state_engine::common::pool::{StateValueList, STATE_OFFSET_KEY, STATE_MASK_KEY, STATE_OFFSET_VALUE, STATE_MASK_VALUE, state_get};
319 /// use serde_json::json;
320 ///
321 /// let mut list = StateValueList::new();
322 /// let idx = list.push(42, json!("hello"));
323 ///
324 /// let record = list.get_record(idx).unwrap();
325 /// assert_eq!(state_get(record, STATE_OFFSET_KEY, STATE_MASK_KEY), 42);
326 ///
327 /// let value = list.get_value(idx).unwrap();
328 /// assert_eq!(value, &json!("hello"));
329 /// ```
330 pub fn push(&mut self, key_index: u16, value: serde_json::Value) -> u16 {
331 let value_index = self.values.len() as u16;
332 self.values.push(value);
333
334 let record = state_set(state_new(), STATE_OFFSET_KEY, STATE_MASK_KEY, key_index);
335 let record = state_set(record, STATE_OFFSET_VALUE, STATE_MASK_VALUE, value_index);
336 self.records.push(record);
337
338 (self.records.len() - 1) as u16
339 }
340
341 /// Updates the value at the given record index.
342 pub fn update(&mut self, index: u16, value: serde_json::Value) -> bool {
343 let record = match self.records.get(index as usize) {
344 Some(&r) => r,
345 None => return false,
346 };
347 let value_index = state_get(record, STATE_OFFSET_VALUE, STATE_MASK_VALUE) as usize;
348 if let Some(slot) = self.values.get_mut(value_index) {
349 *slot = value;
350 true
351 } else {
352 false
353 }
354 }
355
356 /// Removes a record by zeroing it (index remains valid, value becomes Null).
357 pub fn remove(&mut self, index: u16) -> bool {
358 let record = match self.records.get(index as usize) {
359 Some(&r) => r,
360 None => return false,
361 };
362 let value_index = state_get(record, STATE_OFFSET_VALUE, STATE_MASK_VALUE) as usize;
363 if let Some(slot) = self.values.get_mut(value_index) {
364 *slot = serde_json::Value::Null;
365 self.records[index as usize] = 0;
366 true
367 } else {
368 false
369 }
370 }
371
372 pub fn get_record(&self, index: u16) -> Option<StateRecord> {
373 self.records.get(index as usize).copied()
374 }
375
376 pub fn get_value(&self, index: u16) -> Option<&serde_json::Value> {
377 let record = self.records.get(index as usize)?;
378 let value_index = state_get(*record, STATE_OFFSET_VALUE, STATE_MASK_VALUE);
379 self.values.get(value_index as usize)
380 }
381}
382
383impl Default for StateValueList {
384 fn default() -> Self {
385 Self::new()
386 }
387}