governor/
nanos.rs

1//! A time-keeping abstraction (nanoseconds) that works for storing in an atomic integer.
2
3use crate::clock;
4
5use core::convert::TryInto;
6use core::fmt;
7use core::ops::{Add, Div, Mul};
8use core::time::Duration;
9
10/// A number of nanoseconds from a reference point.
11///
12/// Nanos can not represent durations >584 years, but hopefully that
13/// should not be a problem in real-world applications.
14#[derive(PartialEq, Eq, Default, Clone, Copy, PartialOrd, Ord)]
15pub struct Nanos(u64);
16
17impl Nanos {
18    pub fn as_u64(self) -> u64 {
19        self.0
20    }
21}
22
23/// Nanos as used by Jitter and other std-only features.
24#[cfg(feature = "std")]
25impl Nanos {
26    pub const fn new(u: u64) -> Self {
27        Nanos(u)
28    }
29}
30
31impl From<Duration> for Nanos {
32    fn from(d: Duration) -> Self {
33        // This will panic:
34        Nanos(
35            d.as_nanos()
36                .try_into()
37                .expect("Duration is longer than 584 years"),
38        )
39    }
40}
41
42impl fmt::Debug for Nanos {
43    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
44        let d = Duration::from_nanos(self.0);
45        write!(f, "Nanos({d:?})")
46    }
47}
48
49impl Add<Nanos> for Nanos {
50    type Output = Nanos;
51
52    fn add(self, rhs: Nanos) -> Self::Output {
53        Nanos(self.0 + rhs.0)
54    }
55}
56
57impl Mul<u64> for Nanos {
58    type Output = Nanos;
59
60    fn mul(self, rhs: u64) -> Self::Output {
61        Nanos(self.0 * rhs)
62    }
63}
64
65impl Div<Nanos> for Nanos {
66    type Output = u64;
67
68    fn div(self, rhs: Nanos) -> Self::Output {
69        self.0 / rhs.0
70    }
71}
72
73impl From<u64> for Nanos {
74    fn from(u: u64) -> Self {
75        Nanos(u)
76    }
77}
78
79impl From<Nanos> for u64 {
80    fn from(n: Nanos) -> Self {
81        n.0
82    }
83}
84
85impl From<Nanos> for Duration {
86    fn from(n: Nanos) -> Self {
87        Duration::from_nanos(n.0)
88    }
89}
90
91impl Nanos {
92    #[inline]
93    pub fn saturating_sub(self, rhs: Nanos) -> Nanos {
94        Nanos(self.0.saturating_sub(rhs.0))
95    }
96}
97
98impl clock::Reference for Nanos {
99    #[inline]
100    fn duration_since(&self, earlier: Self) -> Nanos {
101        (*self as Nanos).saturating_sub(earlier)
102    }
103
104    #[inline]
105    fn saturating_sub(&self, duration: Nanos) -> Self {
106        (*self as Nanos).saturating_sub(duration)
107    }
108}
109
110impl Add<Duration> for Nanos {
111    type Output = Self;
112
113    fn add(self, other: Duration) -> Self {
114        let other: Nanos = other.into();
115        self + other
116    }
117}
118
119#[cfg(all(feature = "std", test))]
120mod test {
121    use super::*;
122    use std::time::Duration;
123
124    #[test]
125    fn nanos_impls() {
126        let n = Nanos::new(20);
127        assert_eq!("Nanos(20ns)", format!("{n:?}"));
128    }
129
130    #[test]
131    fn nanos_arith_coverage() {
132        let n = Nanos::new(20);
133        let n_half = Nanos::new(10);
134        assert_eq!(n / n_half, 2);
135        assert_eq!(30, (n + Duration::from_nanos(10)).as_u64());
136
137        assert_eq!(n_half.saturating_sub(n), Nanos::new(0));
138        assert_eq!(n.saturating_sub(n_half), n_half);
139        assert_eq!(clock::Reference::saturating_sub(&n_half, n), Nanos::new(0));
140    }
141}