Add functions Duration::try_from_secs_{f32, f64}
This also adds the error type used, `FromSecsError` and its `impl`s.
This commit is contained in:
parent
26c2d1f408
commit
c2c1ca071f
@ -697,6 +697,44 @@ impl Duration {
|
||||
}
|
||||
}
|
||||
|
||||
/// The checked version of [`from_secs_f64`].
|
||||
///
|
||||
/// [`from_secs_f64`]: Duration::from_secs_f64
|
||||
///
|
||||
/// This constructor will return an `Err` if `secs` is not finite, negative or overflows `Duration`.
|
||||
///
|
||||
/// # Examples
|
||||
/// ```
|
||||
/// #![feature(duration_checked_float)]
|
||||
///
|
||||
/// use std::time::Duration;
|
||||
///
|
||||
/// let dur = Duration::try_from_secs_f64(2.7);
|
||||
/// assert_eq!(dur, Ok(Duration::new(2, 700_000_000)));
|
||||
///
|
||||
/// let negative = Duration::try_from_secs_f64(-5.0);
|
||||
/// assert!(negative.is_err());
|
||||
/// ```
|
||||
#[unstable(feature = "duration_checked_float", issue = "83400")]
|
||||
#[inline]
|
||||
pub const fn try_from_secs_f64(secs: f64) -> Result<Duration, FromSecsError> {
|
||||
const MAX_NANOS_F64: f64 = ((u64::MAX as u128 + 1) * (NANOS_PER_SEC as u128)) as f64;
|
||||
let nanos = secs * (NANOS_PER_SEC as f64);
|
||||
if !nanos.is_finite() {
|
||||
Err(FromSecsError { kind: FromSecsErrorKind::NonFinite })
|
||||
} else if nanos >= MAX_NANOS_F64 {
|
||||
Err(FromSecsError { kind: FromSecsErrorKind::Overflow })
|
||||
} else if nanos < 0.0 {
|
||||
Err(FromSecsError { kind: FromSecsErrorKind::Underflow })
|
||||
} else {
|
||||
let nanos = nanos as u128;
|
||||
Ok(Duration {
|
||||
secs: (nanos / (NANOS_PER_SEC as u128)) as u64,
|
||||
nanos: (nanos % (NANOS_PER_SEC as u128)) as u32,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a new `Duration` from the specified number of seconds represented
|
||||
/// as `f32`.
|
||||
///
|
||||
@ -732,6 +770,44 @@ impl Duration {
|
||||
}
|
||||
}
|
||||
|
||||
/// The checked version of [`from_secs_f32`].
|
||||
///
|
||||
/// [`from_secs_f32`]: Duration::from_secs_f32
|
||||
///
|
||||
/// This constructor will return an `Err` if `secs` is not finite, negative or overflows `Duration`.
|
||||
///
|
||||
/// # Examples
|
||||
/// ```
|
||||
/// #![feature(duration_checked_float)]
|
||||
///
|
||||
/// use std::time::Duration;
|
||||
///
|
||||
/// let dur = Duration::try_from_secs_f32(2.7);
|
||||
/// assert_eq!(dur, Ok(Duration::new(2, 700_000_000)));
|
||||
///
|
||||
/// let negative = Duration::try_from_secs_f32(-5.0);
|
||||
/// assert!(negative.is_err());
|
||||
/// ```
|
||||
#[unstable(feature = "duration_checked_float", issue = "83400")]
|
||||
#[inline]
|
||||
pub const fn try_from_secs_f32(secs: f32) -> Result<Duration, FromSecsError> {
|
||||
const MAX_NANOS_F32: f32 = ((u64::MAX as u128 + 1) * (NANOS_PER_SEC as u128)) as f32;
|
||||
let nanos = secs * (NANOS_PER_SEC as f32);
|
||||
if !nanos.is_finite() {
|
||||
Err(FromSecsError { kind: FromSecsErrorKind::NonFinite })
|
||||
} else if nanos >= MAX_NANOS_F32 {
|
||||
Err(FromSecsError { kind: FromSecsErrorKind::Overflow })
|
||||
} else if nanos < 0.0 {
|
||||
Err(FromSecsError { kind: FromSecsErrorKind::Underflow })
|
||||
} else {
|
||||
let nanos = nanos as u128;
|
||||
Ok(Duration {
|
||||
secs: (nanos / (NANOS_PER_SEC as u128)) as u64,
|
||||
nanos: (nanos % (NANOS_PER_SEC as u128)) as u32,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Multiplies `Duration` by `f64`.
|
||||
///
|
||||
/// # Panics
|
||||
@ -1081,3 +1157,55 @@ impl fmt::Debug for Duration {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// An error which can be returned when converting a floating-point value of seconds
|
||||
/// into a [`Duration`].
|
||||
///
|
||||
/// This error is used as the error type for [`Duration::try_from_secs_f32`] and
|
||||
/// [`Duration::try_from_secs_f64`].
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(duration_checked_float)]
|
||||
///
|
||||
/// use std::time::Duration;
|
||||
///
|
||||
/// if let Err(e) = Duration::try_from_secs_f32(-1.0) {
|
||||
/// println!("Failed conversion to Duration: {}", e);
|
||||
/// }
|
||||
/// ```
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
#[unstable(feature = "duration_checked_float", issue = "83400")]
|
||||
pub struct FromSecsError {
|
||||
kind: FromSecsErrorKind,
|
||||
}
|
||||
|
||||
impl FromSecsError {
|
||||
const fn description(&self) -> &'static str {
|
||||
match self.kind {
|
||||
FromSecsErrorKind::NonFinite => {
|
||||
"got non-finite value when converting float to duration"
|
||||
}
|
||||
FromSecsErrorKind::Overflow => "overflow when converting float to duration",
|
||||
FromSecsErrorKind::Underflow => "underflow when converting float to duration",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "duration_checked_float", issue = "83400")]
|
||||
impl fmt::Display for FromSecsError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt::Display::fmt(self.description(), f)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
enum FromSecsErrorKind {
|
||||
// Value is not a finite value (either infinity or NaN).
|
||||
NonFinite,
|
||||
// Value is too large to store in a `Duration`.
|
||||
Overflow,
|
||||
// Value is less than `0.0`.
|
||||
Underflow,
|
||||
}
|
||||
|
@ -529,6 +529,9 @@ impl Error for char::ParseCharError {
|
||||
#[unstable(feature = "try_reserve", reason = "new API", issue = "48043")]
|
||||
impl Error for alloc::collections::TryReserveError {}
|
||||
|
||||
#[unstable(feature = "duration_checked_float", issue = "83400")]
|
||||
impl Error for core::time::FromSecsError {}
|
||||
|
||||
// Copied from `any.rs`.
|
||||
impl dyn Error + 'static {
|
||||
/// Returns `true` if the boxed type is the same as `T`
|
||||
|
@ -256,6 +256,7 @@
|
||||
#![feature(doc_masked)]
|
||||
#![feature(doc_spotlight)]
|
||||
#![feature(dropck_eyepatch)]
|
||||
#![feature(duration_checked_float)]
|
||||
#![feature(duration_constants)]
|
||||
#![feature(duration_zero)]
|
||||
#![feature(exact_size_is_empty)]
|
||||
|
Loading…
x
Reference in New Issue
Block a user