Skip to content

Commit 2ecaf18

Browse files
bors[bot]Stjepan Glavina
and
Stjepan Glavina
authored
Merge #145
145: Add Stream::poll_next r=stjepang a=stjepang Adding `poll_next` to the `Stream` trait will simplify #125. After a discussion with @yoshuawuyts and @withoutboats, we became confident that the `Stream` trait of the future will never solely rely on `async fn next()` and will always have to rely on `fn poll_next()`. This PR now makes our `Stream` trait implementable by end users. I also made a few adjustments around pinning to `all()` and `any()` combinators since they take a `&mut self`, which implies `Self: Unpin`. A rule of thumb is that if a method takes a `&mut self` and then pins `self`, we *have to* require `Self: Unpin`. Co-authored-by: Stjepan Glavina <[email protected]>
2 parents a296760 + 2497f4d commit 2ecaf18

File tree

6 files changed

+104
-61
lines changed

6 files changed

+104
-61
lines changed

Diff for: src/stream/stream/all.rs

+15-22
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,36 @@
1-
use crate::future::Future;
2-
use crate::task::{Context, Poll};
3-
41
use std::marker::PhantomData;
52
use std::pin::Pin;
63

7-
#[derive(Debug)]
8-
pub struct AllFuture<'a, S, F, T>
9-
where
10-
F: FnMut(T) -> bool,
11-
{
4+
use crate::future::Future;
5+
use crate::stream::Stream;
6+
use crate::task::{Context, Poll};
7+
8+
#[doc(hidden)]
9+
#[allow(missing_debug_implementations)]
10+
pub struct AllFuture<'a, S, F, T> {
1211
pub(crate) stream: &'a mut S,
1312
pub(crate) f: F,
1413
pub(crate) result: bool,
15-
pub(crate) __item: PhantomData<T>,
14+
pub(crate) _marker: PhantomData<T>,
1615
}
1716

