]> git.mikk.net Git - mtbl-rs/commitdiff
merger: remove Source paramater from Iter template.
authorChris Mikkelson <cmikk@fsi.io>
Fri, 19 Jul 2024 01:02:20 +0000 (20:02 -0500)
committerChris Mikkelson <cmikk@fsi.io>
Fri, 19 Jul 2024 01:02:20 +0000 (20:02 -0500)
src/merger.rs

index e0e34e11b5e53605343c32e1ed92cd07e29724e8..cf11cf6b6191e6cff63e6d8a39310f241497cde3 100644 (file)
@@ -45,13 +45,13 @@ impl<'a> Ord for MergeEntry<'a> {
     }
 }
 
-struct MergeIter<'a, S: Source> {
-    sources: &'a [S],
+struct MergeIter<'a> {
     heap: BinaryHeap<MergeEntry<'a>>,
+    finished: Vec<Box<dyn Iter + 'a>>,
     last_key: Vec<u8>,
 }
 
-impl<'a, S: Source> Iterator for MergeIter<'a, S> {
+impl<'a> Iterator for MergeIter<'a> {
     type Item = Entry;
 
     fn next(&mut self) -> Option<Self::Item> {
@@ -71,7 +71,7 @@ impl<'a, S: Source> Iterator for MergeIter<'a, S> {
     }
 }
 
-impl<'a, S: Source> Iter for MergeIter<'a, S> {
+impl<'a> Iter for MergeIter<'a> {
     fn seek(&mut self, key: &[u8]) {
         if key > self.last_key.as_slice() {
             loop {
@@ -93,14 +93,24 @@ impl<'a, S: Source> Iter for MergeIter<'a, S> {
                 self.heap.pop();
             }
         }
-        self.heap = BinaryHeap::from_iter(self.sources.iter().filter_map(|s| {
-            let mut it = s.iter();
+
+        // backwards seek; reset heap
+        let mut finished: Vec<Box<dyn Iter + 'a>> = Vec::new();
+        let mut heap_entries: Vec<MergeEntry<'a>> = Vec::new();
+        for mut it in self
+            .heap
+            .drain()
+            .map(|me| me.it)
+            .chain(self.finished.drain(..))
+        {
             it.seek(key);
-            Some(MergeEntry {
-                e: it.next()?,
-                it: Box::new(it),
-            })
-        }));
+            match it.next() {
+                Some(e) => heap_entries.push(MergeEntry { e, it }),
+                None => finished.push(it),
+            }
+        }
+        self.heap = BinaryHeap::from_iter(heap_entries);
+        self.finished = finished;
         self.last_key.clear();
         self.last_key.extend_from_slice(key);
     }
@@ -108,16 +118,24 @@ impl<'a, S: Source> Iter for MergeIter<'a, S> {
 
 impl<'a, S: Source> Source for Merger<'a, 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(),
-            sources: self.sources.as_slice(),
-            heap: BinaryHeap::from_iter(self.sources.as_slice().iter().filter_map(|s| {
-                let mut it = s.iter();
-                Some(MergeEntry {
-                    e: it.next()?,
-                    it: Box::new(it),
-                })
-            })),
         }
     }
 }