use std::io::Result;
use std::marker::PhantomData;
use std::rc::Rc;
use std::time::Duration;
use winapi::shared::minwindef::{BOOL, FILETIME};
use winapi::um::processthreadsapi::{GetCurrentProcess, GetCurrentThread};
use winapi::um::processthreadsapi::{GetProcessTimes, GetThreadTimes};
#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
pub struct ProcessTime(Duration);
#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
pub struct ThreadTime(
Duration,
PhantomData<Rc<()>>,
);
fn to_duration(kernel_time: FILETIME, user_time: FILETIME) -> Duration {
let kns100 = ((kernel_time.dwHighDateTime as u64) << 32) + kernel_time.dwLowDateTime as u64;
let uns100 = ((user_time.dwHighDateTime as u64) << 32) + user_time.dwLowDateTime as u64;
return Duration::new(
(kns100 + uns100) / 10_000_000,
(((kns100 + uns100) * 100) % 1000_000_000) as u32,
);
}
fn zero() -> FILETIME {
FILETIME {
dwLowDateTime: 0,
dwHighDateTime: 0,
}
}
impl ProcessTime {
pub fn try_now() -> Result<Self> {
let mut kernel_time = zero();
let mut user_time = zero();
let process = unsafe { GetCurrentProcess() };
let ok = unsafe { GetProcessTimes(process,
&mut zero(), &mut zero(),
&mut kernel_time, &mut user_time) };
if ok == 0 {
return Err(std::io::Error::last_os_error());
}
Ok(Self(to_duration(kernel_time, user_time)))
}
pub fn now() -> Self {
Self::try_now().expect("GetProcessTimes failed")
}
pub fn try_elapsed(&self) -> Result<Duration> {
Ok(Self::try_now()?.duration_since(*self))
}
pub fn elapsed(&self) -> Duration {
Self::now().duration_since(*self)
}
pub fn duration_since(&self, timestamp: Self) -> Duration {
self.0 - timestamp.0
}
pub fn as_duration(&self) -> Duration {
self.0
}
}
impl ThreadTime {
pub fn try_now() -> Result<Self> {
let mut kernel_time = zero();
let mut user_time = zero();
let thread = unsafe { GetCurrentThread() };
let ok = unsafe { GetThreadTimes(thread,
&mut zero(), &mut zero(),
&mut kernel_time, &mut user_time) };
if ok == 0 {
return Err(std::io::Error::last_os_error());
}
Ok(Self(to_duration(kernel_time, user_time), PhantomData))
}
pub fn now() -> Self {
Self::try_now().expect("GetThreadTimes failed")
}
pub fn try_elapsed(&self) -> Result<Duration> {
Ok(Self::try_now()?.duration_since(*self))
}
pub fn elapsed(&self) -> Duration {
Self::now().duration_since(*self)
}
pub fn duration_since(&self, timestamp: ThreadTime) -> Duration {
self.0 - timestamp.0
}
pub fn as_duration(&self) -> Duration {
self.0
}
}