1use crate::{
8 index::{
9 storage::{insert_front, Cursor as CursorImpl, ImmutableCursor, IndexEntry, Record},
10 Cursor as CursorTrait, Ordered, Unordered,
11 },
12 translator::Translator,
13};
14use commonware_runtime::{
15 telemetry::metrics::{Counter, Gauge, MetricsExt as _},
16 Metrics,
17};
18use std::{
19 collections::{
20 btree_map::{
21 Entry as BTreeEntry, OccupiedEntry as BTreeOccupiedEntry,
22 VacantEntry as BTreeVacantEntry,
23 },
24 BTreeMap,
25 },
26 ops::Bound::{Excluded, Unbounded},
27};
28
29impl<K: Ord + Send + Sync, V: Send + Sync> IndexEntry<V> for BTreeOccupiedEntry<'_, K, Record<V>> {
31 fn get_mut(&mut self) -> &mut Record<V> {
32 self.get_mut()
33 }
34 fn remove(self) {
35 self.remove_entry();
36 }
37}
38
39pub type Cursor<'a, K, V> = CursorImpl<'a, V, BTreeOccupiedEntry<'a, K, Record<V>>>;
41
42pub struct Index<T: Translator, V: Send + Sync> {
45 translator: T,
46 map: BTreeMap<T::Key, Record<V>>,
47
48 keys: Gauge,
49 items: Gauge,
50 pruned: Counter,
51}
52
53impl<T: Translator, V: Send + Sync> Index<T, V> {
54 fn create(keys: &Gauge, items: &Gauge, vacant: BTreeVacantEntry<'_, T::Key, Record<V>>, v: V) {
56 keys.inc();
57 items.inc();
58 vacant.insert(Record {
59 value: v,
60 next: None,
61 });
62 }
63
64 pub fn new(ctx: impl Metrics, translator: T) -> Self {
66 Self {
67 translator,
68 map: BTreeMap::new(),
69 keys: ctx.gauge("keys", "Number of translated keys in the index"),
70 items: ctx.gauge("items", "Number of items in the index"),
71 pruned: ctx.counter("pruned", "Number of items pruned"),
72 }
73 }
74
75 pub(super) fn next_translated_key_no_cycle<'a>(
78 &'a self,
79 key: &[u8],
80 ) -> Option<ImmutableCursor<'a, V>> {
81 let k = self.translator.transform(key);
82 self.map
83 .range((Excluded(k), Unbounded))
84 .next()
85 .map(|(_, record)| ImmutableCursor::new(record))
86 }
87
88 pub(super) fn prev_translated_key_no_cycle<'a>(
91 &'a self,
92 key: &[u8],
93 ) -> Option<ImmutableCursor<'a, V>> {
94 let k = self.translator.transform(key);
95 self.map
96 .range(..k)
97 .next_back()
98 .map(|(_, record)| ImmutableCursor::new(record))
99 }
100}
101
102impl<T: Translator, V: Send + Sync> Ordered for Index<T, V> {
103 type Iterator<'a>
104 = ImmutableCursor<'a, V>
105 where
106 Self: 'a;
107
108 fn prev_translated_key<'a>(&'a self, key: &[u8]) -> Option<(Self::Iterator<'a>, bool)>
109 where
110 Self::Value: 'a,
111 {
112 let res = self.prev_translated_key_no_cycle(key);
113 if let Some(res) = res {
114 return Some((res, false));
115 }
116
117 self.last_translated_key().map(|res| (res, true))
118 }
119
120 fn next_translated_key<'a>(&'a self, key: &[u8]) -> Option<(Self::Iterator<'a>, bool)>
121 where
122 Self::Value: 'a,
123 {
124 let res = self.next_translated_key_no_cycle(key);
125 if let Some(res) = res {
126 return Some((res, false));
127 }
128
129 self.first_translated_key().map(|res| (res, true))
130 }
131
132 fn first_translated_key<'a>(&'a self) -> Option<Self::Iterator<'a>>
133 where
134 Self::Value: 'a,
135 {
136 self.map
137 .first_key_value()
138 .map(|(_, record)| ImmutableCursor::new(record))
139 }
140
141 fn last_translated_key<'a>(&'a self) -> Option<Self::Iterator<'a>>
142 where
143 Self::Value: 'a,
144 {
145 self.map
146 .last_key_value()
147 .map(|(_, record)| ImmutableCursor::new(record))
148 }
149}
150
151impl<T: Translator, V: Send + Sync> super::Factory<T> for Index<T, V> {
152 fn new(ctx: impl commonware_runtime::Metrics, translator: T) -> Self {
153 Self::new(ctx, translator)
154 }
155}
156
157impl<T: Translator, V: Send + Sync> Unordered for Index<T, V> {
158 type Value = V;
159 type Cursor<'a>
160 = Cursor<'a, T::Key, V>
161 where
162 Self: 'a;
163
164 fn get<'a>(&'a self, key: &[u8]) -> impl Iterator<Item = &'a V> + 'a
165 where
166 V: 'a,
167 {
168 let k = self.translator.transform(key);
169 self.map
170 .get(&k)
171 .map(|record| ImmutableCursor::new(record))
172 .into_iter()
173 .flatten()
174 }
175
176 fn get_mut<'a>(&'a mut self, key: &[u8]) -> Option<Self::Cursor<'a>> {
177 let k = self.translator.transform(key);
178 match self.map.entry(k) {
179 BTreeEntry::Occupied(entry) => Some(Cursor::<'_, T::Key, V>::new(
180 entry,
181 &self.keys,
182 &self.items,
183 &self.pruned,
184 )),
185 BTreeEntry::Vacant(_) => None,
186 }
187 }
188
189 fn get_mut_or_insert<'a>(&'a mut self, key: &[u8], value: V) -> Option<Self::Cursor<'a>> {
190 let k = self.translator.transform(key);
191 match self.map.entry(k) {
192 BTreeEntry::Occupied(entry) => Some(Cursor::<'_, T::Key, V>::new(
193 entry,
194 &self.keys,
195 &self.items,
196 &self.pruned,
197 )),
198 BTreeEntry::Vacant(entry) => {
199 Self::create(&self.keys, &self.items, entry, value);
200 None
201 }
202 }
203 }
204
205 fn insert(&mut self, key: &[u8], value: V) {
206 let k = self.translator.transform(key);
207 match self.map.entry(k) {
208 BTreeEntry::Occupied(mut entry) => {
209 insert_front(entry.get_mut(), value);
210 self.items.inc();
211 }
212 BTreeEntry::Vacant(entry) => {
213 Self::create(&self.keys, &self.items, entry, value);
214 }
215 }
216 }
217
218 fn insert_and_retain(&mut self, key: &[u8], value: V, should_retain: impl Fn(&V) -> bool) {
219 let k = self.translator.transform(key);
220 match self.map.entry(k) {
221 BTreeEntry::Occupied(entry) => {
222 let mut cursor =
223 Cursor::<'_, T::Key, V>::new(entry, &self.keys, &self.items, &self.pruned);
224
225 cursor.retain(&should_retain);
227
228 if should_retain(&value) {
230 cursor.insert(value);
231 }
232 }
233 BTreeEntry::Vacant(entry) => {
234 if should_retain(&value) {
236 Self::create(&self.keys, &self.items, entry, value);
237 }
238 }
239 }
240 }
241
242 fn remove(&mut self, key: &[u8]) {
243 let k = self.translator.transform(key);
244 if let Some(mut record) = self.map.remove(&k) {
245 self.keys.dec();
247 self.items.dec();
248 self.pruned.inc();
249 while let Some(next) = record.next.take() {
250 self.items.dec();
251 self.pruned.inc();
252 record = *next;
253 }
254 }
255 }
256
257 #[cfg(test)]
258 fn keys(&self) -> usize {
259 self.map.len()
260 }
261
262 #[cfg(test)]
263 fn items(&self) -> usize {
264 self.items.get() as usize
265 }
266
267 #[cfg(test)]
268 fn pruned(&self) -> usize {
269 self.pruned.get() as usize
270 }
271}
272
273impl<T: Translator, V: Send + Sync> Drop for Index<T, V> {
274 fn drop(&mut self) {
277 for (_, record) in self.map.iter_mut() {
278 let mut next = record.next.take();
279 while let Some(mut record) = next {
280 next = record.next.take();
281 }
282 }
283 }
284}
285
286#[cfg(test)]
287mod tests {
288 use super::*;
289 use crate::translator::OneCap;
290 use commonware_formatting::hex;
291 use commonware_macros::test_traced;
292 use commonware_runtime::{deterministic, Runner};
293
294 #[test_traced]
295 fn test_ordered_empty_index() {
296 let runner = deterministic::Runner::default();
297 runner.start(|context| async move {
298 let index = Index::<_, u64>::new(context, OneCap);
299
300 assert!(index.first_translated_key().is_none());
301 assert!(index.last_translated_key().is_none());
302 assert!(index.prev_translated_key(b"key").is_none());
303 assert!(index.next_translated_key(b"key").is_none());
304 });
305 }
306
307 #[test_traced]
308 fn test_ordered_index_ordering() {
309 let runner = deterministic::Runner::default();
310 runner.start(|context| async move {
311 let mut index = Index::<_, u64>::new(context, OneCap);
312 assert_eq!(index.keys(), 0);
313
314 let k1 = &hex!("0x0b02AA"); let k2 = &hex!("0x1c04CC"); let k2_collides = &hex!("0x1c0311");
317 let k3 = &hex!("0x2d06EE"); index.insert(k1, 1);
319 index.insert(k2, 21);
320 index.insert(k2_collides, 22);
321 index.insert(k3, 3);
322 assert_eq!(index.keys(), 3);
323
324 let mut next = index.first_translated_key().unwrap();
326 assert_eq!(next.next().unwrap(), &1);
327 assert_eq!(next.next(), None);
328
329 let (mut next, wrapped) = index.next_translated_key(&[0x00]).unwrap();
331 assert!(!wrapped);
332 assert_eq!(next.next().unwrap(), &1);
333 assert_eq!(next.next(), None);
334
335 let (mut next, wrapped) = index.next_translated_key(&hex!("0x0b0102")).unwrap();
337 assert!(!wrapped);
338 assert_eq!(next.next().unwrap(), &22);
339 assert_eq!(next.next().unwrap(), &21);
340 assert_eq!(next.next(), None);
341
342 let (mut next, wrapped) = index.next_translated_key(&hex!("0x1b010203")).unwrap();
344 assert!(!wrapped);
345 assert_eq!(next.next().unwrap(), &22);
346 assert_eq!(next.next().unwrap(), &21);
347 assert_eq!(next.next(), None);
348
349 let (mut next, wrapped) = index.next_translated_key(&hex!("0x2a01020304")).unwrap();
351 assert!(!wrapped);
352 assert_eq!(next.next().unwrap(), &3);
353 assert_eq!(next.next(), None);
354
355 let (mut next, wrapped) = index.next_translated_key(k3).unwrap();
357 assert!(wrapped);
358 assert_eq!(next.next().unwrap(), &1);
359 assert_eq!(next.next(), None);
360
361 let (mut next, wrapped) = index.next_translated_key(&hex!("0x2eFF")).unwrap();
363 assert!(wrapped);
364 assert_eq!(next.next().unwrap(), &1);
365 assert_eq!(next.next(), None);
366
367 let (mut prev, wrapped) = index.prev_translated_key(k1).unwrap();
369 assert!(wrapped);
370 assert_eq!(prev.next().unwrap(), &3);
371 assert_eq!(prev.next(), None);
372
373 let (mut prev, wrapped) = index.prev_translated_key(&hex!("0x0c0102")).unwrap();
375 assert!(!wrapped);
376 assert_eq!(prev.next().unwrap(), &1);
377 assert_eq!(prev.next(), None);
378
379 let (mut prev, wrapped) = index.prev_translated_key(&hex!("0x1d0102")).unwrap();
381 assert!(!wrapped);
382 assert_eq!(prev.next().unwrap(), &22);
383 assert_eq!(prev.next().unwrap(), &21);
384 assert_eq!(prev.next(), None);
385
386 let (mut prev, wrapped) = index.prev_translated_key(&hex!("0xCC0102")).unwrap();
388 assert!(!wrapped);
389 assert_eq!(prev.next().unwrap(), &3);
390 assert_eq!(prev.next(), None);
391
392 let mut last = index.last_translated_key().unwrap();
394 assert_eq!(last.next().unwrap(), &3);
395 assert_eq!(last.next(), None);
396 });
397 }
398}