diff --git a/src/stream/stream/mod.rs b/src/stream/stream/mod.rs index 8ddab212..5f4010ca 100644 --- a/src/stream/stream/mod.rs +++ b/src/stream/stream/mod.rs @@ -33,6 +33,7 @@ mod min_by; mod next; mod nth; mod scan; +mod skip; mod take; mod zip; @@ -51,6 +52,7 @@ use fold::FoldFuture; use min_by::MinByFuture; use next::NextFuture; use nth::NthFuture; +use skip::Skip; use std::cmp::Ordering; use std::marker::PhantomData; @@ -661,6 +663,31 @@ pub trait Stream { Scan::new(self, initial_state, f) } + /// Creates a combinator that skips the first `n` elements. + /// + /// ## Examples + /// + /// ``` + /// # fn main() { async_std::task::block_on(async { + /// # + /// use std::collections::VecDeque; + /// use async_std::stream::Stream; + /// + /// let s: VecDeque = vec![1, 2, 3].into_iter().collect(); + /// let mut skipped = s.skip(2); + /// + /// assert_eq!(skipped.next().await, Some(3)); + /// assert_eq!(skipped.next().await, None); + /// # + /// # }) } + /// ``` + fn skip(self, n: usize) -> Skip + where + Self: Sized, + { + Skip::new(self, n) + } + /// 'Zips up' two streams into a single stream of pairs. /// /// `zip()` returns a new stream that will iterate over two other streams, returning a tuple diff --git a/src/stream/stream/skip.rs b/src/stream/stream/skip.rs new file mode 100644 index 00000000..09f5cab8 --- /dev/null +++ b/src/stream/stream/skip.rs @@ -0,0 +1,41 @@ +use std::pin::Pin; +use std::task::{Context, Poll}; + +use crate::stream::Stream; + +#[doc(hidden)] +#[allow(missing_debug_implementations)] +pub struct Skip { + stream: S, + n: usize, +} + +impl Skip { + pin_utils::unsafe_pinned!(stream: S); + pin_utils::unsafe_unpinned!(n: usize); + + pub(crate) fn new(stream: S, n: usize) -> Self { + Skip { stream, n } + } +} + +impl Stream for Skip +where + S: Stream, +{ + type Item = S::Item; + + fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + loop { + let next = futures_core::ready!(self.as_mut().stream().poll_next(cx)); + + match next { + Some(v) => match self.n { + 0 => return Poll::Ready(Some(v)), + _ => *self.as_mut().n() -= 1, + }, + None => return Poll::Ready(None), + } + } + } +}