From ba3da1604ff1d84c8ac90aa6b70d59aae710df7e Mon Sep 17 00:00:00 2001 From: equas <153013428+equas@users.noreply.github.com> Date: Tue, 5 Dec 2023 23:11:26 +0100 Subject: [PATCH] Implement take_while --- src/adapters/mod.rs | 2 ++ src/adapters/take_while.rs | 51 ++++++++++++++++++++++++++++++++++ src/traits/lending_iterator.rs | 16 ++++++++++- 3 files changed, 68 insertions(+), 1 deletion(-) create mode 100644 src/adapters/take_while.rs diff --git a/src/adapters/mod.rs b/src/adapters/mod.rs index f1f965a..6d7d587 100644 --- a/src/adapters/mod.rs +++ b/src/adapters/mod.rs @@ -6,6 +6,7 @@ mod filter_map; mod map; mod step_by; mod take; +mod take_while; mod zip; pub use self::chain::Chain; pub use self::cloned::Cloned; @@ -15,4 +16,5 @@ pub use self::filter_map::FilterMap; pub use self::map::{IntoIter, Map}; pub use self::step_by::StepBy; pub use self::take::Take; +pub use self::take_while::TakeWhile; pub use self::zip::Zip; diff --git a/src/adapters/take_while.rs b/src/adapters/take_while.rs new file mode 100644 index 0000000..d160504 --- /dev/null +++ b/src/adapters/take_while.rs @@ -0,0 +1,51 @@ +use crate::LendingIterator; + +/// A lending iterator that yields items based on a predicate. +/// +/// This iterator is fused. +#[derive(Clone)] +pub struct TakeWhile { + iter: I, + predicate: P, + done: bool, +} + +impl TakeWhile { + pub(crate) fn new(iter: I, predicate: P) -> Self { + Self { + iter, + predicate, + done: false, + } + } +} + +impl LendingIterator for TakeWhile +where + I: LendingIterator, + P: for<'a> FnMut(&I::Item<'a>) -> bool +{ + type Item<'a> = I::Item<'a> where I: 'a, P: 'a; + + fn next(&mut self) -> Option> { + if self.done { + None + } else { + let item = self.iter.next()?; + if (self.predicate)(&item) { + Some(item) + } else { + self.done = true; + None + } + } + } + + fn size_hint(&self) -> (usize, Option) { + if self.done { + (0, Some(0)) + } else { + (0, self.iter.size_hint().1) + } + } +} diff --git a/src/traits/lending_iterator.rs b/src/traits/lending_iterator.rs index 1b5ad88..80e46cc 100644 --- a/src/traits/lending_iterator.rs +++ b/src/traits/lending_iterator.rs @@ -2,7 +2,7 @@ use std::{num::NonZeroUsize, ops::Deref}; use crate::{ Chain, Cloned, Enumerate, Filter, FilterMap, Map, OptionTrait, SingleArgFnMut, SingleArgFnOnce, - StepBy, Take, Zip, + StepBy, Take, Zip, TakeWhile, }; /// Like [`Iterator`], but items may borrow from `&mut self`. @@ -82,6 +82,20 @@ pub trait LendingIterator { Take::new(self, n) } + /// Creates a lending iterator that lends items matching a predicate. + /// + /// The predicate is called once for every item. + /// Once it returns false once, `None` is returned for all subsequent calls to [`next`]. + /// + /// [`next`]: Self::next + fn take_while

(self, predicate: P) -> TakeWhile + where + Self: Sized, + P: for <'a> FnMut(&Self::Item<'a>) -> bool + { + TakeWhile::new(self, predicate) + } + /// Takes two lending iterators and creates a new lending iterator over both in sequence. /// /// See [`Iterator::chain`].