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