use crate::{FromInner, IntoInner};
use std::ffi::{CStr, CString};
use uv::{
uv_clock_gettime, uv_cpu_info, uv_cpu_info_t, uv_cpumask_size, uv_free_cpu_info,
uv_get_available_memory, uv_get_constrained_memory, uv_get_free_memory, uv_get_process_title,
uv_get_total_memory, uv_getrusage, uv_getrusage_thread, uv_gettimeofday, uv_hrtime,
uv_library_shutdown, uv_loadavg, uv_resident_set_memory, uv_rusage_t, uv_set_process_title,
uv_setup_args, uv_sleep, uv_timespec64_t, uv_timeval64_t, uv_timeval_t, uv_uptime,
};
pub mod os;
pub use os::*;
pub struct TimeVal {
pub sec: i64,
pub usec: i64,
}
impl FromInner<uv_timeval_t> for TimeVal {
fn from_inner(tv: uv_timeval_t) -> TimeVal {
TimeVal {
sec: tv.tv_sec as _,
usec: tv.tv_usec as _,
}
}
}
impl FromInner<uv_timeval64_t> for TimeVal {
fn from_inner(tv: uv_timeval64_t) -> TimeVal {
TimeVal {
sec: tv.tv_sec,
usec: tv.tv_usec as _,
}
}
}
pub struct ResourceUsage {
pub usertime: TimeVal,
pub systime: TimeVal,
pub maxrss: u64,
pub ixrss: u64,
pub idrss: u64,
pub isrss: u64,
pub minflt: u64,
pub majflt: u64,
pub nswap: u64,
pub inblock: u64,
pub oublock: u64,
pub msgsnd: u64,
pub msgrcv: u64,
pub nsignals: u64,
pub nvcsw: u64,
pub nivcsw: u64,
}
impl FromInner<uv_rusage_t> for ResourceUsage {
fn from_inner(usage: uv_rusage_t) -> ResourceUsage {
ResourceUsage {
usertime: usage.ru_utime.into_inner(),
systime: usage.ru_stime.into_inner(),
maxrss: usage.ru_maxrss,
ixrss: usage.ru_ixrss,
idrss: usage.ru_idrss,
isrss: usage.ru_isrss,
minflt: usage.ru_minflt,
majflt: usage.ru_majflt,
nswap: usage.ru_nswap,
inblock: usage.ru_inblock,
oublock: usage.ru_oublock,
msgsnd: usage.ru_msgsnd,
msgrcv: usage.ru_msgrcv,
nsignals: usage.ru_nsignals,
nvcsw: usage.ru_nvcsw,
nivcsw: usage.ru_nivcsw,
}
}
}
pub struct CpuInfo {
pub model: String,
pub speed: i32,
pub user_time: u64,
pub nice_time: u64,
pub sys_time: u64,
pub idle_time: u64,
pub irq_time: u64,
}
impl FromInner<&uv_cpu_info_t> for CpuInfo {
fn from_inner(cpu: &uv_cpu_info_t) -> CpuInfo {
let model = unsafe { CStr::from_ptr(cpu.model) }
.to_string_lossy()
.into_owned();
CpuInfo {
model,
speed: cpu.speed,
user_time: cpu.cpu_times.user,
nice_time: cpu.cpu_times.nice,
sys_time: cpu.cpu_times.sys,
idle_time: cpu.cpu_times.idle,
irq_time: cpu.cpu_times.irq,
}
}
}
#[repr(u32)]
pub enum ClockId {
Monotonic = uv::uv_clock_id_UV_CLOCK_MONOTONIC as _,
Realtime = uv::uv_clock_id_UV_CLOCK_REALTIME as _,
}
pub struct TimeSpec64 {
pub sec: i64,
pub nsec: i32,
}
impl FromInner<uv_timespec64_t> for TimeSpec64 {
fn from_inner(timespec: uv_timespec64_t) -> TimeSpec64 {
TimeSpec64 {
sec: timespec.tv_sec,
nsec: timespec.tv_nsec,
}
}
}
pub fn setup_args() -> Result<Vec<String>, std::ffi::NulError> {
let mut args = std::env::args()
.map(|s| CString::new(s).map(|s| s.into_bytes_with_nul()))
.collect::<Result<Vec<_>, std::ffi::NulError>>()?;
let mut argsptr: Vec<*mut std::os::raw::c_char> =
args.iter_mut().map(|s| s.as_mut_ptr() as _).collect();
let argc = args.len();
let args = unsafe { uv_setup_args(argc as _, argsptr.as_mut_ptr()) };
let args = unsafe { std::slice::from_raw_parts(args, argc) };
Ok(args
.iter()
.map(|arg| {
unsafe { CStr::from_ptr(*arg) }
.to_string_lossy()
.into_owned()
})
.collect())
}
pub fn shutdown() {
unsafe { uv_library_shutdown() };
}
pub fn get_process_title() -> crate::Result<String> {
let mut size = 16usize;
let mut buf: Vec<std::os::raw::c_char> = vec![];
loop {
size *= 2;
buf.reserve(size - buf.len());
let result =
crate::uvret(unsafe { uv_get_process_title(buf.as_mut_ptr() as _, size as _) });
if let Err(e) = result {
if e != crate::Error::ENOBUFS {
return Err(e);
}
} else {
break;
}
}
Ok(unsafe { CStr::from_ptr(buf.as_ptr()) }
.to_string_lossy()
.into_owned())
}
pub fn set_process_title(title: &str) -> Result<(), Box<dyn std::error::Error>> {
let title = CString::new(title)?;
crate::uvret(unsafe { uv_set_process_title(title.as_ptr()) }).map_err(|e| Box::new(e) as _)
}
pub fn resident_set_memory() -> crate::Result<usize> {
let mut rss = 0usize;
crate::uvret(unsafe { uv_resident_set_memory(&mut rss as _) }).map(|_| rss as _)
}
pub fn uptime() -> crate::Result<f64> {
let mut uptime = 0f64;
crate::uvret(unsafe { uv_uptime(&mut uptime as _) }).map(|_| uptime)
}
pub fn getrusage() -> crate::Result<ResourceUsage> {
let mut usage: uv_rusage_t = unsafe { std::mem::zeroed() };
crate::uvret(unsafe { uv_getrusage(&mut usage as _) }).map(|_| usage.into_inner())
}
pub fn getrusage_thread() -> crate::Result<ResourceUsage> {
let mut usage: uv_rusage_t = unsafe { std::mem::zeroed() };
crate::uvret(unsafe { uv_getrusage_thread(&mut usage as _) }).map(|_| usage.into_inner())
}
pub fn cpu_info() -> crate::Result<Vec<CpuInfo>> {
let mut infos: *mut uv_cpu_info_t = unsafe { std::mem::zeroed() };
let mut count: std::os::raw::c_int = 0;
crate::uvret(unsafe { uv_cpu_info(&mut infos as _, &mut count as _) })?;
let result = unsafe { std::slice::from_raw_parts(infos, count as _) }
.iter()
.map(|info| info.into_inner())
.collect();
unsafe { uv_free_cpu_info(infos, count as _) };
Ok(result)
}
pub fn cpumask_size() -> i32 {
unsafe { uv_cpumask_size() }
}
pub fn loadavg() -> [f64; 3] {
let mut avg = [0f64; 3];
unsafe { uv_loadavg(avg.as_mut_ptr()) };
return avg;
}
pub fn get_free_memory() -> u64 {
unsafe { uv_get_free_memory() }
}
pub fn get_total_memory() -> u64 {
unsafe { uv_get_total_memory() }
}
pub fn get_constrained_memory() -> u64 {
unsafe { uv_get_constrained_memory() }
}
pub fn get_available_memory() -> u64 {
unsafe { uv_get_available_memory() }
}
pub fn hrtime() -> u64 {
unsafe { uv_hrtime() }
}
pub fn clock_gettime(clock_id: ClockId) -> crate::Result<TimeSpec64> {
let mut timespec: uv_timespec64_t = unsafe { std::mem::zeroed() };
crate::uvret(unsafe { uv_clock_gettime(clock_id as _, &mut timespec as _) })
.map(|_| timespec.into_inner())
}
pub fn gettimeofday() -> crate::Result<TimeVal> {
let mut tv: uv_timeval64_t = unsafe { std::mem::zeroed() };
crate::uvret(unsafe { uv_gettimeofday(&mut tv as _) }).map(|_| tv.into_inner())
}
pub fn sleep(msec: u32) {
unsafe { uv_sleep(msec) };
}