summaryrefslogtreecommitdiffstats
path: root/third_party/rust/peeking_take_while/src
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/rust/peeking_take_while/src')
-rw-r--r--third_party/rust/peeking_take_while/src/lib.rs117
1 files changed, 117 insertions, 0 deletions
diff --git a/third_party/rust/peeking_take_while/src/lib.rs b/third_party/rust/peeking_take_while/src/lib.rs
new file mode 100644
index 0000000000..67f36d84db
--- /dev/null
+++ b/third_party/rust/peeking_take_while/src/lib.rs
@@ -0,0 +1,117 @@
+//! # `peeking_take_while`
+//!
+//! Provides the `peeking_take_while` iterator adaptor method.
+//!
+//! The `peeking_take_while` method is very similar to `take_while`, but behaves
+//! differently when used with a borrowed iterator (perhaps returned by
+//! `Iterator::by_ref`).
+//!
+//! `peeking_take_while` peeks at the next item in the iterator and runs the
+//! predicate on that peeked item. This avoids consuming the first item yielded
+//! by the underlying iterator for which the predicate returns `false`. On the
+//! other hand, `take_while` will consume that first item for which the
+//! predicate returns `false`, and it will be lost.
+//!
+//! ```
+//! extern crate peeking_take_while;
+//!
+//! // Bring the `peeking_take_while` method for peekable iterators into
+//! // scope.
+//! use peeking_take_while::PeekableExt;
+//!
+//! # fn main() {
+//! // Let's say we have two collections we want to iterate through: `xs` and
+//! // `ys`. We want to perform one operation on all the leading contiguous
+//! // elements that match some predicate, and a different thing with the rest of
+//! // the elements. With the `xs`, we will use the normal `take_while`. With the
+//! // `ys`, we will use `peeking_take_while`.
+//!
+//! let xs: Vec<u8> = (0..100).collect();
+//! let ys = xs.clone();
+//!
+//! let mut iter_xs = xs.into_iter();
+//! let mut iter_ys = ys.into_iter().peekable();
+//!
+//! {
+//! // Let's do one thing with all the items that are less than 10.
+//! # fn do_things_with<T>(_: T) {}
+//!
+//! let xs_less_than_ten = iter_xs.by_ref().take_while(|x| *x < 10);
+//! for x in xs_less_than_ten {
+//! do_things_with(x);
+//! }
+//!
+//! let ys_less_than_ten = iter_ys.by_ref().peeking_take_while(|y| *y < 10);
+//! for y in ys_less_than_ten {
+//! do_things_with(y);
+//! }
+//! }
+//!
+//! // And now we will do some other thing with the items that are greater than
+//! // or equal to 10.
+//!
+//! // ...except, when using plain old `take_while` we lost 10!
+//! assert_eq!(iter_xs.next(), Some(11));
+//!
+//! // However, when using `peeking_take_while` we did not! Great!
+//! assert_eq!(iter_ys.next(), Some(10));
+//! # }
+//! ```
+
+use std::iter::Peekable;
+
+/// The iterator returned by `peeking_take_while`.
+///
+/// See the [module documentation](./index.html) for details.
+pub struct PeekingTakeWhile<'a, I, P>
+ where I: 'a + Iterator
+{
+ iter: &'a mut Peekable<I>,
+ predicate: P,
+}
+
+impl<'a, I, P> Iterator for PeekingTakeWhile<'a, I, P>
+ where I: Iterator,
+ I::Item: ::std::fmt::Debug,
+ P: FnMut(&<I as Iterator>::Item) -> bool
+{
+ type Item = <I as Iterator>::Item;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ let predicate = &mut self.predicate;
+ if self.iter.peek().map_or(false, |x| !(predicate)(x)) {
+ None
+ } else {
+ self.iter.next()
+ }
+ }
+}
+
+/// The `Iterator` extension trait that provides the `peeking_take_while`
+/// method.
+///
+/// See the [module documentation](./index.html) for details.
+pub trait PeekableExt<'a, I>: Iterator
+ where I: 'a + Iterator
+{
+ /// The `Iterator` extension trait that provides the `peeking_take_while`
+ /// method.
+ ///
+ /// See the [module documentation](./index.html) for details.
+ fn peeking_take_while<P>(&'a mut self, predicate: P) -> PeekingTakeWhile<'a, I, P>
+ where Self: Sized,
+ P: FnMut(&<Self as Iterator>::Item) -> bool;
+}
+
+impl<'a, I> PeekableExt<'a, I> for Peekable<I>
+ where I: 'a + Iterator
+{
+ fn peeking_take_while<P>(&'a mut self, predicate: P) -> PeekingTakeWhile<I, P>
+ where P: FnMut(&<Self as Iterator>::Item) -> bool
+ {
+ PeekingTakeWhile {
+ iter: self,
+ predicate: predicate,
+ }
+ }
+}