1use core::{
4 fmt::Display,
5 ops::{Add, AddAssign, Sub, SubAssign},
6};
7
8use fixed::{
9 traits::{LosslessTryInto, LossyInto, ToFixed},
10 types::{U112F16, U96F32},
11};
12
13use super::duration::Duration;
14use crate::datastructures::common::WireTimestamp;
15
16#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Default)]
21pub struct Time {
22 inner: U96F32,
24}
25
26impl Time {
27 pub fn from_secs(secs: u64) -> Self {
29 let inner = secs.to_fixed::<U96F32>() * 1_000_000_000.to_fixed::<U96F32>();
30 Self { inner }
31 }
32 pub fn from_millis(millis: u64) -> Self {
34 let inner = millis.to_fixed::<U96F32>() * 1_000_000.to_fixed::<U96F32>();
35 Self { inner }
36 }
37 pub fn from_micros(micros: u64) -> Self {
39 let inner = micros.to_fixed::<U96F32>() * 1_000.to_fixed::<U96F32>();
40 Self { inner }
41 }
42 pub fn from_nanos(nanos: u64) -> Self {
44 let inner = nanos.to_fixed::<U96F32>();
45 Self { inner }
46 }
47 pub fn from_fixed_nanos<F: ToFixed>(nanos: F) -> Self {
51 Self {
52 inner: nanos.to_fixed(),
53 }
54 }
55
56 pub fn from_nanos_subnanos(nanos: u64, subnanos: u32) -> Self {
69 let bits = ((nanos as u128) << 32) | (subnanos as u128);
70 let inner = U96F32::from_bits(bits);
71 Self { inner }
72 }
73
74 pub fn nanos(&self) -> U96F32 {
76 self.inner
77 }
78 pub fn subsec_nanos(&self) -> u32 {
80 (self.inner % 1_000_000_000.to_fixed::<U96F32>()).to_num()
81 }
82 pub fn secs(&self) -> u64 {
84 (self.inner / 1_000_000_000.to_fixed::<U96F32>()).to_num()
85 }
86 pub(crate) fn subnano(&self) -> crate::datastructures::common::TimeInterval {
88 let inter: U112F16 = self.inner.frac().lossy_into();
89 crate::datastructures::common::TimeInterval(inter.lossless_try_into().unwrap())
91 }
92}
93
94impl From<WireTimestamp> for Time {
95 fn from(ts: WireTimestamp) -> Self {
96 Self::from_fixed_nanos(ts.seconds as i128 * 1_000_000_000i128 + ts.nanos as i128)
97 }
98}
99
100impl Add<Duration> for Time {
101 type Output = Time;
102
103 fn add(self, rhs: Duration) -> Self::Output {
104 if rhs.nanos().is_negative() {
105 Time {
106 inner: self.nanos() - rhs.nanos().unsigned_abs(),
107 }
108 } else {
109 Time {
110 inner: self.nanos() + rhs.nanos().unsigned_abs(),
111 }
112 }
113 }
114}
115
116impl AddAssign<Duration> for Time {
117 fn add_assign(&mut self, rhs: Duration) {
118 *self = *self + rhs;
119 }
120}
121
122impl Sub<Duration> for Time {
123 type Output = Time;
124
125 fn sub(self, rhs: Duration) -> Self::Output {
126 self + -rhs
127 }
128}
129
130impl SubAssign<Duration> for Time {
131 fn sub_assign(&mut self, rhs: Duration) {
132 *self = *self - rhs;
133 }
134}
135
136impl Sub<Time> for Time {
137 type Output = Duration;
138
139 fn sub(self, rhs: Time) -> Self::Output {
140 Duration::from_fixed_nanos(self.inner) - Duration::from_fixed_nanos(rhs.inner)
141 }
142}
143
144impl Display for Time {
145 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
146 write!(f, "{}", self.inner)
147 }
148}
149
150#[cfg(test)]
151mod tests {
152 use super::*;
153
154 #[test]
155 fn values() {
156 assert_eq!(
157 Time::from_secs(10).nanos(),
158 10_000_000_000u64.to_fixed::<U96F32>()
159 );
160 assert_eq!(
161 Time::from_millis(10).nanos(),
162 10_000_000u64.to_fixed::<U96F32>()
163 );
164 assert_eq!(
165 Time::from_micros(10).nanos(),
166 10_000u64.to_fixed::<U96F32>()
167 );
168 assert_eq!(Time::from_nanos(10).nanos(), 10u64.to_fixed::<U96F32>());
169 assert_eq!(
170 Time::from_fixed_nanos(10.123f64).nanos(),
171 10.123f64.to_fixed::<U96F32>()
172 );
173 assert_eq!(Time::from_secs(10).secs(), 10);
174 assert_eq!(Time::from_millis(10).secs(), 0);
175 assert_eq!(Time::from_millis(1001).secs(), 1);
176 }
177}