1use std::future::Future;
2use std::pin::Pin;
3use std::sync::{Arc, Mutex};
4use std::time::Duration;
5
6use time::OffsetDateTime;
7
8pub type SharedClock = Arc<dyn Clock>;
9
10pub trait Clock: Send + Sync + 'static {
11 fn now(&self) -> OffsetDateTime;
12
13 fn sleep<'a>(&'a self, duration: Duration) -> Pin<Box<dyn Future<Output = ()> + Send + 'a>>;
14}
15
16#[derive(Clone, Copy, Debug, Default)]
17pub struct SystemClock;
18
19impl Clock for SystemClock {
20 fn now(&self) -> OffsetDateTime {
21 OffsetDateTime::now_utc()
22 }
23
24 fn sleep<'a>(&'a self, duration: Duration) -> Pin<Box<dyn Future<Output = ()> + Send + 'a>> {
25 Box::pin(tokio::time::sleep(duration))
26 }
27}
28
29#[derive(Debug)]
30pub struct ManualClock {
31 now: Mutex<OffsetDateTime>,
32}
33
34impl ManualClock {
35 pub fn new(now: OffsetDateTime) -> Self {
36 Self {
37 now: Mutex::new(now),
38 }
39 }
40
41 pub fn advance(&self, duration: Duration) {
42 let delta = time::Duration::try_from(duration).unwrap_or(time::Duration::MAX);
43 let mut now = self.now.lock().expect("manual clock mutex poisoned");
44 *now += delta;
45 }
46
47 pub fn now(&self) -> OffsetDateTime {
48 *self.now.lock().expect("manual clock mutex poisoned")
49 }
50}
51
52impl Clock for ManualClock {
53 fn now(&self) -> OffsetDateTime {
54 Self::now(self)
55 }
56
57 fn sleep<'a>(&'a self, duration: Duration) -> Pin<Box<dyn Future<Output = ()> + Send + 'a>> {
58 Box::pin(async move {
59 self.advance(duration);
60 tokio::task::yield_now().await;
61 })
62 }
63}