1 //! Some iterator that produces tuples
2 
3 use std::iter::Cycle;
4 use std::iter::Fuse;
5 use std::iter::FusedIterator;
6 
7 use crate::size_hint;
8 
9 // `HomogeneousTuple` is a public facade for `TupleCollect`, allowing
10 // tuple-related methods to be used by clients in generic contexts, while
11 // hiding the implementation details of `TupleCollect`.
12 // See https://github.com/rust-itertools/itertools/issues/387
13 
14 /// Implemented for homogeneous tuples of size up to 12.
15 pub trait HomogeneousTuple: TupleCollect {}
16 
17 impl<T: TupleCollect> HomogeneousTuple for T {}
18 
19 /// An iterator over a incomplete tuple.
20 ///
21 /// See [`.tuples()`](crate::Itertools::tuples) and
22 /// [`Tuples::into_buffer()`].
23 #[derive(Clone, Debug)]
24 pub struct TupleBuffer<T>
25 where
26     T: HomogeneousTuple,
27 {
28     cur: usize,
29     buf: T::Buffer,
30 }
31 
32 impl<T> TupleBuffer<T>
33 where
34     T: HomogeneousTuple,
35 {
new(buf: T::Buffer) -> Self36     fn new(buf: T::Buffer) -> Self {
37         Self { cur: 0, buf }
38     }
39 }
40 
41 impl<T> Iterator for TupleBuffer<T>
42 where
43     T: HomogeneousTuple,
44 {
45     type Item = T::Item;
46 
next(&mut self) -> Option<Self::Item>47     fn next(&mut self) -> Option<Self::Item> {
48         let s = self.buf.as_mut();
49         if let Some(ref mut item) = s.get_mut(self.cur) {
50             self.cur += 1;
51             item.take()
52         } else {
53             None
54         }
55     }
56 
size_hint(&self) -> (usize, Option<usize>)57     fn size_hint(&self) -> (usize, Option<usize>) {
58         let buffer = &self.buf.as_ref()[self.cur..];
59         let len = if buffer.is_empty() {
60             0
61         } else {
62             buffer
63                 .iter()
64                 .position(|x| x.is_none())
65                 .unwrap_or(buffer.len())
66         };
67         (len, Some(len))
68     }
69 }
70 
71 impl<T> ExactSizeIterator for TupleBuffer<T> where T: HomogeneousTuple {}
72 
73 /// An iterator that groups the items in tuples of a specific size.
74 ///
75 /// See [`.tuples()`](crate::Itertools::tuples) for more information.
76 #[derive(Clone, Debug)]
77 #[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
78 pub struct Tuples<I, T>
79 where
80     I: Iterator<Item = T::Item>,
81     T: HomogeneousTuple,
82 {
83     iter: Fuse<I>,
84     buf: T::Buffer,
85 }
86 
87 /// Create a new tuples iterator.
tuples<I, T>(iter: I) -> Tuples<I, T> where I: Iterator<Item = T::Item>, T: HomogeneousTuple,88 pub fn tuples<I, T>(iter: I) -> Tuples<I, T>
89 where
90     I: Iterator<Item = T::Item>,
91     T: HomogeneousTuple,
92 {
93     Tuples {
94         iter: iter.fuse(),
95         buf: Default::default(),
96     }
97 }
98 
99 impl<I, T> Iterator for Tuples<I, T>
100 where
101     I: Iterator<Item = T::Item>,
102     T: HomogeneousTuple,
103 {
104     type Item = T;
105 
next(&mut self) -> Option<Self::Item>106     fn next(&mut self) -> Option<Self::Item> {
107         T::collect_from_iter(&mut self.iter, &mut self.buf)
108     }
109 
size_hint(&self) -> (usize, Option<usize>)110     fn size_hint(&self) -> (usize, Option<usize>) {
111         // The number of elts we've drawn from the underlying iterator, but have
112         // not yet produced as a tuple.
113         let buffered = T::buffer_len(&self.buf);
114         // To that, we must add the size estimates of the underlying iterator.
115         let (unbuffered_lo, unbuffered_hi) = self.iter.size_hint();
116         // The total low estimate is the sum of the already-buffered elements,
117         // plus the low estimate of remaining unbuffered elements, divided by
118         // the tuple size.
119         let total_lo = add_then_div(unbuffered_lo, buffered, T::num_items()).unwrap_or(usize::MAX);
120         // And likewise for the total high estimate, but using the high estimate
121         // of the remaining unbuffered elements.
122         let total_hi = unbuffered_hi.and_then(|hi| add_then_div(hi, buffered, T::num_items()));
123         (total_lo, total_hi)
124     }
125 }
126 
127 /// `(n + a) / d` avoiding overflow when possible, returns `None` if it overflows.
add_then_div(n: usize, a: usize, d: usize) -> Option<usize>128 fn add_then_div(n: usize, a: usize, d: usize) -> Option<usize> {
129     debug_assert_ne!(d, 0);
130     (n / d).checked_add(a / d)?.checked_add((n % d + a % d) / d)
131 }
132 
133 impl<I, T> ExactSizeIterator for Tuples<I, T>
134 where
135     I: ExactSizeIterator<Item = T::Item>,
136     T: HomogeneousTuple,
137 {
138 }
139 
140 impl<I, T> Tuples<I, T>
141 where
142     I: Iterator<Item = T::Item>,
143     T: HomogeneousTuple,
144 {
145     /// Return a buffer with the produced items that was not enough to be grouped in a tuple.
146     ///
147     /// ```
148     /// use itertools::Itertools;
149     ///
150     /// let mut iter = (0..5).tuples();
151     /// assert_eq!(Some((0, 1, 2)), iter.next());
152     /// assert_eq!(None, iter.next());
153     /// itertools::assert_equal(vec![3, 4], iter.into_buffer());
154     /// ```
into_buffer(self) -> TupleBuffer<T>155     pub fn into_buffer(self) -> TupleBuffer<T> {
156         TupleBuffer::new(self.buf)
157     }
158 }
159 
160 /// An iterator over all contiguous windows that produces tuples of a specific size.
161 ///
162 /// See [`.tuple_windows()`](crate::Itertools::tuple_windows) for more
163 /// information.
164 #[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
165 #[derive(Clone, Debug)]
166 pub struct TupleWindows<I, T>
167 where
168     I: Iterator<Item = T::Item>,
169     T: HomogeneousTuple,
170 {
171     iter: I,
172     last: Option<T>,
173 }
174 
175 /// Create a new tuple windows iterator.
tuple_windows<I, T>(iter: I) -> TupleWindows<I, T> where I: Iterator<Item = T::Item>, T: HomogeneousTuple, T::Item: Clone,176 pub fn tuple_windows<I, T>(iter: I) -> TupleWindows<I, T>
177 where
178     I: Iterator<Item = T::Item>,
179     T: HomogeneousTuple,
180     T::Item: Clone,
181 {
182     TupleWindows { last: None, iter }
183 }
184 
185 impl<I, T> Iterator for TupleWindows<I, T>
186 where
187     I: Iterator<Item = T::Item>,
188     T: HomogeneousTuple + Clone,
189     T::Item: Clone,
190 {
191     type Item = T;
192 
next(&mut self) -> Option<Self::Item>193     fn next(&mut self) -> Option<Self::Item> {
194         if T::num_items() == 1 {
195             return T::collect_from_iter_no_buf(&mut self.iter);
196         }
197         if let Some(new) = self.iter.next() {
198             if let Some(ref mut last) = self.last {
199                 last.left_shift_push(new);
200                 Some(last.clone())
201             } else {
202                 use std::iter::once;
203                 let iter = once(new).chain(&mut self.iter);
204                 self.last = T::collect_from_iter_no_buf(iter);
205                 self.last.clone()
206             }
207         } else {
208             None
209         }
210     }
211 
size_hint(&self) -> (usize, Option<usize>)212     fn size_hint(&self) -> (usize, Option<usize>) {
213         let mut sh = self.iter.size_hint();
214         // Adjust the size hint at the beginning
215         // OR when `num_items == 1` (but it does not change the size hint).
216         if self.last.is_none() {
217             sh = size_hint::sub_scalar(sh, T::num_items() - 1);
218         }
219         sh
220     }
221 }
222 
223 impl<I, T> ExactSizeIterator for TupleWindows<I, T>
224 where
225     I: ExactSizeIterator<Item = T::Item>,
226     T: HomogeneousTuple + Clone,
227     T::Item: Clone,
228 {
229 }
230 
231 impl<I, T> FusedIterator for TupleWindows<I, T>
232 where
233     I: FusedIterator<Item = T::Item>,
234     T: HomogeneousTuple + Clone,
235     T::Item: Clone,
236 {
237 }
238 
239 /// An iterator over all windows, wrapping back to the first elements when the
240 /// window would otherwise exceed the length of the iterator, producing tuples
241 /// of a specific size.
242 ///
243 /// See [`.circular_tuple_windows()`](crate::Itertools::circular_tuple_windows) for more
244 /// information.
245 #[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
246 #[derive(Debug, Clone)]
247 pub struct CircularTupleWindows<I, T>
248 where
249     I: Iterator<Item = T::Item> + Clone,
250     T: TupleCollect + Clone,
251 {
252     iter: TupleWindows<Cycle<I>, T>,
253     len: usize,
254 }
255 
circular_tuple_windows<I, T>(iter: I) -> CircularTupleWindows<I, T> where I: Iterator<Item = T::Item> + Clone + ExactSizeIterator, T: TupleCollect + Clone, T::Item: Clone,256 pub fn circular_tuple_windows<I, T>(iter: I) -> CircularTupleWindows<I, T>
257 where
258     I: Iterator<Item = T::Item> + Clone + ExactSizeIterator,
259     T: TupleCollect + Clone,
260     T::Item: Clone,
261 {
262     let len = iter.len();
263     let iter = tuple_windows(iter.cycle());
264 
265     CircularTupleWindows { iter, len }
266 }
267 
268 impl<I, T> Iterator for CircularTupleWindows<I, T>
269 where
270     I: Iterator<Item = T::Item> + Clone,
271     T: TupleCollect + Clone,
272     T::Item: Clone,
273 {
274     type Item = T;
275 
next(&mut self) -> Option<Self::Item>276     fn next(&mut self) -> Option<Self::Item> {
277         if self.len != 0 {
278             self.len -= 1;
279             self.iter.next()
280         } else {
281             None
282         }
283     }
284 
size_hint(&self) -> (usize, Option<usize>)285     fn size_hint(&self) -> (usize, Option<usize>) {
286         (self.len, Some(self.len))
287     }
288 }
289 
290 impl<I, T> ExactSizeIterator for CircularTupleWindows<I, T>
291 where
292     I: Iterator<Item = T::Item> + Clone,
293     T: TupleCollect + Clone,
294     T::Item: Clone,
295 {
296 }
297 
298 impl<I, T> FusedIterator for CircularTupleWindows<I, T>
299 where
300     I: Iterator<Item = T::Item> + Clone,
301     T: TupleCollect + Clone,
302     T::Item: Clone,
303 {
304 }
305 
306 pub trait TupleCollect: Sized {
307     type Item;
308     type Buffer: Default + AsRef<[Option<Self::Item>]> + AsMut<[Option<Self::Item>]>;
309 
buffer_len(buf: &Self::Buffer) -> usize310     fn buffer_len(buf: &Self::Buffer) -> usize {
311         let s = buf.as_ref();
312         s.iter().position(Option::is_none).unwrap_or(s.len())
313     }
314 
collect_from_iter<I>(iter: I, buf: &mut Self::Buffer) -> Option<Self> where I: IntoIterator<Item = Self::Item>315     fn collect_from_iter<I>(iter: I, buf: &mut Self::Buffer) -> Option<Self>
316     where
317         I: IntoIterator<Item = Self::Item>;
318 
collect_from_iter_no_buf<I>(iter: I) -> Option<Self> where I: IntoIterator<Item = Self::Item>319     fn collect_from_iter_no_buf<I>(iter: I) -> Option<Self>
320     where
321         I: IntoIterator<Item = Self::Item>;
322 
num_items() -> usize323     fn num_items() -> usize;
324 
left_shift_push(&mut self, item: Self::Item)325     fn left_shift_push(&mut self, item: Self::Item);
326 }
327 
328 macro_rules! rev_for_each_ident{
329     ($m:ident, ) => {};
330     ($m:ident, $i0:ident, $($i:ident,)*) => {
331         rev_for_each_ident!($m, $($i,)*);
332         $m!($i0);
333     };
334 }
335 
336 macro_rules! impl_tuple_collect {
337     ($dummy:ident,) => {}; // stop
338     ($dummy:ident, $($Y:ident,)*) => (
339         impl_tuple_collect!($($Y,)*);
340         impl<A> TupleCollect for ($(ignore_ident!($Y, A),)*) {
341             type Item = A;
342             type Buffer = [Option<A>; count_ident!($($Y)*) - 1];
343 
344             #[allow(unused_assignments, unused_mut)]
345             fn collect_from_iter<I>(iter: I, buf: &mut Self::Buffer) -> Option<Self>
346                 where I: IntoIterator<Item = A>
347             {
348                 let mut iter = iter.into_iter();
349                 $(
350                     let mut $Y = None;
351                 )*
352 
353                 loop {
354                     $(
355                         $Y = iter.next();
356                         if $Y.is_none() {
357                             break
358                         }
359                     )*
360                     return Some(($($Y.unwrap()),*,))
361                 }
362 
363                 let mut i = 0;
364                 let mut s = buf.as_mut();
365                 $(
366                     if i < s.len() {
367                         s[i] = $Y;
368                         i += 1;
369                     }
370                 )*
371                 return None;
372             }
373 
374             fn collect_from_iter_no_buf<I>(iter: I) -> Option<Self>
375                 where I: IntoIterator<Item = A>
376             {
377                 let mut iter = iter.into_iter();
378 
379                 Some(($(
380                     { let $Y = iter.next()?; $Y },
381                 )*))
382             }
383 
384             fn num_items() -> usize {
385                 count_ident!($($Y)*)
386             }
387 
388             fn left_shift_push(&mut self, mut item: A) {
389                 use std::mem::replace;
390 
391                 let &mut ($(ref mut $Y),*,) = self;
392                 macro_rules! replace_item{($i:ident) => {
393                     item = replace($i, item);
394                 }}
395                 rev_for_each_ident!(replace_item, $($Y,)*);
396                 drop(item);
397             }
398         }
399     )
400 }
401 impl_tuple_collect!(dummy, a, b, c, d, e, f, g, h, i, j, k, l,);
402