hyper/rt/
timer.rs

1//! Provides a timer trait with timer-like functions
2//!
3//! Example using tokio timer:
4//! ```rust
5//! use std::{
6//!     future::Future,
7//!     pin::Pin,
8//!     task::{Context, Poll},
9//!     time::{Duration, Instant},
10//! };
11//!
12//! use pin_project_lite::pin_project;
13//! use hyper::rt::{Timer, Sleep};
14//!
15//! #[derive(Clone, Debug)]
16//! pub struct TokioTimer;
17//!
18//! impl Timer for TokioTimer {
19//!     fn sleep(&self, duration: Duration) -> Pin<Box<dyn Sleep>> {
20//!         Box::pin(TokioSleep {
21//!             inner: tokio::time::sleep(duration),
22//!         })
23//!     }
24//!
25//!     fn sleep_until(&self, deadline: Instant) -> Pin<Box<dyn Sleep>> {
26//!         Box::pin(TokioSleep {
27//!             inner: tokio::time::sleep_until(deadline.into()),
28//!         })
29//!     }
30//!
31//!     fn reset(&self, sleep: &mut Pin<Box<dyn Sleep>>, new_deadline: Instant) {
32//!         if let Some(sleep) = sleep.as_mut().downcast_mut_pin::<TokioSleep>() {
33//!             sleep.reset(new_deadline.into())
34//!         }
35//!     }
36//! }
37//!
38//! pin_project! {
39//!     pub(crate) struct TokioSleep {
40//!         #[pin]
41//!         pub(crate) inner: tokio::time::Sleep,
42//!     }
43//! }
44//!
45//! impl Future for TokioSleep {
46//!     type Output = ();
47//!
48//!     fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
49//!         self.project().inner.poll(cx)
50//!     }
51//! }
52//!
53//! impl Sleep for TokioSleep {}
54//!
55//! impl TokioSleep {
56//!     pub fn reset(self: Pin<&mut Self>, deadline: Instant) {
57//!         self.project().inner.as_mut().reset(deadline.into());
58//!     }
59//! }
60//! ```
61
62use std::{
63    any::TypeId,
64    future::Future,
65    pin::Pin,
66    time::{Duration, Instant},
67};
68
69/// A timer which provides timer-like functions.
70pub trait Timer {
71    /// Return a future that resolves in `duration` time.
72    fn sleep(&self, duration: Duration) -> Pin<Box<dyn Sleep>>;
73
74    /// Return a future that resolves at `deadline`.
75    fn sleep_until(&self, deadline: Instant) -> Pin<Box<dyn Sleep>>;
76
77    /// Return an `Instant` representing the current time.
78    ///
79    /// The default implementation returns [`Instant::now()`].
80    fn now(&self) -> Instant {
81        Instant::now()
82    }
83
84    /// Reset a future to resolve at `new_deadline` instead.
85    fn reset(&self, sleep: &mut Pin<Box<dyn Sleep>>, new_deadline: Instant) {
86        *sleep = self.sleep_until(new_deadline);
87    }
88}
89
90/// A future returned by a `Timer`.
91pub trait Sleep: Send + Sync + Future<Output = ()> {
92    #[doc(hidden)]
93    /// This method is private and can not be implemented by downstream crate
94    fn __type_id(&self, _: private::Sealed) -> TypeId
95    where
96        Self: 'static,
97    {
98        TypeId::of::<Self>()
99    }
100}
101
102impl dyn Sleep {
103    //! This is a re-implementation of downcast methods from std::any::Any
104
105    /// Check whether the type is the same as `T`
106    pub fn is<T>(&self) -> bool
107    where
108        T: Sleep + 'static,
109    {
110        self.__type_id(private::Sealed {}) == TypeId::of::<T>()
111    }
112
113    /// Downcast a pinned &mut Sleep object to its original type
114    pub fn downcast_mut_pin<T>(self: Pin<&mut Self>) -> Option<Pin<&mut T>>
115    where
116        T: Sleep + 'static,
117    {
118        if self.is::<T>() {
119            unsafe {
120                let inner = Pin::into_inner_unchecked(self);
121                Some(Pin::new_unchecked(
122                    &mut *(&mut *inner as *mut dyn Sleep as *mut T),
123                ))
124            }
125        } else {
126            None
127        }
128    }
129}
130
131mod private {
132    #![allow(missing_debug_implementations)]
133    pub struct Sealed {}
134}