From 8e5dedec34e50dd920a40eb8f9cea6bd90baf560 Mon Sep 17 00:00:00 2001 From: Felipe Sere Date: Thu, 28 Nov 2019 12:33:37 +0100 Subject: [PATCH] Restructure package. No longer use a extension trait to match std. Still outstanding: How do I hide the concrete structs from the trait? --- src/stream/double_ended/mod.rs | 267 ------------------ src/stream/double_ended_stream.rs | 24 -- .../from_iter.rs | 4 +- src/stream/double_ended_stream/mod.rs | 243 ++++++++++++++++ .../next_back.rs | 0 .../nth_back.rs | 0 .../rfind.rs | 0 .../rfold.rs | 0 .../try_rfold.rs | 0 src/stream/mod.rs | 3 +- 10 files changed, 246 insertions(+), 295 deletions(-) delete mode 100644 src/stream/double_ended/mod.rs delete mode 100644 src/stream/double_ended_stream.rs rename src/stream/{double_ended => double_ended_stream}/from_iter.rs (90%) create mode 100644 src/stream/double_ended_stream/mod.rs rename src/stream/{double_ended => double_ended_stream}/next_back.rs (100%) rename src/stream/{double_ended => double_ended_stream}/nth_back.rs (100%) rename src/stream/{double_ended => double_ended_stream}/rfind.rs (100%) rename src/stream/{double_ended => double_ended_stream}/rfold.rs (100%) rename src/stream/{double_ended => double_ended_stream}/try_rfold.rs (100%) diff --git a/src/stream/double_ended/mod.rs b/src/stream/double_ended/mod.rs deleted file mode 100644 index b8b78b2..0000000 --- a/src/stream/double_ended/mod.rs +++ /dev/null @@ -1,267 +0,0 @@ -mod next_back; -mod nth_back; -mod rfind; -mod rfold; -mod try_rfold; -mod from_iter; - -use next_back::NextBackFuture; -use nth_back::NthBackFuture; -use rfind::RFindFuture; -use rfold::RFoldFuture; -use try_rfold::TryRFoldFuture; -pub use from_iter::{from_iter, FromIter}; - -extension_trait! { - use crate::stream::Stream; - - use std::pin::Pin; - use std::task::{Context, Poll}; - - - #[doc = r#" - A stream able to yield elements from both ends. - - Something that implements `DoubleEndedStream` has one extra capability - over something that implements [`Stream`]: the ability to also take - `Item`s from the back, as well as the front. - - It is important to note that both back and forth work on the same range, - and do not cross: iteration is over when they meet in the middle. - - In a similar fashion to the [`Stream`] protocol, once a - `DoubleEndedStream` returns `None` from a `next_back()`, calling it again - may or may not ever return `Some` again. `next()` and `next_back()` are - interchangeable for this purpose. - ``` - "#] - pub trait DoubleEndedStream { - #[doc = r#" - The type of items yielded by this stream. - "#] - type Item; - - #[doc = r#" - Attempts to receive the next item from the back of the stream. - - There are several possible return values: - - * `Poll::Pending` means this stream's next_back value is not ready yet. - * `Poll::Ready(None)` means this stream has been exhausted. - * `Poll::Ready(Some(item))` means `item` was received out of the stream. - - # Examples - - ``` - # fn main() { async_std::task::block_on(async { - # - use std::pin::Pin; - - use async_std::prelude::*; - use async_std::stream; - use async_std::task::{Context, Poll}; - - fn increment( - s: impl DoubleEndedStream + Unpin, - ) -> impl DoubleEndedStream + Unpin { - struct Increment(S); - - impl + Unpin> Stream for Increment { - type Item = S::Item; - - fn poll_next_back( - mut self: Pin<&mut Self>, - cx: &mut Context<'_>, - ) -> Poll> { - match Pin::new(&mut self.0).poll_next_back(cx) { - Poll::Pending => Poll::Pending, - Poll::Ready(None) => Poll::Ready(None), - Poll::Ready(Some(item)) => Poll::Ready(Some(item + 1)), - } - } - } - - Increment(s) - } - - let mut s = increment(stream::once(7)); // will need to implement DoubleEndedStream - - assert_eq!(s.next_back().await, Some(8)); - assert_eq!(s.next_back().await, None); - # - # }) } - ``` - "#] - fn poll_next_back(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll>; - } - - #[doc = r#" - Extension methods for [`DoubleEndedStreamExt`]. - - [`Stream`]: ../stream/trait.Stream.html - "#] - pub trait DoubleEndedStreamExt: crate::stream::DoubleEndedStream { - #[doc = r#" - Advances the stream and returns the next value. - - Returns [`None`] when iteration is finished. Individual stream implementations may - choose to resume iteration, and so calling `next()` again may or may not eventually - start returning more values. - - [`None`]: https://doc.rust-lang.org/std/option/enum.Option.html#variant.None - - # Examples - - ``` - # fn main() { async_std::task::block_on(async { - # - use async_std::stream::double_ended::{self, DoubleEndedStreamExt}; - - let mut s = double_ended::from_iter(vec![7u8]); - - assert_eq!(s.next_back().await, Some(7)); - assert_eq!(s.next_back().await, None); - # - # }) } - ``` - "#] - fn next_back(&mut self) -> impl Future> + '_ [NextBackFuture<'_, Self>] - where - Self: Unpin, - { - NextBackFuture { stream: self } - } - - #[doc = r#" - Returns the nth element from the back of the stream. - - # Examples - - Basic usage: - - ``` - # fn main() { async_std::task::block_on(async { - # - use async_std::stream::double_ended::{self, DoubleEndedStreamExt}; - - let mut s = double_ended::from_iter(vec![1u8, 2, 3, 4, 5]); - - let second = s.nth_back(1).await; - assert_eq!(second, Some(4)); - # - # }) } - ``` - "#] - fn nth_back( - &mut self, - n: usize, - ) -> impl Future> + '_ [NthBackFuture<'_, Self>] - where - Self: Unpin + Sized, - { - NthBackFuture::new(self, n) - } - - #[doc = r#" - Returns the the frist element from the right that matches the predicate. - - # Examples - - Basic usage: - - ``` - # fn main() { async_std::task::block_on(async { - # - use async_std::stream::double_ended::{self, DoubleEndedStreamExt}; - - let mut s = double_ended::from_iter(vec![1u8, 2, 3, 4, 5]); - - let second = s.rfind(|v| v % 2 == 0).await; - assert_eq!(second, Some(4)); - # - # }) } - ``` - "#] - fn rfind

( - &mut self, - p: P, - ) -> impl Future> + '_ [RFindFuture<'_, Self, P>] - where - Self: Unpin + Sized, - P: FnMut(&Self::Item) -> bool, - { - RFindFuture::new(self, p) - } - - #[doc = r#" - # Examples - - Basic usage: - - ``` - # fn main() { async_std::task::block_on(async { - # - use async_std::stream::double_ended::{self, DoubleEndedStreamExt}; - - let s = double_ended::from_iter(vec![1u8, 2, 3, 4, 5]); - - let second = s.rfold(0, |acc, v| v + acc).await; - - assert_eq!(second, 15); - # - # }) } - ``` - "#] - fn rfold( - self, - accum: B, - f: F, - ) -> impl Future> [RFoldFuture] - where - Self: Sized, - F: FnMut(B, Self::Item) -> B, - { - RFoldFuture::new(self, accum, f) - } - - #[doc = r#" - A combinator that applies a function as long as it returns successfully, producing a single, final value. - Immediately returns the error when the function returns unsuccessfully. - - # Examples - - Basic usage: - - ``` - # fn main() { async_std::task::block_on(async { - # - use async_std::stream::double_ended::{self, DoubleEndedStreamExt}; - - let s = double_ended::from_iter(vec![1u8, 2, 3, 4, 5]); - let sum = s.try_rfold(0, |acc, v| { - if (acc+v) % 2 == 1 { - Ok(v+3) - } else { - Err("fail") - } - }).await; - - assert_eq!(sum, Err("fail")); - # - # }) } - ``` - "#] - fn try_rfold( - self, - accum: B, - f: F, - ) -> impl Future> [TryRFoldFuture] - where - Self: Sized, - F: FnMut(B, Self::Item) -> Result, - { - TryRFoldFuture::new(self, accum, f) - } - - } -} diff --git a/src/stream/double_ended_stream.rs b/src/stream/double_ended_stream.rs deleted file mode 100644 index 129bb1c..0000000 --- a/src/stream/double_ended_stream.rs +++ /dev/null @@ -1,24 +0,0 @@ -use crate::stream::Stream; - -use std::pin::Pin; -use std::task::{Context, Poll}; - -/// A stream able to yield elements from both ends. -/// -/// Something that implements `DoubleEndedStream` has one extra capability -/// over something that implements [`Stream`]: the ability to also take -/// `Item`s from the back, as well as the front. -/// -/// [`Stream`]: trait.Stream.html -#[cfg(feature = "unstable")] -#[cfg_attr(feature = "docs", doc(cfg(unstable)))] -pub trait DoubleEndedStream: Stream { - /// Removes and returns an element from the end of the stream. - /// - /// Returns `None` when there are no more elements. - /// - /// The [trait-level] docs contain more details. - /// - /// [trait-level]: trait.DoubleEndedStream.html - fn poll_next_back(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll>; -} diff --git a/src/stream/double_ended/from_iter.rs b/src/stream/double_ended_stream/from_iter.rs similarity index 90% rename from src/stream/double_ended/from_iter.rs rename to src/stream/double_ended_stream/from_iter.rs index ae424a5..29a3e7d 100644 --- a/src/stream/double_ended/from_iter.rs +++ b/src/stream/double_ended_stream/from_iter.rs @@ -22,9 +22,9 @@ pub struct FromIter { /// ``` /// # async_std::task::block_on(async { /// # -/// use async_std::stream::double_ended::{self, DoubleEndedStreamExt}; +/// use async_std::stream::double_ended_stream::{self, DoubleEndedStream}; /// -/// let mut s = double_ended::from_iter(vec![0, 1, 2, 3]); +/// let mut s = double_ended_stream::from_iter(vec![0, 1, 2, 3]); /// /// assert_eq!(s.next_back().await, Some(3)); /// assert_eq!(s.next_back().await, Some(2)); diff --git a/src/stream/double_ended_stream/mod.rs b/src/stream/double_ended_stream/mod.rs new file mode 100644 index 0000000..9213661 --- /dev/null +++ b/src/stream/double_ended_stream/mod.rs @@ -0,0 +1,243 @@ +use crate::stream::Stream; + +use std::pin::Pin; +use std::task::{Context, Poll}; + +mod from_iter; +mod next_back; +mod nth_back; +mod rfind; +mod rfold; +mod try_rfold; + +pub use from_iter::{from_iter, FromIter}; +use next_back::NextBackFuture; +use nth_back::NthBackFuture; +use rfind::RFindFuture; +use rfold::RFoldFuture; +use try_rfold::TryRFoldFuture; + +/// A stream able to yield elements from both ends. +/// +/// Something that implements `DoubleEndedStream` has one extra capability +/// over something that implements [`Stream`]: the ability to also take +/// `Item`s from the back, as well as the front. +/// +/// [`Stream`]: trait.Stream.html +#[cfg(feature = "unstable")] +#[cfg_attr(feature = "docs", doc(cfg(unstable)))] +pub trait DoubleEndedStream: Stream { + #[doc = r#" + Attempts to receive the next item from the back of the stream. + + There are several possible return values: + + * `Poll::Pending` means this stream's next_back value is not ready yet. + * `Poll::Ready(None)` means this stream has been exhausted. + * `Poll::Ready(Some(item))` means `item` was received out of the stream. + + # Examples + + ``` + # fn main() { async_std::task::block_on(async { + # + use std::pin::Pin; + + use async_std::prelude::*; + use async_std::stream; + use async_std::task::{Context, Poll}; + + fn increment( + s: impl DoubleEndedStream + Unpin, + ) -> impl DoubleEndedStream + Unpin { + struct Increment(S); + + impl + Unpin> Stream for Increment { + type Item = S::Item; + + fn poll_next( + mut self: Pin<&mut Self>, + cx: &mut Context<'_>, + ) -> Poll> { + match Pin::new(&mut self.0).poll_next(cx) { + Poll::Pending => Poll::Pending, + Poll::Ready(None) => Poll::Ready(None), + Poll::Ready(Some(item)) => Poll::Ready(Some(item + 1)), + } + } + } + + impl + Unpin> DoubleEndedStream for Increment { + fn poll_next_back( + mut self: Pin<&mut Self>, + cx: &mut Context<'_>, + ) -> Poll> { + match Pin::new(&mut self.0).poll_next_back(cx) { + Poll::Pending => Poll::Pending, + Poll::Ready(None) => Poll::Ready(None), + Poll::Ready(Some(item)) => Poll::Ready(Some(item + 1)), + } + } + } + + Increment(s) + } + + let mut s = increment(stream::once(7)); + + assert_eq!(s.next_back().await, Some(8)); + assert_eq!(s.next_back().await, None); + # + # }) } + ``` + "#] + fn poll_next_back(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll>; + + #[doc = r#" + Advances the stream and returns the next value. + + Returns [`None`] when iteration is finished. Individual stream implementations may + choose to resume iteration, and so calling `next()` again may or may not eventually + start returning more values. + + [`None`]: https://doc.rust-lang.org/std/option/enum.Option.html#variant.None + + # Examples + + ``` + # fn main() { async_std::task::block_on(async { + # + use async_std::stream::double_ended_stream::{self, DoubleEndedStream}; + + let mut s = double_ended_stream::from_iter(vec![7u8]); + + assert_eq!(s.next_back().await, Some(7)); + assert_eq!(s.next_back().await, None); + # + # }) } + ``` + "#] + fn next_back(&mut self) -> NextBackFuture<'_, Self> + where + Self: Unpin, + { + NextBackFuture { stream: self } + } + + #[doc = r#" + Returns the nth element from the back of the stream. + + # Examples + + Basic usage: + + ``` + # fn main() { async_std::task::block_on(async { + # + use async_std::stream::double_ended_stream::{self, DoubleEndedStream}; + + let mut s = double_ended_stream::from_iter(vec![1u8, 2, 3, 4, 5]); + + let second = s.nth_back(1).await; + assert_eq!(second, Some(4)); + # + # }) } + ``` + "#] + fn nth_back(&mut self, n: usize) -> NthBackFuture<'_, Self> + where + Self: Unpin + Sized, + { + NthBackFuture::new(self, n) + } + + #[doc = r#" + Returns the the frist element from the right that matches the predicate. + + # Examples + + Basic usage: + + ``` + # fn main() { async_std::task::block_on(async { + # + use async_std::stream::double_ended_stream::{self, DoubleEndedStream}; + + let mut s = double_ended_stream::from_iter(vec![1u8, 2, 3, 4, 5]); + + let second = s.rfind(|v| v % 2 == 0).await; + assert_eq!(second, Some(4)); + # + # }) } + ``` + "#] + fn rfind

