async_time_mock_core/
instant.rs1use crate::TimerRegistry;
2use std::ops::{Add, AddAssign, Sub, SubAssign};
3use std::time::Duration;
4
5#[derive(Copy, Clone, Debug, Hash, PartialOrd, Ord, PartialEq, Eq)]
6pub struct Instant {
7 duration: Duration,
8 timer_registry_id: u64,
9}
10
11impl Instant {
12 pub(crate) const fn new(duration: Duration, timer_registry_id: u64) -> Self {
13 Self {
14 duration,
15 timer_registry_id,
16 }
17 }
18
19 pub(crate) const fn into_duration(self, timer_registry_id: u64) -> Duration {
20 if self.timer_registry_id != timer_registry_id {
21 panic!("Can't use Instants from one TimerRegistry in another TimerRegistry.");
22 }
23 self.duration
24 }
25
26 pub const fn duration_since(&self, earlier: Self) -> Duration {
30 self.assert_instances_are_compatible(&earlier);
31 self.duration.saturating_sub(earlier.duration)
32 }
33
34 pub const fn checked_duration_since(&self, earlier: Self) -> Option<Duration> {
36 self.assert_instances_are_compatible(&earlier);
37 self.duration.checked_sub(earlier.duration)
38 }
39
40 pub const fn saturated_duration_since(&self, earlier: Self) -> Duration {
42 self.assert_instances_are_compatible(&earlier);
43 self.duration.saturating_sub(earlier.duration)
44 }
45
46 pub fn elapsed(&self, timer_registry: &TimerRegistry) -> Duration {
51 timer_registry.now().duration_since(*self)
52 }
53
54 pub const fn checked_add(&self, duration: Duration) -> Option<Self> {
56 let timer_registry_id = self.timer_registry_id;
57 match self.duration.checked_add(duration) {
58 Some(duration) => Some(Self {
59 duration,
60 timer_registry_id,
61 }),
62 None => None,
63 }
64 }
65
66 pub const fn checked_sub(&self, duration: Duration) -> Option<Self> {
68 let timer_registry_id = self.timer_registry_id;
69 match self.duration.checked_sub(duration) {
70 Some(duration) => Some(Self {
71 duration,
72 timer_registry_id,
73 }),
74 None => None,
75 }
76 }
77
78 const fn assert_instances_are_compatible(&self, other: &Self) {
79 if self.timer_registry_id != other.timer_registry_id {
80 panic!("Operations between Instant's from different TimerRegistry instances are not supported.");
81 }
82 }
83}
84
85impl Add<Duration> for Instant {
86 type Output = Instant;
87
88 fn add(self, rhs: Duration) -> Self::Output {
89 Self {
90 duration: self.duration.add(rhs),
91 timer_registry_id: self.timer_registry_id,
92 }
93 }
94}
95
96impl AddAssign<Duration> for Instant {
97 fn add_assign(&mut self, rhs: Duration) {
98 self.duration.add_assign(rhs);
99 }
100}
101
102impl Sub<Duration> for Instant {
103 type Output = Instant;
104
105 fn sub(self, rhs: Duration) -> Self::Output {
106 Self {
107 duration: self.duration.sub(rhs),
108 timer_registry_id: self.timer_registry_id,
109 }
110 }
111}
112
113impl Sub<Instant> for Instant {
114 type Output = Duration;
115
116 fn sub(self, rhs: Instant) -> Self::Output {
117 self.assert_instances_are_compatible(&rhs);
118 self.duration.sub(rhs.duration)
119 }
120}
121
122impl SubAssign<Duration> for Instant {
123 fn sub_assign(&mut self, rhs: Duration) {
124 self.duration.sub_assign(rhs);
125 }
126}
127
128#[cfg(test)]
129mod test {
130 use super::*;
131 use std::time::Duration;
132
133 #[test]
134 #[should_panic]
135 fn should_not_allow_fetching_duration_from_incorrect_timer_registry() {
136 Instant::new(Duration::ZERO, 0).into_duration(1);
137 }
138}