-
Notifications
You must be signed in to change notification settings - Fork 12.7k
/
async_iter.rs
163 lines (147 loc) · 6.29 KB
/
async_iter.rs
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
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
use crate::ops::DerefMut;
use crate::pin::Pin;
use crate::task::{Context, Poll};
/// A trait for dealing with asynchronous iterators.
///
/// This is the main async iterator trait. For more about the concept of async iterators
/// generally, please see the [module-level documentation]. In particular, you
/// may want to know how to [implement `AsyncIterator`][impl].
///
/// [module-level documentation]: index.html
/// [impl]: index.html#implementing-async-iterator
#[unstable(feature = "async_iterator", issue = "79024")]
#[must_use = "async iterators do nothing unless polled"]
#[doc(alias = "Stream")]
#[lang = "async_iterator"]
pub trait AsyncIterator {
/// The type of items yielded by the async iterator.
type Item;
/// Attempts to pull out the next value of this async iterator, registering the
/// current task for wakeup if the value is not yet available, and returning
/// `None` if the async iterator is exhausted.
///
/// # Return value
///
/// There are several possible return values, each indicating a distinct
/// async iterator state:
///
/// - `Poll::Pending` means that this async iterator's next value is not ready
/// yet. Implementations will ensure that the current task will be notified
/// when the next value may be ready.
///
/// - `Poll::Ready(Some(val))` means that the async iterator has successfully
/// produced a value, `val`, and may produce further values on subsequent
/// `poll_next` calls.
///
/// - `Poll::Ready(None)` means that the async iterator has terminated, and
/// `poll_next` should not be invoked again.
///
/// # Panics
///
/// Once an async iterator has finished (returned `Ready(None)` from `poll_next`), calling its
/// `poll_next` method again may panic, block forever, or cause other kinds of
/// problems; the `AsyncIterator` trait places no requirements on the effects of
/// such a call. However, as the `poll_next` method is not marked `unsafe`,
/// Rust's usual rules apply: calls must never cause undefined behavior
/// (memory corruption, incorrect use of `unsafe` functions, or the like),
/// regardless of the async iterator's state.
#[lang = "async_iterator_poll_next"]
fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>>;
/// Returns the bounds on the remaining length of the async iterator.
///
/// Specifically, `size_hint()` returns a tuple where the first element
/// is the lower bound, and the second element is the upper bound.
///
/// The second half of the tuple that is returned is an <code>[Option]<[usize]></code>.
/// A [`None`] here means that either there is no known upper bound, or the
/// upper bound is larger than [`usize`].
///
/// # Implementation notes
///
/// It is not enforced that an async iterator implementation yields the declared
/// number of elements. A buggy async iterator may yield less than the lower bound
/// or more than the upper bound of elements.
///
/// `size_hint()` is primarily intended to be used for optimizations such as
/// reserving space for the elements of the async iterator, but must not be
/// trusted to e.g., omit bounds checks in unsafe code. An incorrect
/// implementation of `size_hint()` should not lead to memory safety
/// violations.
///
/// That said, the implementation should provide a correct estimation,
/// because otherwise it would be a violation of the trait's protocol.
///
/// The default implementation returns <code>(0, [None])</code> which is correct for any
/// async iterator.
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
(0, None)
}
}
#[unstable(feature = "async_iterator", issue = "79024")]
impl<S: ?Sized + AsyncIterator + Unpin> AsyncIterator for &mut S {
type Item = S::Item;
fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
S::poll_next(Pin::new(&mut **self), cx)
}
fn size_hint(&self) -> (usize, Option<usize>) {
(**self).size_hint()
}
}
#[unstable(feature = "async_iterator", issue = "79024")]
impl<P> AsyncIterator for Pin<P>
where
P: DerefMut,
P::Target: AsyncIterator,
{
type Item = <P::Target as AsyncIterator>::Item;
fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
<P::Target as AsyncIterator>::poll_next(self.as_deref_mut(), cx)
}
fn size_hint(&self) -> (usize, Option<usize>) {
(**self).size_hint()
}
}
#[unstable(feature = "async_gen_internals", issue = "none")]
impl<T> Poll<Option<T>> {
/// A helper function for internal desugaring -- produces `Ready(Some(t))`,
/// which corresponds to the async iterator yielding a value.
#[doc(hidden)]
#[unstable(feature = "async_gen_internals", issue = "none")]
#[lang = "AsyncGenReady"]
pub fn async_gen_ready(t: T) -> Self {
Poll::Ready(Some(t))
}
/// A helper constant for internal desugaring -- produces `Pending`,
/// which corresponds to the async iterator pending on an `.await`.
#[doc(hidden)]
#[unstable(feature = "async_gen_internals", issue = "none")]
#[lang = "AsyncGenPending"]
// FIXME(gen_blocks): This probably could be deduplicated.
pub const PENDING: Self = Poll::Pending;
/// A helper constant for internal desugaring -- produces `Ready(None)`,
/// which corresponds to the async iterator finishing its iteration.
#[doc(hidden)]
#[unstable(feature = "async_gen_internals", issue = "none")]
#[lang = "AsyncGenFinished"]
pub const FINISHED: Self = Poll::Ready(None);
}
/// Converts something into an async iterator
#[unstable(feature = "async_iterator", issue = "79024")]
pub trait IntoAsyncIterator {
/// The type of the item yielded by the iterator
type Item;
/// The type of the resulting iterator
type IntoAsyncIter: AsyncIterator<Item = Self::Item>;
/// Converts `self` into an async iterator
#[lang = "into_async_iter_into_iter"]
fn into_async_iter(self) -> Self::IntoAsyncIter;
}
#[unstable(feature = "async_iterator", issue = "79024")]
impl<I: AsyncIterator> IntoAsyncIterator for I {
type Item = I::Item;
type IntoAsyncIter = I;
fn into_async_iter(self) -> Self::IntoAsyncIter {
self
}
}