1use std::time::{Duration, SystemTime};
2
3use static_assertions::{const_assert, const_assert_eq};
4
5use crate::bindings;
6
7#[repr(transparent)]
16#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
17pub struct NDITime(i64);
18
19const NDI_TIME_DEFAULT: i64 = i64::MAX;
20
21const_assert_eq!(NDI_TIME_DEFAULT, bindings::NDIlib_recv_timestamp_undefined);
22const_assert_eq!(NDI_TIME_DEFAULT, bindings::NDIlib_send_timecode_synthesize);
23
24impl Default for NDITime {
25 fn default() -> Self {
26 Self(NDI_TIME_DEFAULT)
27 }
28}
29
30impl NDITime {
31 #[inline]
32 pub fn to_ffi(self) -> i64 {
33 self.0
34 }
35
36 #[inline]
37 pub fn from_ffi(time: i64) -> Self {
38 Self(time)
39 }
40
41 pub fn to_utc(self) -> Option<SystemTime> {
45 fn to_duration(time: u64) -> Duration {
46 let secs = time / 10_000_000;
47 let sub_100ns = time % 10_000_000;
48
49 const_assert!(10_000_000 < i32::MAX);
50
51 let nanos = (sub_100ns * 100) as u32;
52
53 Duration::new(secs, nanos)
54 }
55
56 if self.is_default() {
57 None
58 } else {
59 Some(if self.0 >= 0 {
60 SystemTime::UNIX_EPOCH + to_duration(self.0 as u64)
61 } else {
62 SystemTime::UNIX_EPOCH - to_duration(self.0.saturating_abs() as u64)
63 })
64 }
65 }
66
67 pub fn is_default(self) -> bool {
68 self.0 == NDI_TIME_DEFAULT
69 }
70
71 pub const UNDEFINED: Self = Self(NDI_TIME_DEFAULT);
72 pub const SYNTHESIZE: Self = Self(NDI_TIME_DEFAULT);
74}