std_embedded_time/
lib.rs

1//! # Standard `embedded-time`
2//!
3//! This library provides an [embedded_time::Clock] that can be used for host-side testing.
4//!
5//! The provided [embedded_time::Clock] implementation is based on [std::time].
6//!
7//! # Usage
8//!
9//! ```rust
10//! use std_embedded_time::StandardClock;
11//! use embedded_time::Clock;
12//!
13//! fn main() {
14//!     let clock = StandardClock::default();
15//!
16//!     let now = clock.try_now().unwrap();
17//!     println!("Current time: {:?}", now);
18//! }
19//! ```
20
21pub use embedded_time;
22
23use embedded_time::{fraction::Fraction, Instant};
24
25/// A clock with nanosecond precision.
26///
27/// To construct a clock, use [StandardClock::default()].
28///
29/// The clock is "started" when it is constructed.
30///
31/// # Limitations
32/// The clock represents up to ~584 years worth of time, after which it will roll over.
33#[derive(Copy, Clone, Debug)]
34pub struct StandardClock {
35    start: std::time::Instant,
36}
37
38impl Default for StandardClock {
39    fn default() -> Self {
40        Self {
41            start: std::time::Instant::now(),
42        }
43    }
44}
45
46impl embedded_time::Clock for StandardClock {
47    /// With a 64-bit tick register, the clock can represent times up to approximately 594 years in
48    /// duration, after which the clock will roll over.
49    type T = u64;
50
51    /// Each tick of the clock is equivalent to 1 nanosecond.
52    const SCALING_FACTOR: Fraction = Fraction::new(1, 1_000_000_000);
53
54    /// Get the current time from the clock.
55    fn try_now(&self) -> Result<Instant<Self>, embedded_time::clock::Error> {
56        let now = std::time::Instant::now();
57
58        let elapsed = now.duration_since(self.start);
59
60        // Note: We are discarding the upper 64 bits of nanoseconds. However, even while doing so,
61        // we can represent ~594 years of time, so this should not be relevant.
62        Ok(Instant::new(elapsed.as_nanos() as u64))
63    }
64}
65
66#[cfg(test)]
67mod test {
68    use super::StandardClock;
69    use core::convert::TryFrom;
70    use embedded_time::{duration::*, Clock};
71    use std::time::Duration;
72
73    #[test]
74    fn test_measurement() {
75        let clock = StandardClock::default();
76
77        let start = clock.try_now().unwrap();
78        std::thread::sleep(Duration::from_secs(1));
79        let end = clock.try_now().unwrap();
80
81        let elapsed = end - start;
82
83        let lower_bound = Milliseconds::<u64>::try_from(999u32.milliseconds()).unwrap();
84        assert!(elapsed > lower_bound.into());
85
86        let upper_bound = Milliseconds::<u64>::try_from(2000u32.milliseconds()).unwrap();
87        assert!(elapsed < upper_bound.into());
88    }
89}