18-
impl<'a, S, F, T> AllFuture<'a, S, F, T>
19-
where
20-
F: FnMut(T) -> bool,
21-
{
22-
pin_utils::unsafe_pinned!(stream: &'a mut S);
23-
pin_utils::unsafe_unpinned!(result: bool);
24-
pin_utils::unsafe_unpinned!(f: F);
25-
}
17+
impl<S: Unpin, F, T> Unpin for AllFuture<'_, S, F, T> {}
2618

2719
impl<S, F> Future for AllFuture<'_, S, F, S::Item>
2820
where
29-
S: futures_core::stream::Stream + Unpin + Sized,
21+
S: Stream + Unpin + Sized,
3022
F: FnMut(S::Item) -> bool,
3123
{
3224
type Output = bool;
3325

3426
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
35-
use futures_core::stream::Stream;
36-
let next = futures_core::ready!(self.as_mut().stream().poll_next(cx));
27+
let next = futures_core::ready!(Pin::new(&mut *self.stream).poll_next(cx));
28+
3729
match next {
3830
Some(v) => {
39-
let result = (self.as_mut().f())(v);
40-
*self.as_mut().result() = result;
31+
let result = (&mut self.f)(v);
32+
self.result = result;
33+
4134
if result {
4235
// don't forget to wake this task again to pull the next item from stream
4336
cx.waker().wake_by_ref();

Diff for: src/stream/stream/any.rs

+15-22
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,36 @@
1-
use crate::future::Future;
2-
use crate::task::{Context, Poll};
3-
41
use std::marker::PhantomData;
52
use std::pin::Pin;
63

7-
#[derive(Debug)]
8-
pub struct AnyFuture<'a, S, F, T>
9-
where
10-
F: FnMut(T) -> bool,
11-
{
4+
use crate::future::Future;
5+
use crate::stream::Stream;
6+
use crate::task::{Context, Poll};
7+
8+
#[doc(hidden)]
9+
#[allow(missing_debug_implementations)]
10+
pub struct AnyFuture<'a, S, F, T> {
1211
pub(crate) stream: &'a mut S,
1312
pub(crate) f: F,
1413
pub(crate) result: bool,
15-
pub(crate) __item: PhantomData<T>,
14+
pub(crate) _marker: PhantomData<T>,
1615
}
1716

18-
impl<'a, S, F, T> AnyFuture<'a, S, F, T>
19-
where
20-
F: FnMut(T) -> bool,
21-
{
22-
pin_utils::unsafe_pinned!(stream: &'a mut S);
23-
pin_utils::unsafe_unpinned!(result: bool);
24-
pin_utils::unsafe_unpinned!(f: F);
25-
}
17+
impl<S: Unpin, F, T> Unpin for AnyFuture<'_, S, F, T> {}
2618

2719
impl<S, F> Future for AnyFuture<'_, S, F, S::Item>
2820
where
29-
S: futures_core::stream::Stream + Unpin + Sized,
21+
S: Stream + Unpin + Sized,
3022
F: FnMut(S::Item) -> bool,
3123
{
3224
type Output = bool;
3325

3426
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
35-
use futures_core::stream::Stream;
36-
let next = futures_core::ready!(self.as_mut().stream().poll_next(cx));
27+
let next = futures_core::ready!(Pin::new(&mut *self.stream).poll_next(cx));
28+
3729
match next {
3830
Some(v) => {
39-
let result = (self.as_mut().f())(v);
40-
*self.as_mut().result() = result;
31+
let result = (&mut self.f)(v);
32+
self.result = result;
33+
4134
if result {
4235
Poll::Ready(true)
4336
} else {

Diff for: src/stream/stream/min_by.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@ use std::cmp::Ordering;
22
use std::pin::Pin;
33

44
use crate::future::Future;
5+
use crate::stream::Stream;
56
use crate::task::{Context, Poll};
67

8+
#[doc(hidden)]
79
#[allow(missing_debug_implementations)]
810
pub struct MinByFuture<S, F, T> {
911
stream: S,
@@ -27,7 +29,7 @@ impl<S, F, T> MinByFuture<S, F, T> {
2729

2830
impl<S, F> Future for MinByFuture<S, F, S::Item>
2931
where
30-
S: futures_core::stream::Stream + Unpin + Sized,
32+
S: Stream + Unpin + Sized,
3133
S::Item: Copy,
3234
F: FnMut(&S::Item, &S::Item) -> Ordering,
3335
{

Diff for: src/stream/stream/mod.rs

+62-10
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,12 @@ use nth::NthFuture;
4444

4545
use std::cmp::Ordering;
4646
use std::marker::PhantomData;
47+
use std::pin::Pin;
4748

4849
use cfg_if::cfg_if;
4950

51+
use crate::task::{Context, Poll};
52+
5053
cfg_if! {
5154
if #[cfg(feature = "docs")] {
5255
#[doc(hidden)]
@@ -83,6 +86,55 @@ pub trait Stream {
8386
/// The type of items yielded by this stream.
8487
type Item;
8588

89+
/// Attempts to receive the next item from the stream.
90+
///
91+
/// There are several possible return values:
92+
///
93+
/// * `Poll::Pending` means this stream's next value is not ready yet.
94+
/// * `Poll::Ready(None)` means this stream has been exhausted.
95+
/// * `Poll::Ready(Some(item))` means `item` was received out of the stream.
96+
///
97+
/// # Examples
98+
///
99+
/// ```
100+
/// # fn main() { async_std::task::block_on(async {
101+
/// #
102+
/// use std::pin::Pin;
103+
///
104+
/// use async_std::prelude::*;
105+
/// use async_std::stream;
106+
/// use async_std::task::{Context, Poll};
107+
///
108+
/// fn increment(s: impl Stream<Item = i32> + Unpin) -> impl Stream<Item = i32> + Unpin {
109+
/// struct Increment<S>(S);
110+
///
111+
/// impl<S: Stream<Item = i32> + Unpin> Stream for Increment<S> {
112+
/// type Item = S::Item;
113+
///
114+
/// fn poll_next(
115+
/// mut self: Pin<&mut Self>,
116+
/// cx: &mut Context<'_>,
117+
/// ) -> Poll<Option<Self::Item>> {
118+
/// match Pin::new(&mut self.0).poll_next(cx) {
119+
/// Poll::Pending => Poll::Pending,
120+
/// Poll::Ready(None) => Poll::Ready(None),
121+
/// Poll::Ready(Some(item)) => Poll::Ready(Some(item + 1)),
122+
/// }
123+
/// }
124+
/// }
125+
///
126+
/// Increment(s)
127+
/// }
128+
///
129+
/// let mut s = increment(stream::once(7));
130+
///
131+
/// assert_eq!(s.next().await, Some(8));
132+
/// assert_eq!(s.next().await, None);
133+
/// #
134+
/// # }) }
135+
/// ```
136+
fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>>;
137+
86138
/// Advances the stream and returns the next value.
87139
///
88140
/// Returns [`None`] when iteration is finished. Individual stream implementations may
@@ -108,7 +160,10 @@ pub trait Stream {
108160
/// ```
109161
fn next(&mut self) -> ret!('_, NextFuture, Option<Self::Item>)
110162
where
111-
Self: Unpin;
163+
Self: Unpin,
164+
{
165+
NextFuture { stream: self }
166+
}
112167

113168
/// Creates a stream that yields its first `n` elements.
114169
///
@@ -312,13 +367,13 @@ pub trait Stream {
312367
#[inline]
313368
fn all<F>(&mut self, f: F) -> ret!('_, AllFuture, bool, F, Self::Item)
314369
where
315-
Self: Sized,
370+
Self: Unpin + Sized,
316371
F: FnMut(Self::Item) -> bool,
317372
{
318373
AllFuture {
319374
stream: self,
320375
result: true, // the default if the empty stream
321-
__item: PhantomData,
376+
_marker: PhantomData,
322377
f,
323378
}
324379
}
@@ -436,13 +491,13 @@ pub trait Stream {
436491
#[inline]
437492
fn any<F>(&mut self, f: F) -> ret!('_, AnyFuture, bool, F, Self::Item)
438493
where
439-
Self: Sized,
494+
Self: Unpin + Sized,
440495
F: FnMut(Self::Item) -> bool,
441496
{
442497
AnyFuture {
443498
stream: self,
444499
result: false, // the default if the empty stream
445-
__item: PhantomData,
500+
_marker: PhantomData,
446501
f,
447502
}
448503
}
@@ -451,10 +506,7 @@ pub trait Stream {
451506
impl<T: futures_core::stream::Stream + Unpin + ?Sized> Stream for T {
452507
type Item = <Self as futures_core::stream::Stream>::Item;
453508

454-
fn next(&mut self) -> ret!('_, NextFuture, Option<Self::Item>)
455-
where
456-
Self: Unpin,
457-
{
458-
NextFuture { stream: self }
509+
fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
510+
futures_core::stream::Stream::poll_next(self, cx)
459511
}
460512
}

Diff for: src/stream/stream/next.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
1+
use std::pin::Pin;
2+
13
use crate::future::Future;
4+
use crate::stream::Stream;
25
use crate::task::{Context, Poll};
3-
use std::pin::Pin;
46

57
#[doc(hidden)]
68
#[allow(missing_debug_implementations)]
79
pub struct NextFuture<'a, T: Unpin + ?Sized> {
810
pub(crate) stream: &'a mut T,
911
}
1012

11-
impl<T: futures_core::stream::Stream + Unpin + ?Sized> Future for NextFuture<'_, T> {
13+
impl<T: Stream + Unpin + ?Sized> Future for NextFuture<'_, T> {
1214
type Output = Option<T::Item>;
1315

1416
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {

Diff for: src/stream/stream/take.rs

+5-4
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1-
use crate::task::{Context, Poll};
2-
31
use std::pin::Pin;
42

3+
use crate::stream::Stream;
4+
use crate::task::{Context, Poll};
5+
56
/// A stream that yields the first `n` items of another stream.
67
#[derive(Clone, Debug)]
78
pub struct Take<S> {
@@ -11,12 +12,12 @@ pub struct Take<S> {
1112

1213
impl<S: Unpin> Unpin for Take<S> {}
1314

14-
impl<S: futures_core::stream::Stream> Take<S> {
15+
impl<S: Stream> Take<S> {
1516
pin_utils::unsafe_pinned!(stream: S);
1617
pin_utils::unsafe_unpinned!(remaining: usize);
1718
}
1819

19-
impl<S: futures_core::stream::Stream> futures_core::stream::Stream for Take<S> {
20+
impl<S: Stream> futures_core::stream::Stream for Take<S> {
2021
type Item = S::Item;
2122

2223
fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<S::Item>> {

0 commit comments

Comments
 (0)