libpulse_binding/time/microseconds.rs
1// Copyright 2018 Lyndon Brown
2//
3// This file is part of the PulseAudio Rust language binding.
4//
5// Licensed under the MIT license or the Apache license (version 2.0), at your option. You may not
6// copy, modify, or distribute this file except in compliance with said license. You can find copies
7// of these licenses either in the LICENSE-MIT and LICENSE-APACHE files, or alternatively at
8// <http://opensource.org/licenses/MIT> and <http://www.apache.org/licenses/LICENSE-2.0>
9// respectively.
10//
11// Portions of documentation are copied from the LGPL 2.1+ licensed PulseAudio C headers on a
12// fair-use basis, as discussed in the overall project readme (available in the git repository).
13
14//! MicroSeconds.
15
16use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Rem, RemAssign, Sub, SubAssign};
17use std::time::Duration;
18use super::op_err;
19
20/// Microseconds. Represents a span of time like [`std::time::Duration`].
21///
22/// This is an unsigned 64-bit type, and thus represents absolute values only.
23#[repr(transparent)]
24#[derive(Copy, Clone, Debug, Default, Eq, PartialEq, Ord, PartialOrd)]
25pub struct MicroSeconds(pub u64);
26
27impl MicroSeconds {
28 /// `MicroSeconds` value representing an ‘invalid’ time.
29 ///
30 /// # Examples
31 ///
32 /// ```rust
33 /// # use libpulse_binding::time::MicroSeconds;
34 /// assert_eq!(MicroSeconds::INVALID, MicroSeconds(std::u64::MAX));
35 /// ```
36 pub const INVALID: Self = Self(capi::PA_USEC_INVALID);
37
38 /// One second in microseconds.
39 ///
40 /// # Examples
41 ///
42 /// ```rust
43 /// # use libpulse_binding::time::MicroSeconds;
44 /// assert_eq!(MicroSeconds::SECOND, MicroSeconds(1_000_000));
45 /// ```
46 pub const SECOND: Self = Self(super::MICROS_PER_SEC);
47
48 /// One millisecond in microseconds.
49 ///
50 /// # Examples
51 ///
52 /// ```rust
53 /// # use libpulse_binding::time::MicroSeconds;
54 /// assert_eq!(MicroSeconds::MILLISECOND, MicroSeconds(1_000));
55 /// ```
56 pub const MILLISECOND: Self = Self(super::MICROS_PER_MILLI);
57
58 /// Zero value.
59 ///
60 /// # Examples
61 ///
62 /// ```rust
63 /// # use libpulse_binding::time::MicroSeconds;
64 /// assert_eq!(MicroSeconds::ZERO, MicroSeconds(0));
65 /// ```
66 pub const ZERO: Self = Self(0);
67
68 /// Smallest _valid_ time value (zero).
69 ///
70 /// # Examples
71 ///
72 /// ```rust
73 /// # use libpulse_binding::time::MicroSeconds;
74 /// assert_eq!(MicroSeconds::MIN, MicroSeconds(0));
75 /// ```
76 pub const MIN: Self = Self(0);
77
78 /// Largest _valid_ time value (largest integer value is reserved for representing ‘invalid’).
79 ///
80 /// Roughly equal to 5,124,095,576 hours, 213,503,982 days, or 584,542 years.
81 ///
82 /// # Examples
83 ///
84 /// ```rust
85 /// # use libpulse_binding::time::MicroSeconds;
86 /// assert_eq!(MicroSeconds::MAX, MicroSeconds(std::u64::MAX - 1));
87 /// ```
88 pub const MAX: Self = Self(capi::PA_USEC_MAX);
89
90 /// Get the inner `u64` value.
91 ///
92 /// # Examples
93 ///
94 /// ```rust
95 /// # use libpulse_binding::time::MicroSeconds;
96 /// assert_eq!(MicroSeconds(100).inner(), 100);
97 /// ```
98 #[inline]
99 pub const fn inner(&self) -> u64 {
100 self.0
101 }
102
103 /// Returns `true` so long as inner value is not [`Self::INVALID`].
104 ///
105 /// # Examples
106 ///
107 /// ```rust
108 /// # use libpulse_binding::time::{MicroSeconds, MICROS_PER_SEC};
109 /// assert_eq!(MicroSeconds::MIN.is_valid(), true);
110 /// assert_eq!(MicroSeconds::MAX.is_valid(), true);
111 /// assert_eq!(MicroSeconds::INVALID.is_valid(), false);
112 /// assert_eq!(MicroSeconds::ZERO.is_valid(), true);
113 /// assert_eq!(MicroSeconds(60 * MICROS_PER_SEC).is_valid(), true);
114 /// ```
115 #[inline]
116 pub const fn is_valid(&self) -> bool {
117 self.0 != Self::INVALID.0
118 }
119
120 /// Returns `true` so long as inner value is zero.
121 ///
122 /// # Examples
123 ///
124 /// ```rust
125 /// # use libpulse_binding::time::MicroSeconds;
126 /// assert_eq!(MicroSeconds::ZERO.is_zero(), true);
127 /// assert_eq!(MicroSeconds(0).is_zero(), true);
128 /// assert_eq!(MicroSeconds(1).is_zero(), false);
129 /// ```
130 #[inline]
131 pub const fn is_zero(&self) -> bool {
132 self.0 == 0
133 }
134
135 /// Creates a new `MicroSeconds` from the specified number of whole seconds. Returns `None` on
136 /// overflow.
137 ///
138 /// # Examples
139 ///
140 /// ```rust
141 /// # use libpulse_binding::time::MicroSeconds;
142 /// assert_eq!(MicroSeconds::from_secs(2), Some(MicroSeconds(2_000_000)));
143 /// assert_eq!(MicroSeconds::from_secs(0xffff_ffff_0000_0000), None);
144 /// ```
145 #[inline]
146 pub fn from_secs(secs: u64) -> Option<Self> {
147 secs.checked_mul(super::MICROS_PER_SEC).and_then(|i| Some(Self(i)))
148 }
149
150 /// Creates a new `MicroSeconds` from the specified number of whole milliseconds. Returns `None`
151 /// on overflow.
152 ///
153 /// # Examples
154 ///
155 /// ```rust
156 /// # use libpulse_binding::time::MicroSeconds;
157 /// assert_eq!(MicroSeconds::from_millis(23), Some(MicroSeconds(23_000)));
158 /// assert_eq!(MicroSeconds::from_millis(0xffff_ffff_0000_0000), None);
159 /// ```
160 #[inline]
161 pub fn from_millis(millis: u64) -> Option<Self> {
162 millis.checked_mul(super::MICROS_PER_MILLI).and_then(|i| Some(Self(i)))
163 }
164
165 /// Returns the absolute difference with `other`.
166 ///
167 /// # Examples
168 ///
169 /// ```rust
170 /// # use libpulse_binding::time::MicroSeconds;
171 /// assert_eq!(MicroSeconds(0).diff(MicroSeconds(0)), MicroSeconds(0));
172 /// assert_eq!(MicroSeconds(100).diff(MicroSeconds(100)), MicroSeconds(0));
173 /// assert_eq!(MicroSeconds(200).diff(MicroSeconds(150)), MicroSeconds(50));
174 /// assert_eq!(MicroSeconds(150).diff(MicroSeconds(200)), MicroSeconds(50));
175 /// ```
176 #[inline]
177 pub fn diff(self, other: Self) -> Self {
178 match self >= other {
179 true => Self(self.0 - other.0),
180 false => Self(other.0 - self.0),
181 }
182 }
183
184 /// Returns the total number of whole seconds.
185 ///
186 /// # Examples
187 ///
188 /// ```rust
189 /// # use libpulse_binding::time::MicroSeconds;
190 /// assert_eq!(MicroSeconds(2_300_000).as_secs(), 2);
191 /// assert_eq!(MicroSeconds(2_800_000).as_secs(), 2);
192 /// ```
193 #[inline]
194 pub const fn as_secs(&self) -> u64 {
195 self.0 / super::MICROS_PER_SEC
196 }
197
198 /// Returns the total number of whole milliseconds.
199 ///
200 /// # Examples
201 ///
202 /// ```rust
203 /// # use libpulse_binding::time::MicroSeconds;
204 /// assert_eq!(MicroSeconds(23_000_300).as_millis(), 23_000);
205 /// assert_eq!(MicroSeconds(23_000_800).as_millis(), 23_000);
206 /// ```
207 #[inline]
208 pub const fn as_millis(&self) -> u64 {
209 self.0 / super::MICROS_PER_MILLI
210 }
211
212 /// Creates a new `MicroSeconds` from the specified number of seconds represented as `f64`.
213 ///
214 /// **Panics** if `secs` is not finite, is negative, or the value overflows.
215 ///
216 /// # Examples
217 ///
218 /// ```rust
219 /// # use libpulse_binding::time::MicroSeconds;
220 /// assert_eq!(MicroSeconds::from_secs_f64(0.5), MicroSeconds(500_000));
221 /// assert_eq!(MicroSeconds::from_secs_f64(2.3), MicroSeconds(2_300_000));
222 /// ```
223 ///
224 /// These should panic.
225 ///
226 /// ```rust,should_panic
227 /// # use libpulse_binding::time::MicroSeconds;
228 /// MicroSeconds::from_secs_f64(std::f64::INFINITY);
229 /// ```
230 ///
231 /// ```rust,should_panic
232 /// # use libpulse_binding::time::MicroSeconds;
233 /// MicroSeconds::from_secs_f64(-0.5);
234 /// ```
235 ///
236 /// ```rust,should_panic
237 /// # use libpulse_binding::time::MicroSeconds;
238 /// MicroSeconds::from_secs_f64(std::f64::MAX);
239 /// ```
240 ///
241 /// ```rust,should_panic
242 /// # use libpulse_binding::time::MicroSeconds;
243 /// MicroSeconds::from_secs_f64(std::f64::NAN);
244 /// ```
245 #[inline]
246 pub fn from_secs_f64(secs: f64) -> Self {
247 let duration = Duration::from_secs_f64(secs);
248 Self::try_from(duration).expect("overflow during microseconds conversion")
249 }
250
251 /// Creates a new `MicroSeconds` from the specified number of seconds represented as `f32`.
252 ///
253 /// **Panics** if `secs` is not finite, is negative, or the value overflows.
254 ///
255 /// # Examples
256 ///
257 /// ```rust
258 /// # use libpulse_binding::time::MicroSeconds;
259 /// assert_eq!(MicroSeconds::from_secs_f32(0.5), MicroSeconds(500_000));
260 /// assert_eq!(MicroSeconds::from_secs_f32(2.3), MicroSeconds(2_299_999));
261 /// ```
262 ///
263 /// These should panic.
264 ///
265 /// ```rust,should_panic
266 /// # use libpulse_binding::time::MicroSeconds;
267 /// MicroSeconds::from_secs_f32(std::f32::INFINITY);
268 /// ```
269 ///
270 /// ```rust,should_panic
271 /// # use libpulse_binding::time::MicroSeconds;
272 /// MicroSeconds::from_secs_f32(-0.5);
273 /// ```
274 ///
275 /// ```rust,should_panic
276 /// # use libpulse_binding::time::MicroSeconds;
277 /// MicroSeconds::from_secs_f32(std::f32::MAX);
278 /// ```
279 ///
280 /// ```rust,should_panic
281 /// # use libpulse_binding::time::MicroSeconds;
282 /// MicroSeconds::from_secs_f32(std::f32::NAN);
283 /// ```
284 #[inline]
285 pub fn from_secs_f32(secs: f32) -> Self {
286 let duration = Duration::from_secs_f32(secs);
287 Self::try_from(duration).expect("overflow during microseconds conversion")
288 }
289
290 /// Returns the number of seconds as `f64`.
291 ///
292 /// # Examples
293 ///
294 /// ```rust
295 /// # use libpulse_binding::time::MicroSeconds;
296 /// assert_eq!(MicroSeconds(2_300_000).as_secs_f64(), 2.3);
297 /// assert_eq!(MicroSeconds(500_000).as_secs_f64(), 0.5);
298 /// ```
299 #[inline]
300 pub fn as_secs_f64(&self) -> f64 {
301 (self.0 as f64) / (super::MICROS_PER_SEC as f64)
302 }
303
304 /// Returns the number of seconds as `f32`.
305 ///
306 /// # Examples
307 ///
308 /// ```rust
309 /// # use libpulse_binding::time::MicroSeconds;
310 /// assert_eq!(MicroSeconds(2_300_000).as_secs_f32(), 2.3);
311 /// assert_eq!(MicroSeconds(500_000).as_secs_f32(), 0.5);
312 /// ```
313 #[inline]
314 pub fn as_secs_f32(&self) -> f32 {
315 (self.0 as f32) / (super::MICROS_PER_SEC as f32)
316 }
317
318 /// Checked integer addition. Computes `self + rhs`, returning `None` if overflow occurred,
319 /// using the inner integer’s [`checked_add()`](u64::checked_add) method.
320 ///
321 /// # Examples
322 ///
323 /// ```rust
324 /// # use libpulse_binding::time::{MicroSeconds, MICROS_PER_SEC};
325 /// let quater_minute = MicroSeconds(15 * MICROS_PER_SEC);
326 /// let half_minute = MicroSeconds(30 * MICROS_PER_SEC);
327 /// let three_quater_minute = MicroSeconds(45 * MICROS_PER_SEC);
328 ///
329 /// assert_eq!(half_minute.checked_add(quater_minute), Some(three_quater_minute));
330 /// assert_eq!(MicroSeconds::MAX.checked_add(half_minute), None);
331 /// ```
332 #[inline]
333 pub fn checked_add(self, other: Self) -> Option<Self> {
334 self.0.checked_add(other.0).and_then(|i| Some(Self(i)))
335 }
336
337 /// Checked integer addition. Computes `self + rhs`, returning `None` if overflow occurred,
338 /// using the inner integer’s [`checked_add()`](u64::checked_add) method.
339 ///
340 /// # Examples
341 ///
342 /// ```rust
343 /// # use std::time::Duration;
344 /// # use libpulse_binding::time::{MicroSeconds, MICROS_PER_SEC, NANOS_PER_MICRO};
345 /// let half_minute = MicroSeconds(30 * MICROS_PER_SEC);
346 /// let duration1 = Duration::new(2, 5 * NANOS_PER_MICRO + 20); // 2s + 5us + 20ns
347 /// let duration2 = Duration::new(MicroSeconds::MAX.inner() / MICROS_PER_SEC, 0);
348 ///
349 /// assert_eq!(half_minute.checked_add_duration(duration1), Some(MicroSeconds(32_000_005)));
350 /// assert_eq!(half_minute.checked_add_duration(duration2), None);
351 /// ```
352 #[inline]
353 pub fn checked_add_duration(self, rhs: Duration) -> Option<Self> {
354 let usecs = Self::try_from(rhs).ok()?;
355 self.0.checked_add(usecs.0).and_then(|i| Some(Self(i)))
356 }
357
358 /// Checked integer subtraction. Computes `self - rhs`, returning `None` if overflow occurred,
359 /// using the inner integer’s [`checked_sub()`](u64::checked_sub) method.
360 ///
361 /// # Examples
362 ///
363 /// ```rust
364 /// # use libpulse_binding::time::{MicroSeconds, MICROS_PER_SEC};
365 /// let quater_minute = MicroSeconds(15 * MICROS_PER_SEC);
366 /// let three_quater_minute = MicroSeconds(45 * MICROS_PER_SEC);
367 /// let whole_minute = MicroSeconds(60 * MICROS_PER_SEC);
368 ///
369 /// assert_eq!(whole_minute.checked_sub(quater_minute), Some(three_quater_minute));
370 /// assert_eq!(quater_minute.checked_sub(whole_minute), None);
371 /// ```
372 #[inline]
373 pub fn checked_sub(self, other: Self) -> Option<Self> {
374 self.0.checked_sub(other.0).and_then(|i| Some(Self(i)))
375 }
376
377 /// Checked integer subtraction. Computes `self - rhs`, returning `None` if overflow occurred,
378 /// using the inner integer’s [`checked_sub()`](u64::checked_sub) method.
379 ///
380 /// # Examples
381 ///
382 /// ```rust
383 /// # use std::time::Duration;
384 /// # use libpulse_binding::time::{MicroSeconds, MICROS_PER_SEC, NANOS_PER_MICRO};
385 /// let half_minute = MicroSeconds(30 * MICROS_PER_SEC);
386 /// let duration1 = Duration::new(2, 5 * NANOS_PER_MICRO + 20); // 2s + 5us + 20ns
387 /// let duration2 = Duration::new(45, 0);
388 ///
389 /// assert_eq!(half_minute.checked_sub_duration(duration1), Some(MicroSeconds(27_999_995)));
390 /// assert_eq!(half_minute.checked_sub_duration(duration2), None);
391 /// ```
392 #[inline]
393 pub fn checked_sub_duration(self, rhs: Duration) -> Option<Self> {
394 let usecs = Self::try_from(rhs).ok()?;
395 self.0.checked_sub(usecs.0).and_then(|i| Some(Self(i)))
396 }
397
398 /// Checked integer multiplication. Computes `self * rhs`, returning `None` if overflow
399 /// occurred, using the inner integer’s [`checked_mul()`](u64::checked_mul) method.
400 ///
401 /// # Examples
402 ///
403 /// ```rust
404 /// # use libpulse_binding::time::{MicroSeconds, MICROS_PER_SEC};
405 /// let quater_minute = MicroSeconds(15 * MICROS_PER_SEC);
406 /// let whole_minute = MicroSeconds(60 * MICROS_PER_SEC);
407 ///
408 /// assert_eq!(quater_minute.checked_mul(4), Some(whole_minute));
409 /// assert_eq!(MicroSeconds::MAX.checked_mul(2), None);
410 /// ```
411 #[inline]
412 pub fn checked_mul(self, rhs: u32) -> Option<Self> {
413 self.0.checked_mul(rhs as u64).and_then(|i| Some(Self(i)))
414 }
415
416 /// Checked integer division. Computes `self / rhs`, returning `None` if `rhs == 0`, using the
417 /// inner integer’s [`checked_div()`](u64::checked_div) method.
418 ///
419 /// # Examples
420 ///
421 /// ```rust
422 /// # use libpulse_binding::time::{MicroSeconds, MICROS_PER_SEC};
423 /// let quater_minute = MicroSeconds(15 * MICROS_PER_SEC);
424 /// let whole_minute = MicroSeconds(60 * MICROS_PER_SEC);
425 ///
426 /// assert_eq!(whole_minute.checked_div(4), Some(quater_minute));
427 /// assert_eq!(whole_minute.checked_div(0), None);
428 /// ```
429 #[inline]
430 pub fn checked_div(self, rhs: u32) -> Option<Self> {
431 self.0.checked_div(rhs as u64).and_then(|i| Some(Self(i)))
432 }
433
434 /// Checked integer remainder. Computes `self % rhs`, returning `None` if `rhs == 0`, using the
435 /// inner integer’s [`checked_rem()`](u64::checked_rem) method.
436 ///
437 /// # Examples
438 ///
439 /// ```rust
440 /// # use libpulse_binding::time::{MicroSeconds, MICROS_PER_SEC};
441 /// let quater_minute = MicroSeconds(15 * MICROS_PER_SEC);
442 /// let whole_minute = MicroSeconds(60 * MICROS_PER_SEC);
443 ///
444 /// assert_eq!(whole_minute.checked_rem(4), Some(MicroSeconds::ZERO));
445 /// assert_eq!(whole_minute.checked_rem(7), Some(MicroSeconds(4)));
446 /// assert_eq!(whole_minute.checked_rem(0), None);
447 /// ```
448 #[inline]
449 pub fn checked_rem(self, rhs: u32) -> Option<Self> {
450 self.0.checked_rem(rhs as u64).and_then(|i| Some(Self(i)))
451 }
452
453 /// Multiplies `MicroSeconds` by `f64`.
454 ///
455 /// Converts to an `f64` representing seconds, multiplies by the given factor, then converts
456 /// back to microseconds.
457 ///
458 /// **Panics** if `rhs` is not finite, is negative, or the value overflows.
459 ///
460 /// # Examples
461 ///
462 /// ```rust
463 /// # use libpulse_binding::time::{MicroSeconds, MICROS_PER_SEC};
464 /// let micros = MicroSeconds(2_700_000_000);
465 ///
466 /// assert_eq!(micros.mul_f64(3.14), MicroSeconds(8_478_000_000));
467 /// assert_eq!(micros.mul_f64(3.14e5), MicroSeconds(847_800_000_000_000));
468 /// ```
469 ///
470 /// These should panic.
471 ///
472 /// ```rust,should_panic
473 /// # use libpulse_binding::time::MicroSeconds;
474 /// MicroSeconds::SECOND.mul_f64(std::f64::INFINITY);
475 /// ```
476 ///
477 /// ```rust,should_panic
478 /// # use libpulse_binding::time::MicroSeconds;
479 /// MicroSeconds::SECOND.mul_f64(-0.5);
480 /// ```
481 ///
482 /// ```rust,should_panic
483 /// # use libpulse_binding::time::{MicroSeconds, MICROS_PER_SEC};
484 /// MicroSeconds(2 * MICROS_PER_SEC).mul_f64(std::f64::MAX / 10.0);
485 /// ```
486 ///
487 /// ```rust,should_panic
488 /// # use libpulse_binding::time::MicroSeconds;
489 /// MicroSeconds::SECOND.mul_f64(std::f64::NAN);
490 /// ```
491 #[inline]
492 pub fn mul_f64(self, rhs: f64) -> Self {
493 // It is expected that overflow in the initial multiplication would result in `NaN`.
494 // We rely upon the underlying `Duration::from_secs_f64()` to panic appropriately for
495 // unsupported input and result values.
496 Self::from_secs_f64(rhs * self.as_secs_f64())
497 }
498
499 /// Multiplies `MicroSeconds` by `f32`.
500 ///
501 /// Converts to an `f32` representing seconds, multiplies by the given factor, then converts
502 /// back to microseconds.
503 ///
504 /// **Panics** if `rhs` is not finite, is negative, or the value overflows.
505 ///
506 /// # Examples
507 ///
508 /// ```rust
509 /// # use libpulse_binding::time::{MicroSeconds, MICROS_PER_SEC};
510 /// let micros = MicroSeconds(2_700_000_000);
511 ///
512 /// // Note the rounding errors that are clear here.
513 /// assert_eq!(micros.mul_f32(3.14), MicroSeconds(8_478_000_000));
514 /// assert_eq!(micros.mul_f32(3.14e5), MicroSeconds(847_800_000_000_000));
515 /// ```
516 ///
517 /// These should panic.
518 ///
519 /// ```rust,should_panic
520 /// # use libpulse_binding::time::MicroSeconds;
521 /// MicroSeconds::SECOND.mul_f32(std::f32::INFINITY);
522 /// ```
523 ///
524 /// ```rust,should_panic
525 /// # use libpulse_binding::time::MicroSeconds;
526 /// MicroSeconds::SECOND.mul_f32(-0.5);
527 /// ```
528 ///
529 /// ```rust,should_panic
530 /// # use libpulse_binding::time::{MicroSeconds, MICROS_PER_SEC};
531 /// MicroSeconds(2 * MICROS_PER_SEC).mul_f32(std::f32::MAX / 10.0);
532 /// ```
533 ///
534 /// ```rust,should_panic
535 /// # use libpulse_binding::time::MicroSeconds;
536 /// MicroSeconds::SECOND.mul_f32(std::f32::NAN);
537 /// ```
538 #[inline]
539 pub fn mul_f32(self, rhs: f32) -> Self {
540 // It is expected that overflow in the initial multiplication would result in `NaN`.
541 // We rely upon the underlying `Duration::from_secs_f64()` to panic appropriately for
542 // unsupported input and result values.
543 Self::from_secs_f32(rhs * self.as_secs_f32())
544 }
545
546 /// Divides `MicroSeconds` by `f64`.
547 ///
548 /// Converts to an `f64` representing seconds, divides by the given factor, then converts back
549 /// to microseconds.
550 ///
551 /// **Panics** if `rhs` is not finite, is negative, or the value overflows.
552 ///
553 /// # Examples
554 ///
555 /// ```rust
556 /// # use libpulse_binding::time::{MicroSeconds, MICROS_PER_SEC};
557 /// let micros = MicroSeconds(2_700_000_000);
558 ///
559 /// assert_eq!(micros.div_f64(3.14), MicroSeconds(859_872_611));
560 /// assert_eq!(micros.div_f64(3.14e5), MicroSeconds(8_598));
561 /// ```
562 ///
563 /// These should panic.
564 ///
565 /// ```rust,should_panic
566 /// # use libpulse_binding::time::MicroSeconds;
567 /// MicroSeconds::SECOND.div_f64(-2.0);
568 /// ```
569 ///
570 /// ```rust,should_panic
571 /// # use libpulse_binding::time::{MicroSeconds, MICROS_PER_SEC};
572 /// MicroSeconds::MAX.div_f64(0.5);
573 /// ```
574 ///
575 /// ```rust,should_panic
576 /// # use libpulse_binding::time::MicroSeconds;
577 /// MicroSeconds::SECOND.div_f64(std::f64::NAN);
578 /// ```
579 #[inline]
580 pub fn div_f64(self, rhs: f64) -> Self {
581 // Note that division by zero results in a ∞ or −∞ value, which will be handled by the
582 // underlying `Duration::from_secs_f64()` which we rely upon to panic appropriately.
583 Self::from_secs_f64(self.as_secs_f64() / rhs)
584 }
585
586 /// Divides `MicroSeconds` by `f32`.
587 ///
588 /// Converts to an `f32` representing seconds, divides by the given factor, then converts back
589 /// to microseconds.
590 ///
591 /// **Panics** if `rhs` is not finite, is negative, or the value overflows.
592 ///
593 /// # Examples
594 ///
595 /// ```rust
596 /// # use libpulse_binding::time::{MicroSeconds, MICROS_PER_SEC};
597 /// let micros = MicroSeconds(2_700_000_000);
598 ///
599 /// assert_eq!(micros.div_f32(3.14), MicroSeconds(859_872_558));
600 /// assert_eq!(micros.div_f32(3.14e5), MicroSeconds(8_598));
601 /// ```
602 ///
603 /// These should panic.
604 ///
605 /// ```rust,should_panic
606 /// # use libpulse_binding::time::MicroSeconds;
607 /// MicroSeconds::SECOND.div_f32(-2.0);
608 /// ```
609 ///
610 /// ```rust,should_panic
611 /// # use libpulse_binding::time::{MicroSeconds, MICROS_PER_SEC};
612 /// MicroSeconds::MAX.div_f32(0.5);
613 /// ```
614 ///
615 /// ```rust,should_panic
616 /// # use libpulse_binding::time::MicroSeconds;
617 /// MicroSeconds::SECOND.div_f32(std::f32::NAN);
618 /// ```
619 #[inline]
620 pub fn div_f32(self, rhs: f32) -> Self {
621 // Note that division by zero results in a ∞ or −∞ value, which will be handled by the
622 // underlying `Duration::from_secs_f64()` which we rely upon to panic appropriately.
623 Self::from_secs_f32(self.as_secs_f32() / rhs)
624 }
625}
626
627impl std::fmt::Display for MicroSeconds {
628 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
629 write!(f, "{} µs", self.0)
630 }
631}
632
633impl Add for MicroSeconds {
634 type Output = Self;
635
636 #[track_caller]
637 #[inline]
638 fn add(self, other: Self) -> Self {
639 self.checked_add(other).expect(op_err::ADD)
640 }
641}
642impl AddAssign for MicroSeconds {
643 #[track_caller]
644 #[inline]
645 fn add_assign(&mut self, rhs: Self) {
646 *self = self.add(rhs);
647 }
648}
649
650impl Sub for MicroSeconds {
651 type Output = Self;
652
653 #[track_caller]
654 #[inline]
655 fn sub(self, other: Self) -> Self {
656 self.checked_sub(other).expect(op_err::SUB)
657 }
658}
659impl SubAssign for MicroSeconds {
660 #[track_caller]
661 #[inline]
662 fn sub_assign(&mut self, rhs: Self) {
663 *self = self.sub(rhs);
664 }
665}
666
667////////////////////////////////////////////////////////////////////////////////////////////////////
668// Operations with `Duration`
669////////////////////////////////////////////////////////////////////////////////////////////////////
670
671impl Add<Duration> for MicroSeconds {
672 type Output = Self;
673
674 #[track_caller]
675 #[inline]
676 fn add(self, rhs: Duration) -> Self {
677 self.checked_add_duration(rhs).expect(op_err::ADD)
678 }
679}
680impl AddAssign<Duration> for MicroSeconds {
681 #[track_caller]
682 #[inline]
683 fn add_assign(&mut self, rhs: Duration) {
684 *self = self.add(rhs);
685 }
686}
687
688impl Add<MicroSeconds> for Duration {
689 type Output = Self;
690
691 #[track_caller]
692 #[inline]
693 fn add(self, rhs: MicroSeconds) -> Self {
694 self.checked_add(Duration::from_micros(rhs.0)).expect(op_err::ADD)
695 }
696}
697impl AddAssign<MicroSeconds> for Duration {
698 #[track_caller]
699 #[inline]
700 fn add_assign(&mut self, rhs: MicroSeconds) {
701 *self = self.add(rhs);
702 }
703}
704
705impl Sub<Duration> for MicroSeconds {
706 type Output = Self;
707
708 #[track_caller]
709 #[inline]
710 fn sub(self, rhs: Duration) -> Self {
711 self.checked_sub_duration(rhs).expect(op_err::SUB)
712 }
713}
714impl SubAssign<Duration> for MicroSeconds {
715 #[track_caller]
716 #[inline]
717 fn sub_assign(&mut self, rhs: Duration) {
718 *self = self.sub(rhs);
719 }
720}
721
722impl Sub<MicroSeconds> for Duration {
723 type Output = Self;
724
725 #[track_caller]
726 #[inline]
727 fn sub(self, rhs: MicroSeconds) -> Self {
728 self.checked_sub(Duration::from_micros(rhs.0)).expect(op_err::SUB)
729 }
730}
731impl SubAssign<MicroSeconds> for Duration {
732 #[track_caller]
733 #[inline]
734 fn sub_assign(&mut self, rhs: MicroSeconds) {
735 *self = self.sub(rhs);
736 }
737}
738
739////////////////////////////////////////////////////////////////////////////////////////////////////
740// Operations with primitives
741//
742// NOTE 1: We only implement `u32` here because:
743// - We do not expect operations will be needed for the larger `u64` range, otherwise we should
744// switch to that.
745// - Although implementing for the set of { `u8`, `u16`, `u32`, `u64 } is very easy with a macro,
746// and may avoid possible need for `as u32` for non-`u32` variables, it introduces ambiguity such
747// that the compiler does not know which type the `2` should be in the example use case of `2 *
748// MicroSeconds::SECOND` and so it goes with `i32`, and since we don't implement the ops for
749// `i32`, the user thus gets an error, forcing them to write instead `2u32 *
750// MicroSeconds::SECOND`.
751//
752// NOTE 2: Addition and subtraction deliberately not implemented, since allowing arbitrary such
753// operations would allow mistakes to be made that the `MicroSeconds` type exists to prevent. I.e.
754// allowing the following:
755//
756// ```rust
757// let a = 10u32;
758// let b = MicroSeconds(1) + a;
759// ```
760//
761// ...would allow mistakes to be made around the form of `a`. We must force `a` to be wrapped in
762// `MicroSeconds`.
763//
764// NOTE 3: We support an integer being the Lhs of the operation for multiplicaton (for example
765// `2 * MicroSeconds`), but not for division/remainder, because dividing a generic integer by an
766// amount of microseconds makes no sense.
767//
768////////////////////////////////////////////////////////////////////////////////////////////////////
769
770impl Mul<u32> for MicroSeconds {
771 type Output = Self;
772
773 #[track_caller]
774 #[inline]
775 fn mul(self, rhs: u32) -> Self {
776 Self(self.0.checked_mul(rhs as u64).expect(op_err::MUL))
777 }
778}
779impl MulAssign<u32> for MicroSeconds {
780 #[track_caller]
781 #[inline]
782 fn mul_assign(&mut self, rhs: u32) {
783 *self = self.mul(rhs);
784 }
785}
786
787impl Mul<MicroSeconds> for u32 {
788 type Output = MicroSeconds;
789
790 #[track_caller]
791 #[inline]
792 fn mul(self, rhs: MicroSeconds) -> MicroSeconds {
793 rhs.mul(self)
794 }
795}
796
797impl Div<u32> for MicroSeconds {
798 type Output = Self;
799
800 #[track_caller]
801 #[inline]
802 fn div(self, rhs: u32) -> Self {
803 Self(self.0.checked_div(rhs as u64).expect(op_err::DIV))
804 }
805}
806impl DivAssign<u32> for MicroSeconds {
807 #[track_caller]
808 #[inline]
809 fn div_assign(&mut self, rhs: u32) {
810 *self = self.div(rhs);
811 }
812}
813
814impl Rem<u32> for MicroSeconds {
815 type Output = Self;
816
817 #[track_caller]
818 #[inline]
819 fn rem(self, rhs: u32) -> Self {
820 Self(self.0.checked_rem(rhs as u64).expect(op_err::REM))
821 }
822}
823impl RemAssign<u32> for MicroSeconds {
824 #[track_caller]
825 #[inline]
826 fn rem_assign(&mut self, rhs: u32) {
827 *self = self.rem(rhs);
828 }
829}