core/iter/adapters/
take_while.rs1use crate::fmt;
2#[cfg(not(feature = "ferrocene_subset"))]
3use crate::iter::adapters::SourceIter;
4#[cfg(not(feature = "ferrocene_subset"))]
5use crate::iter::{FusedIterator, InPlaceIterable, TrustedFused};
6#[cfg(not(feature = "ferrocene_subset"))]
7use crate::num::NonZero;
8use crate::ops::{ControlFlow, Try};
9
10#[must_use = "iterators are lazy and do nothing unless consumed"]
18#[stable(feature = "rust1", since = "1.0.0")]
19#[derive(Clone)]
20pub struct TakeWhile<I, P> {
21 iter: I,
22 flag: bool,
23 predicate: P,
24}
25
26impl<I, P> TakeWhile<I, P> {
27 pub(in crate::iter) fn new(iter: I, predicate: P) -> TakeWhile<I, P> {
28 TakeWhile { iter, flag: false, predicate }
29 }
30}
31
32#[stable(feature = "core_impl_debug", since = "1.9.0")]
33impl<I: fmt::Debug, P> fmt::Debug for TakeWhile<I, P> {
34 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
35 f.debug_struct("TakeWhile").field("iter", &self.iter).field("flag", &self.flag).finish()
36 }
37}
38
39#[stable(feature = "rust1", since = "1.0.0")]
40impl<I: Iterator, P> Iterator for TakeWhile<I, P>
41where
42 P: FnMut(&I::Item) -> bool,
43{
44 type Item = I::Item;
45
46 #[inline]
47 fn next(&mut self) -> Option<I::Item> {
48 if self.flag {
49 None
50 } else {
51 let x = self.iter.next()?;
52 if (self.predicate)(&x) {
53 Some(x)
54 } else {
55 self.flag = true;
56 None
57 }
58 }
59 }
60
61 #[inline]
62 fn size_hint(&self) -> (usize, Option<usize>) {
63 if self.flag {
64 (0, Some(0))
65 } else {
66 let (_, upper) = self.iter.size_hint();
67 (0, upper) }
69 }
70
71 #[inline]
72 fn try_fold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R
73 where
74 Self: Sized,
75 Fold: FnMut(Acc, Self::Item) -> R,
76 R: Try<Output = Acc>,
77 {
78 fn check<'a, T, Acc, R: Try<Output = Acc>>(
79 flag: &'a mut bool,
80 p: &'a mut impl FnMut(&T) -> bool,
81 mut fold: impl FnMut(Acc, T) -> R + 'a,
82 ) -> impl FnMut(Acc, T) -> ControlFlow<R, Acc> + 'a {
83 move |acc, x| {
84 if p(&x) {
85 ControlFlow::from_try(fold(acc, x))
86 } else {
87 *flag = true;
88 ControlFlow::Break(try { acc })
89 }
90 }
91 }
92
93 if self.flag {
94 try { init }
95 } else {
96 let flag = &mut self.flag;
97 let p = &mut self.predicate;
98 self.iter.try_fold(init, check(flag, p, fold)).into_try()
99 }
100 }
101
102 impl_fold_via_try_fold! { fold -> try_fold }
103}
104
105#[cfg(not(feature = "ferrocene_subset"))]
106#[stable(feature = "fused", since = "1.26.0")]
107impl<I, P> FusedIterator for TakeWhile<I, P>
108where
109 I: FusedIterator,
110 P: FnMut(&I::Item) -> bool,
111{
112}
113
114#[cfg(not(feature = "ferrocene_subset"))]
115#[unstable(issue = "none", feature = "trusted_fused")]
116unsafe impl<I: TrustedFused, P> TrustedFused for TakeWhile<I, P> {}
117
118#[cfg(not(feature = "ferrocene_subset"))]
119#[unstable(issue = "none", feature = "inplace_iteration")]
120unsafe impl<P, I> SourceIter for TakeWhile<I, P>
121where
122 I: SourceIter,
123{
124 type Source = I::Source;
125
126 #[inline]
127 unsafe fn as_inner(&mut self) -> &mut I::Source {
128 unsafe { SourceIter::as_inner(&mut self.iter) }
130 }
131}
132
133#[cfg(not(feature = "ferrocene_subset"))]
134#[unstable(issue = "none", feature = "inplace_iteration")]
135unsafe impl<I: InPlaceIterable, F> InPlaceIterable for TakeWhile<I, F> {
136 const EXPAND_BY: Option<NonZero<usize>> = I::EXPAND_BY;
137 const MERGE_BY: Option<NonZero<usize>> = I::MERGE_BY;
138}