1use crate::time::Time;
32
33#[cfg(target_has_atomic = "64")]
36use core::sync::atomic::{AtomicI64, Ordering};
37
38#[cfg(not(target_has_atomic = "64"))]
40use core::sync::atomic::{AtomicI32, Ordering};
41
42#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
44pub enum ClockType {
45 #[default]
51 SystemTime,
52
53 SteadyTime,
59
60 RosTime,
66}
67
68#[cfg(target_has_atomic = "64")]
70mod atomic_time {
71 use super::*;
72
73 pub(super) static ROS_TIME_OVERRIDE_NANOS: AtomicI64 = AtomicI64::new(-1);
77
78 pub(super) static STEADY_TIME_NANOS: AtomicI64 = AtomicI64::new(0);
81
82 pub(super) fn get_ros_override() -> i64 {
83 ROS_TIME_OVERRIDE_NANOS.load(Ordering::Relaxed)
84 }
85
86 pub(super) fn set_ros_override(nanos: i64) {
87 ROS_TIME_OVERRIDE_NANOS.store(nanos, Ordering::Relaxed);
88 }
89
90 pub(super) fn get_steady() -> i64 {
91 STEADY_TIME_NANOS.load(Ordering::Relaxed)
92 }
93
94 pub(super) fn set_steady(nanos: i64) {
95 STEADY_TIME_NANOS.store(nanos, Ordering::Relaxed);
96 }
97
98 pub(super) fn add_steady(delta: i64) {
99 STEADY_TIME_NANOS.fetch_add(delta, Ordering::Relaxed);
100 }
101}
102
103#[cfg(not(target_has_atomic = "64"))]
106mod atomic_time {
107 use super::*;
108
109 static ROS_TIME_OVERRIDE_LOW: AtomicI32 = AtomicI32::new(-1);
111 static ROS_TIME_OVERRIDE_HIGH: AtomicI32 = AtomicI32::new(-1);
112 static STEADY_TIME_LOW: AtomicI32 = AtomicI32::new(0);
113 static STEADY_TIME_HIGH: AtomicI32 = AtomicI32::new(0);
114
115 pub(super) fn get_ros_override() -> i64 {
116 let high = ROS_TIME_OVERRIDE_HIGH.load(Ordering::Relaxed);
117 let low = ROS_TIME_OVERRIDE_LOW.load(Ordering::Relaxed);
118 if high < 0 {
119 -1
120 } else {
121 ((high as i64) << 32) | (low as u32 as i64)
122 }
123 }
124
125 pub(super) fn set_ros_override(nanos: i64) {
126 if nanos < 0 {
127 ROS_TIME_OVERRIDE_HIGH.store(-1, Ordering::Relaxed);
128 ROS_TIME_OVERRIDE_LOW.store(-1, Ordering::Relaxed);
129 } else {
130 ROS_TIME_OVERRIDE_HIGH.store((nanos >> 32) as i32, Ordering::Relaxed);
131 ROS_TIME_OVERRIDE_LOW.store(nanos as i32, Ordering::Relaxed);
132 }
133 }
134
135 pub(super) fn get_steady() -> i64 {
136 let high = STEADY_TIME_HIGH.load(Ordering::Relaxed);
137 let low = STEADY_TIME_LOW.load(Ordering::Relaxed);
138 ((high as i64) << 32) | (low as u32 as i64)
139 }
140
141 pub(super) fn set_steady(nanos: i64) {
142 STEADY_TIME_HIGH.store((nanos >> 32) as i32, Ordering::Relaxed);
143 STEADY_TIME_LOW.store(nanos as i32, Ordering::Relaxed);
144 }
145
146 pub(super) fn add_steady(delta: i64) {
147 let current = get_steady();
148 set_steady(current.saturating_add(delta));
149 }
150}
151
152#[derive(Debug, Clone, Copy)]
157pub struct Clock {
158 clock_type: ClockType,
159}
160
161impl Default for Clock {
162 fn default() -> Self {
163 Self::system()
164 }
165}
166
167impl Clock {
168 pub const fn new(clock_type: ClockType) -> Self {
170 Self { clock_type }
171 }
172
173 pub const fn system() -> Self {
177 Self {
178 clock_type: ClockType::SystemTime,
179 }
180 }
181
182 pub const fn steady() -> Self {
187 Self {
188 clock_type: ClockType::SteadyTime,
189 }
190 }
191
192 pub const fn ros_time() -> Self {
197 Self {
198 clock_type: ClockType::RosTime,
199 }
200 }
201
202 pub const fn clock_type(&self) -> ClockType {
204 self.clock_type
205 }
206
207 #[cfg(feature = "std")]
214 pub fn now(&self) -> Time {
215 match self.clock_type {
216 ClockType::SystemTime => {
217 let duration = std::time::SystemTime::now()
218 .duration_since(std::time::UNIX_EPOCH)
219 .unwrap_or_default();
220 Time::new(duration.as_secs() as i32, duration.subsec_nanos())
221 }
222 ClockType::SteadyTime => {
223 let nanos = atomic_time::get_steady();
225 Time::from_nanos(nanos)
226 }
227 ClockType::RosTime => {
228 let override_nanos = atomic_time::get_ros_override();
229 if override_nanos >= 0 {
230 Time::from_nanos(override_nanos)
231 } else {
232 Clock::system().now()
234 }
235 }
236 }
237 }
238
239 #[cfg(not(feature = "std"))]
244 pub fn now(&self) -> Time {
245 match self.clock_type {
246 ClockType::SystemTime | ClockType::SteadyTime => {
247 let nanos = atomic_time::get_steady();
248 Time::from_nanos(nanos)
249 }
250 ClockType::RosTime => {
251 let override_nanos = atomic_time::get_ros_override();
252 if override_nanos >= 0 {
253 Time::from_nanos(override_nanos)
254 } else {
255 let nanos = atomic_time::get_steady();
256 Time::from_nanos(nanos)
257 }
258 }
259 }
260 }
261
262 pub fn set_ros_time_override(nanos: i64) {
270 atomic_time::set_ros_override(nanos);
271 }
272
273 pub fn set_ros_time_override_time(time: Time) {
275 Self::set_ros_time_override(time.to_nanos());
276 }
277
278 pub fn clear_ros_time_override() {
282 atomic_time::set_ros_override(-1);
283 }
284
285 pub fn is_ros_time_override_active() -> bool {
287 atomic_time::get_ros_override() >= 0
288 }
289
290 pub fn get_ros_time_override() -> Option<Time> {
292 let nanos = atomic_time::get_ros_override();
293 if nanos >= 0 {
294 Some(Time::from_nanos(nanos))
295 } else {
296 None
297 }
298 }
299
300 pub fn update_steady_time(delta_nanos: i64) {
308 atomic_time::add_steady(delta_nanos);
309 }
310
311 pub fn update_steady_time_ms(delta_ms: u64) {
318 let delta_nanos = delta_ms as i64 * 1_000_000;
319 Self::update_steady_time(delta_nanos);
320 }
321
322 pub fn set_steady_time(nanos: i64) {
327 atomic_time::set_steady(nanos);
328 }
329
330 pub fn get_steady_time_nanos() -> i64 {
332 atomic_time::get_steady()
333 }
334}
335
336#[cfg(test)]
337mod tests {
338 use super::*;
339
340 #[test]
341 fn test_clock_type_default() {
342 let clock_type = ClockType::default();
343 assert_eq!(clock_type, ClockType::SystemTime);
344 }
345
346 #[test]
347 fn test_clock_constructors() {
348 let system = Clock::system();
349 assert_eq!(system.clock_type(), ClockType::SystemTime);
350
351 let steady = Clock::steady();
352 assert_eq!(steady.clock_type(), ClockType::SteadyTime);
353
354 let ros = Clock::ros_time();
355 assert_eq!(ros.clock_type(), ClockType::RosTime);
356
357 let custom = Clock::new(ClockType::SteadyTime);
358 assert_eq!(custom.clock_type(), ClockType::SteadyTime);
359 }
360
361 #[test]
362 fn test_clock_default() {
363 let clock = Clock::default();
364 assert_eq!(clock.clock_type(), ClockType::SystemTime);
365 }
366
367 #[test]
368 fn test_ros_time_override() {
369 Clock::clear_ros_time_override();
371 assert!(!Clock::is_ros_time_override_active());
372 assert!(Clock::get_ros_time_override().is_none());
373
374 let override_time = Time::new(1234567890, 123456789);
376 Clock::set_ros_time_override_time(override_time);
377 assert!(Clock::is_ros_time_override_active());
378 assert_eq!(Clock::get_ros_time_override(), Some(override_time));
379
380 let ros_clock = Clock::ros_time();
382 let now = ros_clock.now();
383 assert_eq!(now, override_time);
384
385 Clock::clear_ros_time_override();
387 assert!(!Clock::is_ros_time_override_active());
388 }
389
390 #[test]
391 fn test_steady_time_update() {
392 Clock::set_steady_time(0);
394 assert_eq!(Clock::get_steady_time_nanos(), 0);
395
396 Clock::update_steady_time_ms(100);
398 assert_eq!(Clock::get_steady_time_nanos(), 100_000_000);
399
400 Clock::update_steady_time(500_000_000);
402 assert_eq!(Clock::get_steady_time_nanos(), 600_000_000);
403
404 let steady_clock = Clock::steady();
406 let now = steady_clock.now();
407 assert_eq!(now.to_nanos(), 600_000_000);
408 }
409
410 #[test]
411 #[cfg(feature = "std")]
412 #[cfg_attr(miri, ignore)] fn test_system_clock_returns_nonzero() {
414 let clock = Clock::system();
415 let now = clock.now();
416 assert!(now.sec > 0);
418 }
419}