use std::fs::File;
use std::io::{self, Read};
use std::os::fd::{AsRawFd, IntoRawFd, RawFd};
use crate::sys;
use crate::SliceAsBytesMut;
use crate::{check_errno_syscall, CountAndTime};
pub struct Counter {
file: File,
id: u64,
}
impl Counter {
pub(crate) fn new(file: File, id: u64) -> Self {
Self { file, id }
}
pub fn id(&self) -> u64 {
self.id
}
pub fn enable(&mut self) -> io::Result<()> {
check_errno_syscall(|| unsafe { sys::ioctls::ENABLE(self.file.as_raw_fd(), 0) }).map(|_| ())
}
pub fn disable(&mut self) -> io::Result<()> {
check_errno_syscall(|| unsafe { sys::ioctls::DISABLE(self.file.as_raw_fd(), 0) })
.map(|_| ())
}
pub fn reset(&mut self) -> io::Result<()> {
check_errno_syscall(|| unsafe { sys::ioctls::RESET(self.file.as_raw_fd(), 0) }).map(|_| ())
}
pub fn read(&mut self) -> io::Result<u64> {
Ok(self.read_count_and_time()?.count)
}
pub fn read_count_and_time(&mut self) -> io::Result<CountAndTime> {
let mut buf = [0_u64; 3];
self.file.read_exact(u64::slice_as_bytes_mut(&mut buf))?;
let cat = CountAndTime {
count: buf[0],
time_enabled: buf[1],
time_running: buf[2],
};
assert!(cat.time_running <= cat.time_enabled);
Ok(cat)
}
}
impl std::fmt::Debug for Counter {
fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(
fmt,
"Counter {{ fd: {}, id: {} }}",
self.file.as_raw_fd(),
self.id
)
}
}
impl AsRawFd for Counter {
fn as_raw_fd(&self) -> RawFd {
self.file.as_raw_fd()
}
}
impl IntoRawFd for Counter {
fn into_raw_fd(self) -> RawFd {
self.file.into_raw_fd()
}
}