Port read_loop() and write_loop() to rust

The existing code is kept, but a rusty version of these functions is added for
code that needs them.

These should only be temporarily used when porting 1-to-1 from C++; we should
use the std library's `read()` and `write_all()` methods instead in the future.
This commit is contained in:
Mahmoud Al-Qudsi 2023-03-04 23:41:49 -06:00
parent f2f7d1d183
commit 78a78a834c

View file

@ -2,6 +2,7 @@ use crate::ffi;
use crate::wchar_ext::WExt;
use crate::wchar_ffi::c_str;
use crate::wchar_ffi::{wstr, WCharFromFFI, WString};
use std::os::fd::AsRawFd;
use std::{ffi::c_uint, mem};
/// A scoped manager to save the current value of some variable, and optionally set it to a new
@ -116,6 +117,47 @@ pub const fn assert_send<T: Send>() {}
pub const fn assert_sync<T: Sync>() {}
/// A rusty port of the C++ `write_loop()` function from `common.cpp`. This should be deprecated in
/// favor of native rust read/write methods at some point.
///
/// Returns the number of bytes written or an IO error.
pub fn write_loop<Fd: AsRawFd>(fd: &Fd, buf: &[u8]) -> std::io::Result<usize> {
let fd = fd.as_raw_fd();
let mut total = 0;
while total < buf.len() {
let written =
unsafe { libc::write(fd, buf[total..].as_ptr() as *const _, buf.len() - total) };
if written < 0 {
let errno = errno::errno().0;
if matches!(errno, libc::EAGAIN | libc::EINTR) {
continue;
}
return Err(std::io::Error::from_raw_os_error(errno));
}
total += written as usize;
}
Ok(total)
}
/// A rusty port of the C++ `read_loop()` function from `common.cpp`. This should be deprecated in
/// favor of native rust read/write methods at some point.
///
/// Returns the number of bytes read or an IO error.
pub fn read_loop<Fd: AsRawFd>(fd: &Fd, buf: &mut [u8]) -> std::io::Result<usize> {
let fd = fd.as_raw_fd();
loop {
let read = unsafe { libc::read(fd, buf.as_mut_ptr() as *mut _, buf.len()) };
if read < 0 {
let errno = errno::errno().0;
if matches!(errno, libc::EAGAIN | libc::EINTR) {
continue;
}
return Err(std::io::Error::from_raw_os_error(errno));
}
return Ok(read as usize);
}
}
/// Asserts that a slice is alphabetically sorted by a [`&wstr`] `name` field.
///
/// Mainly useful for static asserts/const eval.