From 05c1d280b73ce2dc4c66b92de5900c3534f99b5d Mon Sep 17 00:00:00 2001 From: Chris Mikkelson Date: Tue, 8 Apr 2025 00:14:43 -0500 Subject: [PATCH] Reduce lifetime proliferation. Makes Source trait non-dyn-compatible again, but an improvement in reducing lifetimes and function generics. --- src/dupsort.rs | 41 ++++++++++++++----------- src/filter.rs | 33 ++++++++++---------- src/iter.rs | 2 +- src/merge.rs | 40 ++++++++++++------------- src/merger.rs | 10 +++---- src/reader/mod.rs | 9 ++++-- src/sorter.rs | 8 ++--- src/source.rs | 76 ++++++++++++++++++----------------------------- tests/rwtest.rs | 3 +- 9 files changed, 107 insertions(+), 115 deletions(-) diff --git a/src/dupsort.rs b/src/dupsort.rs index f0a53ef..04b449f 100644 --- a/src/dupsort.rs +++ b/src/dupsort.rs @@ -1,40 +1,45 @@ use crate::{SeekableIter, Source}; use std::cmp::Ordering; -use std::marker::PhantomData; -pub struct DupsortSource<'a, S, F> +pub struct DupsortSource where - S: Source<'a>, - F: Fn(&::Item, &::Item) -> Ordering, + S: Source, { source: S, - dupsort_func: F, - phantom: PhantomData<&'a char>, + #[allow(clippy::type_complexity)] + // Attempting to factor out the `::Item` type removes the ability to use the + // implicit '_ lifetime. + dupsort_func: + Box as Iterator>::Item, & as Iterator>::Item) -> Ordering>, } -impl<'a, S, F> DupsortSource<'a, S, F> +impl DupsortSource where - S: Source<'a>, - F: Fn(&::Item, &::Item) -> Ordering, + S: Source, { - pub fn new(source: S, dupsort_func: F) -> Self { + pub fn new(source: S, dupsort_func: F) -> Self + where + F: Fn(& as Iterator>::Item, & as Iterator>::Item) -> Ordering + + 'static, + { Self { source, - dupsort_func, - phantom: PhantomData, + dupsort_func: Box::new(dupsort_func), } } } -impl<'a, S, F> Source<'a> for DupsortSource<'a, S, F> +impl Source for DupsortSource where - S: Source<'a>, - ::Item: PartialEq, - F: Fn(&::Item, &::Item) -> Ordering + 'a, + S: Source + 'static, + for<'i> as Iterator>::Item: PartialEq, { - type Iter = DupsortIter; + type Iter<'i> = DupsortIter< + S::Iter<'i>, + &'i dyn Fn(& as Iterator>::Item, & as Iterator>::Item) -> Ordering, + >; - fn iter(&'a self) -> Self::Iter { + fn iter(&self) -> Self::Iter<'_> { self.source.iter().dupsort_func(&self.dupsort_func) } } diff --git a/src/filter.rs b/src/filter.rs index f0ccd5e..b420c21 100644 --- a/src/filter.rs +++ b/src/filter.rs @@ -1,5 +1,4 @@ use crate::{SeekableIter, Source}; -use std::marker::PhantomData; pub struct FilterIter { iter: I, @@ -53,33 +52,37 @@ where } } -pub struct FilterSource<'a, S, F> { +pub struct FilterSource +where + S: Source, +{ source: S, - filter_func: F, - phantom: PhantomData<&'a char>, + #[allow(clippy::type_complexity)] + filter_func: Box as Iterator>::Item, &mut Vec) -> bool>, } -impl<'a, S, F> FilterSource<'a, S, F> +impl FilterSource where - S: Source<'a>, - F: Fn(&::Item, &mut Vec) -> bool, + S: Source, { - pub fn new(source: S, filter_func: F) -> Self { + pub fn new(source: S, filter_func: F) -> Self + where + F: Fn(& as Iterator>::Item, &mut Vec) -> bool + 'static, + { Self { source, - filter_func, - phantom: PhantomData, + filter_func: Box::new(filter_func), } } } -impl<'a, S, F> Source<'a> for FilterSource<'a, S, F> +impl Source for FilterSource where - S: Source<'a>, - F: Fn(&::Item, &mut Vec) -> bool + 'a, + S: Source + 'static, { - type Iter = FilterIter; - fn iter(&'a self) -> Self::Iter { + type Iter<'i> = + FilterIter, &'i dyn Fn(& as Iterator>::Item, &mut Vec) -> bool>; + fn iter(&self) -> Self::Iter<'_> { self.source.iter().filter_func(&self.filter_func) } } diff --git a/src/iter.rs b/src/iter.rs index 080e9c2..3d9599d 100644 --- a/src/iter.rs +++ b/src/iter.rs @@ -10,7 +10,7 @@ pub trait SeekableIter: Iterator { fn merge_func(self, merge_func: F) -> MergeIter where - F: FnMut(&mut Vec, &Entry), + F: Fn(&mut Vec, &Entry), Self: Sized, { MergeIter::new(self, merge_func) diff --git a/src/merge.rs b/src/merge.rs index 567c2d9..e6f79dd 100644 --- a/src/merge.rs +++ b/src/merge.rs @@ -1,39 +1,37 @@ use crate::{Entry, SeekableIter, Source}; -use std::marker::PhantomData; -pub struct MergeSource<'a, S: Source<'a>, F: Fn(&mut Vec, &Entry)> { +pub struct MergeSource { source: S, - merge_func: F, - phantom: PhantomData<&'a char>, + #[allow(clippy::type_complexity)] + merge_func: Box, &Entry)>, } -impl<'a, S, F> MergeSource<'a, S, F> +impl MergeSource where - S: Source<'a>, - F: Fn(&mut Vec, &Entry), + S: Source, { - pub fn new(source: S, merge_func: F) -> Self { + pub fn new(source: S, merge_func: F) -> Self + where + F: Fn(&mut Vec, &Entry) + 'static, + { Self { source, - merge_func, - phantom: PhantomData, + merge_func: Box::new(merge_func), } } } - -impl<'a, S, F> Source<'a> for MergeSource<'a, S, F> +impl Source for MergeSource where - S: Source<'a>, - S::Iter: Iterator, - F: Fn(&mut Vec, &Entry) + 'a, + S: Source + 'static, + for<'a> S::Iter<'a>: Iterator, { - type Iter = MergeIter; - fn iter(&'a self) -> Self::Iter { + type Iter<'i> = MergeIter, &'i dyn Fn(&mut Vec, &Entry)>; + fn iter(&self) -> Self::Iter<'_> { self.source.iter().merge_func(&self.merge_func) } } -pub struct MergeIter, &Entry)> { +pub struct MergeIter, &Entry)> { prev: Option, iter: I, merge_func: F, @@ -41,7 +39,7 @@ pub struct MergeIter, &Entry)> { impl MergeIter where - F: FnMut(&mut Vec, &Entry), + F: Fn(&mut Vec, &Entry), { pub fn new(iter: I, merge_func: F) -> Self { Self { @@ -55,7 +53,7 @@ where impl Iterator for MergeIter where I: Iterator, - F: FnMut(&mut Vec, &Entry), + F: Fn(&mut Vec, &Entry), { type Item = Entry; fn next(&mut self) -> Option { @@ -75,7 +73,7 @@ where impl SeekableIter for MergeIter where I: SeekableIter, - F: FnMut(&mut Vec, &Entry), + F: Fn(&mut Vec, &Entry), { fn seek(&mut self, key: &[u8]) { self.prev.take(); diff --git a/src/merger.rs b/src/merger.rs index 7fb405f..6d611f6 100644 --- a/src/merger.rs +++ b/src/merger.rs @@ -134,13 +134,13 @@ impl> SeekableIter for MergeIter { } } -impl<'a, S> Source<'a> for Merger +impl Source for Merger where - S: Source<'a>, - S::Iter: Iterator, + S: Source + 'static, + for<'i> S::Iter<'i>: Iterator + 'i, { - type Iter = MergeIter; - fn iter(&'a self) -> Self::Iter { + type Iter<'i> = MergeIter>; + fn iter(&self) -> Self::Iter<'_> { MergeIter::from(self.sources.iter().map(|s| s.iter())) } } diff --git a/src/reader/mod.rs b/src/reader/mod.rs index 0b5ad43..d956d51 100644 --- a/src/reader/mod.rs +++ b/src/reader/mod.rs @@ -176,10 +176,13 @@ impl> SeekableIter for ReaderIter { } } -impl<'a, D: AsRef<[u8]>> Source<'a> for Reader { - type Iter = ReaderIter; +impl> Source for Reader { + type Iter<'i> + = ReaderIter + where + D: 'i; - fn iter(&'a self) -> Self::Iter { + fn iter(&self) -> Self::Iter<'_> { ReaderIter { reader: self.clone(), next_offset: 0, diff --git a/src/sorter.rs b/src/sorter.rs index fe4073f..a582cc0 100644 --- a/src/sorter.rs +++ b/src/sorter.rs @@ -1,4 +1,4 @@ -use crate::{merge::MergeSource, Entry, Merger, Reader, Source, Writer}; +use crate::{merge::MergeSource, Entry, Merger, Reader, SeekableIter, Source, Writer}; use memmap::Mmap; use std::cell::Cell; @@ -13,7 +13,7 @@ pub struct Sorter, &Entry)> { impl Sorter where - F: Fn(&mut Vec, &Entry), + F: Fn(&mut Vec, &Entry) + 'static, { pub fn new(max_size: usize, merge_func: F) -> Self { Self { @@ -35,7 +35,7 @@ where self.batch_size += esize; } - pub fn source<'a>(mut self) -> MergeSource<'a, Merger>, F> { + pub fn source(mut self) -> MergeSource>> { if !self.batch.get_mut().is_empty() { self.write_chunk(); } @@ -53,8 +53,8 @@ where .sort_unstable_by(|a, b| a.key().cmp(b.key())); self.batch .take() - .merge_func(&self.merge_func) .iter() + .merge_func(&self.merge_func) .for_each(|e| { w.add(e).unwrap(); }); diff --git a/src/source.rs b/src/source.rs index a785fce..75b9a0e 100644 --- a/src/source.rs +++ b/src/source.rs @@ -4,85 +4,67 @@ use crate::iter::{PrefixIter, RangeIter}; use crate::merge::MergeSource; use crate::{Entry, SeekableIter}; -pub trait Source<'a> { - type Iter: SeekableIter; +pub trait Source { + type Iter<'i>: SeekableIter + where + Self: 'i; - fn iter(&'a self) -> Self::Iter; - fn get(&'a self, key: &[u8]) -> RangeIter + fn iter(&self) -> Self::Iter<'_>; + fn get(&self, key: &[u8]) -> RangeIter> where - ::Item: PartialOrd<[u8]>, + for<'a> as Iterator>::Item: PartialOrd<[u8]>, { RangeIter::new(self.iter(), key, key) } - fn get_prefix(&'a self, prefix: &[u8]) -> PrefixIter + fn get_prefix(&self, prefix: &[u8]) -> PrefixIter> where - ::Item: AsRef<[u8]>, + for<'a> as Iterator>::Item: AsRef<[u8]>, { PrefixIter::new(self.iter(), prefix) } - fn get_range(&'a self, start: &[u8], end: &[u8]) -> RangeIter + fn get_range(&self, start: &[u8], end: &[u8]) -> RangeIter> where - ::Item: PartialOrd<[u8]>, + for<'a> as Iterator>::Item: PartialOrd<[u8]>, { RangeIter::new(self.iter(), start, end) } - fn merge_func(self, merge_func: F) -> MergeSource<'a, Self, F> + fn merge_func(self, merge_func: F) -> MergeSource where Self: Sized, - F: Fn(&mut Vec, &Entry), + F: Fn(&mut Vec, &Entry) + 'static, { MergeSource::new(self, merge_func) } - fn dupsort_func(self, dupsort_func: F) -> DupsortSource<'a, Self, F> + fn dupsort_func(self, dupsort_func: F) -> DupsortSource where Self: Sized, F: Fn( - &::Item, - &::Item, - ) -> std::cmp::Ordering, + & as Iterator>::Item, + & as Iterator>::Item, + ) -> std::cmp::Ordering + + 'static, { DupsortSource::new(self, dupsort_func) } - fn filter(self, filter_func: F) -> FilterSource<'a, Self, F> + fn filter(self, filter_func: F) -> FilterSource where Self: Sized, - F: Fn(&::Item, &mut Vec) -> bool, + F: Fn(& as Iterator>::Item, &mut Vec) -> bool + 'static, { FilterSource::new(self, filter_func) } - - fn into_boxed( - self, - ) -> Box< - dyn Source<'a, Iter = Box::Item>>> - + 'a, - > - where - Self: Sized + 'a, - { - Box::new(BoxedSource::<'a>(self, std::marker::PhantomData)) - } } -impl<'a, S: Source<'a> + ?Sized> Source<'a> for Box { - type Iter = Box::Item> + 'a>; - fn iter(&'a self) -> Self::Iter { +impl Source for Box { + type Iter<'i> = Box as Iterator>::Item> + 'i>; + fn iter(&self) -> Self::Iter<'_> { Box::new(self.as_ref().iter()) } } -struct BoxedSource<'a, S: Source<'a>>(S, std::marker::PhantomData<&'a S>); -impl<'a, S: Source<'a>> Source<'a> for BoxedSource<'a, S> { - type Iter = Box::Item> + 'a>; - - fn iter(&'a self) -> Self::Iter { - Box::new(self.0.iter()) - } -} - pub struct VecIter<'a> { index: usize, vec: &'a Vec, @@ -117,9 +99,9 @@ impl SeekableIter for VecIter<'_> { } } -impl<'a> Source<'a> for Vec { - type Iter = VecIter<'a>; - fn iter(&'a self) -> Self::Iter { +impl Source for Vec { + type Iter<'i> = VecIter<'i>; + fn iter(&self) -> Self::Iter<'_> { VecIter { index: 0, vec: self, @@ -162,9 +144,9 @@ pub mod test_source { } } - impl<'a> Source<'a> for TestSource { - type Iter = TestIter<'a>; - fn iter(&'a self) -> Self::Iter { + impl Source for TestSource { + type Iter<'i> = TestIter<'i>; + fn iter(&self) -> Self::Iter<'_> { TestIter { source: self, off: 0, diff --git a/tests/rwtest.rs b/tests/rwtest.rs index e3136b7..efc808b 100644 --- a/tests/rwtest.rs +++ b/tests/rwtest.rs @@ -1,5 +1,6 @@ use mtbl::{Entry, Reader, Source, Writer}; +//#[test] #[test] fn test_write_readback() { let mut store = Vec::::new(); @@ -14,7 +15,7 @@ fn test_write_readback() { } assert!(store.len() > 512); - let r = Reader::new(&store); + let r = Reader::new(store); let ri = r.iter(); assert_eq!(ri.collect::>(), reference); -- 2.50.1