Skip to content

Commit 08b643d

Browse files
zhy2020zhy
andauthored
Add stream::repeat_with() method (#2279)
Co-authored-by: zhy <zhy@gmail.com>
1 parent 440e74e commit 08b643d

File tree

3 files changed

+97
-0
lines changed

3 files changed

+97
-0
lines changed

futures-util/src/stream/mod.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,9 @@ pub use self::iter::{iter, Iter};
6565
mod repeat;
6666
pub use self::repeat::{repeat, Repeat};
6767

68+
mod repeat_with;
69+
pub use self::repeat_with::{repeat_with, RepeatWith};
70+
6871
mod empty;
6972
pub use self::empty::{empty, Empty};
7073

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
use core::pin::Pin;
2+
use futures_core::stream::{Stream, FusedStream};
3+
use futures_core::task::{Context, Poll};
4+
5+
/// An stream that repeats elements of type `A` endlessly by
6+
/// applying the provided closure `F: FnMut() -> A`.
7+
///
8+
/// This `struct` is created by the [`repeat_with()`] function.
9+
/// See its documentation for more.
10+
#[derive(Debug, Clone)]
11+
#[must_use = "streams do nothing unless polled"]
12+
pub struct RepeatWith<F> {
13+
repeater: F,
14+
}
15+
16+
impl<A, F: FnMut() -> A> Unpin for RepeatWith<F> {}
17+
18+
impl<A, F: FnMut() -> A> Stream for RepeatWith<F> {
19+
type Item = A;
20+
21+
fn poll_next(mut self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<Option<Self::Item>> {
22+
Poll::Ready(Some((&mut self.repeater)()))
23+
}
24+
25+
fn size_hint(&self) -> (usize, Option<usize>) {
26+
(usize::max_value(), None)
27+
}
28+
}
29+
30+
impl<A, F: FnMut() -> A> FusedStream for RepeatWith<F>
31+
{
32+
fn is_terminated(&self) -> bool {
33+
false
34+
}
35+
}
36+
37+
/// Creates a new stream that repeats elements of type `A` endlessly by
38+
/// applying the provided closure, the repeater, `F: FnMut() -> A`.
39+
///
40+
/// The `repeat_with()` function calls the repeater over and over again.
41+
///
42+
/// Infinite stream like `repeat_with()` are often used with adapters like
43+
/// [`stream.take()`], in order to make them finite.
44+
///
45+
/// If the element type of the stream you need implements [`Clone`], and
46+
/// it is OK to keep the source element in memory, you should instead use
47+
/// the [`stream.repeat()`] function.
48+
///
49+
/// # Examples
50+
///
51+
/// Basic usage:
52+
///
53+
/// ```
54+
/// # futures::executor::block_on(async {
55+
/// use futures::stream::{self, StreamExt};
56+
///
57+
/// // let's assume we have some value of a type that is not `Clone`
58+
/// // or which don't want to have in memory just yet because it is expensive:
59+
/// #[derive(PartialEq, Debug)]
60+
/// struct Expensive;
61+
///
62+
/// // a particular value forever:
63+
/// let mut things = stream::repeat_with(|| Expensive);
64+
///
65+
/// assert_eq!(Some(Expensive), things.next().await);
66+
/// assert_eq!(Some(Expensive), things.next().await);
67+
/// assert_eq!(Some(Expensive), things.next().await);
68+
/// # });
69+
/// ```
70+
///
71+
/// Using mutation and going finite:
72+
///
73+
/// ```rust
74+
/// # futures::executor::block_on(async {
75+
/// use futures::stream::{self, StreamExt};
76+
///
77+
/// // From the zeroth to the third power of two:
78+
/// let mut curr = 1;
79+
/// let mut pow2 = stream::repeat_with(|| { let tmp = curr; curr *= 2; tmp })
80+
/// .take(4);
81+
///
82+
/// assert_eq!(Some(1), pow2.next().await);
83+
/// assert_eq!(Some(2), pow2.next().await);
84+
/// assert_eq!(Some(4), pow2.next().await);
85+
/// assert_eq!(Some(8), pow2.next().await);
86+
///
87+
/// // ... and now we're done
88+
/// assert_eq!(None, pow2.next().await);
89+
/// # });
90+
/// ```
91+
pub fn repeat_with<A, F: FnMut() -> A>(repeater: F) -> RepeatWith<F> {
92+
RepeatWith { repeater }
93+
}

futures/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -448,6 +448,7 @@ pub mod stream {
448448
pub use futures_util::stream::{
449449
iter, Iter,
450450
repeat, Repeat,
451+
repeat_with,RepeatWith,
451452
empty, Empty,
452453
pending, Pending,
453454
once, Once,

0 commit comments

Comments
 (0)