fluent_iterable/ops/
combining.rs1use std::collections::HashMap;
4use std::hash::Hash;
5
6pub struct Combine<I, J, K, KL, KR>
12where
13 I: Iterator,
14 J: Iterator,
15{
16 pub(crate) left: I,
17 pub(crate) key_left: KL,
18 pub(crate) right: J,
19 pub(crate) key_right: KR,
20 pub(crate) indexed: bool,
21 pub(crate) idx: HashMap<K, Vec<J::Item>>,
22 pub(crate) pending: Option<(I::Item, K, usize)>,
25}
26
27impl<I, J, K, KL, KR> Iterator for Combine<I, J, K, KL, KR>
28where
29 I: Iterator,
30 J: Iterator,
31 K: Eq + Hash + Clone,
32 KL: FnMut(&I::Item) -> K,
33 KR: FnMut(&J::Item) -> K,
34 I::Item: Clone,
35 J::Item: Clone,
36{
37 type Item = (I::Item, J::Item);
38
39 fn next(&mut self) -> Option<Self::Item> {
40 if !self.indexed {
41 for r in self.right.by_ref() {
42 self.idx.entry((self.key_right)(&r)).or_default().push(r);
43 }
44 self.indexed = true;
45 }
46 loop {
47 if self.pending.is_none() {
48 loop {
50 let l = self.left.next()?;
51 let k = (self.key_left)(&l);
52 if self.idx.get(&k).is_some_and(|b| !b.is_empty()) {
53 self.pending = Some((l, k, 0));
54 break;
55 }
56 }
57 }
58 let (left, key, pos) = self.pending.take().expect("pending was just set");
59 let bucket = &self.idx[&key];
60 if pos < bucket.len() {
61 let pair = (left.clone(), bucket[pos].clone());
62 self.pending = Some((left, key, pos + 1));
63 return Some(pair);
64 }
65 }
67 }
68}