futures_concurrency/future/
wait_until.rs

1use core::future::Future;
2use core::pin::Pin;
3use core::task::{ready, Context, Poll};
4
5/// Suspends a future until the specified deadline.
6///
7/// This `struct` is created by the [`wait_until`] method on [`FutureExt`]. See its
8/// documentation for more.
9///
10/// [`wait_until`]: crate::future::FutureExt::wait_until
11/// [`FutureExt`]: crate::future::FutureExt
12#[derive(Debug)]
13#[pin_project::pin_project]
14#[must_use = "futures do nothing unless polled or .awaited"]
15pub struct WaitUntil<F, D> {
16    #[pin]
17    future: F,
18    #[pin]
19    deadline: D,
20    state: State,
21}
22
23/// The internal state
24#[derive(Debug)]
25enum State {
26    Started,
27    PollFuture,
28    Completed,
29}
30
31impl<F, D> WaitUntil<F, D> {
32    pub(super) fn new(future: F, deadline: D) -> Self {
33        Self {
34            future,
35            deadline,
36            state: State::Started,
37        }
38    }
39}
40
41impl<F: Future, D: Future> Future for WaitUntil<F, D> {
42    type Output = F::Output;
43
44    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
45        let mut this = self.project();
46        loop {
47            match this.state {
48                State::Started => {
49                    ready!(this.deadline.as_mut().poll(cx));
50                    *this.state = State::PollFuture;
51                }
52                State::PollFuture => {
53                    let value = ready!(this.future.as_mut().poll(cx));
54                    *this.state = State::Completed;
55                    return Poll::Ready(value);
56                }
57                State::Completed => panic!("future polled after completing"),
58            }
59        }
60    }
61}