async_time_mock_smol/
lib.rs

1#![doc = include_str!("../README.md")]
2
3use std::future::Future;
4use std::time::{Duration, SystemTime};
5
6mod instant;
7pub use instant::Instant;
8
9mod timer;
10pub use timer::Timer;
11
12#[cfg(feature = "mock")]
13pub use async_time_mock_core as core;
14
15#[derive(Clone)]
16pub enum MockableClock {
17	Real,
18	#[cfg(feature = "mock")]
19	Mock(std::sync::Arc<async_time_mock_core::TimerRegistry>),
20}
21
22pub enum TimeHandlerGuard {
23	Real,
24	#[cfg(feature = "mock")]
25	Mock(async_time_mock_core::TimeHandlerGuard),
26}
27
28#[cfg(feature = "mock")]
29impl From<async_time_mock_core::TimeHandlerGuard> for TimeHandlerGuard {
30	fn from(guard: async_time_mock_core::TimeHandlerGuard) -> Self {
31		Self::Mock(guard)
32	}
33}
34
35impl MockableClock {
36	#[cfg(feature = "mock")]
37	pub fn mock() -> (Self, std::sync::Arc<async_time_mock_core::TimerRegistry>) {
38		let timer_registry = std::sync::Arc::new(async_time_mock_core::TimerRegistry::default());
39		(Self::Mock(timer_registry.clone()), timer_registry)
40	}
41
42	pub fn now(&self) -> Instant {
43		use MockableClock::*;
44		match self {
45			Real => std::time::Instant::now().into(),
46			#[cfg(feature = "mock")]
47			Mock(registry) => registry.now().into(),
48		}
49	}
50
51	pub fn system_time(&self) -> SystemTime {
52		use MockableClock::*;
53		match self {
54			Real => SystemTime::now(),
55			#[cfg(feature = "mock")]
56			Mock(registry) => registry.system_time(),
57		}
58	}
59
60	pub fn sleep(&self, duration: Duration) -> impl Future<Output = TimeHandlerGuard> + Send + 'static {
61		let clock = self.clone();
62		async move {
63			use MockableClock::*;
64			match clock {
65				Real => {
66					async_io::Timer::after(duration).await;
67					TimeHandlerGuard::Real
68				}
69				#[cfg(feature = "mock")]
70				Mock(registry) => registry.sleep(duration).await.into(),
71			}
72		}
73	}
74
75	pub fn sleep_until(&self, until: Instant) -> impl Future<Output = TimeHandlerGuard> + Send + 'static {
76		let clock = self.clone();
77		async move {
78			match (clock, until) {
79				(MockableClock::Real, Instant::Real(until)) => {
80					async_io::Timer::at(until).await;
81					TimeHandlerGuard::Real
82				}
83				#[cfg(feature = "mock")]
84				(MockableClock::Mock(registry), Instant::Mock(until)) => registry.sleep_until(until).await.into(),
85				#[cfg(feature = "mock")]
86				_ => panic!("Clock and instant weren't compatible, both need to be either real or mocked"),
87			}
88		}
89	}
90
91	pub fn interval(&self, period: Duration) -> Timer {
92		use MockableClock::*;
93		match self {
94			Real => async_io::Timer::interval(period).into(),
95			#[cfg(feature = "mock")]
96			Mock(registry) => registry.interval(period).into(),
97		}
98	}
99
100	pub fn interval_at(&self, start: Instant, period: Duration) -> Timer {
101		match (self, start) {
102			(MockableClock::Real, Instant::Real(start)) => async_io::Timer::interval_at(start, period).into(),
103			#[cfg(feature = "mock")]
104			(MockableClock::Mock(registry), Instant::Mock(start)) => registry.interval_at(start, period).into(),
105			#[cfg(feature = "mock")]
106			_ => panic!("Clock and instant weren't compatible, both need to be either real or mocked"),
107		}
108	}
109
110	// AFAIK smol doesn't have any timeout functionality
111}