Skip to content

Commit 568f6a6

Browse files
bors[bot]montekki
andauthored
Merge #179
179: adds stream::find combinator r=yoshuawuyts a=montekki A find combinator --- Stdlib: https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.find Ref: #129 Co-authored-by: Fedor Sakharov <[email protected]>
2 parents 6f9ec66 + 97a5f9b commit 568f6a6

File tree

2 files changed

+95
-0
lines changed

2 files changed

+95
-0
lines changed

src/stream/stream/find.rs

+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
use crate::task::{Context, Poll};
2+
use std::marker::PhantomData;
3+
use std::pin::Pin;
4+
5+
#[doc(hidden)]
6+
#[allow(missing_debug_implementations)]
7+
pub struct FindFuture<'a, S, P, T> {
8+
stream: &'a mut S,
9+
p: P,
10+
__t: PhantomData<T>,
11+
}
12+
13+
impl<'a, S, P, T> FindFuture<'a, S, P, T> {
14+
pin_utils::unsafe_pinned!(stream: &'a mut S);
15+
pin_utils::unsafe_unpinned!(p: P);
16+
17+
pub(super) fn new(stream: &'a mut S, p: P) -> Self {
18+
FindFuture {
19+
stream,
20+
p,
21+
__t: PhantomData,
22+
}
23+
}
24+
}
25+
26+
impl<'a, S, P> futures_core::future::Future for FindFuture<'a, S, P, S::Item>
27+
where
28+
S: futures_core::stream::Stream + Unpin + Sized,
29+
P: FnMut(&S::Item) -> bool,
30+
{
31+
type Output = Option<S::Item>;
32+
33+
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
34+
use futures_core::stream::Stream;
35+
36+
let item = futures_core::ready!(self.as_mut().stream().poll_next(cx));
37+
38+
match item {
39+
Some(v) => match (self.as_mut().p())(&v) {
40+
true => Poll::Ready(Some(v)),
41+
false => {
42+
cx.waker().wake_by_ref();
43+
Poll::Pending
44+
}
45+
},
46+
None => Poll::Ready(None),
47+
}
48+
}
49+
}

src/stream/stream/mod.rs

+46
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
mod all;
2525
mod any;
2626
mod filter_map;
27+
mod find;
2728
mod find_map;
2829
mod min_by;
2930
mod next;
@@ -35,6 +36,7 @@ pub use take::Take;
3536
use all::AllFuture;
3637
use any::AnyFuture;
3738
use filter_map::FilterMap;
39+
use find::FindFuture;
3840
use find_map::FindMapFuture;
3941
use min_by::MinByFuture;
4042
use next::NextFuture;
@@ -321,6 +323,50 @@ pub trait Stream {
321323
}
322324
}
323325

326+
/// Searches for an element in a stream that satisfies a predicate.
327+
///
328+
/// # Examples
329+
///
330+
/// Basic usage:
331+
///
332+
/// ```
333+
/// # fn main() { async_std::task::block_on(async {
334+
/// #
335+
/// use async_std::prelude::*;
336+
/// use std::collections::VecDeque;
337+
///
338+
/// let mut s: VecDeque<usize> = vec![1, 2, 3].into_iter().collect();
339+
/// let res = s.find(|x| *x == 2).await;
340+
/// assert_eq!(res, Some(2));
341+
/// #
342+
/// # }) }
343+
/// ```
344+
///
345+
/// Resuming after a first find:
346+
///
347+
/// ```
348+
/// # fn main() { async_std::task::block_on(async {
349+
/// #
350+
/// use async_std::prelude::*;
351+
/// use std::collections::VecDeque;
352+
///
353+
/// let mut s: VecDeque<usize> = vec![1, 2, 3].into_iter().collect();
354+
/// let res = s.find(|x| *x == 2).await;
355+
/// assert_eq!(res, Some(2));
356+
///
357+
/// let next = s.next().await;
358+
/// assert_eq!(next, Some(3));
359+
/// #
360+
/// # }) }
361+
/// ```
362+
fn find<P>(&mut self, p: P) -> ret!('_, FindFuture, Option<Self::Item>, P, Self::Item)
363+
where
364+
Self: Sized,
365+
P: FnMut(&Self::Item) -> bool,
366+
{
367+
FindFuture::new(self, p)
368+
}
369+
324370
/// Applies function to the elements of stream and returns the first non-none result.
325371
///
326372
/// ```

0 commit comments

Comments
 (0)