use std::{fs::File, io, os::unix::prelude::AsRawFd, sync::Arc};
use libc::{c_int, c_void, size_t};
use crate::reply::ReplySender;
#[derive(Debug)]
pub struct Channel(Arc<File>);
impl Channel {
pub(crate) fn new(device: Arc<File>) -> Self {
Self(device)
}
pub fn receive(&self, buffer: &mut [u8]) -> io::Result<usize> {
let rc = unsafe {
libc::read(
self.0.as_raw_fd(),
buffer.as_ptr() as *mut c_void,
buffer.len() as size_t,
)
};
if rc < 0 {
Err(io::Error::last_os_error())
} else {
Ok(rc as usize)
}
}
pub fn sender(&self) -> ChannelSender {
ChannelSender(self.0.clone())
}
}
#[derive(Clone, Debug)]
pub struct ChannelSender(Arc<File>);
impl ReplySender for ChannelSender {
fn send(&self, bufs: &[io::IoSlice<'_>]) -> io::Result<()> {
let rc = unsafe {
libc::writev(
self.0.as_raw_fd(),
bufs.as_ptr() as *const libc::iovec,
bufs.len() as c_int,
)
};
if rc < 0 {
Err(io::Error::last_os_error())
} else {
debug_assert_eq!(bufs.iter().map(|b| b.len()).sum::<usize>(), rc as usize);
Ok(())
}
}
}