use std::time::{Duration, Instant};
mod bit_pattern;
pub(crate) use bit_pattern::BitPattern;
pub(crate) mod value_history;
mod time_tricks;
pub(crate) use time_tricks::{InstantExt, SystemTimeExt, not_happening};
pub(crate) use time_tricks::{already_happened, epoch_to_beginning};
mod average;
pub(crate) use average::MovingAverage;
pub(crate) trait Soonest {
fn soonest(self, other: Self) -> Self;
}
impl<T: Default> Soonest for (Option<Instant>, T) {
fn soonest(self, other: Self) -> Self {
match (self, other) {
((Some(v1), s1), (Some(v2), s2)) => {
if v1 < v2 {
(Some(v1), s1)
} else {
(Some(v2), s2)
}
}
((None, _), (None, _)) => (None, T::default()),
((None, _), (v, s)) => (v, s),
((v, s), (None, _)) => (v, s),
}
}
}
pub(crate) fn calculate_rtt(ntp_time: Duration, delay: u32, last_report: u32) -> Option<Duration> {
if delay == 0 {
return None;
}
let now_secs = ntp_time.as_secs();
let now_fract_ns = ntp_time.subsec_nanos() as u64;
let now_fract = ((now_fract_ns * u32::MAX as u64) / 1_000_000_000) as u32;
let now = (now_secs as u32) << 16 | (now_fract >> 16);
let rtt = now.checked_sub(delay)?.checked_sub(last_report)?;
let rtt_seconds = rtt >> 16;
let rtt_fraction = (rtt & (u16::MAX as u32)) as f32 / (u16::MAX as u32) as f32;
let nanos = (rtt_fraction * 1_000_000_000.0) as u32;
Some(Duration::new(rtt_seconds as u64, nanos))
}