1mod cursor;
42mod partition;
43
44pub use self::cursor::Cursor;
45use self::partition::Partition;
46use crate::{
47 index::{
48 partitioned::partition_index_and_sub_key, Cursor as CursorTrait, Factory, Ordered,
49 Unordered,
50 },
51 translator::Translator,
52};
53use commonware_runtime::{
54 telemetry::metrics::{Counter, Gauge, MetricsExt as _},
55 Metrics,
56};
57use std::{
58 collections::{btree_map, hash_map, BTreeMap, HashMap},
59 ops::Bound,
60};
61
62const SPILL_THRESHOLD: usize = 512;
68
69pub struct Index<T: Translator, V: Send + Sync, const P: usize> {
73 translator: T,
75
76 partitions: Box<[Partition<T::Key, V>]>,
80
81 spilled: HashMap<usize, BTreeMap<T::Key, Vec<V>>>,
85
86 threshold: usize,
89
90 keys: Gauge,
92
93 items: Gauge,
95
96 pruned: Counter,
98}
99
100impl<T: Translator, V: Send + Sync, const P: usize> Index<T, V, P> {
101 pub fn new(ctx: impl Metrics, translator: T) -> Self {
103 const {
104 assert!(P > 0 && P <= 3, "P must be in 1..=3");
105 }
106 let count = 1usize << (P * 8);
107 let partitions = (0..count)
108 .map(|_| Partition::default())
109 .collect::<Vec<_>>()
110 .into_boxed_slice();
111 Self {
112 translator,
113 partitions,
114 spilled: HashMap::new(),
115 threshold: SPILL_THRESHOLD,
116 keys: ctx.gauge("keys", "Number of translated keys in the index"),
117 items: ctx.gauge("items", "Number of items in the index"),
118 pruned: ctx.counter("pruned", "Number of items pruned"),
119 }
120 }
121
122 #[cfg(test)]
126 pub(crate) fn with_threshold(ctx: impl Metrics, translator: T, threshold: usize) -> Self {
127 assert!(threshold > 0, "spill threshold must be at least 1");
128 let mut index = Self::new(ctx, translator);
129 index.threshold = threshold;
130 index
131 }
132
133 fn maybe_spill(&mut self, i: usize) {
135 if self.partitions[i].len() < self.threshold {
136 return;
137 }
138 let inner: BTreeMap<T::Key, Vec<V>> = self.partitions[i].drain_runs().into_iter().collect();
139 self.spilled.insert(i, inner);
140 }
141
142 fn spilled_partition(&self, i: usize) -> Option<&BTreeMap<T::Key, Vec<V>>> {
145 if self.spilled.is_empty() {
146 return None;
147 }
148 self.spilled.get(&i)
149 }
150
151 fn partition_values(&self, i: usize, k: &T::Key) -> &[V] {
154 if !self.partitions[i].is_empty() {
155 return self.partitions[i].values(k);
156 }
157 self.spilled_partition(i)
158 .and_then(|inner| inner.get(k))
159 .map_or(&[], Vec::as_slice)
160 }
161
162 fn partition_first(&self, i: usize) -> Option<&[V]> {
164 self.partitions[i].first_values().or_else(|| {
165 self.spilled_partition(i)?
166 .first_key_value()
167 .map(|(_, v)| v.as_slice())
168 })
169 }
170
171 fn partition_last(&self, i: usize) -> Option<&[V]> {
173 self.partitions[i].last_values().or_else(|| {
174 self.spilled_partition(i)?
175 .last_key_value()
176 .map(|(_, v)| v.as_slice())
177 })
178 }
179
180 fn is_empty(&self) -> bool {
182 self.keys.get() == 0
183 }
184
185 fn partition_next_after(&self, i: usize, k: &T::Key) -> Option<&[V]> {
187 self.partitions[i].next_values_after(k).or_else(|| {
188 self.spilled_partition(i)?
189 .range((Bound::Excluded(*k), Bound::Unbounded))
190 .next()
191 .map(|(_, v)| v.as_slice())
192 })
193 }
194
195 fn partition_prev_before(&self, i: usize, k: &T::Key) -> Option<&[V]> {
197 self.partitions[i].prev_values_before(k).or_else(|| {
198 self.spilled_partition(i)?
199 .range((Bound::Unbounded, Bound::Excluded(*k)))
200 .next_back()
201 .map(|(_, v)| v.as_slice())
202 })
203 }
204
205 #[cfg(test)]
207 pub(crate) fn spilled_count(&self) -> usize {
208 self.spilled.len()
209 }
210}
211
212impl<T: Translator, V: Send + Sync, const P: usize> Factory<T> for Index<T, V, P> {
213 fn new(ctx: impl Metrics, translator: T) -> Self {
214 Self::new(ctx, translator)
215 }
216}
217
218impl<T: Translator, V: Send + Sync, const P: usize> Unordered for Index<T, V, P> {
219 type Value = V;
220 type Cursor<'a>
221 = Cursor<'a, T::Key, V>
222 where
223 Self: 'a;
224
225 fn get<'a>(&'a self, key: &[u8]) -> impl Iterator<Item = &'a V> + Send + 'a
226 where
227 V: 'a,
228 {
229 let (i, sub) = partition_index_and_sub_key::<P>(key);
230 let k = self.translator.transform(sub);
231 self.partition_values(i, &k).iter()
232 }
233
234 fn get_many<'a, K: AsRef<[u8]>>(&'a self, keys: &[K], mut visit: impl FnMut(usize, &'a V))
235 where
236 V: 'a,
237 {
238 let mut order: Vec<(usize, T::Key, usize)> = keys
242 .iter()
243 .enumerate()
244 .map(|(key_idx, key)| {
245 let (partition, sub) = partition_index_and_sub_key::<P>(key.as_ref());
246 (partition, self.translator.transform(sub), key_idx)
247 })
248 .collect();
249 order.sort_unstable();
250 for (partition, translated, key_idx) in order {
251 for value in self.partition_values(partition, &translated) {
252 visit(key_idx, value);
253 }
254 }
255 }
256
257 fn get_mut<'a>(&'a mut self, key: &[u8]) -> Option<Self::Cursor<'a>> {
258 let (i, sub) = partition_index_and_sub_key::<P>(key);
259 let k = self.translator.transform(sub);
260 self.maybe_spill(i);
261 if !self.partitions[i].is_empty() {
262 let run = self.partitions[i].run_range(&k);
263 if run.is_empty() {
264 return None;
265 }
266 return Some(Cursor::soa(
267 &mut self.partitions[i],
268 k,
269 run,
270 &self.keys,
271 &self.items,
272 &self.pruned,
273 ));
274 }
275
276 if self
278 .spilled_partition(i)
279 .is_some_and(|inner| inner.contains_key(&k))
280 {
281 return Some(Cursor::spilled(
282 &mut self.spilled,
283 i,
284 k,
285 &self.keys,
286 &self.items,
287 &self.pruned,
288 ));
289 }
290
291 None
293 }
294
295 fn get_mut_or_insert<'a>(
296 &'a mut self,
297 key: &[u8],
298 value: Self::Value,
299 ) -> Option<Self::Cursor<'a>> {
300 let (i, sub) = partition_index_and_sub_key::<P>(key);
301 let k = self.translator.transform(sub);
302 self.maybe_spill(i);
303 if !self.partitions[i].is_empty() {
304 let run = self.partitions[i].run_range(&k);
305 if !run.is_empty() {
306 return Some(Cursor::soa(
307 &mut self.partitions[i],
308 k,
309 run,
310 &self.keys,
311 &self.items,
312 &self.pruned,
313 ));
314 }
315 self.partitions[i].insert_at(run.end, k, value);
316 self.keys.inc();
317 self.items.inc();
318 self.maybe_spill(i);
319 return None;
320 }
321
322 if let Some(inner) = self.spilled_partition(i) {
325 if inner.contains_key(&k) {
326 return Some(Cursor::spilled(
327 &mut self.spilled,
328 i,
329 k,
330 &self.keys,
331 &self.items,
332 &self.pruned,
333 ));
334 }
335 self.spilled.get_mut(&i).unwrap().insert(k, vec![value]);
336 self.keys.inc();
337 self.items.inc();
338 return None;
339 }
340
341 self.partitions[i].insert_at(0, k, value);
343 self.keys.inc();
344 self.items.inc();
345 self.maybe_spill(i);
346
347 None
348 }
349
350 fn insert(&mut self, key: &[u8], value: Self::Value) {
351 let (i, sub) = partition_index_and_sub_key::<P>(key);
352 let k = self.translator.transform(sub);
353 self.maybe_spill(i);
354 if !self.partitions[i].is_empty() {
355 let run = self.partitions[i].run_range(&k);
356 let new_key = run.is_empty();
357 self.partitions[i].insert_at(run.end, k, value);
358 self.items.inc();
359 if new_key {
360 self.keys.inc();
361 }
362 self.maybe_spill(i);
363 return;
364 }
365
366 if !self.spilled.is_empty() {
368 if let hash_map::Entry::Occupied(mut partition) = self.spilled.entry(i) {
369 match partition.get_mut().entry(k) {
370 btree_map::Entry::Occupied(mut run) => run.get_mut().push(value),
371 btree_map::Entry::Vacant(run) => {
372 run.insert(vec![value]);
373 self.keys.inc();
374 }
375 }
376 self.items.inc();
377 return;
378 }
379 }
380
381 self.partitions[i].insert_at(0, k, value);
383 self.items.inc();
384 self.keys.inc();
385 self.maybe_spill(i);
386 }
387
388 fn insert_and_retain(
389 &mut self,
390 key: &[u8],
391 value: Self::Value,
392 should_retain: impl Fn(&Self::Value) -> bool,
393 ) {
394 let (i, _) = partition_index_and_sub_key::<P>(key);
395 if let Some(mut cursor) = self.get_mut(key) {
396 cursor.retain(&should_retain);
397 if should_retain(&value) {
398 cursor.insert(value);
399 }
400 } else if should_retain(&value) {
401 self.insert(key, value);
402 }
403 self.maybe_spill(i);
404 }
405
406 fn remove(&mut self, key: &[u8]) {
407 let (i, sub) = partition_index_and_sub_key::<P>(key);
408 let k = self.translator.transform(sub);
409 self.maybe_spill(i);
410 if !self.partitions[i].is_empty() {
411 let run = self.partitions[i].run_range(&k);
412 if run.is_empty() {
413 return;
414 }
415 let n = run.len();
416 self.partitions[i].remove_run(run);
417 self.keys.dec();
418 self.items.dec_by(n as i64);
419 self.pruned.inc_by(n as u64);
420 return;
421 }
422 if !self.spilled.is_empty() {
425 if let hash_map::Entry::Occupied(mut partition) = self.spilled.entry(i) {
426 if let Some(vals) = partition.get_mut().remove(&k) {
427 let n = vals.len();
428 self.keys.dec();
429 self.items.dec_by(n as i64);
430 self.pruned.inc_by(n as u64);
431 if partition.get().is_empty() {
432 partition.remove();
433 }
434 }
435 }
436 }
437 }
438
439 #[cfg(test)]
440 fn keys(&self) -> usize {
441 self.keys.get() as usize
442 }
443
444 #[cfg(test)]
445 fn items(&self) -> usize {
446 self.items.get() as usize
447 }
448
449 #[cfg(test)]
450 fn pruned(&self) -> usize {
451 self.pruned.get() as usize
452 }
453}
454
455impl<T: Translator, V: Send + Sync, const P: usize> Ordered for Index<T, V, P> {
456 fn prev_translated_key<'a>(
457 &'a self,
458 key: &[u8],
459 ) -> Option<(impl Iterator<Item = &'a V> + Send + 'a, bool)>
460 where
461 V: 'a,
462 {
463 if self.is_empty() {
465 return None;
466 }
467
468 let (i, sub) = partition_index_and_sub_key::<P>(key);
471 let k = self.translator.transform(sub);
472 if let Some(vals) = self.partition_prev_before(i, &k) {
473 return Some((vals.iter(), false));
474 }
475 for p in (0..i).rev() {
476 if let Some(vals) = self.partition_last(p) {
477 return Some((vals.iter(), false));
478 }
479 }
480 for p in (0..self.partitions.len()).rev() {
481 if let Some(vals) = self.partition_last(p) {
482 return Some((vals.iter(), true));
483 }
484 }
485 None
486 }
487
488 fn next_translated_key<'a>(
489 &'a self,
490 key: &[u8],
491 ) -> Option<(impl Iterator<Item = &'a V> + Send + 'a, bool)>
492 where
493 V: 'a,
494 {
495 if self.is_empty() {
497 return None;
498 }
499
500 let (i, sub) = partition_index_and_sub_key::<P>(key);
503 let k = self.translator.transform(sub);
504 if let Some(vals) = self.partition_next_after(i, &k) {
505 return Some((vals.iter(), false));
506 }
507 for p in i + 1..self.partitions.len() {
508 if let Some(vals) = self.partition_first(p) {
509 return Some((vals.iter(), false));
510 }
511 }
512 for p in 0..self.partitions.len() {
513 if let Some(vals) = self.partition_first(p) {
514 return Some((vals.iter(), true));
515 }
516 }
517 None
518 }
519
520 fn first_translated_key<'a>(&'a self) -> Option<impl Iterator<Item = &'a V> + Send + 'a>
521 where
522 V: 'a,
523 {
524 if self.is_empty() {
526 return None;
527 }
528
529 for p in 0..self.partitions.len() {
531 if let Some(vals) = self.partition_first(p) {
532 return Some(vals.iter());
533 }
534 }
535 None
536 }
537
538 fn last_translated_key<'a>(&'a self) -> Option<impl Iterator<Item = &'a V> + Send + 'a>
539 where
540 V: 'a,
541 {
542 if self.is_empty() {
544 return None;
545 }
546
547 for p in (0..self.partitions.len()).rev() {
549 if let Some(vals) = self.partition_last(p) {
550 return Some(vals.iter());
551 }
552 }
553 None
554 }
555}
556
557#[cfg(test)]
558mod tests {
559 use super::*;
560 use crate::translator::OneCap;
561 use commonware_formatting::hex;
562 use commonware_macros::test_traced;
563 use commonware_runtime::{deterministic, Runner};
564
565 fn new_index(context: deterministic::Context) -> Index<OneCap, u64, 1> {
566 Index::new(context, OneCap)
567 }
568
569 fn new_index_spilling(context: deterministic::Context) -> Index<OneCap, u64, 1> {
573 Index::with_threshold(context, OneCap, 2)
574 }
575
576 #[test_traced]
577 fn test_empty_and_sparse_nav() {
578 deterministic::Runner::default().start(|context| async move {
579 let mut index = new_index(context);
580
581 assert!(index.first_translated_key().is_none());
584 assert!(index.last_translated_key().is_none());
585 assert!(index.prev_translated_key(&[0x80, 0x00]).is_none());
586 assert!(index.next_translated_key(&[0x80, 0x00]).is_none());
587
588 index.insert(&[0x05, 0x01], 1);
591 index.insert(&[0xF0, 0x02], 2);
592 assert_eq!(index.keys(), 2);
593 assert_eq!(
594 index
595 .first_translated_key()
596 .unwrap()
597 .copied()
598 .collect::<Vec<_>>(),
599 vec![1]
600 );
601 assert_eq!(
602 index
603 .last_translated_key()
604 .unwrap()
605 .copied()
606 .collect::<Vec<_>>(),
607 vec![2]
608 );
609
610 let (it, wrapped) = index.next_translated_key(&[0x05, 0x01]).unwrap();
612 assert_eq!((it.copied().collect::<Vec<_>>(), wrapped), (vec![2], false));
613 let (it, wrapped) = index.next_translated_key(&[0xF0, 0x02]).unwrap();
614 assert_eq!((it.copied().collect::<Vec<_>>(), wrapped), (vec![1], true));
615
616 let (it, wrapped) = index.prev_translated_key(&[0xF0, 0x02]).unwrap();
618 assert_eq!((it.copied().collect::<Vec<_>>(), wrapped), (vec![1], false));
619 let (it, wrapped) = index.prev_translated_key(&[0x05, 0x01]).unwrap();
620 assert_eq!((it.copied().collect::<Vec<_>>(), wrapped), (vec![2], true));
621
622 let (it, wrapped) = index.prev_translated_key(&[0x80, 0x00]).unwrap();
624 assert_eq!((it.copied().collect::<Vec<_>>(), wrapped), (vec![1], false));
625 let (it, wrapped) = index.next_translated_key(&[0x80, 0x00]).unwrap();
626 assert_eq!((it.copied().collect::<Vec<_>>(), wrapped), (vec![2], false));
627
628 index.remove(&[0x05, 0x01]);
630 index.remove(&[0xF0, 0x02]);
631 assert_eq!(index.keys(), 0);
632 assert!(index.prev_translated_key(&[0x80, 0x00]).is_none());
633 assert!(index.next_translated_key(&[0x80, 0x00]).is_none());
634 });
635 }
636
637 #[test_traced]
638 fn test_spill_transition() {
639 deterministic::Runner::default().start(|context| async move {
640 let mut index = new_index_spilling(context);
641 index.insert(&[0x10, 0x01], 1);
643 assert_eq!(index.spilled_count(), 0);
644 index.insert(&[0x10, 0x02], 2); assert_eq!(index.spilled_count(), 1);
646 index.insert(&[0x10, 0x03], 3); assert_eq!(index.spilled_count(), 1);
648 assert_eq!(index.keys(), 3);
649 assert_eq!(index.items(), 3);
650
651 assert_eq!(
653 index.get(&[0x10, 0x01]).copied().collect::<Vec<_>>(),
654 vec![1]
655 );
656 index.insert(&[0x10, 0x02], 22);
657 assert_eq!(
658 index.get(&[0x10, 0x02]).copied().collect::<Vec<_>>(),
659 vec![2, 22]
660 );
661 assert_eq!(index.items(), 4);
662
663 index.insert(&[0x20, 0x05], 5);
665 assert_eq!(index.spilled_count(), 1);
666 assert_eq!(
667 index.get(&[0x20, 0x05]).copied().collect::<Vec<_>>(),
668 vec![5]
669 );
670 });
671 }
672
673 #[test_traced]
674 fn test_spill_after_cursor_growth() {
675 deterministic::Runner::default().start(|context| async move {
676 let mut index = new_index_spilling(context);
677 let key = [0x10, 0x01];
678
679 index.insert(&key, 1);
680 {
681 let mut cursor = index.get_mut(&key).unwrap();
682 assert_eq!(cursor.next().copied(), Some(1));
683 assert_eq!(cursor.next(), None);
684 cursor.insert(2);
685 }
686 assert_eq!(index.spilled_count(), 0);
687
688 index.insert(&key, 3);
690 assert_eq!(index.spilled_count(), 1);
691 assert_eq!(index.get(&key).copied().collect::<Vec<_>>(), vec![1, 2, 3]);
692
693 let other = [0x20, 0x01];
695 index.insert(&other, 4);
696 index.insert_and_retain(&other, 5, |_| true);
697 assert_eq!(index.spilled_count(), 2);
698 assert_eq!(index.get(&other).copied().collect::<Vec<_>>(), vec![4, 5]);
699
700 let third = [0x30, 0x01];
703 index.insert(&third, 6);
704 {
705 let mut cursor = index.get_mut(&third).unwrap();
706 assert_eq!(cursor.next().copied(), Some(6));
707 assert_eq!(cursor.next(), None);
708 cursor.insert(7);
709 }
710 assert_eq!(index.spilled_count(), 2);
711 {
712 let mut cursor = index.get_mut(&third).unwrap();
713 assert_eq!(cursor.next().copied(), Some(6));
714 assert_eq!(cursor.next().copied(), Some(7));
715 assert_eq!(cursor.next(), None);
716 }
717 assert_eq!(index.spilled_count(), 3);
718 assert_eq!(index.get(&third).copied().collect::<Vec<_>>(), vec![6, 7]);
719
720 let fourth = [0x40, 0x01];
722 index.insert(&fourth, 8);
723 {
724 let mut cursor = index.get_mut(&fourth).unwrap();
725 assert_eq!(cursor.next().copied(), Some(8));
726 assert_eq!(cursor.next(), None);
727 cursor.insert(9);
728 }
729 assert_eq!(index.spilled_count(), 3);
730 index.remove(&[0x40, 0x02]);
731 assert_eq!(index.spilled_count(), 4);
732 assert_eq!(index.get(&fourth).copied().collect::<Vec<_>>(), vec![8, 9]);
733 });
734 }
735
736 #[test_traced]
737 fn test_spill_after_get_mut_or_insert_cursor_growth() {
738 deterministic::Runner::default().start(|context| async move {
739 let mut index = new_index_spilling(context);
740 let key = [0x10, 0x01];
741
742 index.insert(&key, 1);
743 {
744 let mut cursor = index.get_mut_or_insert(&key, 2).unwrap();
745 assert_eq!(cursor.next().copied(), Some(1));
746 assert_eq!(cursor.next(), None);
747 cursor.insert(2);
748 }
749 assert_eq!(index.spilled_count(), 0);
750
751 assert!(index.get_mut_or_insert(&key, 3).is_some());
753 assert_eq!(index.spilled_count(), 1);
754 assert_eq!(index.get(&key).copied().collect::<Vec<_>>(), vec![1, 2]);
755 });
756 }
757
758 #[test_traced]
759 fn test_spill_nav() {
760 deterministic::Runner::default().start(|context| async move {
761 let mut index = new_index_spilling(context);
762 index.insert(&[0x10, 0x01], 1);
765 index.insert(&[0x10, 0x02], 2);
766 index.insert(&[0x20, 0x05], 5);
767 index.insert(&[0x30, 0x07], 7);
768 index.insert(&[0x30, 0x08], 8);
769 assert_eq!(index.spilled_count(), 2); assert_eq!(index.first_translated_key().unwrap().next(), Some(&1));
772 assert_eq!(index.last_translated_key().unwrap().next(), Some(&8));
773
774 let (mut it, wrapped) = index.next_translated_key(&[0x10, 0x01]).unwrap();
776 assert!(!wrapped);
777 assert_eq!(it.next(), Some(&2));
778 let (mut it, wrapped) = index.next_translated_key(&[0x10, 0x02]).unwrap();
780 assert!(!wrapped);
781 assert_eq!(it.next(), Some(&5));
782 let (mut it, wrapped) = index.next_translated_key(&[0x20, 0x05]).unwrap();
784 assert!(!wrapped);
785 assert_eq!(it.next(), Some(&7));
786 let (mut it, wrapped) = index.prev_translated_key(&[0x30, 0x07]).unwrap();
788 assert!(!wrapped);
789 assert_eq!(it.next(), Some(&5));
790 let (mut it, wrapped) = index.prev_translated_key(&[0x20, 0x05]).unwrap();
792 assert!(!wrapped);
793 assert_eq!(it.next(), Some(&2));
794 let (mut it, wrapped) = index.next_translated_key(&[0x30, 0x08]).unwrap();
796 assert!(wrapped);
797 assert_eq!(it.next(), Some(&1));
798 });
799 }
800
801 #[test_traced]
802 fn test_spill_despill_on_full_drain() {
803 deterministic::Runner::default().start(|context| async move {
804 let mut index = new_index_spilling(context);
805 index.insert(&[0x10, 0x01], 1);
806 index.insert(&[0x10, 0x02], 2); assert_eq!(index.spilled_count(), 1);
808
809 index.remove(&[0x10, 0x01]);
810 assert_eq!(index.spilled_count(), 1); index.remove(&[0x10, 0x02]);
812 assert_eq!(index.spilled_count(), 0); assert_eq!(index.keys(), 0);
814
815 index.insert(&[0x10, 0x09], 9);
817 assert_eq!(index.spilled_count(), 0);
818 assert_eq!(
819 index.get(&[0x10, 0x09]).copied().collect::<Vec<_>>(),
820 vec![9]
821 );
822 });
823 }
824
825 #[test_traced]
826 fn test_spill_full_lifecycle() {
827 deterministic::Runner::default().start(|context| async move {
828 let mut index = new_index_spilling(context);
829
830 assert_eq!(index.spilled_count(), 0);
832 assert_eq!(index.keys(), 0);
833 assert_eq!(index.items(), 0);
834
835 index.insert(&[0x10, 0x01], 1);
837 assert_eq!(index.spilled_count(), 0);
838
839 index.insert(&[0x10, 0x02], 2);
841 assert_eq!(index.spilled_count(), 1);
842 assert_eq!(index.keys(), 2);
843 assert_eq!(index.items(), 2);
844
845 {
848 let mut cursor = index.get_mut(&[0x10, 0x01]).unwrap();
849 assert_eq!(cursor.next().copied(), Some(1));
850 cursor.delete();
851 }
852 assert_eq!(index.spilled_count(), 1); {
854 let mut cursor = index.get_mut(&[0x10, 0x02]).unwrap();
855 assert_eq!(cursor.next().copied(), Some(2));
856 cursor.delete();
857 }
858 assert_eq!(index.spilled_count(), 0); assert_eq!(index.keys(), 0);
860 assert_eq!(index.items(), 0);
861
862 index.insert(&[0x10, 0x03], 3);
864 assert_eq!(index.spilled_count(), 0);
865 index.insert(&[0x10, 0x04], 4);
866 assert_eq!(index.spilled_count(), 1);
867 assert_eq!(
868 index.get(&[0x10, 0x03]).copied().collect::<Vec<_>>(),
869 vec![3]
870 );
871 assert_eq!(
872 index.get(&[0x10, 0x04]).copied().collect::<Vec<_>>(),
873 vec![4]
874 );
875
876 index.remove(&[0x10, 0x03]);
878 assert_eq!(index.spilled_count(), 1); index.remove(&[0x10, 0x04]);
880 assert_eq!(index.spilled_count(), 0);
881 assert_eq!(index.keys(), 0);
882 assert_eq!(index.items(), 0);
883
884 assert_eq!(index.pruned(), 4);
886 });
887 }
888
889 #[test_traced]
890 fn test_spill_get_mut_or_insert() {
891 deterministic::Runner::default().start(|context| async move {
892 let mut index = new_index_spilling(context);
893 index.insert(&[0x10, 0x01], 1);
894 index.insert(&[0x10, 0x02], 2); assert_eq!(index.spilled_count(), 1);
896 assert_eq!(index.keys(), 2);
897 assert_eq!(index.items(), 2);
898
899 {
902 let mut cursor = index.get_mut_or_insert(&[0x10, 0x01], 99).unwrap();
903 assert_eq!(cursor.next().copied(), Some(1));
904 assert!(cursor.next().is_none());
905 }
906 assert_eq!(index.keys(), 2);
907 assert_eq!(index.items(), 2);
908 assert_eq!(
909 index.get(&[0x10, 0x01]).copied().collect::<Vec<_>>(),
910 vec![1]
911 );
912
913 assert!(index.get_mut_or_insert(&[0x10, 0x03], 3).is_none());
916 assert_eq!(index.spilled_count(), 1);
917 assert_eq!(index.keys(), 3);
918 assert_eq!(index.items(), 3);
919 assert_eq!(
920 index.get(&[0x10, 0x03]).copied().collect::<Vec<_>>(),
921 vec![3]
922 );
923 });
924 }
925
926 #[test_traced]
927 #[should_panic(expected = "must call Cursor::next()")]
928 fn test_spill_cursor_delete_before_next_panics() {
929 deterministic::Runner::default().start(|context| async move {
930 let mut index = new_index_spilling(context);
931 index.insert(&[0x10, 0x01], 1);
932 index.insert(&[0x10, 0x02], 2); let mut cursor = index.get_mut(&[0x10, 0x01]).unwrap(); cursor.delete();
935 });
936 }
937
938 #[test_traced]
939 fn test_soa_basic() {
940 deterministic::Runner::default().start(|context| async move {
941 let mut index = new_index(context);
942 assert_eq!(index.keys(), 0);
943
944 let key = b"duplicate".as_slice();
945 index.insert(key, 1);
946 index.insert(key, 2);
947 index.insert(key, 3);
948 assert_eq!(index.keys(), 1);
949 assert_eq!(index.items(), 3);
950 assert_eq!(index.get(key).copied().collect::<Vec<_>>(), vec![1, 2, 3]);
951
952 {
953 let mut cursor = index.get_mut(key).unwrap();
954 assert_eq!(*cursor.next().unwrap(), 1);
955 assert_eq!(*cursor.next().unwrap(), 2);
956 assert_eq!(*cursor.next().unwrap(), 3);
957 assert!(cursor.next().is_none());
958 }
959
960 index.insert(key, 3);
961 index.insert(key, 4);
962 index.retain(key, |i| *i != 3);
963 assert_eq!(index.get(key).copied().collect::<Vec<_>>(), vec![1, 2, 4]);
964
965 index.retain(key, |_| false);
966 assert_eq!(
967 index.get(key).copied().collect::<Vec<_>>(),
968 Vec::<u64>::new()
969 );
970 assert_eq!(index.keys(), 0);
971 assert!(index.get_mut(key).is_none());
972
973 index.retain(key, |_| false);
975 });
976 }
977
978 #[test_traced]
979 fn test_soa_cursor_find() {
980 deterministic::Runner::default().start(|context| async move {
981 let mut index = new_index(context);
982 let key = b"test_key";
983 for v in [10u64, 20, 30, 40] {
984 index.insert(key, v);
985 }
986
987 {
988 let mut cursor = index.get_mut(key).unwrap();
989 assert!(cursor.find(|&v| v == 30));
990 cursor.update(35);
991 }
992 let values: Vec<u64> = index.get(key).copied().collect();
993 assert!(values.contains(&35) && !values.contains(&30));
994
995 {
996 let mut cursor = index.get_mut(key).unwrap();
997 assert!(!cursor.find(|&v| v == 100));
998 assert!(cursor.next().is_none());
999 }
1000
1001 {
1002 let mut cursor = index.get_mut(key).unwrap();
1003 assert!(cursor.find(|&v| v == 20));
1004 cursor.delete();
1005 }
1006 let values: Vec<u64> = index.get(key).copied().collect();
1007 assert!(!values.contains(&20));
1008 assert_eq!(values.len(), 3);
1009 });
1010 }
1011
1012 #[test_traced]
1013 fn test_soa_get_many_and_partitions() {
1014 deterministic::Runner::default().start(|context| async move {
1015 let mut index = new_index(context);
1016 index.insert(b"ab", 1);
1018 index.insert(b"ab", 2);
1019 index.insert(b"abX", 3);
1020 index.insert(b"zz", 4);
1021
1022 let keys: Vec<&[u8]> = vec![b"zz", b"missing", b"ab", b"zz"];
1023 let mut visits: Vec<Vec<u64>> = vec![Vec::new(); keys.len()];
1024 index.get_many(&keys, |key_idx, value| visits[key_idx].push(*value));
1025 assert_eq!(visits[0], vec![4]);
1026 assert!(visits[1].is_empty());
1027 assert_eq!(visits[2], vec![1, 2, 3]);
1028 assert_eq!(visits[3], vec![4]);
1029 });
1030 }
1031
1032 #[test_traced]
1033 fn test_soa_insert_and_retain() {
1034 deterministic::Runner::default().start(|context| async move {
1035 let mut index = new_index(context);
1036 index.insert(b"k", 1u64);
1038 index.insert_and_retain(b"k", 2, |_| true);
1039 assert_eq!(index.get(b"k").copied().collect::<Vec<_>>(), vec![1, 2]);
1040
1041 index.insert_and_retain(b"k", 9, |v| *v != 9);
1043 assert_eq!(index.get(b"k").copied().collect::<Vec<_>>(), vec![1, 2]);
1044
1045 index.insert_and_retain(b"k", 9, |_| false);
1047 assert!(index.get_mut(b"k").is_none());
1048 assert_eq!(index.keys(), 0);
1049
1050 index.insert_and_retain(b"new", 7, |_| true);
1052 assert_eq!(index.get(b"new").copied().collect::<Vec<_>>(), vec![7]);
1053 assert_eq!(index.keys(), 1);
1054 });
1055 }
1056
1057 #[test_traced]
1058 fn test_soa_remove() {
1059 deterministic::Runner::default().start(|context| async move {
1060 let mut index = new_index(context);
1061 index.insert(b"k", 1u64);
1062 index.insert(b"k", 2);
1063 index.insert(b"other", 3);
1064 assert_eq!(index.items(), 3);
1065 assert_eq!(index.keys(), 2);
1066
1067 index.remove(b"k");
1068 assert!(index.get_mut(b"k").is_none());
1069 assert_eq!(index.keys(), 1);
1070 assert_eq!(index.items(), 1);
1071 assert_eq!(index.pruned(), 2);
1072 assert_eq!(index.get(b"other").copied().collect::<Vec<_>>(), vec![3]);
1073
1074 index.remove(b"missing"); assert_eq!(index.keys(), 1);
1076 });
1077 }
1078
1079 #[test_traced]
1080 fn test_soa_ordered() {
1081 deterministic::Runner::default().start(|context| async move {
1082 let mut index = new_index(context);
1083 assert!(index.first_translated_key().is_none());
1084 assert!(index.last_translated_key().is_none());
1085 assert!(index.next_translated_key(b"key").is_none());
1086 assert!(index.prev_translated_key(b"key").is_none());
1087
1088 let k1 = &hex!("0x0b02AA"); let k2 = &hex!("0x1c04CC"); let k2_collides = &hex!("0x1c0411"); let k3 = &hex!("0x2d06EE"); index.insert(k1, 1);
1094 index.insert(k2, 21);
1095 index.insert(k2_collides, 22);
1096 index.insert(k3, 3);
1097 assert_eq!(index.keys(), 3);
1098
1099 assert_eq!(index.first_translated_key().unwrap().next(), Some(&1));
1100 assert_eq!(index.last_translated_key().unwrap().next(), Some(&3));
1101
1102 let (mut it, wrapped) = index.next_translated_key(&[0x00]).unwrap();
1104 assert!(!wrapped);
1105 assert_eq!(it.next(), Some(&1));
1106 assert_eq!(it.next(), None);
1107
1108 let (mut it, wrapped) = index.next_translated_key(&hex!("0x0b02F2")).unwrap();
1110 assert!(!wrapped);
1111 assert_eq!(it.next(), Some(&21));
1112 assert_eq!(it.next(), Some(&22));
1113 assert_eq!(it.next(), None);
1114
1115 let (mut it, wrapped) = index.next_translated_key(k3).unwrap();
1117 assert!(wrapped);
1118 assert_eq!(it.next(), Some(&1));
1119
1120 let (mut it, wrapped) = index.prev_translated_key(k1).unwrap();
1122 assert!(wrapped);
1123 assert_eq!(it.next(), Some(&3));
1124
1125 let (mut it, wrapped) = index.prev_translated_key(&hex!("0x1d0102")).unwrap();
1127 assert!(!wrapped);
1128 assert_eq!(it.next(), Some(&21));
1129 assert_eq!(it.next(), Some(&22));
1130 assert_eq!(it.next(), None);
1131 });
1132 }
1133
1134 #[test_traced]
1135 fn test_soa_ordered_exhaustive_traversal() {
1136 deterministic::Runner::default().start(|context| async move {
1137 let mut index = new_index(context);
1138
1139 let prefixes = [0x00u8, 0x05, 0xAA, 0xFF];
1143 let subkeys = [0x00u8, 0x80, 0xFF];
1144 let mut keys: Vec<[u8; 2]> = Vec::new();
1145 for &p in &prefixes {
1146 for &s in &subkeys {
1147 keys.push([p, s]);
1148 }
1149 }
1150 let value_of = |k: &[u8; 2]| ((k[0] as u64) << 8) | k[1] as u64;
1151 let n = keys.len();
1152
1153 let mut scrambled = keys.clone();
1155 scrambled.reverse();
1156 scrambled.rotate_left(5);
1157 for k in &scrambled {
1158 index.insert(k, value_of(k));
1159 }
1160 assert_eq!(index.keys(), n);
1161
1162 assert_eq!(
1163 index.first_translated_key().unwrap().next(),
1164 Some(&value_of(&keys[0]))
1165 );
1166 assert_eq!(
1167 index.last_translated_key().unwrap().next(),
1168 Some(&value_of(&keys[n - 1]))
1169 );
1170
1171 for i in 0..n {
1174 let next = value_of(&keys[(i + 1) % n]);
1175 let (mut it, wrapped) = index.next_translated_key(&keys[i]).unwrap();
1176 assert_eq!(wrapped, i + 1 == n, "next wrap at index {i}");
1177 assert_eq!(it.next(), Some(&next), "next at {i}");
1178 assert_eq!(it.next(), None);
1179
1180 let prev = value_of(&keys[(i + n - 1) % n]);
1181 let (mut it, wrapped) = index.prev_translated_key(&keys[i]).unwrap();
1182 assert_eq!(wrapped, i == 0, "prev wrap at index {i}");
1183 assert_eq!(it.next(), Some(&prev), "prev at {i}");
1184 assert_eq!(it.next(), None);
1185 }
1186 });
1187 }
1188}