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}