]>
Commit | Line | Data |
---|---|---|
532ac7d7 XL |
1 | use std::iter::Fuse; |
2 | use super::size_hint; | |
3 | ||
4 | #[derive(Clone)] | |
5 | /// An iterator adaptor to insert a particular value | |
6 | /// between each element of the adapted iterator. | |
7 | /// | |
8 | /// Iterator element type is `I::Item` | |
9 | /// | |
10 | /// This iterator is *fused*. | |
11 | /// | |
12 | /// See [`.intersperse()`](../trait.Itertools.html#method.intersperse) for more information. | |
13 | #[must_use = "iterator adaptors are lazy and do nothing unless consumed"] | |
14 | #[derive(Debug)] | |
15 | pub struct Intersperse<I> | |
16 | where I: Iterator | |
17 | { | |
18 | element: I::Item, | |
19 | iter: Fuse<I>, | |
20 | peek: Option<I::Item>, | |
21 | } | |
22 | ||
23 | /// Create a new Intersperse iterator | |
24 | pub fn intersperse<I>(iter: I, elt: I::Item) -> Intersperse<I> | |
25 | where I: Iterator | |
26 | { | |
27 | let mut iter = iter.fuse(); | |
28 | Intersperse { | |
29 | peek: iter.next(), | |
30 | iter: iter, | |
31 | element: elt, | |
32 | } | |
33 | } | |
34 | ||
35 | impl<I> Iterator for Intersperse<I> | |
36 | where I: Iterator, | |
37 | I::Item: Clone | |
38 | { | |
39 | type Item = I::Item; | |
40 | #[inline] | |
41 | fn next(&mut self) -> Option<I::Item> { | |
42 | if self.peek.is_some() { | |
43 | self.peek.take() | |
44 | } else { | |
45 | self.peek = self.iter.next(); | |
46 | if self.peek.is_some() { | |
47 | Some(self.element.clone()) | |
48 | } else { | |
49 | None | |
50 | } | |
51 | } | |
52 | } | |
53 | ||
54 | fn size_hint(&self) -> (usize, Option<usize>) { | |
55 | // 2 * SH + { 1 or 0 } | |
56 | let has_peek = self.peek.is_some() as usize; | |
57 | let sh = self.iter.size_hint(); | |
58 | size_hint::add_scalar(size_hint::add(sh, sh), has_peek) | |
59 | } | |
60 | } |