Documentation
#[cfg(any(target_os = "linux", target_os = "macos"))]
use crate::time::unix::UnixClock;

pub struct Timestamp {
    sec: u64,
    nano: u64,
}

#[repr(C)]
pub(crate) struct Timespec(Timestamp);

pub trait Clock {
    fn precise() -> Timestamp;
}

#[cfg(target_os = "linux")]
pub type SystemClock = UnixClock;

#[cfg(any(target_os = "linux", target_os = "macos"))]
mod unix {
    use core::mem::MaybeUninit;

    use crate::time::Timespec;

    pub struct UnixClock;

    impl super::Clock for UnixClock {
        fn precise() -> super::Timestamp {
            let mut spec = MaybeUninit::uninit();
            unsafe { (TIME)(0, &mut spec as *mut _ as *mut _) };
            let super::Timespec(stamp) = unsafe { spec.assume_init() };
            stamp
        }
    }

    type Syscall = unsafe fn(i32, *mut Timespec) -> i32;
    #[cfg(any(target_os = "linux"))]
    const TIME: Syscall = super::linux::clock_gettime;
    #[cfg(any(target_os = "macos"))]
    const TIME: Syscall = super::macos::clock_gettime;
}

#[cfg(any(target_os = "linux"))]
mod linux {
    use core::arch::asm;

    use crate::time::Timespec;
    pub unsafe fn clock_gettime(clock_id: i32, tp: *mut Timespec) -> i32 {
        let mut ret: i32;
        asm!(
            "syscall",
            in("rax") 228,  // __NR_clock_gettime on x86_64
            in("rdi") clock_id,
            in("rsi") tp,
            lateout("rax") ret,
            out("rcx") _,
            out("r11") _,
        );
        ret
    }
}

#[cfg(target_os = "macos")]
mod macos {
    use crate::time::Timespec;
    pub unsafe fn clock_gettime(clock_id: i32, tp: *mut Timespec) -> i32 {
        let mut ret: i32;
        asm!(
            "syscall",
            in("rax") 0x2000074,  // SYS_clock_gettime on macOS
            in("rdi") clock_id,
            in("rsi") tp,
            lateout("rax") ret,
            out("rcx") _,
            out("r11") _,
        );
        ret
    }
}