nautilus_network/ratelimiter/
nanos.rs1use std::{
19 fmt::Debug,
20 ops::{Add, Div, Mul},
21 prelude::v1::*,
22 time::Duration,
23};
24
25use super::clock;
26
27#[derive(PartialEq, Eq, Default, Clone, Copy, PartialOrd, Ord)]
32pub struct Nanos(u64);
33
34impl Nanos {
35 pub const fn as_u64(self) -> u64 {
36 self.0
37 }
38}
39
40impl Nanos {
41 pub const fn new(u: u64) -> Self {
42 Self(u)
43 }
44}
45
46impl From<Duration> for Nanos {
47 fn from(d: Duration) -> Self {
48 Self(
50 d.as_nanos()
51 .try_into()
52 .expect("Duration is longer than 584 years"),
53 )
54 }
55}
56
57impl Debug for Nanos {
58 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
59 let d = Duration::from_nanos(self.0);
60 write!(f, "Nanos({d:?})")
61 }
62}
63
64impl Add<Self> for Nanos {
65 type Output = Self;
66
67 fn add(self, rhs: Self) -> Self::Output {
68 Self(self.0 + rhs.0)
69 }
70}
71
72impl Mul<u64> for Nanos {
73 type Output = Self;
74
75 fn mul(self, rhs: u64) -> Self::Output {
76 Self(self.0 * rhs)
77 }
78}
79
80impl Div<Self> for Nanos {
81 type Output = u64;
82
83 fn div(self, rhs: Self) -> Self::Output {
84 self.0 / rhs.0
85 }
86}
87
88impl From<u64> for Nanos {
89 fn from(u: u64) -> Self {
90 Self(u)
91 }
92}
93
94impl From<Nanos> for u64 {
95 fn from(n: Nanos) -> Self {
96 n.0
97 }
98}
99
100impl From<Nanos> for Duration {
101 fn from(n: Nanos) -> Self {
102 Self::from_nanos(n.0)
103 }
104}
105
106impl Nanos {
107 #[inline]
108 pub const fn saturating_sub(self, rhs: Self) -> Self {
109 Self(self.0.saturating_sub(rhs.0))
110 }
111}
112
113impl clock::Reference for Nanos {
114 #[inline]
115 fn duration_since(&self, earlier: Self) -> Nanos {
116 (*self as Self).saturating_sub(earlier)
117 }
118
119 #[inline]
120 fn saturating_sub(&self, duration: Nanos) -> Self {
121 (*self as Self).saturating_sub(duration)
122 }
123}
124
125impl Add<Duration> for Nanos {
126 type Output = Self;
127
128 fn add(self, other: Duration) -> Self {
129 let other: Self = other.into();
130 self + other
131 }
132}
133
134#[cfg(test)]
138mod test {
139 use std::time::Duration;
140
141 use rstest::rstest;
142
143 use super::*;
144
145 #[rstest]
146 fn nanos_impls() {
147 let n = Nanos::new(20);
148 assert_eq!("Nanos(20ns)", format!("{n:?}"));
149 }
150
151 #[rstest]
152 fn nanos_arith_coverage() {
153 let n = Nanos::new(20);
154 let n_half = Nanos::new(10);
155 assert_eq!(n / n_half, 2);
156 assert_eq!(30, (n + Duration::from_nanos(10)).as_u64());
157
158 assert_eq!(n_half.saturating_sub(n), Nanos::new(0));
159 assert_eq!(n.saturating_sub(n_half), n_half);
160 assert_eq!(clock::Reference::saturating_sub(&n_half, n), Nanos::new(0));
161 }
162}