mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer-rs.git
synced 2024-11-22 09:31:06 +00:00
gstreamer: Add seconds_f32 & seconds_f64 methods and from_seconds_f32 & from_seconds_f64 constructor for ClockTime and Signed<ClockTime>
Closes #443 Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer-rs/-/merge_requests/1223>
This commit is contained in:
parent
cd8e8cea5a
commit
862f4d014c
1 changed files with 323 additions and 0 deletions
|
@ -14,6 +14,20 @@ use super::{
|
|||
SpecificFormattedValueFullRange, SpecificFormattedValueIntrinsic,
|
||||
};
|
||||
|
||||
const TRY_FROM_FLOAT_SECS_ERROR_MSG: &str =
|
||||
"can not convert float seconds to ClockTime: value is either negative, too big or NaN";
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct TryFromFloatSecsError;
|
||||
|
||||
impl fmt::Display for TryFromFloatSecsError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.write_str(TRY_FROM_FLOAT_SECS_ERROR_MSG)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::error::Error for TryFromFloatSecsError {}
|
||||
|
||||
#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy, Default)]
|
||||
pub struct ClockTime(u64);
|
||||
|
||||
|
@ -44,6 +58,16 @@ impl ClockTime {
|
|||
self.0 / Self::SECOND.0
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn seconds_f32(self) -> f32 {
|
||||
self.0 as f32 / Self::SECOND.0 as f32
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn seconds_f64(self) -> f64 {
|
||||
self.0 as f64 / Self::SECOND.0 as f64
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub const fn mseconds(self) -> u64 {
|
||||
self.0 / Self::MSECOND.0
|
||||
|
@ -76,6 +100,62 @@ impl ClockTime {
|
|||
})
|
||||
}
|
||||
|
||||
// rustdoc-stripper-ignore-next
|
||||
/// Builds a new `ClockTime` which value is the given number of seconds.
|
||||
///
|
||||
/// Returns an error if seconds is negative, infinite or NaN, or
|
||||
/// the resulting duration in nanoseconds exceeds the `u64` range.
|
||||
#[inline]
|
||||
pub fn try_from_seconds_f32(seconds: f32) -> Result<Self, TryFromFloatSecsError> {
|
||||
skip_assert_initialized!();
|
||||
|
||||
let dur = Duration::try_from_secs_f32(seconds).map_err(|_| TryFromFloatSecsError)?;
|
||||
ClockTime::try_from(dur).map_err(|_| TryFromFloatSecsError)
|
||||
}
|
||||
|
||||
// rustdoc-stripper-ignore-next
|
||||
/// Builds a new `ClockTime` which value is the given number of seconds.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if seconds is negative, infinite or NaN, or the resulting duration
|
||||
/// in nanoseconds exceeds the `u64` range.
|
||||
#[track_caller]
|
||||
#[inline]
|
||||
pub fn from_seconds_f32(seconds: f32) -> Self {
|
||||
skip_assert_initialized!();
|
||||
|
||||
Self::try_from_seconds_f32(seconds).expect(TRY_FROM_FLOAT_SECS_ERROR_MSG)
|
||||
}
|
||||
|
||||
// rustdoc-stripper-ignore-next
|
||||
/// Builds a new `ClockTime` which value is the given number of seconds.
|
||||
///
|
||||
/// Returns an error if seconds is negative, infinite or NaN, or
|
||||
/// the resulting duration in nanoseconds exceeds the `u64` range.
|
||||
#[inline]
|
||||
pub fn try_from_seconds_f64(seconds: f64) -> Result<Self, TryFromFloatSecsError> {
|
||||
skip_assert_initialized!();
|
||||
|
||||
let dur = Duration::try_from_secs_f64(seconds).map_err(|_| TryFromFloatSecsError)?;
|
||||
ClockTime::try_from(dur).map_err(|_| TryFromFloatSecsError)
|
||||
}
|
||||
|
||||
// rustdoc-stripper-ignore-next
|
||||
/// Builds a new `ClockTime` which value is the given number of seconds.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if seconds is negative, infinite or NaN, or the resulting duration
|
||||
/// in nanoseconds exceeds the `u64` range.
|
||||
#[track_caller]
|
||||
#[inline]
|
||||
pub fn from_seconds_f64(seconds: f64) -> Self {
|
||||
skip_assert_initialized!();
|
||||
|
||||
Self::try_from_seconds_f64(seconds).expect(TRY_FROM_FLOAT_SECS_ERROR_MSG)
|
||||
}
|
||||
|
||||
// rustdoc-stripper-ignore-next
|
||||
/// Builds a new `ClockTime` which value is the given number of milliseconds.
|
||||
///
|
||||
|
@ -203,6 +283,26 @@ impl Signed<ClockTime> {
|
|||
}
|
||||
}
|
||||
|
||||
// rustdoc-stripper-ignore-next
|
||||
/// Returns the `self` in f32 seconds.
|
||||
#[inline]
|
||||
pub fn seconds_f32(self) -> f32 {
|
||||
match self {
|
||||
Signed::Positive(val) => val.seconds_f32(),
|
||||
Signed::Negative(val) => -val.seconds_f32(),
|
||||
}
|
||||
}
|
||||
|
||||
// rustdoc-stripper-ignore-next
|
||||
/// Returns the `self` in f64 seconds.
|
||||
#[inline]
|
||||
pub fn seconds_f64(self) -> f64 {
|
||||
match self {
|
||||
Signed::Positive(val) => val.seconds_f64(),
|
||||
Signed::Negative(val) => -val.seconds_f64(),
|
||||
}
|
||||
}
|
||||
|
||||
// rustdoc-stripper-ignore-next
|
||||
/// Creates new value from seconds.
|
||||
#[inline]
|
||||
|
@ -213,6 +313,72 @@ impl Signed<ClockTime> {
|
|||
Signed::Negative(val) => Signed::Negative(ClockTime::from_seconds(val)),
|
||||
}
|
||||
}
|
||||
|
||||
// rustdoc-stripper-ignore-next
|
||||
/// Builds a new `Signed<ClockTime>` which value is the given number of seconds.
|
||||
///
|
||||
/// Returns an error if seconds is infinite or NaN, or
|
||||
/// the resulting duration in nanoseconds exceeds the `u64` range.
|
||||
#[inline]
|
||||
pub fn try_from_seconds_f32(seconds: f32) -> Result<Self, TryFromFloatSecsError> {
|
||||
skip_assert_initialized!();
|
||||
|
||||
ClockTime::try_from_seconds_f32(seconds.abs()).map(|ct| {
|
||||
if seconds.is_sign_positive() {
|
||||
Signed::Positive(ct)
|
||||
} else {
|
||||
Signed::Negative(ct)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// rustdoc-stripper-ignore-next
|
||||
/// Builds a new `Signed<ClockTime>` which value is the given number of seconds.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if seconds is infinite or NaN, or the resulting duration
|
||||
/// in nanoseconds exceeds the `u64` range.
|
||||
#[track_caller]
|
||||
#[inline]
|
||||
pub fn from_seconds_f32(seconds: f32) -> Self {
|
||||
skip_assert_initialized!();
|
||||
|
||||
Self::try_from_seconds_f32(seconds).expect(TRY_FROM_FLOAT_SECS_ERROR_MSG)
|
||||
}
|
||||
|
||||
// rustdoc-stripper-ignore-next
|
||||
/// Builds a new `Signed<ClockTime>` which value is the given number of seconds.
|
||||
///
|
||||
/// Returns an error if seconds is infinite or NaN, or
|
||||
/// the resulting duration in nanoseconds exceeds the `u64` range.
|
||||
#[inline]
|
||||
pub fn try_from_seconds_f64(seconds: f64) -> Result<Self, TryFromFloatSecsError> {
|
||||
skip_assert_initialized!();
|
||||
|
||||
ClockTime::try_from_seconds_f64(seconds.abs()).map(|ct| {
|
||||
if seconds.is_sign_positive() {
|
||||
Signed::Positive(ct)
|
||||
} else {
|
||||
Signed::Negative(ct)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// rustdoc-stripper-ignore-next
|
||||
/// Builds a new `Signed<ClockTime>` which value is the given number of seconds.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if seconds is infinite or NaN, or the resulting duration
|
||||
/// in nanoseconds exceeds the `u64` range.
|
||||
#[track_caller]
|
||||
#[inline]
|
||||
pub fn from_seconds_f64(seconds: f64) -> Self {
|
||||
skip_assert_initialized!();
|
||||
|
||||
Self::try_from_seconds_f64(seconds).expect(TRY_FROM_FLOAT_SECS_ERROR_MSG)
|
||||
}
|
||||
}
|
||||
|
||||
impl_format_value_traits!(ClockTime, Time, Time, u64);
|
||||
|
@ -1478,4 +1644,161 @@ mod tests {
|
|||
obj.set_optional_clock_time(ClockTime::MAX);
|
||||
assert_eq!(obj.optional_clock_time(), Some(ClockTime::MAX));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn seconds_float() {
|
||||
let res = ClockTime::ZERO;
|
||||
assert_eq!(res.seconds_f32(), 0.0);
|
||||
assert_eq!(res.seconds_f64(), 0.0);
|
||||
|
||||
let res = ClockTime::from_nseconds(2_700_000_000);
|
||||
assert_eq!(res.seconds_f32(), 2.7);
|
||||
assert_eq!(res.seconds_f64(), 2.7);
|
||||
|
||||
let res = ClockTime::MAX;
|
||||
assert_eq!(res.seconds_f32(), 18_446_744_073.709_553);
|
||||
assert_eq!(res.seconds_f64(), 18_446_744_073.709_553);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn seconds_float_signed() {
|
||||
let pos = Signed::Positive(ClockTime::ZERO);
|
||||
assert_eq!(pos.seconds_f32(), 0.0);
|
||||
assert_eq!(pos.seconds_f64(), 0.0);
|
||||
let neg = Signed::Negative(ClockTime::ZERO);
|
||||
assert_eq!(neg.seconds_f32(), 0.0);
|
||||
assert_eq!(neg.seconds_f64(), 0.0);
|
||||
|
||||
let pos = Signed::Positive(ClockTime::from_nseconds(2_700_000_000));
|
||||
assert_eq!(pos.seconds_f32(), 2.7);
|
||||
assert_eq!(pos.seconds_f64(), 2.7);
|
||||
let neg = Signed::Negative(ClockTime::from_nseconds(2_700_000_000));
|
||||
assert_eq!(neg.seconds_f32(), -2.7);
|
||||
assert_eq!(neg.seconds_f64(), -2.7);
|
||||
|
||||
let pos = Signed::Positive(ClockTime::MAX);
|
||||
assert_eq!(pos.seconds_f32(), 18_446_744_073.709_553);
|
||||
assert_eq!(pos.seconds_f64(), 18_446_744_073.709_553);
|
||||
let neg = Signed::Negative(ClockTime::MAX);
|
||||
assert_eq!(neg.seconds_f32(), -18_446_744_073.709_553);
|
||||
assert_eq!(neg.seconds_f64(), -18_446_744_073.709_553);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn try_from_seconds_f32() {
|
||||
let res = ClockTime::try_from_seconds_f32(0.0);
|
||||
assert_eq!(res, Ok(ClockTime::ZERO));
|
||||
let res = ClockTime::try_from_seconds_f32(1e-20);
|
||||
assert_eq!(res, Ok(ClockTime::ZERO));
|
||||
let res = ClockTime::try_from_seconds_f32(4.2e-7);
|
||||
assert_eq!(res, Ok(ClockTime::from_nseconds(420)));
|
||||
let res = ClockTime::try_from_seconds_f32(2.7);
|
||||
assert_eq!(res, Ok(ClockTime::from_nseconds(2_700_000_048)));
|
||||
// subnormal float:
|
||||
let res = ClockTime::try_from_seconds_f32(f32::from_bits(1));
|
||||
assert_eq!(res, Ok(ClockTime::ZERO));
|
||||
|
||||
// the conversion uses rounding with tie resolution to even
|
||||
let res = ClockTime::try_from_seconds_f32(0.999e-9);
|
||||
assert_eq!(res, Ok(ClockTime::from_nseconds(1)));
|
||||
|
||||
let res = ClockTime::try_from_seconds_f32(-5.0);
|
||||
assert!(res.is_err());
|
||||
let res = ClockTime::try_from_seconds_f32(f32::NAN);
|
||||
assert!(res.is_err());
|
||||
let res = ClockTime::try_from_seconds_f32(2e19);
|
||||
assert!(res.is_err());
|
||||
|
||||
// this float represents exactly 976562.5e-9
|
||||
let val = f32::from_bits(0x3A80_0000);
|
||||
let res = ClockTime::try_from_seconds_f32(val);
|
||||
assert_eq!(res, Ok(ClockTime::from_nseconds(976_562)));
|
||||
|
||||
// this float represents exactly 2929687.5e-9
|
||||
let val = f32::from_bits(0x3B40_0000);
|
||||
let res = ClockTime::try_from_seconds_f32(val);
|
||||
assert_eq!(res, Ok(ClockTime::from_nseconds(2_929_688)));
|
||||
|
||||
// this float represents exactly 1.000_976_562_5
|
||||
let val = f32::from_bits(0x3F802000);
|
||||
let res = ClockTime::try_from_seconds_f32(val);
|
||||
assert_eq!(res, Ok(ClockTime::from_nseconds(1_000_976_562)));
|
||||
|
||||
// this float represents exactly 1.002_929_687_5
|
||||
let val = f32::from_bits(0x3F806000);
|
||||
let res = ClockTime::try_from_seconds_f32(val);
|
||||
assert_eq!(res, Ok(ClockTime::from_nseconds(1_002_929_688)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn try_from_seconds_f64() {
|
||||
let res = ClockTime::try_from_seconds_f64(0.0);
|
||||
assert_eq!(res, Ok(ClockTime::ZERO));
|
||||
let res = ClockTime::try_from_seconds_f64(1e-20);
|
||||
assert_eq!(res, Ok(ClockTime::ZERO));
|
||||
let res = ClockTime::try_from_seconds_f64(4.2e-7);
|
||||
assert_eq!(res, Ok(ClockTime::from_nseconds(420)));
|
||||
let res = ClockTime::try_from_seconds_f64(2.7);
|
||||
assert_eq!(res, Ok(ClockTime::from_nseconds(2_700_000_000)));
|
||||
// subnormal float:
|
||||
let res = ClockTime::try_from_seconds_f64(f64::from_bits(1));
|
||||
assert_eq!(res, Ok(ClockTime::ZERO));
|
||||
|
||||
// the conversion uses rounding with tie resolution to even
|
||||
let res = ClockTime::try_from_seconds_f64(0.999e-9);
|
||||
assert_eq!(res, Ok(ClockTime::from_nseconds(1)));
|
||||
let res = ClockTime::try_from_seconds_f64(0.999_999_999_499);
|
||||
assert_eq!(res, Ok(ClockTime::from_nseconds(999_999_999)));
|
||||
let res = ClockTime::try_from_seconds_f64(0.999_999_999_501);
|
||||
assert_eq!(res, Ok(ClockTime::from_seconds(1)));
|
||||
let res = ClockTime::try_from_seconds_f64(42.999_999_999_499);
|
||||
assert_eq!(res, Ok(ClockTime::from_nseconds(42_999_999_999)));
|
||||
let res = ClockTime::try_from_seconds_f64(42.999_999_999_501);
|
||||
assert_eq!(res, Ok(ClockTime::from_seconds(43)));
|
||||
|
||||
let res = ClockTime::try_from_seconds_f64(-5.0);
|
||||
assert!(res.is_err());
|
||||
let res = ClockTime::try_from_seconds_f64(f64::NAN);
|
||||
assert!(res.is_err());
|
||||
let res = ClockTime::try_from_seconds_f64(2e19);
|
||||
assert!(res.is_err());
|
||||
|
||||
// this float represents exactly 976562.5e-9
|
||||
let val = f64::from_bits(0x3F50_0000_0000_0000);
|
||||
let res = ClockTime::try_from_seconds_f64(val);
|
||||
assert_eq!(res, Ok(ClockTime::from_nseconds(976_562)));
|
||||
|
||||
// this float represents exactly 2929687.5e-9
|
||||
let val = f64::from_bits(0x3F68_0000_0000_0000);
|
||||
let res = ClockTime::try_from_seconds_f64(val);
|
||||
assert_eq!(res, Ok(ClockTime::from_nseconds(2_929_688)));
|
||||
|
||||
// this float represents exactly 1.000_976_562_5
|
||||
let val = f64::from_bits(0x3FF0_0400_0000_0000);
|
||||
let res = ClockTime::try_from_seconds_f64(val);
|
||||
assert_eq!(res, Ok(ClockTime::from_nseconds(1_000_976_562)));
|
||||
|
||||
// this float represents exactly 1.002_929_687_5
|
||||
let val = f64::from_bits(0x3FF0_0C00_0000_0000);
|
||||
let res = ClockTime::try_from_seconds_f64(val);
|
||||
assert_eq!(res, Ok(ClockTime::from_nseconds(1_002_929_688)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn try_from_seconds_f32_signed() {
|
||||
let pos = Signed::<ClockTime>::from_seconds_f32(5.0);
|
||||
assert!(pos.is_positive());
|
||||
|
||||
let neg = Signed::<ClockTime>::from_seconds_f32(-5.0);
|
||||
assert!(neg.is_negative());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn try_from_seconds_f64_signed() {
|
||||
let pos = Signed::<ClockTime>::from_seconds_f64(5.0);
|
||||
assert!(pos.is_positive());
|
||||
|
||||
let neg = Signed::<ClockTime>::from_seconds_f64(-5.0);
|
||||
assert!(neg.is_negative());
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue