1 use core::iter::FusedIterator;
2 use 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)]
12 pub struct TakeWhileInclusive<I, F> {
13     iter: I,
14     predicate: F,
15     done: bool,
16 }
17 
18 impl<I, F> TakeWhileInclusive<I, F>
19 where
20     I: Iterator,
21     F: FnMut(&I::Item) -> bool,
22 {
23     /// Create a new [`TakeWhileInclusive`] from an iterator and a predicate.
new(iter: I, predicate: F) -> Self24     pub(crate) fn new(iter: I, predicate: F) -> Self {
25         Self {
26             iter,
27             predicate,
28             done: false,
29         }
30     }
31 }
32 
33 impl<I, F> fmt::Debug for TakeWhileInclusive<I, F>
34 where
35     I: Iterator + fmt::Debug,
36 {
37     debug_fmt_fields!(TakeWhileInclusive, iter, done);
38 }
39 
40 impl<I, F> Iterator for TakeWhileInclusive<I, F>
41 where
42     I: Iterator,
43     F: FnMut(&I::Item) -> bool,
44 {
45     type Item = I::Item;
46 
next(&mut self) -> Option<Self::Item>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 
size_hint(&self) -> (usize, Option<usize>)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 
fold<B, Fold>(mut self, init: B, mut f: Fold) -> B where Fold: FnMut(B, Self::Item) -> B,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 
91 impl<I, F> FusedIterator for TakeWhileInclusive<I, F>
92 where
93     I: Iterator,
94     F: FnMut(&I::Item) -> bool,
95 {
96 }
97