From 78a78a834c3b72f3c16586d68aaaaef74589d2a3 Mon Sep 17 00:00:00 2001 From: Mahmoud Al-Qudsi Date: Sat, 4 Mar 2023 23:41:49 -0600 Subject: [PATCH] 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. --- fish-rust/src/common.rs | 42 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/fish-rust/src/common.rs b/fish-rust/src/common.rs index 3c70d0214..e7e9bdae8 100644 --- a/fish-rust/src/common.rs +++ b/fish-rust/src/common.rs @@ -2,6 +2,7 @@ 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() {} pub const fn assert_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: &Fd, buf: &[u8]) -> std::io::Result { + 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: &Fd, buf: &mut [u8]) -> std::io::Result { + 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.