itertools/
take_while_inclusive.rs

1use core::iter::FusedIterator;
2use std::fmt;
3
4/// An iterator adaptor that consumes elements while the given predicate is
5/// `true`, including the element for which the predicate first returned
6/// `false`.
7///
8/// See [`.take_while_inclusive()`](crate::Itertools::take_while_inclusive)
9/// for more information.
10#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
11#[derive(Clone)]
12pub struct TakeWhileInclusive<I, F> {
13    iter: I,
14    predicate: F,
15    done: bool,
16}
17
18impl<I, F> TakeWhileInclusive<I, F>
19where
20    I: Iterator,
21    F: FnMut(&I::Item) -> bool,
22{
23    /// Create a new [`TakeWhileInclusive`] from an iterator and a predicate.
24    pub(crate) fn new(iter: I, predicate: F) -> Self {
25        Self {
26            iter,
27            predicate,
28            done: false,
29        }
30    }
31}
32
33impl<I, F> fmt::Debug for TakeWhileInclusive<I, F>
34where
35    I: Iterator + fmt::Debug,
36{
37    debug_fmt_fields!(TakeWhileInclusive, iter, done);
38}
39
40impl<I, F> Iterator for TakeWhileInclusive<I, F>
41where
42    I: Iterator,
43    F: FnMut(&I::Item) -> bool,
44{
45    type Item = I::Item;
46
47    fn next(&mut self) -> Option<Self::Item> {
48        if self.done {
49            None
50        } else {
51            self.iter.next().map(|item| {
52                if !(self.predicate)(&item) {
53                    self.done = true;
54                }
55                item
56            })
57        }
58    }
59
60    fn size_hint(&self) -> (usize, Option<usize>) {
61        if self.done {
62            (0, Some(0))
63        } else {
64            (0, self.iter.size_hint().1)
65        }
66    }
67
68    fn fold<B, Fold>(mut self, init: B, mut f: Fold) -> B
69    where
70        Fold: FnMut(B, Self::Item) -> B,
71    {
72        if self.done {
73            init
74        } else {
75            let predicate = &mut self.predicate;
76            self.iter
77                .try_fold(init, |mut acc, item| {
78                    let is_ok = predicate(&item);
79                    acc = f(acc, item);
80                    if is_ok {
81                        Ok(acc)
82                    } else {
83                        Err(acc)
84                    }
85                })
86                .unwrap_or_else(|err| err)
87        }
88    }
89}
90
91impl<I, F> FusedIterator for TakeWhileInclusive<I, F>
92where
93    I: Iterator,
94    F: FnMut(&I::Item) -> bool,
95{
96}