1use crate::{group::Group, groups::Groups};
2use std::iter::Fuse;
3
4pub struct FlatZip<I, K, G>
5where
6 I: Iterator<Item = (K, G)>,
7 K: Clone,
8 G: IntoIterator,
9{
10 groups: Fuse<Groups<I>>,
12 front: Option<Group<K, G::IntoIter>>,
13 back: Option<Group<K, G::IntoIter>>,
14}
15
16impl<I, K, G> FlatZip<I, K, G>
17where
18 I: Iterator<Item = (K, G)>,
19 K: Clone,
20 G: IntoIterator,
21{
22 pub fn new<T: IntoIterator<IntoIter = I>>(iter: T) -> Self {
23 Self {
24 groups: Groups::new(iter).fuse(),
25 front: None,
26 back: None,
27 }
28 }
29
30 fn fold_groups<B, F>(self, mut acc: B, mut f: F) -> B
31 where
32 F: FnMut(B, Group<K, G::IntoIter>) -> B,
33 {
34 if let Some(group) = self.front {
35 acc = f(acc, group);
36 }
37
38 acc = self.groups.fold(acc, &mut f);
39
40 if let Some(group) = self.back {
41 acc = f(acc, group);
42 }
43
44 acc
45 }
46
47 fn rfold_groups<B, F>(self, mut acc: B, mut f: F) -> B
48 where
49 F: FnMut(B, Group<K, G::IntoIter>) -> B,
50 I: DoubleEndedIterator,
51 G::IntoIter: DoubleEndedIterator,
52 {
53 if let Some(group) = self.back {
54 acc = f(acc, group);
55 }
56
57 acc = self.groups.rfold(acc, &mut f);
58
59 if let Some(group) = self.front {
60 acc = f(acc, group);
61 }
62
63 acc
64 }
65}
66
67impl<I, K, G, V> Iterator for FlatZip<I, K, G>
68where
69 I: Iterator<Item = (K, G)>,
70 K: Clone,
71 G: IntoIterator<Item = V>,
72{
73 type Item = (K, V);
74
75 fn next(&mut self) -> Option<Self::Item> {
76 loop {
77 if let Some(group) = &mut self.front {
78 if let Some(item) = group.next() {
79 break Some(item);
80 }
81 self.front = None;
82 }
83
84 if let Some(group) = self.groups.next() {
85 self.front = Some(group);
86 continue;
87 }
88
89 if let Some(group) = &mut self.back {
90 if let Some(item) = group.next() {
91 break Some(item);
92 }
93 self.back = None;
94 }
95
96 break None;
97 }
98 }
99
100 fn fold<B, F>(self, init: B, mut f: F) -> B
101 where
102 F: FnMut(B, Self::Item) -> B,
103 {
104 self.fold_groups(init, |acc, group| group.fold(acc, &mut f))
105 }
106
107 fn count(self) -> usize {
108 self.fold_groups(0, |n, group| n + group.count())
109 }
110
111 fn last(self) -> Option<Self::Item> {
112 self.fold_groups(None, |acc, group| group.last().or(acc))
113 }
114}
115
116impl<I, K, G, V> DoubleEndedIterator for FlatZip<I, K, G>
117where
118 I: DoubleEndedIterator<Item = (K, G)>,
119 K: Clone,
120 G: IntoIterator<Item = V>,
121 G::IntoIter: DoubleEndedIterator,
122{
123 fn next_back(&mut self) -> Option<Self::Item> {
124 loop {
125 if let Some(group) = &mut self.back {
126 if let Some(item) = group.next_back() {
127 break Some(item);
128 }
129 self.back = None;
130 }
131
132 if let Some(group) = self.groups.next_back() {
133 self.back = Some(group);
134 continue;
135 }
136
137 if let Some(group) = &mut self.front {
138 if let Some(item) = group.next_back() {
139 break Some(item);
140 }
141 self.front = None;
142 }
143
144 break None;
145 }
146 }
147
148 fn rfold<B, F>(self, init: B, mut f: F) -> B
149 where
150 F: FnMut(B, Self::Item) -> B,
151 {
152 self.rfold_groups(init, |acc, group| group.rfold(acc, &mut f))
153 }
154}