]> git.mikk.net Git - mtbl-rs/commitdiff
Reduce lifetime proliferation.
authorChris Mikkelson <chris@mikk.net>
Tue, 8 Apr 2025 05:14:43 +0000 (00:14 -0500)
committerChris Mikkelson <chris@mikk.net>
Tue, 8 Apr 2025 05:14:43 +0000 (00:14 -0500)
Makes Source trait non-dyn-compatible again, but an improvement in
reducing lifetimes and function generics.

src/dupsort.rs
src/filter.rs
src/iter.rs
src/merge.rs
src/merger.rs
src/reader/mod.rs
src/sorter.rs
src/source.rs
tests/rwtest.rs

index f0a53ef1658c5cf0641fb3f4dda4f1720b7f3055..04b449fa87093e8a4146fddc5d858c48ada971bf 100644 (file)
@@ -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<S>
 where
-    S: Source<'a>,
-    F: Fn(&<S::Iter as Iterator>::Item, &<S::Iter as Iterator>::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<dyn Fn(&<S::Iter<'_> as Iterator>::Item, &<S::Iter<'_> as Iterator>::Item) -> Ordering>,
 }
 
-impl<'a, S, F> DupsortSource<'a, S, F>
+impl<S> DupsortSource<S>
 where
-    S: Source<'a>,
-    F: Fn(&<S::Iter as Iterator>::Item, &<S::Iter as Iterator>::Item) -> Ordering,
+    S: Source,
 {
-    pub fn new(source: S, dupsort_func: F) -> Self {
+    pub fn new<F>(source: S, dupsort_func: F) -> Self
+    where
+        F: Fn(&<S::Iter<'_> as Iterator>::Item, &<S::Iter<'_> 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<S> Source for DupsortSource<S>
 where
-    S: Source<'a>,
-    <S::Iter as Iterator>::Item: PartialEq,
-    F: Fn(&<S::Iter as Iterator>::Item, &<S::Iter as Iterator>::Item) -> Ordering + 'a,
+    S: Source + 'static,
+    for<'i> <S::Iter<'i> as Iterator>::Item: PartialEq,
 {
-    type Iter = DupsortIter<S::Iter, &'a F>;
+    type Iter<'i> = DupsortIter<
+        S::Iter<'i>,
+        &'i dyn Fn(&<S::Iter<'_> as Iterator>::Item, &<S::Iter<'_> as Iterator>::Item) -> Ordering,
+    >;
 
-    fn iter(&'a self) -> Self::Iter {
+    fn iter(&self) -> Self::Iter<'_> {
         self.source.iter().dupsort_func(&self.dupsort_func)
     }
 }
index f0ccd5eae94dc47813bc18f55719c5d8d47b7975..b420c218a36bed5c1a33a5df6243e23147b916a5 100644 (file)
@@ -1,5 +1,4 @@
 use crate::{SeekableIter, Source};
-use std::marker::PhantomData;
 
 pub struct FilterIter<I, F> {
     iter: I,
@@ -53,33 +52,37 @@ where
     }
 }
 
-pub struct FilterSource<'a, S, F> {
+pub struct FilterSource<S>
+where
+    S: Source,
+{
     source: S,
-    filter_func: F,
-    phantom: PhantomData<&'a char>,
+    #[allow(clippy::type_complexity)]
+    filter_func: Box<dyn Fn(&<S::Iter<'_> as Iterator>::Item, &mut Vec<u8>) -> bool>,
 }
 
-impl<'a, S, F> FilterSource<'a, S, F>
+impl<S> FilterSource<S>
 where
-    S: Source<'a>,
-    F: Fn(&<S::Iter as Iterator>::Item, &mut Vec<u8>) -> bool,
+    S: Source,
 {
-    pub fn new(source: S, filter_func: F) -> Self {
+    pub fn new<F>(source: S, filter_func: F) -> Self
+    where
+        F: Fn(&<S::Iter<'_> as Iterator>::Item, &mut Vec<u8>) -> 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<S> Source for FilterSource<S>
 where
-    S: Source<'a>,
-    F: Fn(&<S::Iter as Iterator>::Item, &mut Vec<u8>) -> bool + 'a,
+    S: Source + 'static,
 {
-    type Iter = FilterIter<S::Iter, &'a F>;
-    fn iter(&'a self) -> Self::Iter {
+    type Iter<'i> =
+        FilterIter<S::Iter<'i>, &'i dyn Fn(&<S::Iter<'_> as Iterator>::Item, &mut Vec<u8>) -> bool>;
+    fn iter(&self) -> Self::Iter<'_> {
         self.source.iter().filter_func(&self.filter_func)
     }
 }
index 080e9c2c2689edee9a2958e1028156b1c5355f58..3d9599d1dd2e7aef6f894c063ce0cd726ea48c19 100644 (file)
@@ -10,7 +10,7 @@ pub trait SeekableIter: Iterator {
 
     fn merge_func<F>(self, merge_func: F) -> MergeIter<Self, F>
     where
-        F: FnMut(&mut Vec<u8>, &Entry),
+        F: Fn(&mut Vec<u8>, &Entry),
         Self: Sized,
     {
         MergeIter::new(self, merge_func)
index 567c2d99160315b50af7090397a6c96a3a8bd8b2..e6f79ddc94642060e26e62fc691587000a5ff93f 100644 (file)
@@ -1,39 +1,37 @@
 use crate::{Entry, SeekableIter, Source};
-use std::marker::PhantomData;
 
-pub struct MergeSource<'a, S: Source<'a>, F: Fn(&mut Vec<u8>, &Entry)> {
+pub struct MergeSource<S: Source> {
     source: S,
-    merge_func: F,
-    phantom: PhantomData<&'a char>,
+    #[allow(clippy::type_complexity)]
+    merge_func: Box<dyn Fn(&mut Vec<u8>, &Entry)>,
 }
 
-impl<'a, S, F> MergeSource<'a, S, F>
+impl<S> MergeSource<S>
 where
-    S: Source<'a>,
-    F: Fn(&mut Vec<u8>, &Entry),
+    S: Source,
 {
-    pub fn new(source: S, merge_func: F) -> Self {
+    pub fn new<F>(source: S, merge_func: F) -> Self
+    where
+        F: Fn(&mut Vec<u8>, &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<S> Source for MergeSource<S>
 where
-    S: Source<'a>,
-    S::Iter: Iterator<Item = Entry>,
-    F: Fn(&mut Vec<u8>, &Entry) + 'a,
+    S: Source + 'static,
+    for<'a> S::Iter<'a>: Iterator<Item = Entry>,
 {
-    type Iter = MergeIter<S::Iter, &'a F>;
-    fn iter(&'a self) -> Self::Iter {
+    type Iter<'i> = MergeIter<S::Iter<'i>, &'i dyn Fn(&mut Vec<u8>, &Entry)>;
+    fn iter(&self) -> Self::Iter<'_> {
         self.source.iter().merge_func(&self.merge_func)
     }
 }
 
-pub struct MergeIter<I, F: FnMut(&mut Vec<u8>, &Entry)> {
+pub struct MergeIter<I, F: Fn(&mut Vec<u8>, &Entry)> {
     prev: Option<Entry>,
     iter: I,
     merge_func: F,
@@ -41,7 +39,7 @@ pub struct MergeIter<I, F: FnMut(&mut Vec<u8>, &Entry)> {
 
 impl<I, F> MergeIter<I, F>
 where
-    F: FnMut(&mut Vec<u8>, &Entry),
+    F: Fn(&mut Vec<u8>, &Entry),
 {
     pub fn new(iter: I, merge_func: F) -> Self {
         Self {
@@ -55,7 +53,7 @@ where
 impl<I, F> Iterator for MergeIter<I, F>
 where
     I: Iterator<Item = Entry>,
-    F: FnMut(&mut Vec<u8>, &Entry),
+    F: Fn(&mut Vec<u8>, &Entry),
 {
     type Item = Entry;
     fn next(&mut self) -> Option<Self::Item> {
@@ -75,7 +73,7 @@ where
 impl<I, F> SeekableIter for MergeIter<I, F>
 where
     I: SeekableIter<Item = Entry>,
-    F: FnMut(&mut Vec<u8>, &Entry),
+    F: Fn(&mut Vec<u8>, &Entry),
 {
     fn seek(&mut self, key: &[u8]) {
         self.prev.take();
index 7fb405fb26ec28d3e3782b3d4ffd352215201280..6d611f6ebc7ecf349c1e70d669ab3caf18054cf9 100644 (file)
@@ -134,13 +134,13 @@ impl<I: SeekableIter<Item = Entry>> SeekableIter for MergeIter<I> {
     }
 }
 
-impl<'a, S> Source<'a> for Merger<S>
+impl<S> Source for Merger<S>
 where
-    S: Source<'a>,
-    S::Iter: Iterator<Item = Entry>,
+    S: Source + 'static,
+    for<'i> S::Iter<'i>: Iterator<Item = Entry> + 'i,
 {
-    type Iter = MergeIter<S::Iter>;
-    fn iter(&'a self) -> Self::Iter {
+    type Iter<'i> = MergeIter<S::Iter<'i>>;
+    fn iter(&self) -> Self::Iter<'_> {
         MergeIter::from(self.sources.iter().map(|s| s.iter()))
     }
 }
index 0b5ad43059c658fb1005f6b7465f28b0d96ecbf5..d956d5169d4e4138aa14a873f4b344e4d248aed8 100644 (file)
@@ -176,10 +176,13 @@ impl<D: AsRef<[u8]>> SeekableIter for ReaderIter<D> {
     }
 }
 
-impl<'a, D: AsRef<[u8]>> Source<'a> for Reader<D> {
-    type Iter = ReaderIter<D>;
+impl<D: AsRef<[u8]>> Source for Reader<D> {
+    type Iter<'i>
+        = ReaderIter<D>
+    where
+        D: 'i;
 
-    fn iter(&'a self) -> Self::Iter {
+    fn iter(&self) -> Self::Iter<'_> {
         ReaderIter {
             reader: self.clone(),
             next_offset: 0,
index fe4073f563623e6cb2db4cf7298843d06e82b948..a582cc0d304a1d344768457414b2390dfb5e8987 100644 (file)
@@ -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<F: Fn(&mut Vec<u8>, &Entry)> {
 
 impl<F> Sorter<F>
 where
-    F: Fn(&mut Vec<u8>, &Entry),
+    F: Fn(&mut Vec<u8>, &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<Reader<Mmap>>, F> {
+    pub fn source(mut self) -> MergeSource<Merger<Reader<Mmap>>> {
         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();
             });
index a785fceb27a28c8964e05b265710c1a9055c317b..75b9a0e9f2a650fd8d49be1890e95b476f1523d7 100644 (file)
@@ -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<Self::Iter>
+    fn iter(&self) -> Self::Iter<'_>;
+    fn get(&self, key: &[u8]) -> RangeIter<Self::Iter<'_>>
     where
-        <Self::Iter as Iterator>::Item: PartialOrd<[u8]>,
+        for<'a> <Self::Iter<'a> as Iterator>::Item: PartialOrd<[u8]>,
     {
         RangeIter::new(self.iter(), key, key)
     }
-    fn get_prefix(&'a self, prefix: &[u8]) -> PrefixIter<Self::Iter>
+    fn get_prefix(&self, prefix: &[u8]) -> PrefixIter<Self::Iter<'_>>
     where
-        <Self::Iter as Iterator>::Item: AsRef<[u8]>,
+        for<'a> <Self::Iter<'a> as Iterator>::Item: AsRef<[u8]>,
     {
         PrefixIter::new(self.iter(), prefix)
     }
-    fn get_range(&'a self, start: &[u8], end: &[u8]) -> RangeIter<Self::Iter>
+    fn get_range(&self, start: &[u8], end: &[u8]) -> RangeIter<Self::Iter<'_>>
     where
-        <Self::Iter as Iterator>::Item: PartialOrd<[u8]>,
+        for<'a> <Self::Iter<'a> as Iterator>::Item: PartialOrd<[u8]>,
     {
         RangeIter::new(self.iter(), start, end)
     }
 
-    fn merge_func<F>(self, merge_func: F) -> MergeSource<'a, Self, F>
+    fn merge_func<F>(self, merge_func: F) -> MergeSource<Self>
     where
         Self: Sized,
-        F: Fn(&mut Vec<u8>, &Entry),
+        F: Fn(&mut Vec<u8>, &Entry) + 'static,
     {
         MergeSource::new(self, merge_func)
     }
 
-    fn dupsort_func<F>(self, dupsort_func: F) -> DupsortSource<'a, Self, F>
+    fn dupsort_func<F>(self, dupsort_func: F) -> DupsortSource<Self>
     where
         Self: Sized,
         F: Fn(
-            &<Self::Iter as Iterator>::Item,
-            &<Self::Iter as Iterator>::Item,
-        ) -> std::cmp::Ordering,
+                &<Self::Iter<'_> as Iterator>::Item,
+                &<Self::Iter<'_> as Iterator>::Item,
+            ) -> std::cmp::Ordering
+            + 'static,
     {
         DupsortSource::new(self, dupsort_func)
     }
 
-    fn filter<F>(self, filter_func: F) -> FilterSource<'a, Self, F>
+    fn filter<F>(self, filter_func: F) -> FilterSource<Self>
     where
         Self: Sized,
-        F: Fn(&<Self::Iter as Iterator>::Item, &mut Vec<u8>) -> bool,
+        F: Fn(&<Self::Iter<'_> as Iterator>::Item, &mut Vec<u8>) -> bool + 'static,
     {
         FilterSource::new(self, filter_func)
     }
-
-    fn into_boxed(
-        self,
-    ) -> Box<
-        dyn Source<'a, Iter = Box<dyn 'a + SeekableIter<Item = <Self::Iter as Iterator>::Item>>>
-            + 'a,
-    >
-    where
-        Self: Sized + 'a,
-    {
-        Box::new(BoxedSource::<'a>(self, std::marker::PhantomData))
-    }
 }
 
-impl<'a, S: Source<'a> + ?Sized> Source<'a> for Box<S> {
-    type Iter = Box<dyn SeekableIter<Item = <S::Iter as Iterator>::Item> + 'a>;
-    fn iter(&'a self) -> Self::Iter {
+impl<S: Source + ?Sized + 'static> Source for Box<S> {
+    type Iter<'i> = Box<dyn SeekableIter<Item = <S::Iter<'i> 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<dyn SeekableIter<Item = <S::Iter as Iterator>::Item> + 'a>;
-
-    fn iter(&'a self) -> Self::Iter {
-        Box::new(self.0.iter())
-    }
-}
-
 pub struct VecIter<'a> {
     index: usize,
     vec: &'a Vec<Entry>,
@@ -117,9 +99,9 @@ impl SeekableIter for VecIter<'_> {
     }
 }
 
-impl<'a> Source<'a> for Vec<Entry> {
-    type Iter = VecIter<'a>;
-    fn iter(&'a self) -> Self::Iter {
+impl Source for Vec<Entry> {
+    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,
index e3136b71f0f0f539ba266ecb40369d015a19cb79..efc808b366f6b9ecddff894b365b63fd607643d5 100644 (file)
@@ -1,5 +1,6 @@
 use mtbl::{Entry, Reader, Source, Writer};
 
+//#[test]
 #[test]
 fn test_write_readback() {
     let mut store = Vec::<u8>::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::<Vec<_>>(), reference);