1use core::fmt;
4use core::future::Future;
5use core::pin::Pin;
6use core::task::{Context, Poll};
7use std::time::Duration;
8
9use super::Instant;
10
11use super::error::Elapsed;
12use super::sleep::{Sleep, far_future, sleep_until};
13
14pub fn timeout<F: Future>(duration: Duration, future: F) -> Timeout<F> {
18 timeout_at(
19 Instant::now()
20 .checked_add(duration)
21 .unwrap_or_else(far_future),
22 future,
23 )
24}
25
26pub fn timeout_at<F: Future>(deadline: impl Into<Instant>, future: F) -> Timeout<F> {
28 Timeout {
29 future,
30 sleep: sleep_until(deadline),
31 }
32}
33
34#[must_use = "a timeout does nothing unless awaited"]
36pub struct Timeout<F> {
37 future: F,
38 sleep: Sleep,
39}
40
41impl<F> Timeout<F> {
42 pub fn get_ref(&self) -> &F {
44 &self.future
45 }
46
47 pub fn get_mut(&mut self) -> &mut F {
49 &mut self.future
50 }
51
52 pub fn into_inner(self) -> F {
54 self.future
55 }
56}
57
58impl<F: Future> Future for Timeout<F> {
59 type Output = Result<F::Output, Elapsed>;
60
61 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
62 let this = unsafe { self.get_unchecked_mut() };
65 let future = unsafe { Pin::new_unchecked(&mut this.future) };
67 if let Poll::Ready(output) = future.poll(cx) {
68 return Poll::Ready(Ok(output));
69 }
70 Pin::new(&mut this.sleep)
71 .poll(cx)
72 .map(|()| Err(Elapsed::new()))
73 }
74}
75
76impl<F: fmt::Debug> fmt::Debug for Timeout<F> {
77 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
78 f.debug_struct("Timeout")
79 .field("future", &self.future)
80 .field("deadline", &self.sleep.deadline())
81 .finish()
82 }
83}