(&mut self, p: P) -> RFindFuture<'_, Self, P> + where + Self: Unpin + Sized, + P: FnMut(&Self::Item) -> bool, + { + RFindFuture::new(self, p) + } + + #[doc = r#" + # Examples + + Basic usage: + + ``` + # fn main() { async_std::task::block_on(async { + # + use async_std::stream::double_ended_stream::{self, DoubleEndedStream}; + + let s = double_ended_stream::from_iter(vec![1u8, 2, 3, 4, 5]); + + let second = s.rfold(0, |acc, v| v + acc).await; + + assert_eq!(second, 15); + # + # }) } + ``` + "#] + fn rfold(self, accum: B, f: F) -> RFoldFuture + where + Self: Sized, + F: FnMut(B, Self::Item) -> B, + { + RFoldFuture::new(self, accum, f) + } + + #[doc = r#" + A combinator that applies a function as long as it returns successfully, producing a single, final value. + Immediately returns the error when the function returns unsuccessfully. + + # Examples + + Basic usage: + + ``` + # fn main() { async_std::task::block_on(async { + # + use async_std::stream::double_ended_stream::{self, DoubleEndedStream}; + + let s = double_ended_stream::from_iter(vec![1u8, 2, 3, 4, 5]); + let sum = s.try_rfold(0, |acc, v| { + if (acc+v) % 2 == 1 { + Ok(v+3) + } else { + Err("fail") + } + }).await; + + assert_eq!(sum, Err("fail")); + # + # }) } + ``` + "#] + fn try_rfold(self, accum: B, f: F) -> TryRFoldFuture + where + Self: Sized, + F: FnMut(B, Self::Item) -> Result, + { + TryRFoldFuture::new(self, accum, f) + } +} diff --git a/src/stream/double_ended/next_back.rs b/src/stream/double_ended_stream/next_back.rs similarity index 100% rename from src/stream/double_ended/next_back.rs rename to src/stream/double_ended_stream/next_back.rs diff --git a/src/stream/double_ended/nth_back.rs b/src/stream/double_ended_stream/nth_back.rs similarity index 100% rename from src/stream/double_ended/nth_back.rs rename to src/stream/double_ended_stream/nth_back.rs diff --git a/src/stream/double_ended/rfind.rs b/src/stream/double_ended_stream/rfind.rs similarity index 100% rename from src/stream/double_ended/rfind.rs rename to src/stream/double_ended_stream/rfind.rs diff --git a/src/stream/double_ended/rfold.rs b/src/stream/double_ended_stream/rfold.rs similarity index 100% rename from src/stream/double_ended/rfold.rs rename to src/stream/double_ended_stream/rfold.rs diff --git a/src/stream/double_ended/try_rfold.rs b/src/stream/double_ended_stream/try_rfold.rs similarity index 100% rename from src/stream/double_ended/try_rfold.rs rename to src/stream/double_ended_stream/try_rfold.rs diff --git a/src/stream/mod.rs b/src/stream/mod.rs index 9b8ee8a..ebce3a3 100644 --- a/src/stream/mod.rs +++ b/src/stream/mod.rs @@ -319,8 +319,7 @@ mod repeat_with; cfg_unstable! { #[doc(hidden)] - pub mod double_ended; - mod double_ended_stream; + pub mod double_ended_stream; mod exact_size_stream; mod extend; mod from_stream;