diff --git a/src/iter/filter.rs b/src/iter/filter.rs new file mode 100644 index 0000000..387acf7 --- /dev/null +++ b/src/iter/filter.rs @@ -0,0 +1,48 @@ +/// An async iterator that filters the elements of `iter` with `predicate`. +/// +/// This `struct` is created by the [`filter`] method on [`Iterator`]. See its +/// documentation for more. +/// +/// [`filter`]: crate::Iterator::filter +/// [`Iterator`]: crate::Iterator +#[derive(Debug)] +pub struct Filter +where + I: crate::Iterator, + P: async FnMut(&I::Item) -> bool, +{ + iter: I, + predicate: P, +} + +impl crate::Iterator for Filter +where + I: crate::Iterator, + P: async FnMut(&I::Item) -> bool, +{ + type Item = I::Item; + + async fn next(&mut self) -> Option { + loop { + let item = self.iter.next().await?; + if (self.predicate)(&item).await { + return Some(item); + } + } + } + + fn size_hint(&self) -> (usize, Option) { + let (_, upper) = self.iter.size_hint(); + (0, upper) // can't know a lower bound, due to the predicate + } +} + +impl Filter +where + I: crate::Iterator, + P: async FnMut(&I::Item) -> bool, +{ + pub(crate) fn new(iter: I, predicate: P) -> Self { + Self { iter, predicate } + } +} diff --git a/src/iter/mod.rs b/src/iter/mod.rs index 9954a89..cf6fd79 100644 --- a/src/iter/mod.rs +++ b/src/iter/mod.rs @@ -1,7 +1,9 @@ +mod filter; mod lend; mod lend_mut; mod map; +pub use filter::Filter; pub use lend::Lend; pub use lend_mut::LendMut; pub use map::Map; @@ -33,6 +35,17 @@ pub trait Iterator { Map::new(self, f) } + /// Creates an iterator which uses a closure to determine if an element should be yielded. + #[must_use = "iterators do nothing unless iterated over"] + fn filter

(self, predicate: P) -> Filter + where + P: async FnMut(&Self::Item) -> bool, + // P: FnMut(&Self::Item) -> bool, + Self: Sized, + { + Filter::new(self, predicate) + } + /// Transforms an iterator into a collection. #[must_use = "if you really need to exhaust the iterator, consider `.for_each(drop)` instead"] async fn collect>(self) -> B diff --git a/src/lib.rs b/src/lib.rs index 42947b3..a52d4e7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -18,9 +18,8 @@ //! the traits, use `async_trait`. //! #![cfg_attr(not(feature = "std"), no_std)] -#![allow(incomplete_features)] -#![feature(return_position_impl_trait_in_trait)] -#![feature(async_fn_in_trait)] +#![allow(async_fn_in_trait)] +#![feature(async_closure)] #![forbid(unsafe_code, future_incompatible)] #![deny(missing_debug_implementations, nonstandard_style)] #![warn(missing_docs)]