governor/
nanos.rs

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