1use std::{
2 fmt::Debug,
3 ops::{Deref, DerefMut},
4 sync::{
5 atomic::{AtomicU64, Ordering},
6 Arc,
7 },
8 time::{SystemTime, UNIX_EPOCH},
9};
10
11pub trait Clock {
12 fn now(&self) -> u64;
13}
14
15#[derive(Debug)]
16pub struct SystemClock {}
17
18impl Clock for SystemClock {
19 fn now(&self) -> u64 {
20 SystemTime::now()
21 .duration_since(UNIX_EPOCH)
22 .unwrap()
23 .as_millis() as u64
24 }
25}
26
27#[derive(Debug)]
28pub struct DebugClock {
29 time: AtomicU64,
30}
31
32impl DebugClock {
33 pub fn new(time: u64) -> DebugClock {
34 DebugClock {
35 time: AtomicU64::new(time),
36 }
37 }
38
39 pub fn set(&self, time: u64) {
40 self.time.store(time, Ordering::Release);
41 }
42}
43
44impl Clock for DebugClock {
45 fn now(&self) -> u64 {
46 self.time.load(Ordering::Acquire)
47 }
48}
49
50#[derive(Debug)]
51pub enum ClockImpl {
52 System(SystemClock),
53 Debug(Arc<DebugClock>),
54}
55
56impl Clock for ClockImpl {
57 fn now(&self) -> u64 {
58 match self {
59 ClockImpl::System(c) => c.now(),
60 ClockImpl::Debug(c) => c.now(),
61 }
62 }
63}
64
65#[derive(Debug)]
66pub struct BitcaskyClock {
67 pub clock: ClockImpl,
68}
69
70impl Clock for BitcaskyClock {
71 fn now(&self) -> u64 {
72 self.clock.now()
73 }
74}
75
76impl Deref for BitcaskyClock {
77 type Target = ClockImpl;
78
79 fn deref(&self) -> &Self::Target {
80 &self.clock
81 }
82}
83
84impl DerefMut for BitcaskyClock {
85 fn deref_mut(&mut self) -> &mut Self::Target {
86 &mut self.clock
87 }
88}
89
90impl Default for BitcaskyClock {
91 fn default() -> Self {
92 Self {
93 clock: ClockImpl::System(SystemClock {}),
94 }
95 }
96}