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. |
24 | pub 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 | |
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 | |
91 | impl<I, F> FusedIterator for TakeWhileInclusive<I, F> |
92 | where |
93 | I: Iterator, |
94 | F: FnMut(&I::Item) -> bool, |
95 | { |
96 | } |
97 | |