button_driver/
instant.rs

1use core::{ops::Sub, time::Duration};
2
3/// An abstraction for retrieving the current time.
4///
5/// The underlying counter shell be monotonic in order for the crate to
6/// operate correctly.
7pub trait InstantProvider<D = Duration>
8where
9    // `Clone` is less strict then `Copy` and usually implemented using it.
10    Self: Sub<Self, Output = D> + Clone,
11{
12    /// Returns an instant corresponding to "now".
13    fn now() -> Self;
14
15    /// Returns the amount of time elapsed since this instant.
16    fn elapsed(&self) -> D {
17        Self::now() - self.clone()
18    }
19}
20
21#[cfg(feature = "std")]
22impl InstantProvider<std::time::Duration> for std::time::Instant {
23    fn now() -> Self {
24        std::time::Instant::now()
25    }
26}
27
28#[cfg(feature = "embassy")]
29impl InstantProvider<embassy_time::Duration> for embassy_time::Instant {
30    fn now() -> Self {
31        embassy_time::Instant::now()
32    }
33}
34
35#[cfg(feature = "wasm")]
36pub mod wasm {
37    //! A JS Date-based implementation of `InstantProvider`.
38    //! This can be useful for `wasm32-*` targets.
39
40    use core::{ops::Sub, time::Duration};
41
42    use crate::InstantProvider;
43
44    /// A wrapper around `js_sys::Date` that implements `InstantProvider`.
45    ///
46    /// This type stores the timestamp as milliseconds since the Unix epoch.
47    #[derive(Clone, PartialEq)]
48    pub struct Instant(f64);
49
50    impl Sub for Instant {
51        type Output = Duration;
52
53        fn sub(self, rhs: Self) -> Self::Output {
54            // Instant should be monotonic, so self.0 >= rhs.0
55            let delta_ms = self.0 - rhs.0;
56            let millis = delta_ms.trunc() as u64;
57            let micros = (delta_ms.fract() * 1000.0) as u64;
58            Duration::from_millis(millis) + Duration::from_micros(micros)
59        }
60    }
61
62    impl InstantProvider<Duration> for Instant {
63        fn now() -> Self {
64            Instant(js_sys::Date::now())
65        }
66    }
67}