Skip to main content

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}