]> git.lizzy.rs Git - rust.git/blob - library/core/src/iter/adapters/intersperse.rs
Auto merge of #79827 - tmiasko:size-align, r=kennytm
[rust.git] / library / core / src / iter / adapters / intersperse.rs
1 use super::Peekable;
2
3 /// An iterator adapter that places a separator between all elements.
4 #[unstable(feature = "iter_intersperse", reason = "recently added", issue = "79524")]
5 #[derive(Debug, Clone)]
6 pub struct Intersperse<I: Iterator>
7 where
8     I::Item: Clone,
9 {
10     separator: I::Item,
11     iter: Peekable<I>,
12     needs_sep: bool,
13 }
14
15 impl<I: Iterator> Intersperse<I>
16 where
17     I::Item: Clone,
18 {
19     pub(in crate::iter) fn new(iter: I, separator: I::Item) -> Self {
20         Self { iter: iter.peekable(), separator, needs_sep: false }
21     }
22 }
23
24 #[unstable(feature = "iter_intersperse", reason = "recently added", issue = "79524")]
25 impl<I> Iterator for Intersperse<I>
26 where
27     I: Iterator,
28     I::Item: Clone,
29 {
30     type Item = I::Item;
31
32     #[inline]
33     fn next(&mut self) -> Option<I::Item> {
34         if self.needs_sep && self.iter.peek().is_some() {
35             self.needs_sep = false;
36             Some(self.separator.clone())
37         } else {
38             self.needs_sep = true;
39             self.iter.next()
40         }
41     }
42
43     fn fold<B, F>(mut self, init: B, mut f: F) -> B
44     where
45         Self: Sized,
46         F: FnMut(B, Self::Item) -> B,
47     {
48         let mut accum = init;
49
50         // Use `peek()` first to avoid calling `next()` on an empty iterator.
51         if !self.needs_sep || self.iter.peek().is_some() {
52             if let Some(x) = self.iter.next() {
53                 accum = f(accum, x);
54             }
55         }
56
57         let element = &self.separator;
58
59         self.iter.fold(accum, |mut accum, x| {
60             accum = f(accum, element.clone());
61             accum = f(accum, x);
62             accum
63         })
64     }
65
66     fn size_hint(&self) -> (usize, Option<usize>) {
67         let (lo, hi) = self.iter.size_hint();
68         let next_is_elem = !self.needs_sep;
69         let lo = lo.saturating_sub(next_is_elem as usize).saturating_add(lo);
70         let hi = match hi {
71             Some(hi) => hi.saturating_sub(next_is_elem as usize).checked_add(hi),
72             None => None,
73         };
74         (lo, hi)
75     }
76 }