1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127
//! 可组合的异步迭代。 //! //! 如果 futures 是异步值,则流是异步迭代器。 //! 如果您发现自己具有某种异步集合,并且需要对所述集合的元素执行操作,那么您会很快遇到 'streams'。 //! 流在惯用的异步 Rust 代码中大量使用,因此值得熟悉它们。 //! //! 在解释更多内容之前,让我们讨论一下该模块的结构: //! //! # Organization //! //! 该模块主要是按类型来组织的: //! //! * [Traits] 是核心部分: 这些 traits 定义了存在哪种类型的流以及可以对其进行处理。这些 traits 的方法值得投入一些额外的学习时间。 //! * 函数提供了一些有用的方法来创建一些基本流。 //! * 结构体通常是该模块的 traits 上各种方法的返回类型。通常,您将需要查看创建 `struct` 的方法,而不是 `struct` 本身。 //! 有关原因的更多详细信息,请参见 [实现流](#implementing-stream)。 //! //! [Traits]: #traits //! //! 就是这样! 让我们深入研究流。 //! //! # Stream //! //! 该模块的核心是 [`Stream`] trait。[`Stream`] 的核心如下所示: //! //! ``` //! # use core::task::{Context, Poll}; //! # use core::pin::Pin; //! trait Stream { //! type Item; //! fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>>; //! } //! ``` //! //! 与 `Iterator` 不同,`Stream` 区分了实现 `Stream` 时使用的 [`poll_next`] 方法和使用流时使用的 (to-be-implemented) `next` 方法。 //! //! `Stream` 的使用者只需要考虑 `next`,当调用 `next` 时,它会返回 future 并产生 `Option<Stream::Item>`。 //! //! 只要有元素,`next` 返回的 future 就会产生 `Some(Item)`,一旦所有元素用完,就会产生 `None` 来指示迭代已完成。 //! 如果我们正在等待异步处理,则 future 将等待,直到流准备再次屈服。 //! //! 各个流可能选择恢复迭代,因此再次调用 `next` 可能会或可能最终不会在某个时候再次产生 `Some(Item)`。 //! //! [`Stream`] 的完整定义还包括许多其他方法,但是它们是默认方法,基于 [`poll_next`] 构建,因此您可以免费获得它们。 //! //! [`Poll`]: super::task::Poll //! [`poll_next`]: Stream::poll_next //! //! # 实现流 //! //! 创建自己的流涉及两个步骤: 创建一个 `struct` 来保存流的状态,然后为该 `struct` 实现 [`Stream`]。 //! //! 让我们创建一个名为 `Counter` 的流,它从 `1` 到 `5` 计数: //! //! ```no_run //! #![feature(async_stream)] //! # use core::stream::Stream; //! # use core::task::{Context, Poll}; //! # use core::pin::Pin; //! //! // 首先,结构体: //! //! /// 从一数到五的流 //! struct Counter { //! count: usize, //! } //! //! // 我们希望计数从一开始,所以让我们添加一个 new() 方法来提供帮助。 //! // 这不是严格必要的,但很方便。 //! // 请注意,我们将 `count` 从零开始,我们将在下面的 `poll_next () ` 的实现中看到其原因。 //! impl Counter { //! fn new() -> Counter { //! Counter { count: 0 } //! } //! } //! //! // 然后,我们为 `Counter` 实现 `Stream`: //! //! impl Stream for Counter { //! // 我们将使用 usize 进行计数 //! type Item = usize; //! //! // poll_next() 是唯一需要的方法 //! fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> { //! // 增加我们的数量。这就是为什么我们从零开始。 //! self.count += 1; //! //! // 检查我们是否已经完成计数。 //! if self.count < 6 { //! Poll::Ready(Some(self.count)) //! } else { //! Poll::Ready(None) //! } //! } //! } //! ``` //! //! # Laziness //! //! 流是懒惰的。这意味着仅仅创建一个流并不能做很多事情。除非您调用 `next`,否则什么都不会发生。 //! 当仅出于其副作用创建流时,这有时会引起混乱。 //! 编译器将警告我们这种行为: //! //! ```text //! warning: unused result that must be used: streams do nothing unless polled //! ``` //! //! //! //! //! //! //! //! //! //! //! //! //! //! //! //! //! mod stream; pub use stream::Stream;