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
128
//! 可组合的异步迭代。
//!
//! 如果您发现自己使用某种异步集合,并且需要对所述集合的元素执行操作,您将很快遇到异步迭代器。
//! 异步迭代器在惯用的异步 Rust 代码中大量使用,因此熟悉它们是值得的。
//!
//! 在解释更多内容之前,让我们讨论一下该模块的结构:
//!
//! # Organization
//!
//! 该模块主要是按类型来组织的:
//!
//! * [Traits] 是核心部分:这些 traits 定义了存在什么样的异步迭代器以及您可以用它们做什么。这些 traits 的方法值得投入一些额外的学习时间。
//! * 函数提供了一些有用的方法来创建一些基本的异步迭代器。
//! * 结构体通常是该模块的 traits 上各种方法的返回类型。通常,您将需要查看创建 `struct` 的方法,而不是 `struct` 本身。
//! 有关原因的更多详细信息,请参见 [实现异步迭代器](#implementing-async-iterator)。
//!
//! [Traits]: #traits
//!
//! 就是这样! 让我们深入研究异步迭代器。
//!
//! # 异步迭代器
//!
//! 这个模块的核心和灵魂是 [`AsyncIterator`] trait。[`AsyncIterator`] 的核心是这样的:
//!
//! ```
//! # use core::task::{Context, Poll};
//! # use core::pin::Pin;
//! trait AsyncIterator {
//!     type Item;
//!     fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>>;
//! }
//! ```
//!
//! 与 `Iterator` 不同,`AsyncIterator` 区分了实现 `AsyncIterator` 时使用的 [`poll_next`] 方法和使用异步迭代器时使用的 (to-be-implemented) `next` 方法。
//!
//! `AsyncIterator` 的消费者只需要考虑 `next`,它在调用时会返回一个 future,它产生 `Option<AsyncIterator::Item>`。
//!
//! 只要有元素,`next` 返回的 future 就会产生 `Some(Item)`,一旦所有元素用完,就会产生 `None` 来指示迭代已完成。
//! 如果我们正在等待异步解决问题,future 将等待异步迭代器再次准备好再次 yield。
//!
//! 单个异步迭代器可能会选择恢复迭代,因此再次调用 `next` 最终可能会或可能不会最终在某个时候再次产生 `Some(Item)`。
//!
//! [`AsyncIterator`] 的完整定义还包括许多其他方法,但它们是默认方法,建立在 [`poll_next`] 之上,因此您可以免费获得它们。
//!
//! [`Poll`]: super::task::Poll
//! [`poll_next`]: AsyncIterator::poll_next
//!
//! # 实现异步迭代器
//!
//! 创建自己的异步迭代器涉及两个步骤:创建一个 `struct` 来保存异步迭代器的状态,然后为该 `struct` 实现 [`AsyncIterator`]。
//!
//! 让我们创建一个名为 `Counter` 的异步迭代器,它从 `1` 计数到 `5`:
//!
//! ```no_run
//! #![feature(async_iterator)]
//! # use core::async_iter::AsyncIterator;
//! # use core::task::{Context, Poll};
//! # use core::pin::Pin;
//!
//! // 首先,结构体:
//!
//! /// 一个从 1 计数到 5 的异步迭代器
//! struct Counter {
//!     count: usize,
//! }
//!
//! // 我们希望计数从一开始,所以让我们添加一个 new() 方法来提供帮助。
//! // 这不是严格必要的,但很方便。
//! // 请注意,我们将 `count` 从零开始,我们将在下面的 `poll_next () ` 的实现中看到其原因。
//! impl Counter {
//!     fn new() -> Counter {
//!         Counter { count: 0 }
//!     }
//! }
//!
//! // 然后,我们为我们的 `Counter` 实现 `AsyncIterator`:
//!
//! impl AsyncIterator 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
//!
//! 异步迭代器是惰性的。这意味着仅仅创建一个异步迭代器并不能做很多事情。在您调用 `poll_next` 之前,什么都不会发生。
//! 当创建一个异步迭代器仅仅为了它的副作用时,这有时是一个混乱的根源。
//! 编译器将警告我们这种行为:
//!
//! ```text
//! warning: unused result that must be used: async iterators do nothing unless polled
//! ```
//!
//!
//!
//!
//!
//!
//!
//!
//!
//!
//!
//!
//!
//!
//!
//!
//!

mod async_iter;
mod from_iter;

pub use async_iter::AsyncIterator;
pub use from_iter::{from_iter, FromIter};