• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //! # `peeking_take_while`
2 //!
3 //! Provides the `peeking_take_while` iterator adaptor method.
4 //!
5 //! The `peeking_take_while` method is very similar to `take_while`, but behaves
6 //! differently when used with a borrowed iterator (perhaps returned by
7 //! `Iterator::by_ref`).
8 //!
9 //! `peeking_take_while` peeks at the next item in the iterator and runs the
10 //! predicate on that peeked item. This avoids consuming the first item yielded
11 //! by the underlying iterator for which the predicate returns `false`. On the
12 //! other hand, `take_while` will consume that first item for which the
13 //! predicate returns `false`, and it will be lost.
14 //!
15 //! ```
16 //! extern crate peeking_take_while;
17 //!
18 //! // Bring the `peeking_take_while` method for peekable iterators into
19 //! // scope.
20 //! use peeking_take_while::PeekableExt;
21 //!
22 //! # fn main() {
23 //! // Let's say we have two collections we want to iterate through: `xs` and
24 //! // `ys`. We want to perform one operation on all the leading contiguous
25 //! // elements that match some predicate, and a different thing with the rest of
26 //! // the elements. With the `xs`, we will use the normal `take_while`. With the
27 //! // `ys`, we will use `peeking_take_while`.
28 //!
29 //! let xs: Vec<u8> = (0..100).collect();
30 //! let ys = xs.clone();
31 //!
32 //! let mut iter_xs = xs.into_iter();
33 //! let mut iter_ys = ys.into_iter().peekable();
34 //!
35 //! {
36 //!     // Let's do one thing with all the items that are less than 10.
37 //! #   fn do_things_with<T>(_: T) {}
38 //!
39 //!     let xs_less_than_ten = iter_xs.by_ref().take_while(|x| *x < 10);
40 //!     for x in xs_less_than_ten {
41 //!         do_things_with(x);
42 //!     }
43 //!
44 //!     let ys_less_than_ten = iter_ys.by_ref().peeking_take_while(|y| *y < 10);
45 //!     for y in ys_less_than_ten {
46 //!         do_things_with(y);
47 //!     }
48 //! }
49 //!
50 //! // And now we will do some other thing with the items that are greater than
51 //! // or equal to 10.
52 //!
53 //! // ...except, when using plain old `take_while` we lost 10!
54 //! assert_eq!(iter_xs.next(), Some(11));
55 //!
56 //! // However, when using `peeking_take_while` we did not! Great!
57 //! assert_eq!(iter_ys.next(), Some(10));
58 //! # }
59 //! ```
60 
61 use std::iter::Peekable;
62 
63 /// The iterator returned by `peeking_take_while`.
64 ///
65 /// See the [module documentation](./index.html) for details.
66 pub struct PeekingTakeWhile<'a, I, P>
67     where I: 'a + Iterator
68 {
69     iter: &'a mut Peekable<I>,
70     predicate: P,
71 }
72 
73 impl<'a, I, P> Iterator for PeekingTakeWhile<'a, I, P>
74     where I: Iterator,
75           I::Item: ::std::fmt::Debug,
76           P: FnMut(&<I as Iterator>::Item) -> bool
77 {
78     type Item = <I as Iterator>::Item;
79 
next(&mut self) -> Option<Self::Item>80     fn next(&mut self) -> Option<Self::Item> {
81         let predicate = &mut self.predicate;
82         if self.iter.peek().map_or(false, |x| !(predicate)(x)) {
83             None
84         } else {
85             self.iter.next()
86         }
87     }
88 }
89 
90 /// The `Iterator` extension trait that provides the `peeking_take_while`
91 /// method.
92 ///
93 /// See the [module documentation](./index.html) for details.
94 pub trait PeekableExt<'a, I>: Iterator
95     where I: 'a + Iterator
96 {
97     /// The `Iterator` extension trait that provides the `peeking_take_while`
98     /// method.
99     ///
100     /// See the [module documentation](./index.html) for details.
peeking_take_while<P>(&'a mut self, predicate: P) -> PeekingTakeWhile<'a, I, P> where Self: Sized, P: FnMut(&<Self as Iterator>::Item) -> bool101     fn peeking_take_while<P>(&'a mut self, predicate: P) -> PeekingTakeWhile<'a, I, P>
102         where Self: Sized,
103               P: FnMut(&<Self as Iterator>::Item) -> bool;
104 }
105 
106 impl<'a, I> PeekableExt<'a, I> for Peekable<I>
107     where I: 'a + Iterator
108 {
peeking_take_while<P>(&'a mut self, predicate: P) -> PeekingTakeWhile<I, P> where P: FnMut(&<Self as Iterator>::Item) -> bool109     fn peeking_take_while<P>(&'a mut self, predicate: P) -> PeekingTakeWhile<I, P>
110         where P: FnMut(&<Self as Iterator>::Item) -> bool
111     {
112         PeekingTakeWhile {
113             iter: self,
114             predicate: predicate,
115         }
116     }
117 }
118