1 use crate::fmt;
2 use crate::iter::{adapters::SourceIter, FusedIterator, InPlaceIterable};
3 use crate::ops::Try;
4 
5 /// An iterator that rejects elements while `predicate` returns `true`.
6 ///
7 /// This `struct` is created by the [`skip_while`] method on [`Iterator`]. See its
8 /// documentation for more.
9 ///
10 /// [`skip_while`]: Iterator::skip_while
11 /// [`Iterator`]: trait.Iterator.html
12 #[must_use = "iterators are lazy and do nothing unless consumed"]
13 #[stable(feature = "rust1", since = "1.0.0")]
14 #[derive(Clone)]
15 pub struct SkipWhile<I, P> {
16     iter: I,
17     flag: bool,
18     predicate: P,
19 }
20 
21 impl<I, P> SkipWhile<I, P> {
new(iter: I, predicate: P) -> SkipWhile<I, P>22     pub(in crate::iter) fn new(iter: I, predicate: P) -> SkipWhile<I, P> {
23         SkipWhile { iter, flag: false, predicate }
24     }
25 }
26 
27 #[stable(feature = "core_impl_debug", since = "1.9.0")]
28 impl<I: fmt::Debug, P> fmt::Debug for SkipWhile<I, P> {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result29     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
30         f.debug_struct("SkipWhile").field("iter", &self.iter).field("flag", &self.flag).finish()
31     }
32 }
33 
34 #[stable(feature = "rust1", since = "1.0.0")]
35 impl<I: Iterator, P> Iterator for SkipWhile<I, P>
36 where
37     P: FnMut(&I::Item) -> bool,
38 {
39     type Item = I::Item;
40 
41     #[inline]
next(&mut self) -> Option<I::Item>42     fn next(&mut self) -> Option<I::Item> {
43         fn check<'a, T>(
44             flag: &'a mut bool,
45             pred: &'a mut impl FnMut(&T) -> bool,
46         ) -> impl FnMut(&T) -> bool + 'a {
47             move |x| {
48                 if *flag || !pred(x) {
49                     *flag = true;
50                     true
51                 } else {
52                     false
53                 }
54             }
55         }
56 
57         let flag = &mut self.flag;
58         let pred = &mut self.predicate;
59         self.iter.find(check(flag, pred))
60     }
61 
62     #[inline]
size_hint(&self) -> (usize, Option<usize>)63     fn size_hint(&self) -> (usize, Option<usize>) {
64         let (_, upper) = self.iter.size_hint();
65         (0, upper) // can't know a lower bound, due to the predicate
66     }
67 
68     #[inline]
try_fold<Acc, Fold, R>(&mut self, mut init: Acc, mut fold: Fold) -> R where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try<Output = Acc>,69     fn try_fold<Acc, Fold, R>(&mut self, mut init: Acc, mut fold: Fold) -> R
70     where
71         Self: Sized,
72         Fold: FnMut(Acc, Self::Item) -> R,
73         R: Try<Output = Acc>,
74     {
75         if !self.flag {
76             match self.next() {
77                 Some(v) => init = fold(init, v)?,
78                 None => return try { init },
79             }
80         }
81         self.iter.try_fold(init, fold)
82     }
83 
84     #[inline]
fold<Acc, Fold>(mut self, mut init: Acc, mut fold: Fold) -> Acc where Fold: FnMut(Acc, Self::Item) -> Acc,85     fn fold<Acc, Fold>(mut self, mut init: Acc, mut fold: Fold) -> Acc
86     where
87         Fold: FnMut(Acc, Self::Item) -> Acc,
88     {
89         if !self.flag {
90             match self.next() {
91                 Some(v) => init = fold(init, v),
92                 None => return init,
93             }
94         }
95         self.iter.fold(init, fold)
96     }
97 }
98 
99 #[stable(feature = "fused", since = "1.26.0")]
100 impl<I, P> FusedIterator for SkipWhile<I, P>
101 where
102     I: FusedIterator,
103     P: FnMut(&I::Item) -> bool,
104 {
105 }
106 
107 #[unstable(issue = "none", feature = "inplace_iteration")]
108 unsafe impl<P, I> SourceIter for SkipWhile<I, P>
109 where
110     I: SourceIter,
111 {
112     type Source = I::Source;
113 
114     #[inline]
as_inner(&mut self) -> &mut I::Source115     unsafe fn as_inner(&mut self) -> &mut I::Source {
116         // SAFETY: unsafe function forwarding to unsafe function with the same requirements
117         unsafe { SourceIter::as_inner(&mut self.iter) }
118     }
119 }
120 
121 #[unstable(issue = "none", feature = "inplace_iteration")]
122 unsafe impl<I: InPlaceIterable, F> InPlaceIterable for SkipWhile<I, F> where
123     F: FnMut(&I::Item) -> bool
124 {
125 }
126