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