forked from mirror/async-std
Add initial Fuse implementation for Stream
Signed-off-by: Yoshua Wuyts <yoshuawuyts@gmail.com>
This commit is contained in:
parent
e6880e12e8
commit
78c49f92b6
3 changed files with 89 additions and 1 deletions
|
@ -27,7 +27,7 @@ pub use from_stream::FromStream;
|
|||
pub use into_stream::IntoStream;
|
||||
pub use once::{once, Once};
|
||||
pub use repeat::{repeat, Repeat};
|
||||
pub use stream::{Scan, Stream, Take, Zip};
|
||||
pub use stream::{Fuse, Scan, Stream, Take, Zip};
|
||||
|
||||
mod double_ended_stream;
|
||||
mod empty;
|
||||
|
|
54
src/stream/stream/fuse.rs
Normal file
54
src/stream/stream/fuse.rs
Normal file
|
@ -0,0 +1,54 @@
|
|||
use std::pin::Pin;
|
||||
|
||||
use crate::task::{Context, Poll};
|
||||
|
||||
/// A `Stream` that is permanently closed
|
||||
/// once a single call to `poll` results in
|
||||
/// `Poll::Ready(None)`, returning `Poll::Ready(None)`
|
||||
/// for all future calls to `poll`.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Fuse<S> {
|
||||
stream: S,
|
||||
done: bool,
|
||||
}
|
||||
|
||||
impl<S: Unpin> Unpin for Fuse<S> {}
|
||||
|
||||
impl<S: futures::Stream> Fuse<S> {
|
||||
pin_utils::unsafe_pinned!(stream: S);
|
||||
pin_utils::unsafe_unpinned!(done: bool);
|
||||
|
||||
/// Returns `true` if the underlying stream is fused.
|
||||
///
|
||||
/// If this `Stream` is fused, all future calls to
|
||||
/// `poll` will return `Poll::Ready(None)`.
|
||||
pub fn is_done(&self) -> bool {
|
||||
self.done
|
||||
}
|
||||
|
||||
/// Consumes this `Fuse` and returns the inner
|
||||
/// `Stream`, unfusing it if it had become
|
||||
/// fused.
|
||||
pub fn into_inner(self) -> S
|
||||
where
|
||||
S: Sized,
|
||||
{
|
||||
self.stream
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: futures::Stream> futures::Stream for Fuse<S> {
|
||||
type Item = S::Item;
|
||||
|
||||
fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<S::Item>> {
|
||||
if self.done {
|
||||
Poll::Ready(None)
|
||||
} else {
|
||||
let next = futures::ready!(self.as_mut().stream().poll_next(cx));
|
||||
if next.is_none() {
|
||||
*self.as_mut().done() = true;
|
||||
}
|
||||
Poll::Ready(next)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -28,6 +28,7 @@ mod filter_map;
|
|||
mod find;
|
||||
mod find_map;
|
||||
mod fold;
|
||||
mod fuse;
|
||||
mod min_by;
|
||||
mod next;
|
||||
mod nth;
|
||||
|
@ -35,6 +36,7 @@ mod scan;
|
|||
mod take;
|
||||
mod zip;
|
||||
|
||||
pub use fuse::Fuse;
|
||||
pub use scan::Scan;
|
||||
pub use take::Take;
|
||||
pub use zip::Zip;
|
||||
|
@ -246,6 +248,38 @@ pub trait Stream {
|
|||
Enumerate::new(self)
|
||||
}
|
||||
|
||||
/// Transforms this `Stream` into a "fused" `Stream`
|
||||
/// such that after the first time `poll` returns
|
||||
/// `Poll::Ready(None)`, all future calls to
|
||||
/// `poll` will also return `Poll::Ready(None)`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// # #![feature(async_await)]
|
||||
/// # fn main() { async_std::task::block_on(async {
|
||||
/// #
|
||||
/// use async_std::prelude::*;
|
||||
/// use async_std::stream;
|
||||
///
|
||||
/// let mut s = stream::repeat(9).take(3);
|
||||
///
|
||||
/// while let Some(v) = s.next().await {
|
||||
/// assert_eq!(v, 9);
|
||||
/// }
|
||||
/// #
|
||||
/// # }) }
|
||||
/// ```
|
||||
fn fuse(self) -> Fuse<Self>
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
Fuse {
|
||||
stream: self,
|
||||
done: false,
|
||||
}
|
||||
}
|
||||
|
||||
/// Both filters and maps a stream.
|
||||
///
|
||||
/// # Examples
|
||||
|
|
Loading…
Reference in a new issue