git-ents.gitmain
⌘K
foforge
counting.rs69 lines · 1.8 KB · rusthistorycomment on this file
1//! An object-read counter, for asserting incremental-evaluation bounds.
2
3use std::cell::Cell;
4
5use gix_object::Find;
6use gix_object::find;
7
8/// Wraps any [`Find`] and counts `try_find` calls, so a test can assert
9/// that an "incremental" code path really is bounded — for example, that
10/// evaluating a query entry set after a one-commit advance does not
11/// re-walk a three-hundred-commit history (`query.incremental`).
12///
13/// # Examples
14///
15/// ```
16/// use ents_testutil::{CountingFind, ObjectStore, empty_tree};
17/// use gix_object::Find as _;
18///
19/// let objects = ObjectStore::default();
20/// let tree = empty_tree(&objects);
21///
22/// let counting = CountingFind::new(&objects);
23/// let mut buf = Vec::new();
24/// counting.try_find(&tree, &mut buf).expect("readable");
25/// assert_eq!(counting.reads(), 1);
26///
27/// counting.reset();
28/// assert_eq!(counting.reads(), 0);
29/// ```
30#[derive(Debug)]
31pub struct CountingFind<'a, F: Find> {
32 inner: &'a F,
33 reads: Cell<usize>,
34}
35
36impl<'a, F: Find> CountingFind<'a, F> {
37 /// Wrap `inner`, starting the counter at zero.
38 #[must_use]
39 pub fn new(inner: &'a F) -> Self {
40 Self {
41 inner,
42 reads: Cell::new(0),
43 }
44 }
45
46 /// How many `try_find` calls have happened since the last
47 /// [`CountingFind::reset`].
48 #[must_use]
49 pub fn reads(&self) -> usize {
50 self.reads.get()
51 }
52
53 /// Zero the counter — typically after warming caches, so an assertion
54 /// covers only the increment under test.
55 pub fn reset(&self) {
56 self.reads.set(0);
57 }
58}
59
60impl<F: Find> Find for CountingFind<'_, F> {
61 fn try_find<'b>(
62 &self,
63 id: &gix_hash::oid,
64 buffer: &'b mut Vec<u8>,
65 ) -> Result<Option<gix_object::Data<'b>>, find::Error> {
66 self.reads.set(self.reads.get().saturating_add(1));
67 self.inner.try_find(id, buffer)
68 }
69}