use std::time::Duration;
use crate::error::Error;
pub fn of_secs_f64(seconds: f64) -> Result<Duration, Error> {
of_secs_f64_because(seconds, "")
}
pub(crate) fn of_secs_f64_because(seconds: f64, why: &str) -> Result<Duration, Error> {
Duration::try_from_secs_f64(seconds).map_err(|source| {
Error::invalid_arg(format!(
"{seconds:?} seconds is not a duration: it must be finite, non-negative and below \
2^64{why}"
))
.with_source(source)
})
}
#[cfg(test)]
mod tests {
use super::*;
use crate::error::ErrorKind;
#[test]
fn a_refused_figure_is_named_as_typed_with_the_range_it_missed() {
for (seconds, shown) in [(1e300, "1e300"), (f64::INFINITY, "inf"), (-5.0, "-5.0")] {
let message = of_secs_f64(seconds)
.expect_err("not a duration")
.to_string();
assert!(
message.starts_with(&format!("{shown} seconds is not a duration")),
"{message}"
);
assert!(message.contains("below 2^64"), "{message}");
}
assert_eq!(of_secs_f64(1.25).ok(), Some(Duration::from_millis(1250)));
}
#[test]
fn a_wait_refusal_names_no_report_and_a_cost_refusal_still_does() {
for seconds in [-1.0, f64::NAN, f64::INFINITY] {
let wait = of_secs_f64(seconds).expect_err("not a wait");
assert_eq!(wait.kind(), ErrorKind::InvalidArg);
assert!(!wait.to_string().contains("report"), "{wait}");
let cost = crate::cost::duration_of_secs_f64(seconds).expect_err("not a span");
assert!(cost.to_string().contains("credit on the report"), "{cost}");
assert!(cost.to_string().starts_with(&wait.to_string()), "{cost}");
}
}
}