Skip to content

Commit 4c94db3

Browse files
committed
from/into stream
Signed-off-by: Yoshua Wuyts <yoshuawuyts@gmail.com> update examples Signed-off-by: Yoshua Wuyts <yoshuawuyts@gmail.com> impl collect Signed-off-by: Yoshua Wuyts <yoshuawuyts@gmail.com> compiles! Signed-off-by: Yoshua Wuyts <yoshuawuyts@gmail.com> layout base for collect into vec Signed-off-by: Yoshua Wuyts <yoshuawuyts@gmail.com> fmt Signed-off-by: Yoshua Wuyts <yoshuawuyts@gmail.com> progress Signed-off-by: Yoshua Wuyts <yoshuawuyts@gmail.com> compiles! Signed-off-by: Yoshua Wuyts <yoshuawuyts@gmail.com> define failing test Signed-off-by: Yoshua Wuyts <yoshuawuyts@gmail.com> cargo fmt Signed-off-by: Yoshua Wuyts <yoshuawuyts@gmail.com> stuck again Signed-off-by: Yoshua Wuyts <yoshuawuyts@gmail.com> fix trait bounds! Signed-off-by: Yoshua Wuyts <yoshuawuyts@gmail.com> cargo fmt Signed-off-by: Yoshua Wuyts <yoshuawuyts@gmail.com> hide dyn fut impl Signed-off-by: Yoshua Wuyts <yoshuawuyts@gmail.com> dyn ret for vec Signed-off-by: Yoshua Wuyts <yoshuawuyts@gmail.com> cargo fmt Signed-off-by: Yoshua Wuyts <yoshuawuyts@gmail.com> collect docs Signed-off-by: Yoshua Wuyts <yoshuawuyts@gmail.com> remove macro from vec::from_stream Signed-off-by: Yoshua Wuyts <yoshuawuyts@gmail.com> shorten collect trait bound Signed-off-by: Yoshua Wuyts <yoshuawuyts@gmail.com> Remove some Unpin and Send bounds Signed-off-by: Yoshua Wuyts <yoshuawuyts@gmail.com>
1 parent 6f9ec66 commit 4c94db3

File tree

7 files changed

+164
-1
lines changed

7 files changed

+164
-1
lines changed

src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,4 +42,6 @@ pub mod stream;
4242
pub mod sync;
4343
pub mod task;
4444

45+
mod vec;
46+
4547
pub(crate) mod utils;

src/stream/from_stream.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
use super::IntoStream;
2+
3+
use std::pin::Pin;
4+
5+
/// Conversion from a `Stream`.
6+
///
7+
/// By implementing `FromStream` for a type, you define how it will be created from a stream.
8+
/// This is common for types which describe a collection of some kind.
9+
///
10+
/// See also: [`IntoStream`].
11+
///
12+
/// [`IntoStream`]: trait.IntoStream.html
13+
pub trait FromStream<T> {
14+
/// Creates a value from a stream.
15+
///
16+
/// # Examples
17+
///
18+
/// Basic usage:
19+
///
20+
/// ```
21+
/// // use async_std::stream::FromStream;
22+
///
23+
/// // let _five_fives = async_std::stream::repeat(5).take(5);
24+
/// ```
25+
fn from_stream<'a, S: IntoStream<Item = T> + 'a>(
26+
stream: S,
27+
) -> Pin<Box<dyn core::future::Future<Output = Self> + 'a>>;
28+
}

src/stream/into_stream.rs

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
use futures_core::stream::Stream;
2+
3+
/// Conversion into a `Stream`.
4+
///
5+
/// By implementing `IntoIterator` for a type, you define how it will be
6+
/// converted to an iterator. This is common for types which describe a
7+
/// collection of some kind.
8+
///
9+
/// [`from_stream`]: #tymethod.from_stream
10+
/// [`Stream`]: trait.Stream.html
11+
/// [`collect`]: trait.Stream.html#method.collect
12+
///
13+
/// See also: [`FromStream`].
14+
///
15+
/// [`FromStream`]: trait.FromStream.html
16+
pub trait IntoStream {
17+
/// The type of the elements being iterated over.
18+
type Item;
19+
20+
/// Which kind of stream are we turning this into?
21+
type IntoStream: Stream<Item = Self::Item>;
22+
23+
/// Creates a stream from a value.
24+
fn into_stream(self) -> Self::IntoStream;
25+
}
26+
27+
impl<I: Stream> IntoStream for I {
28+
type Item = I::Item;
29+
type IntoStream = I;
30+
31+
#[inline]
32+
fn into_stream(self) -> I {
33+
self
34+
}
35+
}

src/stream/mod.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,15 @@
2222
//! ```
2323
2424
pub use empty::{empty, Empty};
25+
pub use from_stream::FromStream;
26+
pub use into_stream::IntoStream;
2527
pub use once::{once, Once};
2628
pub use repeat::{repeat, Repeat};
2729
pub use stream::{Stream, Take};
2830

