futures_time/future/
timeout.rs

1use crate::utils::timeout_err;
2
3use std::future::Future;
4use std::io;
5use std::pin::Pin;
6use std::task::{Context, Poll};
7
8use pin_project_lite::pin_project;
9
10pin_project! {
11    /// A future that times out after a duration of time.
12    ///
13    /// This `struct` is created by the [`timeout`] method on [`FutureExt`]. See its
14    /// documentation for more.
15    ///
16    /// [`timeout`]: crate::future::FutureExt::timeout
17    /// [`FutureExt`]: crate::future::futureExt
18    #[must_use = "futures do nothing unless polled or .awaited"]
19    pub struct Timeout<F, D> {
20        #[pin]
21        future: F,
22        #[pin]
23        deadline: D,
24        completed: bool,
25    }
26}
27
28impl<F, D> Timeout<F, D> {
29    pub(super) fn new(future: F, deadline: D) -> Self {
30        Self {
31            future,
32            deadline,
33            completed: false,
34        }
35    }
36}
37
38impl<F: Future, D: Future> Future for Timeout<F, D> {
39    type Output = io::Result<F::Output>;
40
41    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
42        let this = self.project();
43
44        assert!(!*this.completed, "future polled after completing");
45
46        match this.future.poll(cx) {
47            Poll::Ready(v) => {
48                *this.completed = true;
49                Poll::Ready(Ok(v))
50            }
51            Poll::Pending => match this.deadline.poll(cx) {
52                Poll::Ready(_) => {
53                    *this.completed = true;
54                    Poll::Ready(Err(timeout_err("future timed out")))
55                }
56                Poll::Pending => Poll::Pending,
57            },
58        }
59    }
60}