button-driver 0.2.5

Advanced button handling crate
Documentation
use core::{ops::Sub, time::Duration};

/// An abstraction for retrieving the current time.
///
/// The underlying counter shell be monotonic in order for the crate to
/// operate correctly.
pub trait InstantProvider<D = Duration>
where
    // `Clone` is less strict then `Copy` and usually implemented using it.
    Self: Sub<Self, Output = D> + Clone,
{
    /// Returns an instant corresponding to "now".
    fn now() -> Self;

    /// Returns the amount of time elapsed since this instant.
    fn elapsed(&self) -> D {
        Self::now() - self.clone()
    }
}

#[cfg(feature = "std")]
impl InstantProvider<std::time::Duration> for std::time::Instant {
    fn now() -> Self {
        std::time::Instant::now()
    }
}

#[cfg(feature = "embassy")]
impl InstantProvider<embassy_time::Duration> for embassy_time::Instant {
    fn now() -> Self {
        embassy_time::Instant::now()
    }
}

#[cfg(feature = "wasm")]
pub mod wasm {
    //! A JS Date-based implementation of `InstantProvider`.
    //! This can be useful for `wasm32-*` targets.

    use core::{ops::Sub, time::Duration};

    use crate::InstantProvider;

    /// A wrapper around `js_sys::Date` that implements `InstantProvider`.
    ///
    /// This type stores the timestamp as milliseconds since the Unix epoch.
    #[derive(Clone, PartialEq)]
    pub struct Instant(f64);

    impl Sub for Instant {
        type Output = Duration;

        fn sub(self, rhs: Self) -> Self::Output {
            // Instant should be monotonic, so self.0 >= rhs.0
            let delta_ms = self.0 - rhs.0;
            let millis = delta_ms.trunc() as u64;
            let micros = (delta_ms.fract() * 1000.0) as u64;
            Duration::from_millis(millis) + Duration::from_micros(micros)
        }
    }

    impl InstantProvider<Duration> for Instant {
        fn now() -> Self {
            Instant(js_sys::Date::now())
        }
    }
}