1use crate::ops::DerefMut;
2use crate::pin::Pin;
3use crate::task::{Context, Poll};
4
5/// A trait for dealing with asynchronous iterators.
6///
7/// This is the main async iterator trait. For more about the concept of async iterators
8/// generally, please see the [module-level documentation]. In particular, you
9/// may want to know how to [implement `AsyncIterator`][impl].
10///
11/// [module-level documentation]: index.html
12/// [impl]: index.html#implementing-async-iterator
13#[unstable(feature = "async_iterator", issue = "79024")]
14#[must_use = "async iterators do nothing unless polled"]
15#[doc(alias = "Stream")]
16#[lang = "async_iterator"]
17pub trait AsyncIterator {
18 /// The type of items yielded by the async iterator.
19 type Item;
20
21 /// Attempt to pull out the next value of this async iterator, registering the
22 /// current task for wakeup if the value is not yet available, and returning
23 /// `None` if the async iterator is exhausted.
24 ///
25 /// # Return value
26 ///
27 /// There are several possible return values, each indicating a distinct
28 /// async iterator state:
29 ///
30 /// - `Poll::Pending` means that this async iterator's next value is not ready
31 /// yet. Implementations will ensure that the current task will be notified
32 /// when the next value may be ready.
33 ///
34 /// - `Poll::Ready(Some(val))` means that the async iterator has successfully
35 /// produced a value, `val`, and may produce further values on subsequent
36 /// `poll_next` calls.
37 ///
38 /// - `Poll::Ready(None)` means that the async iterator has terminated, and
39 /// `poll_next` should not be invoked again.
40 ///
41 /// # Panics
42 ///
43 /// Once an async iterator has finished (returned `Ready(None)` from `poll_next`), calling its
44 /// `poll_next` method again may panic, block forever, or cause other kinds of
45 /// problems; the `AsyncIterator` trait places no requirements on the effects of
46 /// such a call. However, as the `poll_next` method is not marked `unsafe`,
47 /// Rust's usual rules apply: calls must never cause undefined behavior
48 /// (memory corruption, incorrect use of `unsafe` functions, or the like),
49 /// regardless of the async iterator's state.
50 #[lang = "async_iterator_poll_next"]
51 fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>>;
52
53 /// Returns the bounds on the remaining length of the async iterator.
54 ///
55 /// Specifically, `size_hint()` returns a tuple where the first element
56 /// is the lower bound, and the second element is the upper bound.
57 ///
58 /// The second half of the tuple that is returned is an <code>[Option]<[usize]></code>.
59 /// A [`None`] here means that either there is no known upper bound, or the
60 /// upper bound is larger than [`usize`].
61 ///
62 /// # Implementation notes
63 ///
64 /// It is not enforced that an async iterator implementation yields the declared
65 /// number of elements. A buggy async iterator may yield less than the lower bound
66 /// or more than the upper bound of elements.
67 ///
68 /// `size_hint()` is primarily intended to be used for optimizations such as
69 /// reserving space for the elements of the async iterator, but must not be
70 /// trusted to e.g., omit bounds checks in unsafe code. An incorrect
71 /// implementation of `size_hint()` should not lead to memory safety
72 /// violations.
73 ///
74 /// That said, the implementation should provide a correct estimation,
75 /// because otherwise it would be a violation of the trait's protocol.
76 ///
77 /// The default implementation returns <code>(0, [None])</code> which is correct for any
78 /// async iterator.
79 #[inline]
80 fn size_hint(&self) -> (usize, Option<usize>) {
81 (0, None)
82 }
83}
84
85#[unstable(feature = "async_iterator", issue = "79024")]
86impl<S: ?Sized + AsyncIterator + Unpin> AsyncIterator for &mut S {
87 type Item = S::Item;
88
89 fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
90 S::poll_next(self:Pin::new(&mut **self), cx)
91 }
92
93 fn size_hint(&self) -> (usize, Option<usize>) {
94 (**self).size_hint()
95 }
96}
97
98#[unstable(feature = "async_iterator", issue = "79024")]
99impl<P> AsyncIterator for Pin<P>
100where
101 P: DerefMut,
102 P::Target: AsyncIterator,
103{
104 type Item = <P::Target as AsyncIterator>::Item;
105
106 fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
107 <P::Target as AsyncIterator>::poll_next(self.as_deref_mut(), cx)
108 }
109
110 fn size_hint(&self) -> (usize, Option<usize>) {
111 (**self).size_hint()
112 }
113}
114
115#[unstable(feature = "async_gen_internals", issue = "none")]
116impl<T> Poll<Option<T>> {
117 /// A helper function for internal desugaring -- produces `Ready(Some(t))`,
118 /// which corresponds to the async iterator yielding a value.
119 #[doc(hidden)]
120 #[unstable(feature = "async_gen_internals", issue = "none")]
121 #[lang = "AsyncGenReady"]
122 pub fn async_gen_ready(t: T) -> Self {
123 Poll::Ready(Some(t))
124 }
125
126 /// A helper constant for internal desugaring -- produces `Pending`,
127 /// which corresponds to the async iterator pending on an `.await`.
128 #[doc(hidden)]
129 #[unstable(feature = "async_gen_internals", issue = "none")]
130 #[lang = "AsyncGenPending"]
131 // FIXME(gen_blocks): This probably could be deduplicated.
132 pub const PENDING: Self = Poll::Pending;
133
134 /// A helper constant for internal desugaring -- produces `Ready(None)`,
135 /// which corresponds to the async iterator finishing its iteration.
136 #[doc(hidden)]
137 #[unstable(feature = "async_gen_internals", issue = "none")]
138 #[lang = "AsyncGenFinished"]
139 pub const FINISHED: Self = Poll::Ready(None);
140}
141
142/// Convert something into an async iterator
143#[unstable(feature = "async_iterator", issue = "79024")]
144pub trait IntoAsyncIterator {
145 /// The type of the item yielded by the iterator
146 type Item;
147 /// The type of the resulting iterator
148 type IntoAsyncIter: AsyncIterator<Item = Self::Item>;
149
150 /// Converts `self` into an async iterator
151 #[lang = "into_async_iter_into_iter"]
152 fn into_async_iter(self) -> Self::IntoAsyncIter;
153}
154
155#[unstable(feature = "async_iterator", issue = "79024")]
156impl<I: AsyncIterator> IntoAsyncIterator for I {
157 type Item = I::Item;
158 type IntoAsyncIter = I;
159
160 fn into_async_iter(self) -> Self::IntoAsyncIter {
161 self
162 }
163}
164