Skip to main content

fission_core/
time.rs

1use crate::AppState;
2use anyhow::Result;
3use serde::{Deserialize, Serialize};
4
5pub type CurrentTime = u64; // Milliseconds, monotonic
6
7#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
8pub struct Clock {
9    current_time: CurrentTime,
10}
11
12impl Default for Clock {
13    fn default() -> Self {
14        Self { current_time: 0 }
15    }
16}
17
18impl AppState for Clock {
19    // as_any and as_any_mut are provided by the Downcast trait now.
20}
21
22impl Clock {
23    pub fn current_time(&self) -> CurrentTime {
24        self.current_time
25    }
26
27    // Advance the clock by a duration `dt`.
28    // This should only be called by the runtime in response to a Tick action.
29    pub fn advance_by(&mut self, dt: CurrentTime) -> Result<()> {
30        // Enforce monotonicity and non-negative dt
31        if dt == 0 {
32            return Ok(());
33        }
34        // Check for overflow (unlikely for u64 milliseconds in practice for reasonable durations)
35        self.current_time = self
36            .current_time
37            .checked_add(dt)
38            .ok_or_else(|| anyhow::anyhow!("Clock overflow"))?;
39        Ok(())
40    }
41
42    // Set the clock to a specific time.
43    // This should only be called by the runtime in response to an AdvanceTo action.
44    pub fn set_to(&mut self, new_time: CurrentTime) -> Result<()> {
45        if new_time < self.current_time {
46            anyhow::bail!("Cannot set clock to a time before current time (time regression).");
47        }
48        self.current_time = new_time;
49        Ok(())
50    }
51}