moka/common/time/
instant.rs
1use std::time::Duration;
2
3pub(crate) const MAX_NANOS: u64 = u64::MAX - 1;
4
5#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
8pub(crate) struct Instant {
9 elapsed_ns: u64,
10}
11
12impl Instant {
13 pub(crate) fn from_nanos(nanos: u64) -> Instant {
14 debug_assert!(nanos <= MAX_NANOS);
15 Instant { elapsed_ns: nanos }
16 }
17
18 pub(crate) fn from_duration_since_clock_start(duration: Duration) -> Instant {
19 Instant::from_nanos(Self::duration_to_saturating_nanoseconds(duration))
20 }
21
22 pub(crate) fn as_nanos(&self) -> u64 {
23 self.elapsed_ns
24 }
25
26 pub(crate) fn duration_to_saturating_nanoseconds(duration: Duration) -> u64 {
33 u64::try_from(duration.as_nanos())
34 .map(|n| n.min(MAX_NANOS))
35 .unwrap_or(MAX_NANOS)
36 }
37
38 pub(crate) fn saturating_add(&self, duration: Duration) -> Instant {
39 let dur_ms = Self::duration_to_saturating_nanoseconds(duration);
40 Instant::from_nanos(self.elapsed_ns.saturating_add(dur_ms).min(MAX_NANOS))
41 }
42
43 pub(crate) fn saturating_duration_since(&self, earlier: Self) -> Duration
44 where
45 Self: Sized,
46 {
47 Duration::from_nanos(self.elapsed_ns.saturating_sub(earlier.elapsed_ns))
48 }
49}
50
51#[cfg(test)]
52mod tests {
53 use super::*;
54
55 #[test]
56 fn test_saturating_add() {
57 let instant = Instant::from_nanos(100_000);
58 let duration = Duration::from_nanos(50_000);
59 let result = instant.saturating_add(duration);
60 assert_eq!(result, Instant::from_nanos(150_000));
61
62 let instant = Instant::from_nanos(u64::MAX - 10_000);
63 let duration = Duration::from_nanos(12_000);
64 let result = instant.saturating_add(duration);
65 assert_eq!(result, Instant::from_nanos(u64::MAX - 1));
66 }
67
68 #[test]
69 fn test_saturating_duration_since() {
70 let instant = Instant::from_nanos(100_000);
71 let earlier = Instant::from_nanos(60_000);
72 let result = instant.saturating_duration_since(earlier);
73 assert_eq!(result, Duration::from_nanos(40_000));
74
75 let instant = Instant::from_nanos(60_000);
76 let earlier = Instant::from_nanos(100_000);
77 let result = instant.saturating_duration_since(earlier);
78 assert_eq!(result, Duration::ZERO);
79 }
80}