Implement and use Read and Write traits for AutoCloseFd

This lets us use any std::io functions that build on top of these, such as
`write_all()` in place of our own `write_loop()`.
This commit is contained in:
Mahmoud Al-Qudsi 2023-03-05 00:20:18 -06:00
parent 455b744bca
commit 4828346f8b
2 changed files with 30 additions and 2 deletions

View file

@ -1,5 +1,6 @@
use crate::ffi;
use nix::unistd;
use std::io::{Read, Write};
use std::os::unix::io::{AsRawFd, FromRawFd, RawFd};
/// A helper type for managing and automatically closing a file descriptor
@ -11,6 +12,33 @@ pub struct AutoCloseFd {
fd_: RawFd,
}
impl Read for AutoCloseFd {
fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
unsafe {
match libc::read(self.as_raw_fd(), buf.as_mut_ptr() as *mut _, buf.len()) {
-1 => Err(std::io::Error::from_raw_os_error(errno::errno().0)),
bytes => Ok(bytes as usize),
}
}
}
}
impl Write for AutoCloseFd {
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
unsafe {
match libc::write(self.as_raw_fd(), buf.as_ptr() as *const _, buf.len()) {
-1 => Err(std::io::Error::from_raw_os_error(errno::errno().0)),
bytes => Ok(bytes as usize),
}
}
}
fn flush(&mut self) -> std::io::Result<()> {
// We don't buffer anything so this is a no-op.
Ok(())
}
}
#[cxx::bridge]
mod autoclose_fd_t {
extern "Rust" {

View file

@ -1,9 +1,9 @@
use std::io::Write;
use std::os::fd::AsRawFd;
use std::sync::atomic::{AtomicBool, AtomicU64, AtomicUsize, Ordering};
use std::sync::{Arc, Mutex};
use std::time::Duration;
use crate::common::write_loop;
use crate::fd_monitor::{FdMonitor, FdMonitorItem, FdMonitorItemId, ItemWakeReason};
use crate::fds::{make_autoclose_pipes, AutoCloseFd};
use crate::ffi_tests::add_test;
@ -96,7 +96,7 @@ impl ItemMaker {
fn write42(&self) {
let buf = [0u8; 42];
let mut writer = self.writer.lock().expect("Mutex poisoned!");
write_loop(&mut *writer, &buf).expect("Error writing 42 bytes to pipe!");
writer.write_all(&buf).expect("Error writing 42 bytes to pipe!");
}
}