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 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}
97