radix_rust/iterators/overlaying_iterator.rs
1use crate::prelude::*;
2use core::cmp::*;
3use core::iter::*;
4
5/// An iterator overlaying a "change on a value" (coming from the [`overlaying`] iterator) over a
6/// "base value" (coming from the [`underlying`] iterator).
7/// The one is matched to another by a `K` part (of the iterated tuple `(K, V)`), which both
8/// iterators are assumed to be ordered by.
9pub struct OverlayingIterator<U, O>
10where
11 U: Iterator,
12 O: Iterator,
13{
14 underlying: Peekable<U>,
15 overlaying: Peekable<O>,
16}
17
18impl<K, V, U, O> OverlayingIterator<U, O>
19where
20 K: Ord,
21 U: Iterator<Item = (K, V)>,
22 O: Iterator<Item = (K, Option<V>)>,
23{
24 /// Creates an overlaying iterator.
25 /// The [`underlying`] iterator provides the "base values".
26 /// The [`overlaying`] one provides the "changes" to those values, represented as `Option<V>`:
27 /// - A [`Some`] is an upsert, i.e. it may override an existing base value, or "insert" a
28 /// completely new one to the iterated results.
29 /// - A [`None`] is a delete, which causes the base value to be omitted in the iterated results.
30 #[allow(clippy::new_ret_no_self)]
31 pub fn new(underlying: U, overlaying: O) -> impl Iterator<Item = (K, V)> {
32 Self {
33 underlying: underlying.peekable(),
34 overlaying: overlaying.peekable(),
35 }
36 }
37}
38
39impl<K, V, U, O> Iterator for OverlayingIterator<U, O>
40where
41 K: Ord,
42 U: Iterator<Item = (K, V)>,
43 O: Iterator<Item = (K, Option<V>)>,
44{
45 type Item = (K, V);
46
47 fn next(&mut self) -> Option<Self::Item> {
48 loop {
49 if let Some(overlaying_key) = self.overlaying.peek_key() {
50 if let Some(underlying_key) = self.underlying.peek_key() {
51 match underlying_key.cmp(overlaying_key) {
52 Ordering::Less => {
53 return self.underlying.next(); // return and move it forward
54 }
55 Ordering::Equal => {
56 self.underlying.next(); // only move it forward
57 }
58 Ordering::Greater => {
59 // leave it as-is
60 }
61 };
62 }
63 let (overlaying_key, overlaying_change) = self.overlaying.next().unwrap();
64 match overlaying_change {
65 Some(value) => return Some((overlaying_key, value)),
66 None => continue, // we may need to skip over an unbounded number of deletes
67 }
68 } else {
69 return self.underlying.next();
70 }
71 }
72 }
73}