sim_kernel/
handle_store.rs1use std::collections::{BTreeMap, HashMap};
7
8use crate::{ref_id::HandleId, value::Value};
9
10pub trait HandleStore {
16 fn intern(&mut self, value: Value) -> HandleId;
18 fn get(&self, id: &HandleId) -> Option<&Value>;
20 fn contains(&self, id: &HandleId) -> bool;
22 fn handle_for_value(&self, value: &Value) -> Option<HandleId>;
24}
25
26#[derive(Clone, Debug, Default)]
29pub struct BTreeHandleStore {
30 values: BTreeMap<HandleId, Value>,
31 handles_by_value: HashMap<Value, HandleId>,
32}
33
34impl BTreeHandleStore {
35 pub fn new() -> Self {
37 Self::default()
38 }
39
40 pub fn len(&self) -> usize {
42 self.values.len()
43 }
44
45 pub fn is_empty(&self) -> bool {
47 self.values.is_empty()
48 }
49}
50
51impl HandleStore for BTreeHandleStore {
52 fn intern(&mut self, value: Value) -> HandleId {
53 if let Some(handle) = self.handles_by_value.get(&value) {
54 return *handle;
55 }
56
57 let handle = HandleId::fresh();
58 self.handles_by_value.insert(value.clone(), handle);
59 self.values.insert(handle, value);
60 handle
61 }
62
63 fn get(&self, id: &HandleId) -> Option<&Value> {
64 self.values.get(id)
65 }
66
67 fn contains(&self, id: &HandleId) -> bool {
68 self.values.contains_key(id)
69 }
70
71 fn handle_for_value(&self, value: &Value) -> Option<HandleId> {
72 self.handles_by_value.get(value).copied()
73 }
74}
75
76#[cfg(test)]
77mod tests {
78 use crate::{DefaultFactory, Factory};
79
80 use super::*;
81
82 fn factory() -> DefaultFactory {
83 DefaultFactory
84 }
85
86 #[test]
87 fn handle_store_intern_followed_by_get_returns_original_value() {
88 let mut store = BTreeHandleStore::new();
89 let value = factory().string("stored".to_owned()).unwrap();
90
91 let handle = store.intern(value.clone());
92
93 assert_eq!(store.get(&handle), Some(&value));
94 assert!(store.contains(&handle));
95 }
96
97 #[test]
98 fn handle_store_reuses_handle_for_same_value() {
99 let mut store = BTreeHandleStore::new();
100 let value = factory().bool(true).unwrap();
101
102 let first = store.intern(value.clone());
103 let second = store.intern(value);
104
105 assert_eq!(first, second);
106 assert_eq!(store.len(), 1);
107 }
108
109 #[test]
110 fn handle_store_distinguishes_distinct_values() {
111 let mut store = BTreeHandleStore::new();
112 let first_value = factory().bool(true).unwrap();
113 let second_value = factory().bool(true).unwrap();
114
115 let first = store.intern(first_value);
116 let second = store.intern(second_value);
117
118 assert_ne!(first, second);
119 assert_eq!(store.len(), 2);
120 }
121
122 #[test]
123 fn handle_store_reuses_handle_for_cloned_value() {
124 let mut store = BTreeHandleStore::new();
125 let left = factory().string("same".to_owned()).unwrap();
126 let right = left.clone();
127
128 assert_eq!(store.intern(left), store.intern(right));
129 }
130}