2931
mod empty;
32+
mod from_stream;
33+
mod into_stream;
3034
mod once;
3135
mod repeat;
3236
mod stream;

src/stream/stream/mod.rs

Lines changed: 61 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,12 @@ use min_by::MinByFuture;
4040
use next::NextFuture;
4141
use nth::NthFuture;
4242

43+
use super::from_stream::FromStream;
44+
use crate::future::Future;
45+
use crate::task::{Context, Poll};
4346
use std::cmp::Ordering;
4447
use std::marker::PhantomData;
48+
use std::pin::Pin;
4549

4650
use cfg_if::cfg_if;
4751

@@ -67,6 +71,21 @@ cfg_if! {
6771
}
6872
}
6973

74+
cfg_if! {
75+
if #[cfg(feature = "docs")] {
76+
#[doc(hidden)]
77+
pub struct DynFuture<'a, T>(std::marker::PhantomData<&'a T>);
78+
79+
macro_rules! dyn_ret {
80+
($a:lifetime, $o:ty) => (DynFuture<$a, $o>);
81+
}
82+
} else {
83+
macro_rules! dyn_ret {
84+
($a:lifetime, $o:ty) => (Pin<Box<dyn core::future::Future<Output = $o> + 'a>>)
85+
}
86+
}
87+
}
88+
7089
/// An asynchronous stream of values.
7190
///
7291
/// This trait is an async version of [`std::iter::Iterator`].
@@ -361,7 +380,6 @@ pub trait Stream {
361380
///
362381
/// Basic usage:
363382
///
364-
/// ```
365383
/// # fn main() { async_std::task::block_on(async {
366384
/// #
367385
/// use async_std::prelude::*;
@@ -400,6 +418,48 @@ pub trait Stream {
400418
f,
401419
}
402420
}
421+
422+
/// Transforms a stream into a collection.
423+
///
424+
/// `collect()` can take anything streamable, and turn it into a relevant
425+
/// collection. This is one of the more powerful methods in the async
426+
/// standard library, used in a variety of contexts.
427+
///
428+
/// The most basic pattern in which `collect()` is used is to turn one
429+
/// collection into another. You take a collection, call [`stream`] on it,
430+
/// do a bunch of transformations, and then `collect()` at the end.
431+
///
432+
/// Because `collect()` is so general, it can cause problems with type
433+
/// inference. As such, `collect()` is one of the few times you'll see
434+
/// the syntax affectionately known as the 'turbofish': `::<>`. This
435+
/// helps the inference algorithm understand specifically which collection
436+
/// you're trying to collect into.
437+
///
438+
/// # Examples
439+
///
440+
/// ```
441+
/// # fn main() { async_std::task::block_on(async {
442+
/// #
443+
/// use async_std::prelude::*;
444+
/// use async_std::stream;
445+
///
446+
/// let s = stream::repeat(9u8).take(3);
447+
/// let buf: Vec<u8> = s.collect().await;
448+
///
449+
/// assert_eq!(buf, vec![9; 3]);
450+
/// #
451+
/// # }) }
452+
/// ```
453+
///
454+
/// [`stream`]: trait.Stream.html#tymethod.next
455+
#[must_use = "if you really need to exhaust the iterator, consider `.for_each(drop)` instead (TODO)"]
456+
fn collect<'a, B>(self) -> dyn_ret!('a, B)
457+
where
458+
Self: futures_core::stream::Stream + Sized + 'a,
459+
B: FromStream<<Self as futures_core::stream::Stream>::Item>,
460+
{
461+
FromStream::from_stream(self)
462+
}
403463
}
404464

405465
impl<T: futures_core::stream::Stream + Unpin + ?Sized> Stream for T {

src/vec/from_stream.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
use crate::stream::{FromStream, IntoStream, Stream};
2+
3+
use std::pin::Pin;
4+
5+
impl<T> FromStream<T> for Vec<T> {
6+
#[inline]
7+
fn from_stream<'a, S: IntoStream<Item = T>>(
8+
stream: S,
9+
) -> Pin<Box<dyn core::future::Future<Output = Self> + 'a>>
10+
where
11+
<S as IntoStream>::IntoStream: 'a,
12+
{
13+
let stream = stream.into_stream();
14+
15+
Pin::from(Box::new(async move {
16+
pin_utils::pin_mut!(stream);
17+
18+
let mut out = vec![];
19+
while let Some(item) = stream.next().await {
20+
out.push(item);
21+
}
22+
out
23+
}))
24+
}
25+
}

src/vec/mod.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
//! The Rust core allocation and collections library
2+
//!
3+
//! This library provides smart pointers and collections for managing
4+
//! heap-allocated values.
5+
6+
mod from_stream;
7+
8+
#[doc(inline)]
9+
pub use std::vec::Vec;

0 commit comments

Comments
 (0)