simple_clock/
lib.rs

1//! This library provides a very simple system clock interface with microsecond precision.
2//! Unlike the [`embedded-time`](https://crates.io/crates/embedded-time),
3//! the interface provided by this library is as simple as possible which is better suited
4//! for writing prototypes.
5
6#![cfg_attr(not(test), no_std)]
7
8#[cfg(test)]
9mod tests;
10
11/// Provides an abstraction for hardware-specific clocks with the microsecond precision.
12pub trait SimpleClock {
13    /// Returns an instant time in the microseconds.
14    fn now_us(&self) -> u64;
15}
16
17/// Provides an easy way to calculate elapsed times.
18///
19/// This timer is usually used to compute how much time is elapsed between two events
20/// or to determine the event's deadline in case of polling.
21pub struct ElapsedTimer<'a, T> {
22    clock: &'a T,
23    now: u64,
24}
25
26impl<'a, T: SimpleClock> ElapsedTimer<'a, T> {
27    /// Creates a new elapsed timer instance backed by the specified clock implementation.
28    pub fn new(clock: &'a T) -> Self {
29        Self {
30            clock,
31            now: clock.now_us(),
32        }
33    }
34
35    /// Restarts the timer and returns the number of microseconds
36    /// elapsed since this timer was started.
37    pub fn restart(&mut self) -> u64 {
38        let elapsed = self.elapsed();
39        self.now = self.clock.now_us();
40        elapsed
41    }
42
43    /// Returns the number of microseconds elapsed since this timer was started.
44    pub fn elapsed(&self) -> u64 {
45        self.clock.now_us().saturating_sub(self.now)
46    }
47}
48
49/// The deadline has been reached.
50#[derive(Debug, Clone, Copy, PartialEq, Eq)]
51pub struct DeadlineReached(());
52
53/// Provides an easy way to specify operation deadline
54///
55/// This timer is usually used to limit polling operation by a certain period of time.
56#[derive(Debug)]
57pub struct Deadline<'a, C: SimpleClock> {
58    clock: &'a C,
59    deadline: u64,
60}
61
62impl<'a, C: SimpleClock> Deadline<'a, C> {
63    /// Creates a new deadline timer instance backed by the specified clock implementation
64    pub fn new(clock: &'a C, timeout: u64) -> Self {
65        Self {
66            clock,
67            deadline: clock.now_us() + timeout,
68        }
69    }
70
71    /// Returns error if the deadline has been reached.
72    pub fn reached(&self) -> Result<(), DeadlineReached> {
73        if self.clock.now_us() > self.deadline {
74            Err(DeadlineReached(()))
75        } else {
76            Ok(())
77        }
78    }
79}