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 | |
62 | use std::{ |
63 | any::TypeId, |
64 | future::Future, |
65 | pin::Pin, |
66 | time::{Duration, Instant}, |
67 | }; |
68 | |
69 | /// A timer which provides timer-like functions. |
70 | pub 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 | /// Reset a future to resolve at `new_deadline` instead. |
78 | fn reset(&self, sleep: &mut Pin<Box<dyn Sleep>>, new_deadline: Instant) { |
79 | *sleep = self.sleep_until(new_deadline); |
80 | } |
81 | } |
82 | |
83 | /// A future returned by a `Timer`. |
84 | pub trait Sleep: Send + Sync + Future<Output = ()> { |
85 | #[doc (hidden)] |
86 | /// This method is private and can not be implemented by downstream crate |
87 | fn __type_id(&self, _: private::Sealed) -> TypeId |
88 | where |
89 | Self: 'static, |
90 | { |
91 | TypeId::of::<Self>() |
92 | } |
93 | } |
94 | |
95 | impl dyn Sleep { |
96 | //! This is a re-implementation of downcast methods from std::any::Any |
97 | |
98 | /// Check whether the type is the same as `T` |
99 | pub fn is<T>(&self) -> bool |
100 | where |
101 | T: Sleep + 'static, |
102 | { |
103 | self.__type_id(private::Sealed {}) == TypeId::of::<T>() |
104 | } |
105 | |
106 | /// Downcast a pinned &mut Sleep object to its original type |
107 | pub fn downcast_mut_pin<T>(self: Pin<&mut Self>) -> Option<Pin<&mut T>> |
108 | where |
109 | T: Sleep + 'static, |
110 | { |
111 | if self.is::<T>() { |
112 | unsafe { |
113 | let inner = Pin::into_inner_unchecked(self); |
114 | Some(Pin::new_unchecked( |
115 | &mut *(&mut *inner as *mut dyn Sleep as *mut T), |
116 | )) |
117 | } |
118 | } else { |
119 | None |
120 | } |
121 | } |
122 | } |
123 | |
124 | mod private { |
125 | #![allow (missing_debug_implementations)] |
126 | pub struct Sealed {} |
127 | } |
128 | |