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