Skip to main content

columnar/
lookback.rs

1//! Containers that can store either values, or offsets to prior values.
2//!
3//! This has the potential to be more efficient than a list of `T` when many values repeat in
4//! close proximity. Values must be equatable, and the degree of lookback can be configured.
5use alloc::{vec::Vec, string::String};
6
7use crate::{Options, Results, Push, Index, Len, Clear, Borrow, Container, IndexAs};
8
9/// A container that encodes repeated values with a `None` variant, at the cost of extra bits for every record.
10#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
11#[derive(Copy, Clone, Debug, Default, PartialEq)]
12pub struct Repeats<TC, CC=Vec<u64>, VC=Vec<u64>, WC=[u64; 2]> {
13    /// Some(x) encodes a value, and None indicates the prior `x` value.
14    pub inner: Options<TC, CC, VC, WC>,
15}
16
17impl<T: PartialEq, TC: Push<T> + Len> Push<T> for Repeats<TC>
18where
19    for<'a> &'a TC: Index,
20    for<'a> <&'a TC as Index>::Ref : PartialEq<T>,
21{
22    #[inline]
23    fn push(&mut self, item: T) {
24        // Look at the last `somes` value for a potential match.
25        let insert: Option<T> = if (&self.inner.somes).last().map(|x| x.eq(&item)) == Some(true) {
26            None
27        } else {
28            Some(item)
29        };
30        self.inner.push(insert);
31    }
32}
33
34impl<TC, CC, VC: Len, WC: IndexAs<u64>> Len for Repeats<TC, CC, VC, WC> {
35    #[inline(always)] fn len(&self) -> usize { self.inner.len() }
36}
37
38impl<TC: Index, CC: IndexAs<u64> + Len, VC: IndexAs<u64> + Len, WC: IndexAs<u64>> Index for Repeats<TC, CC, VC, WC> {
39    type Ref = TC::Ref;
40    #[inline(always)] fn get(&self, index: usize) -> Self::Ref {
41        match self.inner.get(index) {
42            Some(item) => item,
43            None => {
44                let pos = self.inner.indexes.rank(index) - 1;
45                self.inner.somes.get(pos)
46            },
47        }
48    }
49}
50
51impl<'a, TC> Index for &'a Repeats<TC>
52where
53    &'a TC: Index,
54{
55    type Ref = <&'a TC as Index>::Ref;
56    #[inline(always)] fn get(&self, index: usize) -> Self::Ref {
57        match (&self.inner).get(index) {
58            Some(item) => item,
59            None => {
60                let pos = self.inner.indexes.rank(index) - 1;
61                (&self.inner.somes).get(pos)
62            },
63        }
64    }
65}
66
67impl<TC: Borrow> Borrow for Repeats<TC> {
68    type Ref<'a> = TC::Ref<'a> where TC: 'a;
69    type Borrowed<'a> = Repeats<TC::Borrowed<'a>, &'a [u64], &'a [u64], &'a [u64]> where TC: 'a;
70    #[inline(always)]
71    fn borrow<'a>(&'a self) -> Self::Borrowed<'a> {
72        Repeats { inner: self.inner.borrow() }
73    }
74    #[inline(always)]
75    fn reborrow<'b, 'a: 'b>(thing: Self::Borrowed<'a>) -> Self::Borrowed<'b> where TC: 'a {
76        Repeats { inner: Options::<TC>::reborrow(thing.inner) }
77    }
78    #[inline(always)]
79    fn reborrow_ref<'b, 'a: 'b>(thing: Self::Ref<'a>) -> Self::Ref<'b> where Self: 'a {
80        TC::reborrow_ref(thing)
81    }
82}
83
84impl<TC: Container> Container for Repeats<TC>
85where
86    for<'a> &'a TC: Index,
87    for<'a> TC::Ref<'a>: PartialEq,
88    for<'a, 'b> <&'a TC as Index>::Ref: PartialEq<TC::Ref<'b>>,
89{
90    fn extend_from_self(&mut self, other: Self::Borrowed<'_>, range: core::ops::Range<usize>) {
91        if !range.is_empty() {
92            // Push the first element, resolving any `None` to its actual value.
93            self.push(other.get(range.start));
94            // The remaining elements can be bulk-copied from the inner `Options`,
95            // as any `None` now has a preceding `Some` to reference.
96            if range.start + 1 < range.end {
97                self.inner.extend_from_self(other.inner, range.start + 1 .. range.end);
98            }
99        }
100    }
101
102    fn reserve_for<'a, I>(&mut self, selves: I) where Self: 'a, I: Iterator<Item = Self::Borrowed<'a>> + Clone {
103        self.inner.somes.reserve_for(selves.map(|x| x.inner.somes));
104    }
105}
106
107impl<TC: Clear> Clear for Repeats<TC> {
108    fn clear(&mut self) {
109        self.inner.clear();
110    }
111}
112
113impl<'a, TC: crate::AsBytes<'a>, CC: crate::AsBytes<'a>, VC: crate::AsBytes<'a>> crate::AsBytes<'a> for Repeats<TC, CC, VC, &'a [u64]> {
114    #[inline(always)]
115    fn as_bytes(&self) -> impl Iterator<Item=(u64, &'a [u8])> {
116        self.inner.as_bytes()
117    }
118}
119
120impl<'a, TC: crate::FromBytes<'a>, CC: crate::FromBytes<'a>, VC: crate::FromBytes<'a>> crate::FromBytes<'a> for Repeats<TC, CC, VC, &'a [u64]> {
121    const SLICE_COUNT: usize = <Options<TC, CC, VC, &'a [u64]>>::SLICE_COUNT;
122    #[inline(always)]
123    fn from_bytes(bytes: &mut impl Iterator<Item=&'a [u8]>) -> Self {
124        Self { inner: crate::FromBytes::from_bytes(bytes) }
125    }
126    #[inline(always)]
127    fn from_store(store: &crate::bytes::indexed::DecodedStore<'a>, offset: &mut usize) -> Self {
128        Self { inner: crate::FromBytes::from_store(store, offset) }
129    }
130    fn element_sizes(sizes: &mut Vec<usize>) -> Result<(), String> {
131        <Options<TC, CC, VC, &'a [u64]>>::element_sizes(sizes)
132    }
133}
134
135#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
136#[derive(Copy, Clone, Debug, Default, PartialEq)]
137pub struct Lookbacks<TC, VC = Vec<u8>, CC=Vec<u64>, RC=Vec<u64>, WC=[u64; 2], const N: u8 = 255> {
138    /// Ok(x) encodes a value, and Err(y) indicates a value `y` back.
139    pub inner: Results<TC, VC, CC, RC, WC>,
140}
141
142impl<T: PartialEq, TC: Push<T> + Len, VC: Push<u8>, const N: u8> Push<T> for Lookbacks<TC, VC, Vec<u64>, Vec<u64>, [u64; 2], N>
143where
144    for<'a> &'a TC: Index,
145    for<'a> <&'a TC as Index>::Ref : PartialEq<T>,
146{
147    #[inline]
148    fn push(&mut self, item: T) {
149        // Look backwards through (0 .. N) to look for a matching value.
150        let oks_len = self.inner.oks.len();
151        let find = (0u8 .. N).take(self.inner.oks.len()).find(|i| (&self.inner.oks).get(oks_len - (*i as usize) - 1) == item);
152        let insert: Result<T, u8> = if let Some(back) = find { Err(back) } else { Ok(item) };
153        self.inner.push(insert);
154    }
155}
156
157impl<TC, VC, CC, RC: Len, WC: IndexAs<u64>, const N: u8> Len for Lookbacks<TC, VC, CC, RC, WC, N> {
158    #[inline(always)] fn len(&self) -> usize { self.inner.len() }
159}
160
161impl<TC: Index, VC: IndexAs<u8>, CC: IndexAs<u64> + Len, RC: IndexAs<u64> + Len, WC: IndexAs<u64>, const N: u8> Index for Lookbacks<TC, VC, CC, RC, WC, N> {
162    type Ref = TC::Ref;
163    #[inline(always)] fn get(&self, index: usize) -> Self::Ref {
164        let rank = self.inner.indexes.rank(index);
165        if self.inner.indexes.get(index) {
166            self.inner.oks.get(rank)
167        } else {
168            let back: u8 = self.inner.errs.index_as(index - rank);
169            self.inner.oks.get(rank - 1 - (back as usize))
170        }
171    }
172}
173
174impl<'a, TC, const N: u8> Index for &'a Lookbacks<TC, Vec<u8>, Vec<u64>, Vec<u64>, [u64; 2], N>
175where
176    &'a TC: Index,
177{
178    type Ref = <&'a TC as Index>::Ref;
179    #[inline(always)] fn get(&self, index: usize) -> Self::Ref {
180        let rank = self.inner.indexes.rank(index);
181        if self.inner.indexes.get(index) {
182            (&self.inner.oks).get(rank)
183        } else {
184            let back: u8 = self.inner.errs.index_as(index - rank);
185            (&self.inner.oks).get(rank - 1 - (back as usize))
186        }
187    }
188}
189
190impl<TC: Borrow, const N: u8> Borrow for Lookbacks<TC, Vec<u8>, Vec<u64>, Vec<u64>, [u64; 2], N> {
191    type Ref<'a> = TC::Ref<'a> where TC: 'a;
192    type Borrowed<'a> = Lookbacks<TC::Borrowed<'a>, &'a [u8], &'a [u64], &'a [u64], &'a [u64], N> where TC: 'a;
193    #[inline(always)]
194    fn borrow<'a>(&'a self) -> Self::Borrowed<'a> {
195        Lookbacks { inner: self.inner.borrow() }
196    }
197    #[inline(always)]
198    fn reborrow<'b, 'a: 'b>(thing: Self::Borrowed<'a>) -> Self::Borrowed<'b> where TC: 'a {
199        Lookbacks { inner: Results::<TC, Vec<u8>>::reborrow(thing.inner) }
200    }
201    #[inline(always)]
202    fn reborrow_ref<'b, 'a: 'b>(thing: Self::Ref<'a>) -> Self::Ref<'b> where Self: 'a {
203        TC::reborrow_ref(thing)
204    }
205}
206
207impl<TC: Container, const N: u8> Container for Lookbacks<TC, Vec<u8>, Vec<u64>, Vec<u64>, [u64; 2], N>
208where
209    for<'a> &'a TC: Index,
210    for<'a> TC::Ref<'a>: PartialEq,
211    for<'a, 'b> <&'a TC as Index>::Ref: PartialEq<TC::Ref<'b>>,
212{
213    // Lookback offsets are relative to oks positions, so bulk-copying a subrange
214    // would break Err(n) references that point outside the range. Use the default
215    // implementation which resolves each element via `get()` and re-pushes.
216
217    fn reserve_for<'a, I>(&mut self, selves: I) where Self: 'a, I: Iterator<Item = Self::Borrowed<'a>> + Clone {
218        self.inner.oks.reserve_for(selves.clone().map(|x| x.inner.oks));
219        self.inner.errs.reserve_for(selves.map(|x| x.inner.errs));
220    }
221}
222
223impl<TC: Clear, const N: u8> Clear for Lookbacks<TC, Vec<u8>, Vec<u64>, Vec<u64>, [u64; 2], N> {
224    fn clear(&mut self) {
225        self.inner.clear();
226    }
227}
228
229impl<'a, TC: crate::AsBytes<'a>, VC: crate::AsBytes<'a>, CC: crate::AsBytes<'a>, RC: crate::AsBytes<'a>> crate::AsBytes<'a> for Lookbacks<TC, VC, CC, RC, &'a [u64]> {
230    #[inline(always)]
231    fn as_bytes(&self) -> impl Iterator<Item=(u64, &'a [u8])> {
232        self.inner.as_bytes()
233    }
234}
235
236impl<'a, TC: crate::FromBytes<'a>, VC: crate::FromBytes<'a>, CC: crate::FromBytes<'a>, RC: crate::FromBytes<'a>> crate::FromBytes<'a> for Lookbacks<TC, VC, CC, RC, &'a [u64]> {
237    const SLICE_COUNT: usize = <Results<TC, VC, CC, RC, &'a [u64]>>::SLICE_COUNT;
238    #[inline(always)]
239    fn from_bytes(bytes: &mut impl Iterator<Item=&'a [u8]>) -> Self {
240        Self { inner: crate::FromBytes::from_bytes(bytes) }
241    }
242    #[inline(always)]
243    fn from_store(store: &crate::bytes::indexed::DecodedStore<'a>, offset: &mut usize) -> Self {
244        Self { inner: crate::FromBytes::from_store(store, offset) }
245    }
246    fn element_sizes(sizes: &mut Vec<usize>) -> Result<(), String> {
247        <Results<TC, VC, CC, RC, &'a [u64]>>::element_sizes(sizes)
248    }
249}
250
251#[cfg(test)]
252mod test {
253
254    use alloc::vec::Vec;
255    use crate::common::{Push, Index, Len, Clear};
256    use crate::{Borrow, Container, AsBytes, FromBytes};
257    use crate::bytes::stash::Stash;
258    use super::{Repeats, Lookbacks};
259
260    /// Helper to populate a `Repeats<Vec<u64>>` from a slice.
261    fn repeats_from(values: &[u64]) -> Repeats<Vec<u64>> {
262        let mut repeats: Repeats<Vec<u64>> = Default::default();
263        for v in values {
264            repeats.push(v);
265        }
266        repeats
267    }
268
269    #[test]
270    fn push_and_index() {
271        let repeats = repeats_from(&[1, 1, 2, 2, 1]);
272
273        assert_eq!(repeats.len(), 5);
274        assert_eq!((&repeats).get(0), 1);
275        assert_eq!((&repeats).get(1), 1);
276        assert_eq!((&repeats).get(2), 2);
277        assert_eq!((&repeats).get(3), 2);
278        assert_eq!((&repeats).get(4), 1);
279
280        // Verify compression: only 3 distinct values stored (1, 2, 1).
281        assert_eq!(repeats.inner.somes.len(), 3);
282    }
283
284    #[test]
285    fn borrow_and_index() {
286        let mut repeats: Repeats<Vec<u64>> = Default::default();
287        for i in 0..50u64 {
288            repeats.push(&i);
289            repeats.push(&i); // repeat
290        }
291
292        assert_eq!(repeats.len(), 100);
293
294        let borrowed = repeats.borrow();
295        assert_eq!(borrowed.len(), 100);
296        for i in 0..50u64 {
297            assert_eq!(*borrowed.get(2 * i as usize), i);
298            assert_eq!(*borrowed.get(2 * i as usize + 1), i);
299        }
300    }
301
302    #[test]
303    fn ref_index() {
304        let repeats = repeats_from(&[10, 10, 20]);
305
306        assert_eq!((&repeats).get(0), 10u64);
307        assert_eq!((&repeats).get(1), 10u64);
308        assert_eq!((&repeats).get(2), 20u64);
309    }
310
311    #[test]
312    fn clear() {
313        let mut repeats = repeats_from(&[1, 2]);
314        assert_eq!(repeats.len(), 2);
315
316        repeats.clear();
317        assert_eq!(repeats.len(), 0);
318
319        repeats.push(&3u64);
320        assert_eq!(repeats.len(), 1);
321        assert_eq!((&repeats).get(0), 3);
322    }
323
324    #[test]
325    fn extend_from_self() {
326        let repeats = repeats_from(&[1, 1, 2, 3, 3]);
327
328        let mut dest: Repeats<Vec<u64>> = Default::default();
329        dest.extend_from_self(repeats.borrow(), 1..4);
330        assert_eq!(dest.len(), 3);
331        assert_eq!(*dest.borrow().get(0), 1);
332        assert_eq!(*dest.borrow().get(1), 2);
333        assert_eq!(*dest.borrow().get(2), 3);
334    }
335
336    #[test]
337    fn as_from_bytes() {
338        let mut repeats: Repeats<Vec<u64>> = Default::default();
339        for i in 0..100u64 {
340            repeats.push(&i);
341            repeats.push(&i);
342        }
343
344        let borrowed = repeats.borrow();
345        let rebuilt = Repeats::<&[u64], &[u64], &[u64], &[u64]>::from_bytes(
346            &mut borrowed.as_bytes().map(|(_, bytes)| bytes)
347        );
348        assert_eq!(rebuilt.len(), 200);
349        for i in 0..100u64 {
350            assert_eq!(*rebuilt.get(2 * i as usize), i);
351            assert_eq!(*rebuilt.get(2 * i as usize + 1), i);
352        }
353    }
354
355    #[test]
356    fn from_store_round_trip() {
357        let mut repeats: Repeats<Vec<u64>> = Default::default();
358        for i in 0..50u64 {
359            repeats.push(&i);
360            repeats.push(&i);
361        }
362
363        let mut store = Vec::new();
364        crate::bytes::indexed::encode(&mut store, &repeats.borrow());
365        let ds = crate::bytes::indexed::DecodedStore::new(&store);
366        let rebuilt = Repeats::<&[u64], &[u64], &[u64], &[u64]>::from_store(&ds, &mut 0);
367        assert_eq!(rebuilt.len(), 100);
368        for i in 0..50u64 {
369            assert_eq!(*rebuilt.get(2 * i as usize), i);
370            assert_eq!(*rebuilt.get(2 * i as usize + 1), i);
371        }
372    }
373
374    #[test]
375    fn validate_via_stash() {
376        let repeats = repeats_from(&[1, 1, 2, 2, 3]);
377
378        let mut bytes: Vec<u8> = Vec::new();
379        crate::bytes::indexed::write(&mut bytes, &repeats.borrow()).unwrap();
380        let stash: Stash<Repeats<Vec<u64>>, Vec<u8>> =
381            Stash::try_from_bytes(bytes).expect("Repeats<Vec<u64>> should validate");
382        let borrowed = stash.borrow();
383        assert_eq!(borrowed.len(), 5);
384        assert_eq!(*borrowed.get(0), 1);
385        assert_eq!(*borrowed.get(1), 1);
386        assert_eq!(*borrowed.get(2), 2);
387        assert_eq!(*borrowed.get(3), 2);
388        assert_eq!(*borrowed.get(4), 3);
389    }
390
391    #[test]
392    fn all_repeats() {
393        let mut repeats: Repeats<Vec<u64>> = Default::default();
394        for _ in 0..100 {
395            repeats.push(&42u64);
396        }
397        assert_eq!(repeats.len(), 100);
398        // Only one distinct value stored.
399        assert_eq!(repeats.inner.somes.len(), 1);
400
401        let borrowed = repeats.borrow();
402        for i in 0..100 {
403            assert_eq!(*borrowed.get(i), 42);
404        }
405    }
406
407    #[test]
408    fn no_repeats() {
409        let mut repeats: Repeats<Vec<u64>> = Default::default();
410        for i in 0..100u64 {
411            repeats.push(&i);
412        }
413        assert_eq!(repeats.len(), 100);
414        // Every value is distinct.
415        assert_eq!(repeats.inner.somes.len(), 100);
416
417        let borrowed = repeats.borrow();
418        for i in 0..100u64 {
419            assert_eq!(*borrowed.get(i as usize), i);
420        }
421    }
422
423    // --- Lookbacks tests ---
424
425    /// Helper to populate a `Lookbacks<Vec<u64>>` from a slice.
426    fn lookbacks_from(values: &[u64]) -> Lookbacks<Vec<u64>> {
427        let mut lookbacks: Lookbacks<Vec<u64>> = Default::default();
428        for v in values {
429            lookbacks.push(v);
430        }
431        lookbacks
432    }
433
434    #[test]
435    fn lookbacks_push_and_index() {
436        let lookbacks = lookbacks_from(&[10, 20, 10, 30, 20]);
437
438        assert_eq!(lookbacks.len(), 5);
439        assert_eq!((&lookbacks).get(0), 10);
440        assert_eq!((&lookbacks).get(1), 20);
441        assert_eq!((&lookbacks).get(2), 10);
442        assert_eq!((&lookbacks).get(3), 30);
443        assert_eq!((&lookbacks).get(4), 20);
444
445        // Values 10 and 20 at indices 2 and 4 should be lookbacks, not new oks.
446        assert_eq!(lookbacks.inner.oks.len(), 3);
447    }
448
449    #[test]
450    fn lookbacks_borrow_and_index() {
451        let mut lookbacks: Lookbacks<Vec<u64>> = Default::default();
452        for i in 0..50u64 {
453            lookbacks.push(&i);
454            lookbacks.push(&i); // lookback
455        }
456
457        assert_eq!(lookbacks.len(), 100);
458
459        let borrowed = lookbacks.borrow();
460        assert_eq!(borrowed.len(), 100);
461        for i in 0..50u64 {
462            assert_eq!(*borrowed.get(2 * i as usize), i);
463            assert_eq!(*borrowed.get(2 * i as usize + 1), i);
464        }
465    }
466
467    #[test]
468    fn lookbacks_clear() {
469        let mut lookbacks = lookbacks_from(&[1, 2]);
470        assert_eq!(lookbacks.len(), 2);
471
472        lookbacks.clear();
473        assert_eq!(lookbacks.len(), 0);
474
475        lookbacks.push(&3u64);
476        assert_eq!(lookbacks.len(), 1);
477        assert_eq!((&lookbacks).get(0), 3);
478    }
479
480    #[test]
481    fn lookbacks_extend_from_self() {
482        let lookbacks = lookbacks_from(&[10, 20, 30, 40, 50]);
483
484        let mut dest: Lookbacks<Vec<u64>> = Default::default();
485        dest.extend_from_self(lookbacks.borrow(), 1..4);
486        assert_eq!(dest.len(), 3);
487        assert_eq!(*dest.borrow().get(0), 20);
488        assert_eq!(*dest.borrow().get(1), 30);
489        assert_eq!(*dest.borrow().get(2), 40);
490    }
491
492    #[test]
493    fn lookbacks_as_from_bytes() {
494        let mut lookbacks: Lookbacks<Vec<u64>> = Default::default();
495        for i in 0..100u64 {
496            lookbacks.push(&i);
497            lookbacks.push(&i);
498        }
499
500        let borrowed = lookbacks.borrow();
501        let rebuilt = Lookbacks::<&[u64], &[u8], &[u64], &[u64], &[u64]>::from_bytes(
502            &mut borrowed.as_bytes().map(|(_, bytes)| bytes)
503        );
504        assert_eq!(rebuilt.len(), 200);
505        for i in 0..100u64 {
506            assert_eq!(*rebuilt.get(2 * i as usize), i);
507            assert_eq!(*rebuilt.get(2 * i as usize + 1), i);
508        }
509    }
510
511    #[test]
512    fn lookbacks_from_store_round_trip() {
513        let mut lookbacks: Lookbacks<Vec<u64>> = Default::default();
514        for i in 0..50u64 {
515            lookbacks.push(&i);
516            lookbacks.push(&i);
517        }
518
519        let mut store = Vec::new();
520        crate::bytes::indexed::encode(&mut store, &lookbacks.borrow());
521        let ds = crate::bytes::indexed::DecodedStore::new(&store);
522        let rebuilt = Lookbacks::<&[u64], &[u8], &[u64], &[u64], &[u64]>::from_store(&ds, &mut 0);
523        assert_eq!(rebuilt.len(), 100);
524        for i in 0..50u64 {
525            assert_eq!(*rebuilt.get(2 * i as usize), i);
526            assert_eq!(*rebuilt.get(2 * i as usize + 1), i);
527        }
528    }
529
530    #[test]
531    fn lookbacks_validate_via_stash() {
532        let lookbacks = lookbacks_from(&[1, 2, 1, 3, 2]);
533
534        let mut bytes: Vec<u8> = Vec::new();
535        crate::bytes::indexed::write(&mut bytes, &lookbacks.borrow()).unwrap();
536        let stash: Stash<Lookbacks<Vec<u64>>, Vec<u8>> =
537            Stash::try_from_bytes(bytes).expect("Lookbacks<Vec<u64>> should validate");
538        let borrowed = stash.borrow();
539        assert_eq!(borrowed.len(), 5);
540        assert_eq!(*borrowed.get(0), 1);
541        assert_eq!(*borrowed.get(1), 2);
542        assert_eq!(*borrowed.get(2), 1);
543        assert_eq!(*borrowed.get(3), 3);
544        assert_eq!(*borrowed.get(4), 2);
545    }
546
547    #[test]
548    fn lookbacks_all_same() {
549        let mut lookbacks: Lookbacks<Vec<u64>> = Default::default();
550        for _ in 0..100 {
551            lookbacks.push(&42u64);
552        }
553        assert_eq!(lookbacks.len(), 100);
554        // Only the first value is stored as Ok; rest are Err lookbacks.
555        assert_eq!(lookbacks.inner.oks.len(), 1);
556
557        let borrowed = lookbacks.borrow();
558        for i in 0..100 {
559            assert_eq!(*borrowed.get(i), 42);
560        }
561    }
562
563    #[test]
564    fn lookbacks_no_matches() {
565        let mut lookbacks: Lookbacks<Vec<u64>> = Default::default();
566        for i in 0..100u64 {
567            lookbacks.push(&(i * 1000)); // all distinct, spaced far apart
568        }
569        assert_eq!(lookbacks.len(), 100);
570        // Every value is unique; all stored as Ok.
571        assert_eq!(lookbacks.inner.oks.len(), 100);
572
573        let borrowed = lookbacks.borrow();
574        for i in 0..100u64 {
575            assert_eq!(*borrowed.get(i as usize), i * 1000);
576        }
577    }
578}