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 | |
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. |
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. |
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 | |
106 | impl<'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 | |