core/iter/adapters/
take_while.rs

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

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy