async_time_mock_async_std/
instant.rs

1use crate::MockableClock;
2use std::cmp::Ordering;
3use std::time::Duration;
4
5#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
6pub enum Instant {
7	Real(std::time::Instant),
8	#[cfg(feature = "mock")]
9	Mock(async_time_mock_core::Instant),
10}
11
12impl From<std::time::Instant> for Instant {
13	fn from(instant: std::time::Instant) -> Self {
14		Self::Real(instant)
15	}
16}
17
18#[cfg(feature = "mock")]
19impl From<async_time_mock_core::Instant> for Instant {
20	fn from(instant: async_time_mock_core::Instant) -> Self {
21		Self::Mock(instant)
22	}
23}
24
25impl Instant {
26	// std::time::Instant::now() isn't supported because it would require a TimerRegistry
27
28	/// Equivalent to [`std::time::Instant::duration_since`].
29	///
30	/// # Panics
31	/// If `self` and `earlier` aren't either both mock or both real.
32	pub fn duration_since(&self, earlier: Self) -> Duration {
33		match (self, earlier) {
34			(Instant::Real(this), Instant::Real(earlier)) => this.duration_since(earlier),
35			#[cfg(feature = "mock")]
36			(Instant::Mock(this), Instant::Mock(earlier)) => this.duration_since(earlier),
37			#[cfg(feature = "mock")]
38			_ => panic!("Instants weren't compatible, both need to be either real or mocked"),
39		}
40	}
41
42	/// Equivalent to [`std::time::Instant::checked_duration_since`].
43	pub fn checked_duration_since(&self, earlier: Self) -> Option<Duration> {
44		match (self, earlier) {
45			(Instant::Real(this), Instant::Real(earlier)) => this.checked_duration_since(earlier),
46			#[cfg(feature = "mock")]
47			(Instant::Mock(this), Instant::Mock(earlier)) => this.checked_duration_since(earlier),
48			#[cfg(feature = "mock")]
49			_ => panic!("Instants weren't compatible, both need to be either real or mocked"),
50		}
51	}
52
53	/// Equivalent to [`std::time::Instant::saturated_duration_since`].
54	pub fn saturated_duration_since(&self, earlier: Self) -> Duration {
55		match (self, earlier) {
56			(Instant::Real(this), Instant::Real(earlier)) => this.saturating_duration_since(earlier),
57			#[cfg(feature = "mock")]
58			(Instant::Mock(this), Instant::Mock(earlier)) => this.saturated_duration_since(earlier),
59			#[cfg(feature = "mock")]
60			_ => panic!("Instants weren't compatible, both need to be either real or mocked"),
61		}
62	}
63
64	/// Similar to [`std::time::Instant::elapsed`], but needs a [`MockableClock`] to calculate the that hat has passed
65	pub fn elapsed(&self, clock: &MockableClock) -> Duration {
66		match (self, clock) {
67			(Instant::Real(this), MockableClock::Real) => this.elapsed(),
68			#[cfg(feature = "mock")]
69			(Instant::Mock(this), MockableClock::Mock(registry)) => this.elapsed(registry),
70			#[cfg(feature = "mock")]
71			_ => panic!("Instant and MockableClock were not compatible"),
72		}
73	}
74
75	/// Equivalent to [`std::time::Instant::checked_add`].
76	pub fn checked_add(&self, duration: Duration) -> Option<Self> {
77		use Instant::*;
78		match self {
79			Real(this) => this.checked_add(duration).map(Into::into),
80			#[cfg(feature = "mock")]
81			Mock(this) => this.checked_add(duration).map(Into::into),
82		}
83	}
84
85	/// Equivalent to [`std::time::Instant::checked_sub`].
86	pub fn checked_sub(&self, duration: Duration) -> Option<Self> {
87		use Instant::*;
88		match self {
89			Real(this) => this.checked_sub(duration).map(Into::into),
90			#[cfg(feature = "mock")]
91			Mock(this) => this.checked_sub(duration).map(Into::into),
92		}
93	}
94}
95
96impl PartialOrd for Instant {
97	fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
98		Some(self.cmp(other))
99	}
100}
101
102impl Ord for Instant {
103	fn cmp(&self, other: &Self) -> Ordering {
104		match (self, other) {
105			(Instant::Real(this), Instant::Real(other)) => this.cmp(other),
106			#[cfg(feature = "mock")]
107			(Instant::Mock(this), Instant::Mock(other)) => this.cmp(other),
108			#[cfg(feature = "mock")]
109			_ => panic!("Instants weren't compatible, both need to be either real or mocked"),
110		}
111	}
112}