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