1 #![cfg(feature = "use_alloc")]
2
3 use crate::size_hint;
4 use crate::Itertools;
5
6 use alloc::vec::Vec;
7
8 #[derive(Clone)]
9 /// An iterator adaptor that iterates over the cartesian product of
10 /// multiple iterators of type `I`.
11 ///
12 /// An iterator element type is `Vec<I>`.
13 ///
14 /// See [`.multi_cartesian_product()`](crate::Itertools::multi_cartesian_product)
15 /// for more information.
16 #[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
17 pub struct MultiProduct<I>(Vec<MultiProductIter<I>>)
18 where I: Iterator + Clone,
19 I::Item: Clone;
20
21 impl<I> std::fmt::Debug for MultiProduct<I>
22 where
23 I: Iterator + Clone + std::fmt::Debug,
24 I::Item: Clone + std::fmt::Debug,
25 {
26 debug_fmt_fields!(CoalesceBy, 0);
27 }
28
29 /// Create a new cartesian product iterator over an arbitrary number
30 /// of iterators of the same type.
31 ///
32 /// Iterator element is of type `Vec<H::Item::Item>`.
multi_cartesian_product<H>(iters: H) -> MultiProduct<<H::Item as IntoIterator>::IntoIter> where H: Iterator, H::Item: IntoIterator, <H::Item as IntoIterator>::IntoIter: Clone, <H::Item as IntoIterator>::Item: Clone33 pub fn multi_cartesian_product<H>(iters: H) -> MultiProduct<<H::Item as IntoIterator>::IntoIter>
34 where H: Iterator,
35 H::Item: IntoIterator,
36 <H::Item as IntoIterator>::IntoIter: Clone,
37 <H::Item as IntoIterator>::Item: Clone
38 {
39 MultiProduct(iters.map(|i| MultiProductIter::new(i.into_iter())).collect())
40 }
41
42 #[derive(Clone, Debug)]
43 /// Holds the state of a single iterator within a `MultiProduct`.
44 struct MultiProductIter<I>
45 where I: Iterator + Clone,
46 I::Item: Clone
47 {
48 cur: Option<I::Item>,
49 iter: I,
50 iter_orig: I,
51 }
52
53 /// Holds the current state during an iteration of a `MultiProduct`.
54 #[derive(Debug)]
55 enum MultiProductIterState {
56 StartOfIter,
57 MidIter { on_first_iter: bool },
58 }
59
60 impl<I> MultiProduct<I>
61 where I: Iterator + Clone,
62 I::Item: Clone
63 {
64 /// Iterates the rightmost iterator, then recursively iterates iterators
65 /// to the left if necessary.
66 ///
67 /// Returns true if the iteration succeeded, else false.
iterate_last( multi_iters: &mut [MultiProductIter<I>], mut state: MultiProductIterState ) -> bool68 fn iterate_last(
69 multi_iters: &mut [MultiProductIter<I>],
70 mut state: MultiProductIterState
71 ) -> bool {
72 use self::MultiProductIterState::*;
73
74 if let Some((last, rest)) = multi_iters.split_last_mut() {
75 let on_first_iter = match state {
76 StartOfIter => {
77 let on_first_iter = !last.in_progress();
78 state = MidIter { on_first_iter };
79 on_first_iter
80 },
81 MidIter { on_first_iter } => on_first_iter
82 };
83
84 if !on_first_iter {
85 last.iterate();
86 }
87
88 if last.in_progress() {
89 true
90 } else if MultiProduct::iterate_last(rest, state) {
91 last.reset();
92 last.iterate();
93 // If iterator is None twice consecutively, then iterator is
94 // empty; whole product is empty.
95 last.in_progress()
96 } else {
97 false
98 }
99 } else {
100 // Reached end of iterator list. On initialisation, return true.
101 // At end of iteration (final iterator finishes), finish.
102 match state {
103 StartOfIter => false,
104 MidIter { on_first_iter } => on_first_iter
105 }
106 }
107 }
108
109 /// Returns the unwrapped value of the next iteration.
curr_iterator(&self) -> Vec<I::Item>110 fn curr_iterator(&self) -> Vec<I::Item> {
111 self.0.iter().map(|multi_iter| {
112 multi_iter.cur.clone().unwrap()
113 }).collect()
114 }
115
116 /// Returns true if iteration has started and has not yet finished; false
117 /// otherwise.
in_progress(&self) -> bool118 fn in_progress(&self) -> bool {
119 if let Some(last) = self.0.last() {
120 last.in_progress()
121 } else {
122 false
123 }
124 }
125 }
126
127 impl<I> MultiProductIter<I>
128 where I: Iterator + Clone,
129 I::Item: Clone
130 {
new(iter: I) -> Self131 fn new(iter: I) -> Self {
132 MultiProductIter {
133 cur: None,
134 iter: iter.clone(),
135 iter_orig: iter
136 }
137 }
138
139 /// Iterate the managed iterator.
iterate(&mut self)140 fn iterate(&mut self) {
141 self.cur = self.iter.next();
142 }
143
144 /// Reset the managed iterator.
reset(&mut self)145 fn reset(&mut self) {
146 self.iter = self.iter_orig.clone();
147 }
148
149 /// Returns true if the current iterator has been started and has not yet
150 /// finished; false otherwise.
in_progress(&self) -> bool151 fn in_progress(&self) -> bool {
152 self.cur.is_some()
153 }
154 }
155
156 impl<I> Iterator for MultiProduct<I>
157 where I: Iterator + Clone,
158 I::Item: Clone
159 {
160 type Item = Vec<I::Item>;
161
next(&mut self) -> Option<Self::Item>162 fn next(&mut self) -> Option<Self::Item> {
163 if MultiProduct::iterate_last(
164 &mut self.0,
165 MultiProductIterState::StartOfIter
166 ) {
167 Some(self.curr_iterator())
168 } else {
169 None
170 }
171 }
172
count(self) -> usize173 fn count(self) -> usize {
174 if self.0.is_empty() {
175 return 0;
176 }
177
178 if !self.in_progress() {
179 return self.0.into_iter().fold(1, |acc, multi_iter| {
180 acc * multi_iter.iter.count()
181 });
182 }
183
184 self.0.into_iter().fold(
185 0,
186 |acc, MultiProductIter { iter, iter_orig, cur: _ }| {
187 let total_count = iter_orig.count();
188 let cur_count = iter.count();
189 acc * total_count + cur_count
190 }
191 )
192 }
193
size_hint(&self) -> (usize, Option<usize>)194 fn size_hint(&self) -> (usize, Option<usize>) {
195 // Not ExactSizeIterator because size may be larger than usize
196 if self.0.is_empty() {
197 return (0, Some(0));
198 }
199
200 if !self.in_progress() {
201 return self.0.iter().fold((1, Some(1)), |acc, multi_iter| {
202 size_hint::mul(acc, multi_iter.iter.size_hint())
203 });
204 }
205
206 self.0.iter().fold(
207 (0, Some(0)),
208 |acc, &MultiProductIter { ref iter, ref iter_orig, cur: _ }| {
209 let cur_size = iter.size_hint();
210 let total_size = iter_orig.size_hint();
211 size_hint::add(size_hint::mul(acc, total_size), cur_size)
212 }
213 )
214 }
215
last(self) -> Option<Self::Item>216 fn last(self) -> Option<Self::Item> {
217 let iter_count = self.0.len();
218
219 let lasts: Self::Item = self.0.into_iter()
220 .map(|multi_iter| multi_iter.iter.last())
221 .while_some()
222 .collect();
223
224 if lasts.len() == iter_count {
225 Some(lasts)
226 } else {
227 None
228 }
229 }
230 }
231