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
61use std::iter::Peekable;
62
63/// The iterator returned by `peeking_take_while`.
64///
65/// See the [module documentation](./index.html) for details.
66pub struct PeekingTakeWhile<'a, I, P>
67 where I: 'a + Iterator
68{
69 iter: &'a mut Peekable<I>,
70 predicate: P,
71}
72
73impl<'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
80 fn next(&mut self) -> Option<Self::Item> {
81 let predicate: &mut P = &mut self.predicate;
82 if self.iter.peek().map_or(default:false, |x: &::Item| !(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.
94pub 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.
101 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
106impl<'a, I> PeekableExt<'a, I> for Peekable<I>
107 where I: 'a + Iterator
108{
109 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