]> git.mikk.net Git - mtbl-rs/commitdiff
merger: Remove all internal use of Box<dyn Iter>
authorChris Mikkelson <cmikk@fsi.io>
Fri, 19 Jul 2024 03:28:00 +0000 (22:28 -0500)
committerChris Mikkelson <cmikk@fsi.io>
Fri, 19 Jul 2024 15:08:08 +0000 (10:08 -0500)
Adding Iter implementation for Box<dyn Iter> allows it
to be used as a concrete type in case of a mixed merger.

src/merger.rs

index cf11cf6b6191e6cff63e6d8a39310f241497cde3..a7d671e26f161119f54c1d5c26577f85c728d2ad 100644 (file)
@@ -1,14 +1,12 @@
 use crate::{Entry, Iter, Source};
 use std::cmp::Ordering;
 use std::collections::BinaryHeap;
-use std::marker::PhantomData;
 
-pub struct Merger<'a, S: Source> {
+pub struct Merger<S: Source> {
     sources: Vec<S>,
-    _p: PhantomData<&'a u8>,
 }
 
-impl<'a, S, I> From<I> for Merger<'a, S>
+impl<S, I> From<I> for Merger<S>
 where
     S: Source,
     I: IntoIterator<Item = S>,
@@ -16,42 +14,72 @@ where
     fn from(i: I) -> Self {
         Merger {
             sources: Vec::from_iter(i),
-            _p: PhantomData,
         }
     }
 }
 
-struct MergeEntry<'a> {
+struct MergeEntry<I: Iter> {
     e: Entry,
-    it: Box<dyn Iter + 'a>,
+    it: I,
 }
 
-impl<'a> PartialEq for MergeEntry<'a> {
+impl<I: Iter> PartialEq for MergeEntry<I> {
     fn eq(&self, other: &Self) -> bool {
         self.e.key == other.e.key
     }
 }
-impl<'a> Eq for MergeEntry<'a> {}
+impl<I: Iter> Eq for MergeEntry<I> {}
 
-impl<'a> PartialOrd for MergeEntry<'a> {
+impl<I: Iter> PartialOrd for MergeEntry<I> {
     fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
         Some(other.e.key.cmp(&self.e.key))
     }
 }
 
-impl<'a> Ord for MergeEntry<'a> {
+impl<I: Iter> Ord for MergeEntry<I> {
     fn cmp(&self, other: &Self) -> Ordering {
         other.e.key.cmp(&self.e.key)
     }
 }
 
-struct MergeIter<'a> {
-    heap: BinaryHeap<MergeEntry<'a>>,
-    finished: Vec<Box<dyn Iter + 'a>>,
+struct MergeIter<I: Iter> {
+    heap: BinaryHeap<MergeEntry<I>>,
+    finished: Vec<I>,
     last_key: Vec<u8>,
 }
 
-impl<'a> Iterator for MergeIter<'a> {
+impl<I: Iter> MergeIter<I> {
+    fn add(&mut self, mut it: I) {
+        match it.next() {
+            Some(e) => self.heap.push(MergeEntry { e, it }),
+            None => self.finished.push(it),
+        }
+    }
+}
+
+impl<I> From<I> for MergeIter<I::Item>
+where
+    I: Iterator,
+    I::Item: Iter,
+{
+    fn from(iters: I) -> Self {
+        let mut v: Vec<I::Item> = Vec::new();
+        let h = BinaryHeap::from_iter(iters.filter_map(|mut it| match it.next() {
+            Some(e) => Some(MergeEntry { e, it }),
+            None => {
+                v.push(it);
+                None
+            }
+        }));
+        MergeIter {
+            finished: v,
+            heap: h,
+            last_key: Vec::new(),
+        }
+    }
+}
+
+impl<I: Iter> Iterator for MergeIter<I> {
     type Item = Entry;
 
     fn next(&mut self) -> Option<Self::Item> {
@@ -71,7 +99,7 @@ impl<'a> Iterator for MergeIter<'a> {
     }
 }
 
-impl<'a> Iter for MergeIter<'a> {
+impl<I: Iter> Iter for MergeIter<I> {
     fn seek(&mut self, key: &[u8]) {
         if key > self.last_key.as_slice() {
             loop {
@@ -95,8 +123,8 @@ impl<'a> Iter for MergeIter<'a> {
         }
 
         // backwards seek; reset heap
-        let mut finished: Vec<Box<dyn Iter + 'a>> = Vec::new();
-        let mut heap_entries: Vec<MergeEntry<'a>> = Vec::new();
+        let mut finished: Vec<I> = Vec::new();
+        let mut heap_entries: Vec<MergeEntry<I>> = Vec::new();
         for mut it in self
             .heap
             .drain()
@@ -116,27 +144,21 @@ impl<'a> Iter for MergeIter<'a> {
     }
 }
 
-impl<'a, S: Source> Source for Merger<'a, S> {
+impl<S: Source> Source for Merger<S> {
     fn iter(&self) -> impl Iter {
-        let mut v: Vec<Box<dyn Iter>> = Vec::new();
-        let h = BinaryHeap::from_iter(self.sources.iter().filter_map(|s| {
-            let mut it = s.iter();
-            match it.next() {
-                Some(e) => Some(MergeEntry {
-                    e,
-                    it: Box::new(it),
-                }),
-                None => {
-                    v.push(Box::new(it));
-                    None
-                }
-            }
-        }));
-        MergeIter {
-            finished: v,
-            heap: h,
-            last_key: Vec::new(),
-        }
+        MergeIter::from(self.sources.iter().map(|s| s.iter()))
+    }
+
+    fn get(&self, key: &[u8]) -> impl Iter {
+        MergeIter::from(self.sources.iter().map(|s| s.get(key)))
+    }
+
+    fn get_prefix(&self, prefix: &[u8]) -> impl Iter {
+        MergeIter::from(self.sources.iter().map(|s| s.get_prefix(prefix)))
+    }
+
+    fn get_range(&self, start: &[u8], end: &[u8]) -> impl Iter {
+        MergeIter::from(self.sources.iter().map(|s| s.get_range(start, end)))
     }
 }