core/task/poll.rs
1#![stable(feature = "futures_api", since = "1.36.0")]
2
3use crate::ops::{self, ControlFlow};
4
5/// Indicates whether a value is available or if the current task has been
6/// scheduled to receive a wakeup instead.
7///
8/// This is returned by [`Future::poll`](core::future::Future::poll).
9#[must_use = "this `Poll` may be a `Pending` variant, which should be handled"]
10#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
11#[lang = "Poll"]
12#[stable(feature = "futures_api", since = "1.36.0")]
13pub enum Poll<T> {
14 /// Represents that a value is immediately ready.
15 #[lang = "Ready"]
16 #[stable(feature = "futures_api", since = "1.36.0")]
17 Ready(#[stable(feature = "futures_api", since = "1.36.0")] T),
18
19 /// Represents that a value is not ready yet.
20 ///
21 /// When a function returns `Pending`, the function *must* also
22 /// ensure that the current task is scheduled to be awoken when
23 /// progress can be made.
24 #[lang = "Pending"]
25 #[stable(feature = "futures_api", since = "1.36.0")]
26 Pending,
27}
28
29impl<T> Poll<T> {
30 /// Maps a `Poll<T>` to `Poll<U>` by applying a function to a contained value.
31 ///
32 /// # Examples
33 ///
34 /// Converts a <code>Poll<[String]></code> into a <code>Poll<[usize]></code>, consuming
35 /// the original:
36 ///
37 /// [String]: ../../std/string/struct.String.html "String"
38 /// ```
39 /// # use core::task::Poll;
40 /// let poll_some_string = Poll::Ready(String::from("Hello, World!"));
41 /// // `Poll::map` takes self *by value*, consuming `poll_some_string`
42 /// let poll_some_len = poll_some_string.map(|s| s.len());
43 ///
44 /// assert_eq!(poll_some_len, Poll::Ready(13));
45 /// ```
46 #[stable(feature = "futures_api", since = "1.36.0")]
47 #[inline]
48 pub fn map<U, F>(self, f: F) -> Poll<U>
49 where
50 F: FnOnce(T) -> U,
51 {
52 match self {
53 Poll::Ready(t) => Poll::Ready(f(t)),
54 Poll::Pending => Poll::Pending,
55 }
56 }
57
58 /// Returns `true` if the poll is a [`Poll::Ready`] value.
59 ///
60 /// # Examples
61 ///
62 /// ```
63 /// # use core::task::Poll;
64 /// let x: Poll<u32> = Poll::Ready(2);
65 /// assert_eq!(x.is_ready(), true);
66 ///
67 /// let x: Poll<u32> = Poll::Pending;
68 /// assert_eq!(x.is_ready(), false);
69 /// ```
70 #[inline]
71 #[rustc_const_stable(feature = "const_poll", since = "1.49.0")]
72 #[stable(feature = "futures_api", since = "1.36.0")]
73 pub const fn is_ready(&self) -> bool {
74 matches!(*self, Poll::Ready(_))
75 }
76
77 /// Returns `true` if the poll is a [`Pending`] value.
78 ///
79 /// [`Pending`]: Poll::Pending
80 ///
81 /// # Examples
82 ///
83 /// ```
84 /// # use core::task::Poll;
85 /// let x: Poll<u32> = Poll::Ready(2);
86 /// assert_eq!(x.is_pending(), false);
87 ///
88 /// let x: Poll<u32> = Poll::Pending;
89 /// assert_eq!(x.is_pending(), true);
90 /// ```
91 #[inline]
92 #[rustc_const_stable(feature = "const_poll", since = "1.49.0")]
93 #[stable(feature = "futures_api", since = "1.36.0")]
94 pub const fn is_pending(&self) -> bool {
95 !self.is_ready()
96 }
97}
98
99impl<T, E> Poll<Result<T, E>> {
100 /// Maps a `Poll<Result<T, E>>` to `Poll<Result<U, E>>` by applying a
101 /// function to a contained `Poll::Ready(Ok)` value, leaving all other
102 /// variants untouched.
103 ///
104 /// This function can be used to compose the results of two functions.
105 ///
106 /// # Examples
107 ///
108 /// ```
109 /// # use core::task::Poll;
110 /// let res: Poll<Result<u8, _>> = Poll::Ready("12".parse());
111 /// let squared = res.map_ok(|n| n * n);
112 /// assert_eq!(squared, Poll::Ready(Ok(144)));
113 /// ```
114 #[stable(feature = "futures_api", since = "1.36.0")]
115 #[inline]
116 pub fn map_ok<U, F>(self, f: F) -> Poll<Result<U, E>>
117 where
118 F: FnOnce(T) -> U,
119 {
120 match self {
121 Poll::Ready(Ok(t)) => Poll::Ready(Ok(f(t))),
122 Poll::Ready(Err(e)) => Poll::Ready(Err(e)),
123 Poll::Pending => Poll::Pending,
124 }
125 }
126
127 /// Maps a `Poll::Ready<Result<T, E>>` to `Poll::Ready<Result<T, U>>` by
128 /// applying a function to a contained `Poll::Ready(Err)` value, leaving all other
129 /// variants untouched.
130 ///
131 /// This function can be used to pass through a successful result while handling
132 /// an error.
133 ///
134 /// # Examples
135 ///
136 /// ```
137 /// # use core::task::Poll;
138 /// let res: Poll<Result<u8, _>> = Poll::Ready("oops".parse());
139 /// let res = res.map_err(|_| 0_u8);
140 /// assert_eq!(res, Poll::Ready(Err(0)));
141 /// ```
142 #[stable(feature = "futures_api", since = "1.36.0")]
143 #[inline]
144 pub fn map_err<U, F>(self, f: F) -> Poll<Result<T, U>>
145 where
146 F: FnOnce(E) -> U,
147 {
148 match self {
149 Poll::Ready(Ok(t)) => Poll::Ready(Ok(t)),
150 Poll::Ready(Err(e)) => Poll::Ready(Err(f(e))),
151 Poll::Pending => Poll::Pending,
152 }
153 }
154}
155
156impl<T, E> Poll<Option<Result<T, E>>> {
157 /// Maps a `Poll<Option<Result<T, E>>>` to `Poll<Option<Result<U, E>>>` by
158 /// applying a function to a contained `Poll::Ready(Some(Ok))` value,
159 /// leaving all other variants untouched.
160 ///
161 /// This function can be used to compose the results of two functions.
162 ///
163 /// # Examples
164 ///
165 /// ```
166 /// # use core::task::Poll;
167 /// let res: Poll<Option<Result<u8, _>>> = Poll::Ready(Some("12".parse()));
168 /// let squared = res.map_ok(|n| n * n);
169 /// assert_eq!(squared, Poll::Ready(Some(Ok(144))));
170 /// ```
171 #[stable(feature = "poll_map", since = "1.51.0")]
172 #[inline]
173 pub fn map_ok<U, F>(self, f: F) -> Poll<Option<Result<U, E>>>
174 where
175 F: FnOnce(T) -> U,
176 {
177 match self {
178 Poll::Ready(Some(Ok(t))) => Poll::Ready(Some(Ok(f(t)))),
179 Poll::Ready(Some(Err(e))) => Poll::Ready(Some(Err(e))),
180 Poll::Ready(None) => Poll::Ready(None),
181 Poll::Pending => Poll::Pending,
182 }
183 }
184
185 /// Maps a `Poll::Ready<Option<Result<T, E>>>` to
186 /// `Poll::Ready<Option<Result<T, F>>>` by applying a function to a
187 /// contained `Poll::Ready(Some(Err))` value, leaving all other variants
188 /// untouched.
189 ///
190 /// This function can be used to pass through a successful result while handling
191 /// an error.
192 ///
193 /// # Examples
194 ///
195 /// ```
196 /// # use core::task::Poll;
197 /// let res: Poll<Option<Result<u8, _>>> = Poll::Ready(Some("oops".parse()));
198 /// let res = res.map_err(|_| 0_u8);
199 /// assert_eq!(res, Poll::Ready(Some(Err(0))));
200 /// ```
201 #[stable(feature = "poll_map", since = "1.51.0")]
202 #[inline]
203 pub fn map_err<U, F>(self, f: F) -> Poll<Option<Result<T, U>>>
204 where
205 F: FnOnce(E) -> U,
206 {
207 match self {
208 Poll::Ready(Some(Ok(t))) => Poll::Ready(Some(Ok(t))),
209 Poll::Ready(Some(Err(e))) => Poll::Ready(Some(Err(f(e)))),
210 Poll::Ready(None) => Poll::Ready(None),
211 Poll::Pending => Poll::Pending,
212 }
213 }
214}
215
216#[stable(feature = "futures_api", since = "1.36.0")]
217#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
218const impl<T> From<T> for Poll<T> {
219 /// Moves the value into a [`Poll::Ready`] to make a `Poll<T>`.
220 ///
221 /// # Example
222 ///
223 /// ```
224 /// # use core::task::Poll;
225 /// assert_eq!(Poll::from(true), Poll::Ready(true));
226 /// ```
227 fn from(t: T) -> Poll<T> {
228 Poll::Ready(t)
229 }
230}
231
232#[unstable(feature = "try_trait_v2", issue = "84277", old_name = "try_trait")]
233impl<T, E> ops::Try for Poll<Result<T, E>> {
234 type Output = Poll<T>;
235 type Residual = Result<!, E>;
236
237 #[inline]
238 fn from_output(c: Self::Output) -> Self {
239 c.map(Ok)
240 }
241
242 #[inline]
243 fn branch(self) -> ControlFlow<Self::Residual, Self::Output> {
244 match self {
245 Poll::Ready(Ok(x)) => ControlFlow::Continue(Poll::Ready(x)),
246 Poll::Ready(Err(e)) => ControlFlow::Break(Err(e)),
247 Poll::Pending => ControlFlow::Continue(Poll::Pending),
248 }
249 }
250}
251
252#[unstable(feature = "try_trait_v2", issue = "84277", old_name = "try_trait")]
253impl<T, E, F: From<E>> ops::FromResidual<Result<!, E>> for Poll<Result<T, F>> {
254 #[inline]
255 fn from_residual(x: Result<!, E>) -> Self {
256 match x {
257 Err(e) => Poll::Ready(Err(From::from(e))),
258 }
259 }
260}
261
262#[unstable(feature = "try_trait_v2", issue = "84277", old_name = "try_trait")]
263impl<T, E> ops::Try for Poll<Option<Result<T, E>>> {
264 type Output = Poll<Option<T>>;
265 type Residual = Result<!, E>;
266
267 #[inline]
268 fn from_output(c: Self::Output) -> Self {
269 c.map(|x| x.map(Ok))
270 }
271
272 #[inline]
273 fn branch(self) -> ControlFlow<Self::Residual, Self::Output> {
274 match self {
275 Poll::Ready(Some(Ok(x))) => ControlFlow::Continue(Poll::Ready(Some(x))),
276 Poll::Ready(Some(Err(e))) => ControlFlow::Break(Err(e)),
277 Poll::Ready(None) => ControlFlow::Continue(Poll::Ready(None)),
278 Poll::Pending => ControlFlow::Continue(Poll::Pending),
279 }
280 }
281}
282
283#[unstable(feature = "try_trait_v2", issue = "84277", old_name = "try_trait")]
284impl<T, E, F: From<E>> ops::FromResidual<Result<!, E>> for Poll<Option<Result<T, F>>> {
285 #[inline]
286 fn from_residual(x: Result<!, E>) -> Self {
287 match x {
288 Err(e) => Poll::Ready(Some(Err(From::from(e)))),
289 }
290 }
291}