notnow/
db.rs

1// Copyright (C) 2022-2025 Daniel Mueller <deso@posteo.net>
2// SPDX-License-Identifier: GPL-3.0-or-later
3
4use std::cell::Cell;
5use std::cell::RefCell;
6use std::collections::HashMap;
7#[cfg(test)]
8use std::collections::HashSet;
9use std::fmt::Debug;
10use std::fmt::Formatter;
11use std::fmt::Result as FmtResult;
12use std::hash::Hash;
13use std::hash::Hasher;
14use std::iter::Map;
15use std::ops::Deref;
16use std::rc::Rc;
17use std::slice;
18
19
20/// An iterator over the items in a `Db`.
21pub type Iter<'db, T, Aux> =
22  Map<slice::Iter<'db, (Rc<T>, Cell<Aux>)>, fn(&'_ (Rc<T>, Cell<Aux>)) -> &'_ Rc<T>>;
23
24
25#[repr(transparent)]
26struct HRc<T>(Rc<T>);
27
28impl<T> Hash for HRc<T> {
29  fn hash<H>(&self, state: &mut H)
30  where
31    H: Hasher,
32  {
33    Rc::as_ptr(&self.0).hash(state)
34  }
35}
36
37impl<T> PartialEq for HRc<T> {
38  fn eq(&self, other: &Self) -> bool {
39    Rc::ptr_eq(&self.0, &other.0)
40  }
41}
42
43impl<T> Eq for HRc<T> {}
44
45impl<T> Deref for HRc<T> {
46  type Target = Rc<T>;
47
48  fn deref(&self) -> &Self::Target {
49    &self.0
50  }
51}
52
53
54/// An object wrapping an item contained in a `Db` and providing
55/// read-only access to it and its (optional) auxiliary data.
56#[derive(Clone)]
57pub struct Entry<'db, T, Aux> {
58  /// The `Db`'s data.
59  data: &'db [(Rc<T>, Cell<Aux>)],
60  /// The index of the item represented by the entry.
61  index: usize,
62}
63
64impl<'db, T, Aux> Entry<'db, T, Aux> {
65  /// Create a new `Entry` object.
66  #[inline]
67  fn new(data: &'db [(Rc<T>, Cell<Aux>)], index: usize) -> Self {
68    Self { data, index }
69  }
70
71  /// Retrieve the `Entry` for the item following this one, if any.
72  #[inline]
73  pub fn next(&self) -> Option<Entry<'db, T, Aux>> {
74    let index = self.index.checked_add(1)?;
75
76    if index < self.data.len() {
77      Some(Entry::new(self.data, index))
78    } else {
79      None
80    }
81  }
82
83  /// Retrieve the `Entry` for the item before this one, if any.
84  #[inline]
85  pub fn prev(&self) -> Option<Entry<'db, T, Aux>> {
86    if self.index > 0 {
87      Some(Entry::new(self.data, self.index - 1))
88    } else {
89      None
90    }
91  }
92
93  /// Retrieve the index of the element that this `Entry` object
94  /// represents in the associated `Db` instance.
95  #[inline]
96  pub fn index(&self) -> usize {
97    self.index
98  }
99}
100
101impl<T, Aux> Entry<'_, T, Aux>
102where
103  Aux: Copy,
104{
105  /// Retrieve a copy of the auxiliary data associated with this
106  /// `Entry`.
107  #[inline]
108  pub fn aux(&self) -> Aux {
109    self.data[self.index].1.get()
110  }
111
112  /// Set the auxiliary data associated with this `Entry`.
113  #[inline]
114  pub fn set_aux(&self, aux: Aux) {
115    let () = self.data[self.index].1.set(aux);
116  }
117}
118
119impl<'db, T, Aux> Deref for Entry<'db, T, Aux> {
120  type Target = Rc<T>;
121
122  fn deref(&self) -> &'db Self::Target {
123    &self.data[self.index].0
124  }
125}
126
127impl<T, Aux> Debug for Entry<'_, T, Aux>
128where
129  T: Debug,
130  Aux: Copy + Debug,
131{
132  fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
133    let Self { data, index } = self;
134
135    f.debug_tuple("Entry").field(&data).field(&index).finish()
136  }
137}
138
139
140/// Update the provided `by_ptr_idx` with index data for `data`.
141fn update_ptr_idx<T, U>(by_ptr_idx: &mut HashMap<HRc<T>, ReplayIdx>, data: &[(Rc<T>, U)]) {
142  let iter = data.iter().enumerate().map(|(idx, (rc, _aux))| {
143    let rep_idx = ReplayIdx::new(idx, Gen(0));
144    (HRc(Rc::clone(rc)), rep_idx)
145  });
146
147  let () = by_ptr_idx.clear();
148  let () = by_ptr_idx.extend(iter);
149}
150
151
152/// Create an index optimized for pointer based access for the provided
153/// data.
154#[inline]
155fn make_ptr_idx<T, U>(data: &[(Rc<T>, U)]) -> HashMap<HRc<T>, ReplayIdx> {
156  let mut idx = HashMap::new();
157  let () = update_ptr_idx(&mut idx, data);
158  idx
159}
160
161
162/// Mask identifying the highest bit in a `u32`. We use it to encode the
163/// operation in `InsDel` objects.
164const INSERT_MASK: u32 = 0b1000_0000_0000_0000;
165
166
167/// A type representing insertions & deletions of elements at certain
168/// indexes in our `Db`.
169#[derive(Debug)]
170#[repr(transparent)]
171struct InsDel(u32);
172
173impl InsDel {
174  /// Create an `InsDel` object representing an "insert" at index `idx`.
175  #[inline]
176  fn insert(idx: usize) -> Self {
177    let idx = if cfg!(debug_assertions) {
178      u32::try_from(idx).unwrap()
179    } else {
180      idx as u32
181    };
182
183    debug_assert!(idx & INSERT_MASK == 0);
184    Self(INSERT_MASK | idx)
185  }
186
187  /// Create an `InsDel` object representing a "delete" of index `idx`.
188  #[inline]
189  fn delete(idx: usize) -> Self {
190    let idx = if cfg!(debug_assertions) {
191      u32::try_from(idx).unwrap()
192    } else {
193      idx as u32
194    };
195
196    debug_assert!(idx & INSERT_MASK == 0);
197    Self(idx)
198  }
199
200  /// Adjust the provided according to the operation (insert/delete)
201  /// represented by this index, if applicable.
202  #[inline]
203  fn adjust(&self, idx: u32) -> u32 {
204    let op_idx = self.0 & !INSERT_MASK;
205
206    // The provided index would only have been affected by inserts or
207    // deletes *before* (or at) it.
208    if op_idx <= idx {
209      let insert = (self.0 & INSERT_MASK) != 0;
210
211      if insert {
212        idx + 1
213      } else {
214        idx - 1
215      }
216    } else {
217      idx
218    }
219  }
220}
221
222
223/// A generation number that doubles as an index into `ins_del`.
224#[derive(Debug)]
225#[repr(transparent)]
226struct Gen(u16);
227
228impl Gen {
229  fn new(r#gen: usize) -> Self {
230    let r#gen = if cfg!(debug_assertions) {
231      r#gen.try_into().unwrap()
232    } else {
233      r#gen as _
234    };
235
236    Self(r#gen)
237  }
238}
239
240
241/// An index that can be adjusted based on a log of operations performed
242/// ("replayed").
243#[derive(Debug)]
244struct ReplayIdx {
245  idx: u32,
246  r#gen: Gen,
247}
248
249impl ReplayIdx {
250  fn new(idx: usize, r#gen: Gen) -> Self {
251    Self {
252      idx: idx as u32,
253      r#gen,
254    }
255  }
256
257  /// Replay a set of insert/delete operations on this index.
258  fn replay(&self, ins_del: &[InsDel]) -> usize {
259    let r#gen = usize::from(self.r#gen.0);
260
261    let idx = if r#gen < ins_del.len() {
262      ins_del[r#gen..]
263        .iter()
264        .fold(self.idx, |idx, op| op.adjust(idx))
265    } else {
266      self.idx
267    };
268
269    idx as usize
270  }
271}
272
273
274/// A database for storing arbitrary data items.
275///
276/// Data is stored in reference-counted, heap-allocated manner using
277/// [`Rc`]. The database ensures that each item is unique, meaning that
278/// it prevents insertion of the same `Rc` instance multiple times (but
279/// it does not make any claims about the uniqueness of the inner `T`).
280///
281/// Associated with each item is optional auxiliary data, which can be
282/// accessed via the `Entry` type.
283pub struct Db<T, Aux = ()> {
284  /// The data this database manages, along with optional auxiliary
285  /// data, in a well-defined order.
286  data: Vec<(Rc<T>, Cell<Aux>)>,
287  /// An index on top of `data`, for efficient lookup of `Rc` pointer
288  /// values.
289  by_ptr_idx: RefCell<HashMap<HRc<T>, ReplayIdx>>,
290  /// A list of insertions and deletions since we rebuilt `by_ptr_idx`.
291  ins_del: Vec<InsDel>,
292}
293
294impl<T> Db<T, ()> {
295  /// Create a database from the items contained in the provided
296  /// iterator.
297  #[cfg(test)]
298  pub fn try_from_iter<I>(iter: I) -> Result<Self, Rc<T>>
299  where
300    I: IntoIterator<Item = Rc<T>>,
301  {
302    let data = iter
303      .into_iter()
304      .map(|item| (item, Cell::default()))
305      .collect::<Vec<_>>();
306    // Check that all pointers provided are unique.
307    let set = HashSet::with_capacity(data.len());
308    let _set = data.iter().try_fold(set, |mut set, (rc, _aux)| {
309      if !set.insert(Rc::as_ptr(rc)) {
310        Err(Rc::clone(rc))
311      } else {
312        Ok(set)
313      }
314    })?;
315
316    let slf = Self {
317      by_ptr_idx: RefCell::new(make_ptr_idx(&data)),
318      data,
319      ins_del: Vec::new(),
320    };
321    Ok(slf)
322  }
323
324  /// Create a database from an iterator of items.
325  #[cfg(test)]
326  pub fn from_iter<I>(iter: I) -> Self
327  where
328    I: IntoIterator<Item = T>,
329  {
330    Self::from_iter_with_aux(iter.into_iter().map(|item| (item, ())))
331  }
332}
333
334impl<T, Aux> Db<T, Aux> {
335  /// Create a database from an iterator of items.
336  pub fn from_iter_with_aux<I>(iter: I) -> Self
337  where
338    I: IntoIterator<Item = (T, Aux)>,
339  {
340    let data = iter
341      .into_iter()
342      .map(|(item, aux)| (Rc::new(item), Cell::new(aux)))
343      .collect::<Vec<_>>();
344
345    Self {
346      by_ptr_idx: RefCell::new(make_ptr_idx(&data)),
347      data,
348      ins_del: Vec::new(),
349    }
350  }
351
352  /// Rebuild our index if the `ins_del` log became too big.
353  #[inline]
354  fn maybe_rebuild_by_ptr_idx(&mut self) -> bool {
355    // 2^12 (4096) elements seem to be a reasonable sweet spot between:
356    // memory consumption is reasonable and with lower values we loose
357    // performance, while with higher values we don't gain much.
358    if self.ins_del.len() >= 1 << 12 {
359      let by_ptr_idx = self.by_ptr_idx.get_mut();
360      // Just rebuild the index from scratch.
361      let () = update_ptr_idx(by_ptr_idx, &self.data);
362      let () = self.ins_del.clear();
363      true
364    } else {
365      false
366    }
367  }
368
369  /// Add the `idx`th element in the `Db` to the `by_ptr_idx` index.
370  ///
371  /// # Notes
372  /// This method should be called *after* the element at `idx` has
373  /// actually been removed from `data`.
374  fn index(&mut self, idx: usize) {
375    if self.maybe_rebuild_by_ptr_idx() {
376      // As per our contract the element at `idx` has already been
377      // inserted and so our newly rebuilt index is up-to-date.
378      return
379    }
380
381    let by_ptr_idx = self.by_ptr_idx.get_mut();
382    let () = self.ins_del.push(InsDel::insert(idx));
383    let r#gen = Gen::new(self.ins_del.len());
384    let rep_idx = ReplayIdx::new(idx, r#gen);
385
386    let rc = &self.data[idx].0;
387    let _prev = by_ptr_idx.insert(HRc(Rc::clone(rc)), rep_idx);
388    debug_assert!(
389      _prev.is_none(),
390      "attempting to index already existing element @ {idx}"
391    );
392  }
393
394  /// Remove the `idx`th element in the `Db` from the `by_ptr_idx` index.
395  ///
396  /// # Notes
397  /// This method should be called *before* the element at `idx` is
398  /// actually removed from `data`.
399  fn deindex(&mut self, idx: usize) {
400    let _rebuilt = self.maybe_rebuild_by_ptr_idx();
401
402    // Even if we rebuilt the index from scratch we still have to update
403    // it to reflect that fact that the element at `idx` is about to be
404    // removed.
405    let by_ptr_idx = self.by_ptr_idx.get_mut();
406
407    let () = self.ins_del.push(InsDel::delete(idx));
408
409    let rc = &self.data[idx].0;
410    // TODO: Should not clone.
411    let _removed = by_ptr_idx.remove(&HRc(Rc::clone(rc)));
412    debug_assert!(
413      _removed.is_some(),
414      "attempting to de-index non-existent element @ {idx}"
415    );
416  }
417
418  /// Look up an item's `Entry` in the `Db`.
419  #[inline]
420  pub fn find(&self, item: &Rc<T>) -> Option<Entry<'_, T, Aux>> {
421    let mut by_ptr_idx = self.by_ptr_idx.borrow_mut();
422
423    // TODO: Should not clone.
424    by_ptr_idx
425      .get_mut(&HRc(Rc::clone(item)))
426      .and_then(|rep_idx| {
427        let data_idx = rep_idx.replay(&self.ins_del);
428
429        let r#gen = Gen::new(self.ins_del.len());
430        *rep_idx = ReplayIdx::new(data_idx, r#gen);
431
432        self.get(data_idx)
433      })
434  }
435
436  /// Insert an item into the database at the given `index`.
437  #[cfg(test)]
438  #[inline]
439  pub fn insert(&mut self, index: usize, item: T) -> Entry<'_, T, Aux>
440  where
441    Aux: Default,
442  {
443    self.insert_with_aux(index, item, Aux::default())
444  }
445
446  /// Insert an item into the database at the given `index`, providing
447  /// an auxiliary value right away.
448  #[cfg(test)]
449  #[inline]
450  pub fn insert_with_aux(&mut self, index: usize, item: T, aux: Aux) -> Entry<'_, T, Aux> {
451    let () = self.data.insert(index, (Rc::new(item), Cell::new(aux)));
452    let () = self.index(index);
453    // SANITY: We know we just inserted an item at `index`, so an entry
454    //         has to exist.
455    self.get(index).unwrap()
456  }
457
458  /// Try inserting an item into the database at the given `index`.
459  ///
460  /// This function succeeds if `item` is not yet present.
461  #[cfg(test)]
462  #[inline]
463  pub fn try_insert(&mut self, index: usize, item: Rc<T>) -> Option<Entry<'_, T, Aux>>
464  where
465    Aux: Default,
466  {
467    self.try_insert_with_aux(index, item, Aux::default())
468  }
469
470  /// Try inserting an item into the database at the given `index`,
471  /// providing a non-default auxiliary value right away.
472  ///
473  /// This function succeeds if `item` is not yet present.
474  #[inline]
475  pub fn try_insert_with_aux(
476    &mut self,
477    index: usize,
478    item: Rc<T>,
479    aux: Aux,
480  ) -> Option<Entry<'_, T, Aux>> {
481    if self.find(&item).is_some() {
482      None
483    } else {
484      let () = self.data.insert(index, (item, Cell::new(aux)));
485      let () = self.index(index);
486      self.get(index)
487    }
488  }
489
490  /// Insert an item at the end of the database.
491  #[cfg(test)]
492  #[inline]
493  pub fn push(&mut self, item: T) -> Entry<'_, T, Aux>
494  where
495    Aux: Default,
496  {
497    self.push_with_aux(item, Aux::default())
498  }
499
500  /// Insert an item at the end of the database, providing a non-default
501  /// auxiliary value right away.
502  #[cfg(test)]
503  #[inline]
504  pub fn push_with_aux(&mut self, item: T, aux: Aux) -> Entry<'_, T, Aux> {
505    let rc = Rc::new(item);
506    let idx = self.data.len();
507    let () = self.data.push((rc, Cell::new(aux)));
508    let () = self.index(idx);
509    // SANITY: We know we just pushed an item, so a last item has to
510    //         exist.
511    self.last().unwrap()
512  }
513
514  /// Try inserting an item at the end of the database.
515  ///
516  /// This function succeeds if `item` is not yet present.
517  #[cfg(test)]
518  #[inline]
519  pub fn try_push(&mut self, item: Rc<T>) -> Option<Entry<'_, T, Aux>>
520  where
521    Aux: Default,
522  {
523    self.try_push_with_aux(item, Aux::default())
524  }
525
526  /// Try inserting an item at the end of the database, providing a
527  /// non-default auxiliary value right away.
528  ///
529  /// This function succeeds if `item` is not yet present.
530  #[cfg(test)]
531  #[inline]
532  pub fn try_push_with_aux(&mut self, item: Rc<T>, aux: Aux) -> Option<Entry<'_, T, Aux>> {
533    if self.find(&item).is_some() {
534      None
535    } else {
536      let idx = self.data.len();
537      let () = self.data.push((item, Cell::new(aux)));
538      let () = self.index(idx);
539      self.last()
540    }
541  }
542
543  /// Remove the item at the provided index.
544  #[inline]
545  pub fn remove(&mut self, index: usize) -> (Rc<T>, Aux) {
546    let () = self.deindex(index);
547    let (item, aux) = self.data.remove(index);
548    (item, aux.into_inner())
549  }
550
551  /// Retrieve an [`Entry`] representing the item at the given index in
552  /// the database.
553  #[inline]
554  pub fn get(&self, index: usize) -> Option<Entry<'_, T, Aux>> {
555    if index < self.data.len() {
556      Some(Entry::new(&self.data, index))
557    } else {
558      None
559    }
560  }
561
562  /// Retrieve the number of elements in the database.
563  #[inline]
564  pub fn len(&self) -> usize {
565    self.data.len()
566  }
567
568  /// Retrieve an [`Entry`] representing the last item in the database.
569  #[inline]
570  pub fn last(&self) -> Option<Entry<'_, T, Aux>> {
571    let len = self.data.len();
572    if len > 0 {
573      Some(Entry::new(&self.data, len - 1))
574    } else {
575      None
576    }
577  }
578
579  /// Retrieve an iterator over the items of the database.
580  #[inline]
581  pub fn iter(&self) -> Iter<'_, T, Aux> {
582    fn map<T, Aux>(x: &(T, Cell<Aux>)) -> &T {
583      &x.0
584    }
585
586    self.data.iter().map(map as _)
587  }
588}
589
590impl<T, Aux> Debug for Db<T, Aux>
591where
592  T: Debug,
593  Aux: Copy + Debug,
594{
595  fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
596    let Self {
597      data,
598      by_ptr_idx: _,
599      ins_del: _,
600    } = self;
601
602    f.debug_struct("Db").field("data", &data).finish()
603  }
604}
605
606
607#[cfg(test)]
608pub mod tests {
609  use super::*;
610
611  #[cfg(feature = "nightly")]
612  use std::hint::black_box;
613  use std::mem::size_of;
614
615  #[cfg(feature = "nightly")]
616  use unstable_test::Bencher;
617
618
619  #[cfg(feature = "nightly")]
620  const ITEM_CNT: usize = 10000;
621
622
623  /// Check the size of various types.
624  #[test]
625  fn type_sizes() {
626    assert_eq!(size_of::<InsDel>(), 4);
627    assert_eq!(size_of::<Gen>(), 2);
628  }
629
630  /// Check that we can set and get auxiliary data from an `Entry`.
631  #[test]
632  fn entry_aux_set_get() {
633    let iter = ["foo", "boo", "blah"]
634      .into_iter()
635      .enumerate()
636      .map(|(idx, item)| (item, idx));
637    let db = Db::from_iter_with_aux(iter);
638    let entry = db.get(1).unwrap();
639    assert_eq!(entry.aux(), 1);
640
641    let () = entry.set_aux(42);
642    assert_eq!(entry.aux(), 42);
643
644    let entry = db.get(1).unwrap();
645    assert_eq!(entry.aux(), 42);
646  }
647
648  /// Check that `Entry::next` and `Entry::prev` work as they should.
649  #[test]
650  fn entry_navigation() {
651    let db = Db::from_iter(["foo", "boo", "blah"]);
652
653    let entry = db.get(0).unwrap();
654    assert_eq!(entry.deref().deref(), &"foo");
655    assert!(entry.prev().is_none());
656
657    let entry = entry.next().unwrap();
658    assert_eq!(entry.deref().deref(), &"boo");
659
660    let entry = entry.next().unwrap();
661    assert_eq!(entry.deref().deref(), &"blah");
662
663    assert!(entry.next().is_none());
664
665    let entry = entry.prev().unwrap();
666    assert_eq!(entry.deref().deref(), &"boo");
667  }
668
669  /// Make sure that we can create a [`Db`] from an iterator.
670  #[test]
671  fn create_from_iter() {
672    let items = ["foo", "bar", "baz", "foobar"];
673    let db = Db::from_iter(items);
674    assert_eq!(**db.get(0).unwrap(), "foo");
675    assert_eq!(**db.get(3).unwrap(), "foobar");
676  }
677
678  /// Make sure that [`Db`] creation fails if duplicate items are
679  /// provided.
680  #[test]
681  fn create_from_iter_duplicate() {
682    let foo = Rc::new("foo");
683    let items = [
684      Rc::clone(&foo),
685      Rc::new("bar"),
686      Rc::new("baz"),
687      Rc::clone(&foo),
688      Rc::new("foobar"),
689    ];
690    let duplicate = Db::try_from_iter(items).unwrap_err();
691    assert!(Rc::ptr_eq(&duplicate, &foo));
692  }
693
694  /// Check that we can lookup an item.
695  #[test]
696  fn find_item() {
697    let items = ["foo", "bar", "baz", "foobar"]
698      .into_iter()
699      .map(Rc::new)
700      .collect::<Vec<_>>();
701    let bar = Rc::clone(&items[1]);
702
703    let db = Db::try_from_iter(items.clone()).unwrap();
704    assert_eq!(db.find(&bar).map(|entry| entry.index()), Some(1));
705
706    let hihi = Rc::new("hihi");
707    let db = Db::try_from_iter(items).unwrap();
708    assert_eq!(db.find(&hihi).map(|entry| entry.index()), None);
709  }
710
711  /// Check that we can insert an item.
712  #[test]
713  fn insert_item() {
714    let items = ["foo", "bar", "baz", "foobar"];
715
716    let mut db = Db::from_iter(items);
717    let item = Rc::clone(&db.insert(0, "foobarbaz"));
718    let idx = db.find(&item).unwrap().index();
719    assert_eq!(idx, 0);
720
721    let item = Rc::clone(&db.insert(5, "outoffoos"));
722    let idx = db.find(&item).unwrap().index();
723    assert_eq!(idx, 5);
724  }
725
726  /// Check that we can insert an item, but fail if it is a duplicate.
727  #[test]
728  fn try_insert_item() {
729    let items = ["foo", "bar", "baz", "foobar"];
730
731    let mut db = Db::from_iter(items);
732    let item = Rc::clone(&db.try_insert(0, Rc::new("foobarbaz")).unwrap());
733    let idx = db.find(&item).unwrap().index();
734    assert_eq!(idx, 0);
735
736    let item = Rc::clone(&db.get(0).unwrap());
737    assert!(db.try_insert(5, item).is_none())
738  }
739
740  /// Check that we can insert an item at the end of a `Db`.
741  #[test]
742  fn push_item() {
743    let mut db = Db::from_iter([]);
744    let item = Rc::clone(&db.push("foo"));
745    let idx = db.find(&item).unwrap().index();
746    assert_eq!(idx, 0);
747
748    let item = Rc::clone(&db.push("bar"));
749    let idx = db.find(&item).unwrap().index();
750    assert_eq!(idx, 1);
751
752    let _removed = db.remove(0);
753    let item = Rc::clone(&db.push("baz"));
754    let idx = db.find(&item).unwrap().index();
755    assert_eq!(idx, 1);
756  }
757
758  /// Check that we can insert an item at the end of a `Db`, but fail if
759  /// it is a duplicate.
760  #[test]
761  fn try_push_item() {
762    let mut db = Db::from_iter(["foo", "boo", "blah"]);
763    let item = Rc::clone(&db.try_push(Rc::new("foo")).unwrap());
764    let idx = db.find(&item).unwrap().index();
765    assert_eq!(idx, 3);
766
767    let item = Rc::clone(&db.get(1).unwrap());
768    assert!(db.try_push(item).is_none())
769  }
770
771  /// Check that we can iterate over the elements of a [`Db`].
772  #[test]
773  fn iteration() {
774    let items = ["foo", "bar", "baz", "foobar"];
775
776    let db = Db::from_iter(items);
777    let vec = db.iter().map(|rc| **rc).collect::<Vec<_>>();
778    assert_eq!(vec, items);
779  }
780
781  /// Benchmark data insertion at the start of a [`Db`].
782  #[cfg(feature = "nightly")]
783  #[bench]
784  fn bench_insert(b: &mut Bencher) {
785    let () = b.iter(|| {
786      let mut db = Db::from_iter([]);
787      // Reserve all necessary memory in a single allocation so that
788      // allocation to minimize allocation overhead.
789      let () = db.data.reserve(ITEM_CNT);
790
791      for i in 1..ITEM_CNT {
792        let _entry = db.insert(0, black_box(i));
793      }
794    });
795  }
796
797  /// Benchmark data insertion at the start of a [`Db`].
798  #[cfg(feature = "nightly")]
799  #[bench]
800  fn bench_try_insert(b: &mut Bencher) {
801    let items = (0..ITEM_CNT).map(Rc::new).collect::<Vec<_>>();
802
803    let () = b.iter(|| {
804      let mut db = Db::from_iter([]);
805      let () = db.data.reserve(ITEM_CNT);
806
807      for item in items.iter() {
808        assert!(db
809          .try_insert(black_box(0), black_box(Rc::clone(item)))
810          .is_some());
811      }
812    });
813  }
814
815  /// Benchmark data insertion at the end of a [`Db`].
816  #[cfg(feature = "nightly")]
817  #[bench]
818  fn bench_push(b: &mut Bencher) {
819    let () = b.iter(|| {
820      let mut db = Db::from_iter([]);
821      let () = db.data.reserve(ITEM_CNT);
822
823      for i in 1..ITEM_CNT {
824        let _entry = db.push(black_box(i));
825      }
826    });
827  }
828
829  /// Benchmark checked data insertion at the end of a [`Db`].
830  #[cfg(feature = "nightly")]
831  #[bench]
832  fn bench_try_push(b: &mut Bencher) {
833    let items = (0..ITEM_CNT).map(Rc::new).collect::<Vec<_>>();
834
835    let () = b.iter(|| {
836      let mut db = Db::from_iter([]);
837      let () = db.data.reserve(ITEM_CNT);
838
839      for item in items.iter() {
840        assert!(db.try_push(black_box(Rc::clone(item))).is_some());
841      }
842    });
843  }
844
845  /// Benchmark data lookup in a [`Db`].
846  #[cfg(feature = "nightly")]
847  #[bench]
848  fn bench_finding(b: &mut Bencher) {
849    let mut db = Db::from_iter([]);
850
851    let items = (1..ITEM_CNT)
852      .map(|i| Rc::clone(db.push(i).deref()))
853      .collect::<HashSet<_>>();
854
855    let () = b.iter(|| {
856      // Lookup each item.
857      let () = items.iter().for_each(|item| {
858        let _item = db.find(black_box(item)).unwrap();
859      });
860    });
861  }
862
863  /// Benchmark repeated removal of the first item from a [`Db`].
864  #[cfg(feature = "nightly")]
865  #[bench]
866  fn bench_remove_first(b: &mut Bencher) {
867    let () = b.iter(|| {
868      let mut db = Db::from_iter(0..ITEM_CNT);
869      for _ in 0..ITEM_CNT {
870        let _item = db.remove(black_box(0));
871      }
872    });
873  }
874
875  /// Benchmark repeated removal of the last item from a [`Db`].
876  #[cfg(feature = "nightly")]
877  #[bench]
878  fn bench_remove_last(b: &mut Bencher) {
879    let () = b.iter(|| {
880      let mut db = Db::from_iter(0..ITEM_CNT);
881      for _ in 0..ITEM_CNT {
882        let _item = db.remove(black_box(db.len() - 1));
883      }
884    });
885  }
886}