use std::time::{SystemTime, UNIX_EPOCH};
use crate::wg::constants::TAI64N_TIMESTAMP_SIZE;
const TAI64N_BASE: u64 = 4_611_686_018_427_387_914;
pub(crate) fn tai64n_now() -> [u8; TAI64N_TIMESTAMP_SIZE] {
let dur = SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap_or_default();
encode_tai64n(dur.as_secs(), dur.subsec_nanos())
}
#[inline]
pub(crate) fn encode_tai64n(unix_secs: u64, nanos: u32) -> [u8; TAI64N_TIMESTAMP_SIZE] {
let mut out = [0u8; TAI64N_TIMESTAMP_SIZE];
let tai_secs = unix_secs.wrapping_add(TAI64N_BASE);
out[0..8].copy_from_slice(&tai_secs.to_be_bytes());
out[8..12].copy_from_slice(&nanos.to_be_bytes());
out
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn tai64n_offset_applied() {
let ts = encode_tai64n(0, 0);
let secs = u64::from_be_bytes(ts[0..8].try_into().unwrap());
assert_eq!(secs, TAI64N_BASE);
let ts = encode_tai64n(0, 123_456_789);
assert_eq!(
u32::from_be_bytes(ts[8..12].try_into().unwrap()),
123_456_789
);
}
#[test]
fn tai64n_now_monotonic_within_clock_resolution() {
let a = tai64n_now();
let b = tai64n_now();
assert!(b >= a, "tai64n_now() went backwards: {:?} -> {:?}", a, b);
}
}