Skip to main content

oxihuman_core/
time_source.rs

1#![allow(dead_code)]
2
3/// A timestamp in milliseconds.
4#[allow(dead_code)]
5#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
6pub struct Timestamp {
7    pub ms: u64,
8}
9
10/// A deterministic time source (no real clock dependency).
11#[allow(dead_code)]
12#[derive(Debug, Clone)]
13pub struct TimeSource {
14    current_ms: u64,
15    start_ms: u64,
16}
17
18/// Creates a new time source starting at the given ms.
19#[allow(dead_code)]
20pub fn new_time_source(start_ms: u64) -> TimeSource {
21    TimeSource {
22        current_ms: start_ms,
23        start_ms,
24    }
25}
26
27/// Returns the current time in ms.
28#[allow(dead_code)]
29pub fn current_time_ms(ts: &TimeSource) -> u64 {
30    ts.current_ms
31}
32
33/// Returns elapsed ms since a given timestamp.
34#[allow(dead_code)]
35pub fn elapsed_since(ts: &TimeSource, since: &Timestamp) -> u64 {
36    ts.current_ms.saturating_sub(since.ms)
37}
38
39/// Returns the difference in ms between two timestamps.
40#[allow(dead_code)]
41pub fn time_diff_ms(a: &Timestamp, b: &Timestamp) -> i64 {
42    (a.ms as i64) - (b.ms as i64)
43}
44
45/// Converts a timestamp to a simple string representation.
46#[allow(dead_code)]
47pub fn timestamp_to_string(t: &Timestamp) -> String {
48    let secs = t.ms / 1000;
49    let millis = t.ms % 1000;
50    format!("{secs}.{millis:03}s")
51}
52
53/// Returns true if timestamp a is after timestamp b.
54#[allow(dead_code)]
55pub fn timestamp_is_after(a: &Timestamp, b: &Timestamp) -> bool {
56    a.ms > b.ms
57}
58
59/// Adds milliseconds to a timestamp.
60#[allow(dead_code)]
61pub fn timestamp_add_ms(t: &Timestamp, ms: u64) -> Timestamp {
62    Timestamp { ms: t.ms + ms }
63}
64
65/// Resets the time source to its start value.
66#[allow(dead_code)]
67pub fn time_source_reset(ts: &mut TimeSource) {
68    ts.current_ms = ts.start_ms;
69}
70
71#[cfg(test)]
72mod tests {
73    use super::*;
74
75    #[test]
76    fn test_new_time_source() {
77        let ts = new_time_source(1000);
78        assert_eq!(current_time_ms(&ts), 1000);
79    }
80
81    #[test]
82    fn test_elapsed_since() {
83        let ts = new_time_source(5000);
84        let stamp = Timestamp { ms: 3000 };
85        assert_eq!(elapsed_since(&ts, &stamp), 2000);
86    }
87
88    #[test]
89    fn test_time_diff_ms() {
90        let a = Timestamp { ms: 5000 };
91        let b = Timestamp { ms: 3000 };
92        assert_eq!(time_diff_ms(&a, &b), 2000);
93        assert_eq!(time_diff_ms(&b, &a), -2000);
94    }
95
96    #[test]
97    fn test_timestamp_to_string() {
98        let t = Timestamp { ms: 1500 };
99        assert_eq!(timestamp_to_string(&t), "1.500s");
100    }
101
102    #[test]
103    fn test_timestamp_is_after() {
104        let a = Timestamp { ms: 200 };
105        let b = Timestamp { ms: 100 };
106        assert!(timestamp_is_after(&a, &b));
107        assert!(!timestamp_is_after(&b, &a));
108    }
109
110    #[test]
111    fn test_timestamp_add_ms() {
112        let t = Timestamp { ms: 1000 };
113        let t2 = timestamp_add_ms(&t, 500);
114        assert_eq!(t2.ms, 1500);
115    }
116
117    #[test]
118    fn test_time_source_reset() {
119        let mut ts = new_time_source(100);
120        ts.current_ms = 999;
121        time_source_reset(&mut ts);
122        assert_eq!(current_time_ms(&ts), 100);
123    }
124
125    #[test]
126    fn test_elapsed_since_future() {
127        let ts = new_time_source(100);
128        let stamp = Timestamp { ms: 500 };
129        assert_eq!(elapsed_since(&ts, &stamp), 0);
130    }
131
132    #[test]
133    fn test_timestamp_equality() {
134        let a = Timestamp { ms: 42 };
135        let b = Timestamp { ms: 42 };
136        assert_eq!(a, b);
137    }
138
139    #[test]
140    fn test_timestamp_ordering() {
141        let a = Timestamp { ms: 10 };
142        let b = Timestamp { ms: 20 };
143        assert!(a < b);
144    }
145}