telltale_runtime/util/
clock.rs1use std::time::{Duration, Instant};
8use std::{
9 collections::hash_map::DefaultHasher,
10 hash::{Hash, Hasher},
11};
12
13use crate::testing::clock::{AsyncClock, Clock, Rng, WallClock};
14use cfg_if::cfg_if;
15
16#[derive(Debug, Clone, Copy, Default)]
21pub struct SystemClock;
22
23impl SystemClock {
24 #[must_use]
29 pub fn timestamp_ns() -> u64 {
30 u64::try_from(
31 std::time::SystemTime::now()
32 .duration_since(std::time::UNIX_EPOCH)
33 .unwrap_or_default()
34 .as_nanos(),
35 )
36 .unwrap_or(u64::MAX)
37 }
38}
39
40impl Clock for SystemClock {
41 fn now(&self) -> Duration {
42 static START: std::sync::OnceLock<Instant> = std::sync::OnceLock::new();
43 START.get_or_init(Instant::now).elapsed()
44 }
45
46 fn advance(&self, _duration: Duration) {
47 }
49}
50
51impl AsyncClock for SystemClock {
52 async fn sleep(&self, duration: Duration) {
53 cfg_if! {
54 if #[cfg(target_arch = "wasm32")] {
55 wasm_timer::Delay::new(duration).await.ok();
56 } else {
57 tokio::time::sleep(duration).await;
58 }
59 }
60 }
61}
62
63impl WallClock for SystemClock {
64 fn now_unix_ns(&self) -> u64 {
65 Self::timestamp_ns()
66 }
67}
68
69#[derive(Debug, Default)]
74pub struct SystemRng {
75 state: u64,
76}
77
78impl SystemRng {
79 #[must_use]
81 pub fn new() -> Self {
82 let seed = u64::try_from(
83 std::time::SystemTime::now()
84 .duration_since(std::time::UNIX_EPOCH)
85 .unwrap_or_default()
86 .as_nanos(),
87 )
88 .unwrap_or(u64::MAX);
89 Self {
90 state: if seed == 0 { 1 } else { seed },
91 }
92 }
93}
94
95impl Rng for SystemRng {
96 fn next_u64(&mut self) -> u64 {
97 let mut hasher = DefaultHasher::new();
99 let ptr: *const Self = self;
100 ptr.hash(&mut hasher);
101 let ptr = hasher.finish();
102 self.state = self
103 .state
104 .wrapping_mul(ptr)
105 .wrapping_add(0x517cc1b727220a95);
106 self.state ^= self.state << 13;
108 self.state ^= self.state >> 7;
109 self.state ^= self.state << 17;
110 self.state
111 }
112
113 fn fork(&mut self) -> Self {
114 let fork_seed = self.next_u64()
116 ^ u64::try_from(
117 std::time::SystemTime::now()
118 .duration_since(std::time::UNIX_EPOCH)
119 .unwrap_or_default()
120 .as_nanos(),
121 )
122 .unwrap_or(u64::MAX);
123 Self {
124 state: if fork_seed == 0 { 1 } else { fork_seed },
125 }
126 }
127}