libpulse_binding/time/
timeval.rs1use std::cmp::Ordering;
17use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Rem, RemAssign, Sub, SubAssign};
18use std::time::Duration;
19use super::{UnixTs, MonotonicTs, MicroSeconds, op_err};
20
21#[cfg(not(windows))]
22pub(crate) type TvSecs = libc::time_t;
23#[cfg(not(windows))]
24pub(crate) type TvUsecs = libc::suseconds_t;
25#[cfg(windows)]
26pub(crate) type TvSecs = libc::c_long;
27#[cfg(windows)]
28pub(crate) type TvUsecs = libc::c_long;
29
30#[repr(transparent)]
32#[derive(Copy, Clone)]
33pub struct Timeval(pub libc::timeval); impl PartialEq for Timeval {
36 fn eq(&self, other: &Self) -> bool {
37 self.0.tv_sec == other.0.tv_sec && self.0.tv_usec == other.0.tv_usec
38 }
39}
40impl Eq for Timeval {}
41
42impl Ord for Timeval {
43 fn cmp(&self, other: &Self) -> Ordering {
44 match unsafe { capi::pa_timeval_cmp(&self.0, &other.0) } {
45 0 => Ordering::Equal,
46 r if r < 0 => Ordering::Less,
47 _ => Ordering::Greater,
48 }
49 }
50}
51
52impl PartialOrd for Timeval {
53 #[inline]
54 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
55 Some(self.cmp(other))
56 }
57}
58
59impl Timeval {
60 const RTCLOCK_BIT: TvUsecs = 1 << 30;
62
63 #[inline]
65 pub const fn new(sec: TvSecs, usec: TvUsecs) -> Self {
66 Self(libc::timeval { tv_sec: sec, tv_usec: usec })
67 }
68
69 #[inline]
71 pub const fn new_zero() -> Self {
72 Self::new(0, 0)
73 }
74
75 #[inline]
77 pub fn diff(a: &Self, b: &Self) -> MicroSeconds {
78 MicroSeconds(unsafe { capi::pa_timeval_diff(&a.0, &b.0) })
79 }
80
81 #[inline]
83 pub fn age(&self) -> MicroSeconds {
84 MicroSeconds(unsafe { capi::pa_timeval_age(&self.0) })
85 }
86
87 pub(crate) fn set_rt(&mut self, v: MicroSeconds, rtclock: bool) -> &mut Self {
96 assert_ne!(v, MicroSeconds::INVALID);
99
100 *self = v.into();
101
102 if rtclock {
103 self.0.tv_usec |= Self::RTCLOCK_BIT;
104 }
105 else {
106 self.wallclock_from_rtclock();
107 }
108 self
109 }
110
111 pub(crate) fn wallclock_from_rtclock(&mut self) -> &mut Self {
112 let wc_now = (UnixTs::now()).0;
115 let rt_now = Timeval::from((MonotonicTs::now()).0);
116
117 let _ = match rt_now.cmp(self) {
118 Ordering::Less => { wc_now.add(Self::diff(self, &rt_now)) },
119 _ => { wc_now.sub(Self::diff(&rt_now, self)) },
120 };
121
122 *self = wc_now;
123 self
124 }
125
126 pub fn checked_add(self, other: Self) -> Option<Self> {
129 let self_us = MicroSeconds::from(self);
130 let other_us = MicroSeconds::from(other);
131 self_us.checked_add(other_us).and_then(|i| Some(i.into()))
132 }
133
134 pub fn checked_add_us(self, rhs: MicroSeconds) -> Option<Self> {
137 let self_us = MicroSeconds::from(self);
138 self_us.checked_add(rhs).and_then(|i| Some(i.into()))
139 }
140
141 pub fn checked_add_duration(self, rhs: Duration) -> Option<Self> {
144 let self_us = MicroSeconds::from(self);
145 let rhs_us = MicroSeconds::try_from(rhs).ok()?;
146 self_us.checked_add(rhs_us).and_then(|i| Some(i.into()))
147 }
148
149 pub fn checked_sub(self, other: Self) -> Option<Self> {
152 let self_us = MicroSeconds::from(self);
153 let other_us = MicroSeconds::from(other);
154 self_us.checked_sub(other_us).and_then(|i| Some(i.into()))
155 }
156
157 pub fn checked_sub_us(self, rhs: MicroSeconds) -> Option<Self> {
160 let self_us = MicroSeconds::from(self);
161 self_us.checked_sub(rhs).and_then(|i| Some(i.into()))
162 }
163
164 pub fn checked_sub_duration(self, rhs: Duration) -> Option<Self> {
167 let self_us = MicroSeconds::from(self);
168 let rhs_us = MicroSeconds::try_from(rhs).ok()?;
169 self_us.checked_sub(rhs_us).and_then(|i| Some(i.into()))
170 }
171
172 pub fn checked_mul(self, rhs: u32) -> Option<Self> {
175 let self_us = MicroSeconds::from(self);
176 self_us.checked_mul(rhs).and_then(|i| Some(i.into()))
177 }
178
179 pub fn checked_div(self, rhs: u32) -> Option<Self> {
182 let self_us = MicroSeconds::from(self);
183 self_us.checked_div(rhs).and_then(|i| Some(i.into()))
184 }
185
186 pub fn checked_rem(self, rhs: u32) -> Option<Self> {
189 let self_us = MicroSeconds::from(self);
190 self_us.checked_rem(rhs).and_then(|i| Some(i.into()))
191 }
192}
193
194impl std::fmt::Debug for Timeval {
195 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
196 write!(f, "timeval {{ tv_sec: {}, tv_usec: {} }}", self.0.tv_sec, self.0.tv_usec)
197 }
198}
199
200impl Add for Timeval {
201 type Output = Self;
202
203 #[track_caller]
204 #[inline]
205 fn add(self, other: Self) -> Self {
206 self.checked_add(other).expect(op_err::ADD)
207 }
208}
209impl AddAssign for Timeval {
210 #[track_caller]
211 #[inline]
212 fn add_assign(&mut self, rhs: Self) {
213 *self = self.add(rhs);
214 }
215}
216
217impl Sub for Timeval {
218 type Output = Self;
219
220 #[track_caller]
221 #[inline]
222 fn sub(self, other: Self) -> Self {
223 self.checked_sub(other).expect(op_err::SUB)
224 }
225}
226impl SubAssign for Timeval {
227 #[track_caller]
228 #[inline]
229 fn sub_assign(&mut self, rhs: Self) {
230 *self = self.sub(rhs);
231 }
232}
233
234impl Add<MicroSeconds> for Timeval {
239 type Output = Self;
240
241 #[track_caller]
242 #[inline]
243 fn add(self, rhs: MicroSeconds) -> Self {
244 self.checked_add_us(rhs).expect(op_err::ADD)
245 }
246}
247impl AddAssign<MicroSeconds> for Timeval {
248 #[track_caller]
249 #[inline]
250 fn add_assign(&mut self, rhs: MicroSeconds) {
251 *self = self.add(rhs);
252 }
253}
254
255impl Sub<MicroSeconds> for Timeval {
256 type Output = Self;
257
258 #[track_caller]
259 #[inline]
260 fn sub(self, rhs: MicroSeconds) -> Self {
261 self.checked_sub_us(rhs).expect(op_err::SUB)
262 }
263}
264impl SubAssign<MicroSeconds> for Timeval {
265 #[track_caller]
266 #[inline]
267 fn sub_assign(&mut self, rhs: MicroSeconds) {
268 *self = self.sub(rhs);
269 }
270}
271
272impl Add<Duration> for Timeval {
277 type Output = Self;
278
279 #[track_caller]
280 #[inline]
281 fn add(self, rhs: Duration) -> Self {
282 self.checked_add_duration(rhs).expect(op_err::ADD)
283 }
284}
285impl AddAssign<Duration> for Timeval {
286 #[track_caller]
287 #[inline]
288 fn add_assign(&mut self, rhs: Duration) {
289 *self = self.add(rhs);
290 }
291}
292
293impl Sub<Duration> for Timeval {
294 type Output = Self;
295
296 #[track_caller]
297 #[inline]
298 fn sub(self, rhs: Duration) -> Self {
299 self.checked_sub_duration(rhs).expect(op_err::SUB)
300 }
301}
302impl SubAssign<Duration> for Timeval {
303 #[track_caller]
304 #[inline]
305 fn sub_assign(&mut self, rhs: Duration) {
306 *self = self.sub(rhs);
307 }
308}
309
310impl Mul<u32> for Timeval {
315 type Output = Self;
316
317 #[track_caller]
318 #[inline]
319 fn mul(self, rhs: u32) -> Self {
320 self.checked_mul(rhs).expect(op_err::MUL)
321 }
322}
323impl MulAssign<u32> for Timeval {
324 #[track_caller]
325 #[inline]
326 fn mul_assign(&mut self, rhs: u32) {
327 *self = self.mul(rhs);
328 }
329}
330
331impl Div<u32> for Timeval {
332 type Output = Self;
333
334 #[track_caller]
335 #[inline]
336 fn div(self, rhs: u32) -> Self {
337 self.checked_div(rhs).expect(op_err::DIV)
338 }
339}
340impl DivAssign<u32> for Timeval {
341 #[track_caller]
342 #[inline]
343 fn div_assign(&mut self, rhs: u32) {
344 *self = self.div(rhs);
345 }
346}
347
348impl Rem<u32> for Timeval {
349 type Output = Self;
350
351 #[track_caller]
352 #[inline]
353 fn rem(self, rhs: u32) -> Self {
354 self.checked_rem(rhs).expect(op_err::REM)
355 }
356}
357impl RemAssign<u32> for Timeval {
358 #[track_caller]
359 #[inline]
360 fn rem_assign(&mut self, rhs: u32) {
361 *self = self.rem(rhs);
362 }
363}