1use std::sync::atomic::{AtomicU64, Ordering};
13use std::sync::Arc;
14
15#[derive(Clone, Debug)]
17pub struct SharedClock(Arc<AtomicU64>);
18
19impl Default for SharedClock {
20 fn default() -> Self {
21 Self::new()
22 }
23}
24
25impl SharedClock {
26 pub fn new() -> Self {
27 Self(Arc::new(AtomicU64::new(0)))
28 }
29 pub fn set_ns(&self, ns: u64) {
31 self.0.store(ns, Ordering::Relaxed);
32 }
33 pub fn position_s(&self) -> f64 {
35 self.0.load(Ordering::Relaxed) as f64 / 1e9
36 }
37}
38
39pub fn highlight_index(word_times: &[f64], position_s: f64) -> Option<usize> {
42 let mut found = None;
44 for (i, &t) in word_times.iter().enumerate() {
45 if t <= position_s {
46 found = Some(i);
47 } else {
48 break;
49 }
50 }
51 found
52}
53
54#[cfg(test)]
55mod tests {
56 use super::*;
57
58 #[test]
59 fn highlight_advances_with_clock() {
60 let times = [0.0, 0.5, 1.0, 1.5, 2.0]; assert_eq!(highlight_index(×, 0.0), Some(0));
62 assert_eq!(highlight_index(×, 0.4), Some(0));
63 assert_eq!(highlight_index(×, 0.5), Some(1));
64 assert_eq!(highlight_index(×, 1.24), Some(2));
65 assert_eq!(highlight_index(×, 2.0), Some(4));
66 assert_eq!(highlight_index(×, 5.0), Some(4)); }
68
69 #[test]
70 fn clock_is_shared_across_clone() {
71 let player_clock = SharedClock::new();
72 let ui_clock = player_clock.clone(); assert_eq!(ui_clock.position_s(), 0.0);
74 player_clock.set_ns(1_500_000_000); assert_eq!(ui_clock.position_s(), 1.5); }
77}