use nss_sys::nspr as ffi;
use std::time::Duration;
use std::u32;
lazy_static! {
static ref NSPR_TICKS_PER_SEC: u32 = {
super::init();
unsafe { ffi::PR_TicksPerSecond() }
};
}
fn scale_u32(input: u32, in_scale: u32, out_scale: u32) -> u32 {
debug_assert!(input <= in_scale);
((input as u64) * (out_scale as u64) / (in_scale as u64)) as u32
}
pub fn duration_to_nspr(d: Duration) -> ffi::PRIntervalTime {
let tps = *NSPR_TICKS_PER_SEC;
let whole = d.as_secs();
let frac = scale_u32(d.subsec_nanos(), 1_000_000_000, tps);
let ticks = whole.saturating_mul(tps as u64).saturating_add(frac as u64);
if ticks <= u32::MAX as u64 {
ticks as u32
} else {
ffi::PR_INTERVAL_NO_TIMEOUT
}
}
pub fn duration_opt_to_nspr(d: Option<Duration>) -> ffi::PRIntervalTime {
d.map_or(ffi::PR_INTERVAL_NO_TIMEOUT, duration_to_nspr)
}
pub fn duration_from_nspr(it: ffi::PRIntervalTime) -> Duration {
let tps = *NSPR_TICKS_PER_SEC;
Duration::new((it / tps) as u64, scale_u32((it % tps), tps, 1_000_000_000))
}
pub fn duration_opt_from_nspr(it: ffi::PRIntervalTime) -> Option<Duration> {
if it == ffi::PR_INTERVAL_NO_TIMEOUT {
None
} else {
Some(duration_from_nspr(it))
}
}