telltale_choreography/runtime/
clock.rs1use std::time::{Duration, Instant};
8
9use crate::testing::clock::{AsyncClock, Clock, Rng, WallClock};
10
11#[derive(Debug, Clone, Copy, Default)]
16pub struct SystemClock;
17
18impl SystemClock {
19 #[must_use]
24 pub fn timestamp_ns() -> u64 {
25 std::time::SystemTime::now()
26 .duration_since(std::time::UNIX_EPOCH)
27 .unwrap_or_default()
28 .as_nanos() as u64
29 }
30}
31
32impl Clock for SystemClock {
33 fn now(&self) -> Duration {
34 static START: std::sync::OnceLock<Instant> = std::sync::OnceLock::new();
35 START.get_or_init(Instant::now).elapsed()
36 }
37
38 fn advance(&self, _duration: Duration) {
39 }
41}
42
43impl AsyncClock for SystemClock {
44 async fn sleep(&self, duration: Duration) {
45 #[cfg(not(target_arch = "wasm32"))]
46 {
47 tokio::time::sleep(duration).await;
48 }
49 #[cfg(target_arch = "wasm32")]
50 {
51 wasm_timer::Delay::new(duration).await.ok();
52 }
53 }
54}
55
56impl WallClock for SystemClock {
57 fn now_unix_ns(&self) -> u64 {
58 Self::timestamp_ns()
59 }
60}
61
62#[derive(Debug, Default)]
67pub struct SystemRng {
68 state: u64,
69}
70
71impl SystemRng {
72 #[must_use]
74 pub fn new() -> Self {
75 let seed = std::time::SystemTime::now()
76 .duration_since(std::time::UNIX_EPOCH)
77 .unwrap_or_default()
78 .as_nanos() as u64;
79 Self {
80 state: if seed == 0 { 1 } else { seed },
81 }
82 }
83}
84
85impl Rng for SystemRng {
86 fn next_u64(&mut self) -> u64 {
87 let ptr = self as *mut Self as u64;
89 self.state = self
90 .state
91 .wrapping_mul(ptr)
92 .wrapping_add(0x517cc1b727220a95);
93 self.state ^= self.state << 13;
95 self.state ^= self.state >> 7;
96 self.state ^= self.state << 17;
97 self.state
98 }
99
100 fn fork(&mut self) -> Self {
101 let fork_seed = self.next_u64()
103 ^ std::time::SystemTime::now()
104 .duration_since(std::time::UNIX_EPOCH)
105 .unwrap_or_default()
106 .as_nanos() as u64;
107 Self {
108 state: if fork_seed == 0 { 1 } else { fork_seed },
109 }
110 }
111}