]> git.mikk.net Git - mtbl-rs/commitdiff
Make Iter, Source generic on item type
authorChris Mikkelson <cmikk@fsi.io>
Sat, 19 Oct 2024 12:22:33 +0000 (14:22 +0200)
committerChris Mikkelson <cmikk@fsi.io>
Sat, 19 Oct 2024 12:22:33 +0000 (14:22 +0200)
This is to allow mapping items to higher level types while preserving seek
functionality.

src/dupsort_func.rs
src/entry.rs
src/filter.rs
src/iter.rs
src/merge_func.rs
src/merger.rs
src/reader/mod.rs
src/sorter.rs
src/source.rs

index 589e8edb1e38bd98198fa3654eddcf8b5ff396ef..c029c292c2d16ed19568f200d961df379fa221eb 100644 (file)
@@ -1,10 +1,11 @@
-use crate::{Entry, Iter, Source};
+use crate::entry::HasPrefix;
+use crate::{Iter, Source};
 use std::cmp::Ordering;
 
 pub struct DupsortFunc<S, F>
 where
     S: Source,
-    F: Fn(&Entry, &Entry) -> Ordering,
+    F: Fn(&S::Item, &S::Item) -> Ordering,
 {
     source: S,
     dupsort_func: F,
@@ -13,7 +14,7 @@ where
 impl<S, F> DupsortFunc<S, F>
 where
     S: Source,
-    F: Fn(&Entry, &Entry) -> Ordering,
+    F: Fn(&S::Item, &S::Item) -> Ordering,
 {
     pub fn new(source: S, dupsort_func: F) -> Self {
         Self {
@@ -26,20 +27,31 @@ where
 impl<S, F> Source for DupsortFunc<S, F>
 where
     S: Source,
-    F: Fn(&Entry, &Entry) -> Ordering,
+    S::Item: PartialEq,
+    F: Fn(&S::Item, &S::Item) -> Ordering,
 {
-    fn iter(&self) -> impl Iter {
+    type Item = S::Item;
+    fn iter(&self) -> impl Iter<Item = Self::Item> {
         self.source.iter().dupsort_func(&self.dupsort_func)
     }
-    fn get(&self, key: &[u8]) -> impl Iter {
+    fn get(&self, key: &[u8]) -> impl Iter<Item = Self::Item>
+    where
+        S::Item: PartialOrd<[u8]>,
+    {
         self.source.get(key).dupsort_func(&self.dupsort_func)
     }
-    fn get_prefix(&self, prefix: &[u8]) -> impl Iter {
+    fn get_prefix(&self, prefix: &[u8]) -> impl Iter<Item = Self::Item>
+    where
+        S::Item: HasPrefix,
+    {
         self.source
             .get_prefix(prefix)
             .dupsort_func(&self.dupsort_func)
     }
-    fn get_range(&self, start: &[u8], end: &[u8]) -> impl Iter {
+    fn get_range(&self, start: &[u8], end: &[u8]) -> impl Iter<Item = Self::Item>
+    where
+        S::Item: PartialOrd<[u8]>,
+    {
         self.source
             .get_range(start, end)
             .dupsort_func(&self.dupsort_func)
@@ -49,17 +61,19 @@ where
 #[derive(Debug)]
 pub struct DupsortFuncIter<'a, I, F>
 where
-    F: Fn(&Entry, &Entry) -> Ordering,
+    I: Iter,
+    F: Fn(&I::Item, &I::Item) -> Ordering,
 {
-    run: Vec<Entry>,
-    next: Option<Entry>,
+    run: Vec<I::Item>,
+    next: Option<I::Item>,
     iter: I,
     dupsort_func: &'a F,
 }
 
 impl<'a, I, F> DupsortFuncIter<'a, I, F>
 where
-    F: Fn(&Entry, &Entry) -> Ordering,
+    I: Iter,
+    F: Fn(&I::Item, &I::Item) -> Ordering,
 {
     pub fn new(iter: I, dupsort_func: &'a F) -> Self {
         Self {
@@ -73,10 +87,11 @@ where
 
 impl<'a, I, F> Iterator for DupsortFuncIter<'a, I, F>
 where
-    I: Iterator<Item = Entry>,
-    F: Fn(&Entry, &Entry) -> Ordering,
+    I: Iter,
+    I::Item: PartialEq,
+    F: Fn(&I::Item, &I::Item) -> Ordering,
 {
-    type Item = Entry;
+    type Item = I::Item;
 
     fn next(&mut self) -> Option<Self::Item> {
         self.run.pop().or_else(|| {
@@ -85,7 +100,7 @@ where
 
             //   println!("2: {:?} / {:?}", self.next, self.run);
             while let Some(e) = self.iter.next() {
-                if e.key() == self.run[0].key() {
+                if e == self.run[0] {
                     self.run.push(e);
                     continue;
                 }
@@ -103,7 +118,8 @@ where
 impl<'a, I, F> Iter for DupsortFuncIter<'a, I, F>
 where
     I: Iter,
-    F: Fn(&Entry, &Entry) -> Ordering,
+    I::Item: PartialEq,
+    F: Fn(&I::Item, &I::Item) -> Ordering,
 {
     fn seek(&mut self, key: &[u8]) {
         self.run.clear();
@@ -115,6 +131,7 @@ where
 #[test]
 fn test_dupsort() {
     use crate::source::test_source::TestSource;
+    use crate::Entry;
 
     let ts = TestSource(
         (1u8..10)
index 491a294f5612759bbc520bee82197cab0047be0c..9fe4fc67629208c40c6a080de25854726a1f90be 100644 (file)
@@ -1,6 +1,7 @@
+use std::cmp::Ordering;
 use std::sync::Arc;
 
-#[derive(Debug, Clone, PartialEq, Eq)]
+#[derive(Debug, Clone, Eq)]
 pub struct Entry {
     key: Arc<Vec<u8>>,
     value: Arc<Vec<u8>>,
@@ -44,3 +45,31 @@ impl Entry {
         Arc::make_mut(&mut self.value)
     }
 }
+
+impl PartialOrd<[u8]> for Entry {
+    fn partial_cmp(&self, other: &[u8]) -> Option<Ordering> {
+        Some(self.key().cmp(other))
+    }
+}
+
+impl PartialEq<[u8]> for Entry {
+    fn eq(&self, other: &[u8]) -> bool {
+        self.key() == other
+    }
+}
+
+impl PartialEq<Entry> for Entry {
+    fn eq(&self, other: &Entry) -> bool {
+        self.key() == other.key()
+    }
+}
+
+pub trait HasPrefix {
+    fn has_prefix(&self, prefix: &[u8]) -> bool;
+}
+
+impl HasPrefix for Entry {
+    fn has_prefix(&self, prefix: &[u8]) -> bool {
+        self.key().starts_with(prefix)
+    }
+}
index ddcdac2d47306729239015a9b86b51e8db591ae5..eb31ee174840383c2c9a2ea4490cc293b4cbbeab 100644 (file)
@@ -1,4 +1,4 @@
-use crate::{Entry, Iter, Source};
+use crate::{entry::HasPrefix, Iter, Source};
 
 pub struct FilterIter<'a, I, F> {
     iter: I,
@@ -7,7 +7,8 @@ pub struct FilterIter<'a, I, F> {
 
 impl<'a, I, F> FilterIter<'a, I, F>
 where
-    F: Fn(&Entry, &mut dyn Iter) -> bool,
+    I: Iter,
+    F: Fn(&I::Item, &mut dyn Iter<Item = I::Item>) -> bool,
 {
     pub fn new(iter: I, filter_func: &'a F) -> Self {
         Self { iter, filter_func }
@@ -16,10 +17,10 @@ where
 
 impl<'a, I, F> Iterator for FilterIter<'a, I, F>
 where
-    F: Fn(&Entry, &mut dyn Iter) -> bool,
     I: Iter,
+    F: Fn(&I::Item, &mut dyn Iter<Item = I::Item>) -> bool,
 {
-    type Item = Entry;
+    type Item = I::Item;
 
     fn next(&mut self) -> Option<Self::Item> {
         while let Some(e) = self.iter.next() {
@@ -34,7 +35,7 @@ where
 impl<'a, I, F> Iter for FilterIter<'a, I, F>
 where
     I: Iter,
-    F: Fn(&Entry, &mut dyn Iter) -> bool,
+    F: Fn(&I::Item, &mut dyn Iter<Item = I::Item>) -> bool,
 {
     fn seek(&mut self, key: &[u8]) {
         self.iter.seek(key);
@@ -49,7 +50,7 @@ pub struct FilterSource<S, F> {
 impl<S, F> FilterSource<S, F>
 where
     S: Source,
-    F: Fn(&Entry, &mut dyn Iter) -> bool,
+    F: Fn(&S::Item, &mut dyn Iter<Item = S::Item>) -> bool,
 {
     pub fn new(source: S, filter_func: F) -> Self {
         Self {
@@ -62,23 +63,33 @@ where
 impl<S, F> Source for FilterSource<S, F>
 where
     S: Source,
-    F: Fn(&Entry, &mut dyn Iter) -> bool,
+    F: Fn(&S::Item, &mut dyn Iter<Item = S::Item>) -> bool,
 {
-    fn iter(&self) -> impl Iter {
+    type Item = S::Item;
+    fn iter(&self) -> impl Iter<Item = Self::Item> {
         self.source.iter().filter_func(&self.filter_func)
     }
 
-    fn get(&self, key: &[u8]) -> impl Iter {
+    fn get(&self, key: &[u8]) -> impl Iter<Item = Self::Item>
+    where
+        Self::Item: PartialOrd<[u8]>,
+    {
         self.source.get(key).filter_func(&self.filter_func)
     }
 
-    fn get_prefix(&self, prefix: &[u8]) -> impl Iter {
+    fn get_prefix(&self, prefix: &[u8]) -> impl Iter<Item = Self::Item>
+    where
+        Self::Item: HasPrefix,
+    {
         self.source
             .get_prefix(prefix)
             .filter_func(&self.filter_func)
     }
 
-    fn get_range(&self, start: &[u8], end: &[u8]) -> impl Iter {
+    fn get_range(&self, start: &[u8], end: &[u8]) -> impl Iter<Item = Self::Item>
+    where
+        Self::Item: PartialOrd<[u8]>,
+    {
         self.source
             .get_range(start, end)
             .filter_func(&self.filter_func)
@@ -88,6 +99,7 @@ where
 #[test]
 fn test_filter() {
     use crate::source::test_source::TestSource;
+    use crate::Entry;
 
     let ts = TestSource(
         (0u8..10)
index eeaececeb712117b80d26ba98ba5f24de89563bb..d47fa064755b7a58c8ecd93362d51c4ea3537fa6 100644 (file)
@@ -1,11 +1,12 @@
 use crate::dupsort_func::DupsortFuncIter;
+use crate::entry::HasPrefix;
 use crate::filter::FilterIter;
 use crate::merge_func::MergeFuncIter;
 use crate::Entry;
 use std::cmp::Ordering;
 use std::iter::Iterator;
 
-pub trait Iter: Iterator<Item = Entry> {
+pub trait Iter: Iterator {
     fn seek(&mut self, key: &[u8]);
 
     fn merge_func<'a, F>(self, merge_func: &'a F) -> MergeFuncIter<'a, Self, F>
@@ -18,7 +19,7 @@ pub trait Iter: Iterator<Item = Entry> {
 
     fn dupsort_func<'a, F>(self, dupsort_func: &'a F) -> DupsortFuncIter<'a, Self, F>
     where
-        F: Fn(&Entry, &Entry) -> Ordering,
+        F: Fn(&Self::Item, &Self::Item) -> Ordering,
         Self: Sized,
     {
         DupsortFuncIter::new(self, dupsort_func)
@@ -26,27 +27,23 @@ pub trait Iter: Iterator<Item = Entry> {
 
     fn filter_func<'a, F>(self, filter_func: &'a F) -> FilterIter<'a, Self, F>
     where
-        F: Fn(&Entry, &mut dyn Iter) -> bool,
+        F: Fn(&Self::Item, &mut dyn Iter<Item = Self::Item>) -> bool,
         Self: Sized,
     {
         FilterIter::new(self, filter_func)
     }
 }
 
-pub type BoxedIter<'a> = Box<dyn Iter + 'a>;
-
-impl<'a> Iter for BoxedIter<'a> {
-    fn seek(&mut self, key: &[u8]) {
-        self.as_mut().seek(key);
-    }
-}
-
-pub struct PrefixIter<I: Iter> {
+pub struct PrefixIter<I> {
     iter: I,
     prefix: Vec<u8>,
 }
 
-impl<I: Iter> PrefixIter<I> {
+impl<E, I> PrefixIter<I>
+where
+    I: Iter<Item = E>,
+    E: HasPrefix,
+{
     pub fn new(mut iter: I, prefix: impl AsRef<[u8]>) -> Self {
         iter.seek(prefix.as_ref());
         Self {
@@ -56,11 +53,15 @@ impl<I: Iter> PrefixIter<I> {
     }
 }
 
-impl<I: Iter> Iterator for PrefixIter<I> {
-    type Item = Entry;
+impl<E, I> Iterator for PrefixIter<I>
+where
+    I: Iter<Item = E>,
+    E: HasPrefix,
+{
+    type Item = E;
     fn next(&mut self) -> Option<Self::Item> {
         let item = self.iter.next()?;
-        if item.key().starts_with(self.prefix.as_slice()) {
+        if item.has_prefix(self.prefix.as_slice()) {
             Some(item)
         } else {
             None
@@ -68,13 +69,17 @@ impl<I: Iter> Iterator for PrefixIter<I> {
     }
 }
 
-impl<I: Iter> Iter for PrefixIter<I> {
+impl<E, I> Iter for PrefixIter<I>
+where
+    I: Iter<Item = E>,
+    E: HasPrefix,
+{
     fn seek(&mut self, key: &[u8]) {
         self.iter.seek(key);
     }
 }
 
-pub struct RangeIter<I: Iter> {
+pub struct RangeIter<I> {
     iter: I,
     start: Vec<u8>,
     end: Vec<u8>,
@@ -91,11 +96,15 @@ impl<I: Iter> RangeIter<I> {
     }
 }
 
-impl<I: Iter> Iterator for RangeIter<I> {
-    type Item = Entry;
+impl<E, I> Iterator for RangeIter<I>
+where
+    I: Iter<Item = E>,
+    E: PartialOrd<[u8]>,
+{
+    type Item = E;
     fn next(&mut self) -> Option<Self::Item> {
         let item = self.iter.next()?;
-        if item.key() <= self.end.as_slice() {
+        if item <= *self.end.as_slice() {
             Some(item)
         } else {
             None
@@ -103,7 +112,11 @@ impl<I: Iter> Iterator for RangeIter<I> {
     }
 }
 
-impl<I: Iter> Iter for RangeIter<I> {
+impl<E, I> Iter for RangeIter<I>
+where
+    I: Iter<Item = E>,
+    E: PartialOrd<[u8]>,
+{
     fn seek(&mut self, key: &[u8]) {
         if key <= self.start.as_slice() {
             self.iter.seek(self.start.as_slice());
index b8d847f7c536f2a2555434a306be7ee00e32ccb8..c0800ea0d0c8047698551d8e8ca73bb8f4f66157 100644 (file)
@@ -17,19 +17,20 @@ where
 
 impl<S, F> Source for MergeFunc<S, F>
 where
-    S: Source,
+    S: Source<Item = Entry>,
     F: Fn(&mut Vec<u8>, &Entry),
 {
-    fn iter(&self) -> impl Iter {
+    type Item = Entry;
+    fn iter(&self) -> impl Iter<Item = Self::Item> {
         self.source.iter().merge_func(&self.merge_func)
     }
-    fn get(&self, key: &[u8]) -> impl Iter {
+    fn get(&self, key: &[u8]) -> impl Iter<Item = Self::Item> {
         self.source.get(key).merge_func(&self.merge_func)
     }
-    fn get_prefix(&self, prefix: &[u8]) -> impl Iter {
+    fn get_prefix(&self, prefix: &[u8]) -> impl Iter<Item = Self::Item> {
         self.source.get_prefix(prefix).merge_func(&self.merge_func)
     }
-    fn get_range(&self, start: &[u8], end: &[u8]) -> impl Iter {
+    fn get_range(&self, start: &[u8], end: &[u8]) -> impl Iter<Item = Self::Item> {
         self.source
             .get_range(start, end)
             .merge_func(&self.merge_func)
@@ -77,7 +78,7 @@ where
 
 impl<'a, I, F> Iter for MergeFuncIter<'a, I, F>
 where
-    I: Iter,
+    I: Iter<Item = Entry>,
     F: Fn(&mut Vec<u8>, &Entry),
 {
     fn seek(&mut self, key: &[u8]) {
index 558a672c68cdd8fd47e405c06763e2a0997af0d5..8d54303bc886418f65ec851125404c46a52930bd 100644 (file)
@@ -2,13 +2,12 @@ use crate::{Entry, Iter, Source};
 use std::cmp::Ordering;
 use std::collections::BinaryHeap;
 
-pub struct Merger<S: Source> {
+pub struct Merger<S> {
     sources: Vec<S>,
 }
 
 impl<S, I> From<I> for Merger<S>
 where
-    S: Source,
     I: IntoIterator<Item = S>,
 {
     fn from(i: I) -> Self {
@@ -51,7 +50,7 @@ pub struct MergeIter<I: Iter> {
 impl<I> From<I> for MergeIter<I::Item>
 where
     I: Iterator,
-    I::Item: Iter,
+    I::Item: Iter<Item = Entry>,
 {
     fn from(iters: I) -> Self {
         let mut v: Vec<I::Item> = Vec::new();
@@ -70,7 +69,7 @@ where
     }
 }
 
-impl<I: Iter> Iterator for MergeIter<I> {
+impl<I: Iter<Item = Entry>> Iterator for MergeIter<I> {
     type Item = Entry;
 
     fn next(&mut self) -> Option<Self::Item> {
@@ -90,7 +89,7 @@ impl<I: Iter> Iterator for MergeIter<I> {
     }
 }
 
-impl<I: Iter> Iter for MergeIter<I> {
+impl<I: Iter<Item = Entry>> Iter for MergeIter<I> {
     fn seek(&mut self, key: &[u8]) {
         if key > self.last_key.as_slice() {
             loop {
@@ -135,20 +134,21 @@ impl<I: Iter> Iter for MergeIter<I> {
     }
 }
 
-impl<S: Source> Source for Merger<S> {
-    fn iter(&self) -> impl Iter {
+impl<S: Source<Item = Entry>> Source for Merger<S> {
+    type Item = Entry;
+    fn iter(&self) -> impl Iter<Item = Self::Item> {
         MergeIter::from(self.sources.iter().map(|s| s.iter()))
     }
 
-    fn get(&self, key: &[u8]) -> impl Iter {
+    fn get(&self, key: &[u8]) -> impl Iter<Item = Self::Item> {
         MergeIter::from(self.sources.iter().map(|s| s.get(key)))
     }
 
-    fn get_prefix(&self, prefix: &[u8]) -> impl Iter {
+    fn get_prefix(&self, prefix: &[u8]) -> impl Iter<Item = Self::Item> {
         MergeIter::from(self.sources.iter().map(|s| s.get_prefix(prefix)))
     }
 
-    fn get_range(&self, start: &[u8], end: &[u8]) -> impl Iter {
+    fn get_range(&self, start: &[u8], end: &[u8]) -> impl Iter<Item = Self::Item> {
         MergeIter::from(self.sources.iter().map(|s| s.get_range(start, end)))
     }
 }
index c79d3f4a390ff87c1f7a42abee4d32690c97d821..8a1568c9bb017620be1fb079dd7518a2a7ba94d7 100644 (file)
@@ -177,7 +177,9 @@ impl<D: AsRef<[u8]>> Iter for ReaderIter<D> {
 }
 
 impl<D: AsRef<[u8]>> Source for Reader<D> {
-    fn iter(&self) -> impl Iter {
+    type Item = Entry;
+
+    fn iter(&self) -> impl Iter<Item = Self::Item> {
         ReaderIter {
             reader: self.clone(),
             next_offset: 0,
index 232bbfcfe04ec91bbafa24c398e3f412ec237512..7685530ee9c90f4dc87ed6bb42ada14d7468e692 100644 (file)
@@ -35,7 +35,7 @@ where
         self.batch_size += esize;
     }
 
-    pub fn source(mut self) -> impl Source {
+    pub fn source(mut self) -> impl Source<Item = Entry> {
         if self.batch.get_mut().len() > 0 {
             self.write_chunk();
         }
index 6d590b5f117bd69021bf6e05597252072eca2d89..55e03171a81eeedc8e943d6ced2fde3932423561 100644 (file)
@@ -1,18 +1,30 @@
 use crate::dupsort_func::DupsortFunc;
+use crate::entry::HasPrefix;
 use crate::filter::FilterSource;
 use crate::iter::{PrefixIter, RangeIter};
 use crate::merge_func::MergeFunc;
 use crate::{Entry, Iter};
 
 pub trait Source {
-    fn iter(&self) -> impl Iter;
-    fn get(&self, key: &[u8]) -> impl Iter {
+    type Item;
+
+    fn iter(&self) -> impl Iter<Item = Self::Item>;
+    fn get(&self, key: &[u8]) -> impl Iter<Item = Self::Item>
+    where
+        Self::Item: PartialOrd<[u8]>,
+    {
         RangeIter::new(self.iter(), key, key)
     }
-    fn get_prefix(&self, prefix: &[u8]) -> impl Iter {
+    fn get_prefix(&self, prefix: &[u8]) -> impl Iter<Item = Self::Item>
+    where
+        Self::Item: HasPrefix,
+    {
         PrefixIter::new(self.iter(), prefix)
     }
-    fn get_range(&self, start: &[u8], end: &[u8]) -> impl Iter {
+    fn get_range(&self, start: &[u8], end: &[u8]) -> impl Iter<Item = Self::Item>
+    where
+        Self::Item: PartialOrd<[u8]>,
+    {
         RangeIter::new(self.iter(), start, end)
     }
 
@@ -27,7 +39,7 @@ pub trait Source {
     fn dupsort_func<F>(self, dupsort_func: F) -> DupsortFunc<Self, F>
     where
         Self: Sized,
-        F: Fn(&Entry, &Entry) -> std::cmp::Ordering,
+        F: Fn(&Self::Item, &Self::Item) -> std::cmp::Ordering,
     {
         DupsortFunc::new(self, dupsort_func)
     }
@@ -35,7 +47,7 @@ pub trait Source {
     fn filter<F>(self, filter_func: F) -> FilterSource<Self, F>
     where
         Self: Sized,
-        F: Fn(&Entry, &mut dyn Iter) -> bool,
+        F: Fn(&Self::Item, &mut dyn Iter<Item = Self::Item>) -> bool,
     {
         FilterSource::new(self, filter_func)
     }
@@ -76,7 +88,8 @@ impl<'a> Iter for VecIter<'a> {
 }
 
 impl Source for Vec<Entry> {
-    fn iter(&self) -> impl Iter {
+    type Item = Entry;
+    fn iter(&self) -> impl Iter<Item = Self::Item> {
         VecIter {
             index: 0,
             vec: self,
@@ -121,7 +134,8 @@ pub mod test_source {
     }
 
     impl Source for TestSource {
-        fn iter(&self) -> impl Iter {
+        type Item = Entry;
+        fn iter(&self) -> impl Iter<Item = Self::Item> {
             TestIter {
                 source: self,
                 off: 0,