Skip to content

Port some functions to safe-io: pt I #1687

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Mar 29, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 12 additions & 13 deletions gio/src/desktop_app_info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
#[cfg(all(unix, feature = "v2_58"))]
use std::boxed::Box as Box_;
#[cfg(all(unix, feature = "v2_58"))]
use std::os::unix::io::AsRawFd;
use std::os::unix::io::{AsFd, AsRawFd};
#[cfg(all(unix, feature = "v2_58"))]
use std::ptr;

Expand Down Expand Up @@ -48,21 +48,16 @@ impl DesktopAppInfo {
pub trait DesktopAppInfoExtManual: IsA<DesktopAppInfo> {
#[cfg_attr(docsrs, doc(cfg(all(feature = "v2_58", unix))))]
#[doc(alias = "g_desktop_app_info_launch_uris_as_manager_with_fds")]
fn launch_uris_as_manager_with_fds<
P: IsA<AppLaunchContext>,
T: AsRawFd,
U: AsRawFd,
V: AsRawFd,
>(
fn launch_uris_as_manager_with_fds<P: IsA<AppLaunchContext>>(
&self,
uris: &[&str],
launch_context: Option<&P>,
spawn_flags: glib::SpawnFlags,
user_setup: Option<Box_<dyn FnOnce() + 'static>>,
pid_callback: Option<&mut dyn (FnMut(&DesktopAppInfo, glib::Pid))>,
stdin_fd: &mut T,
stdout_fd: &mut U,
stderr_fd: &mut V,
stdin_fd: Option<impl AsFd>,
stdout_fd: Option<impl AsFd>,
stderr_fd: Option<impl AsFd>,
) -> Result<(), Error> {
let user_setup_data: Box_<Option<Box_<dyn FnOnce() + 'static>>> = Box_::new(user_setup);
unsafe extern "C" fn user_setup_func(user_data: glib::ffi::gpointer) {
Expand Down Expand Up @@ -99,6 +94,10 @@ pub trait DesktopAppInfoExtManual: IsA<DesktopAppInfo> {
let super_callback0: Box_<Option<Box_<dyn FnOnce() + 'static>>> = user_setup_data;
let super_callback1: &Option<&mut dyn (FnMut(&DesktopAppInfo, glib::Pid))> =
&pid_callback_data;

let stdin_raw_fd = stdin_fd.map_or(-1, |fd| fd.as_fd().as_raw_fd());
let stdout_raw_fd = stdout_fd.map_or(-1, |fd| fd.as_fd().as_raw_fd());
let stderr_raw_fd = stderr_fd.map_or(-1, |fd| fd.as_fd().as_raw_fd());
unsafe {
let mut error = ptr::null_mut();
let _ = ffi::g_desktop_app_info_launch_uris_as_manager_with_fds(
Expand All @@ -110,9 +109,9 @@ pub trait DesktopAppInfoExtManual: IsA<DesktopAppInfo> {
Box_::into_raw(super_callback0) as *mut _,
pid_callback,
super_callback1 as *const _ as *mut _,
stdin_fd.as_raw_fd(),
stdout_fd.as_raw_fd(),
stderr_fd.as_raw_fd(),
stdin_raw_fd,
stdout_raw_fd,
stderr_raw_fd,
&mut error,
);
if error.is_null() {
Expand Down
39 changes: 28 additions & 11 deletions gio/src/socket.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Take a look at the license at the top of the repository in the LICENSE file.

#[cfg(unix)]
use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
use std::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd};
#[cfg(windows)]
use std::os::windows::io::{AsRawSocket, FromRawSocket, IntoRawSocket, RawSocket};
#[cfg(feature = "v2_60")]
Expand All @@ -18,15 +18,18 @@ use crate::{ffi, Cancellable, Socket, SocketAddress, SocketControlMessage};
impl Socket {
#[cfg(unix)]
#[cfg_attr(docsrs, doc(cfg(unix)))]
#[allow(clippy::missing_safety_doc)]
pub unsafe fn from_fd(fd: impl IntoRawFd) -> Result<Socket, glib::Error> {
#[doc(alias = "g_socket_new_from_fd")]
pub fn from_fd(fd: OwnedFd) -> Result<Socket, glib::Error> {
let fd = fd.into_raw_fd();
let mut error = ptr::null_mut();
let ret = ffi::g_socket_new_from_fd(fd, &mut error);
if error.is_null() {
Ok(from_glib_full(ret))
} else {
Err(from_glib_full(error))
unsafe {
let ret = ffi::g_socket_new_from_fd(fd, &mut error);
if error.is_null() {
Ok(from_glib_full(ret))
} else {
libc::close(fd);
Err(from_glib_full(error))
}
}
}
#[cfg(windows)]
Expand All @@ -52,6 +55,17 @@ impl AsRawFd for Socket {
}
}

#[cfg(unix)]
#[cfg_attr(docsrs, doc(cfg(unix)))]
impl AsFd for Socket {
fn as_fd(&self) -> BorrowedFd<'_> {
unsafe {
let raw_fd = self.as_raw_fd();
BorrowedFd::borrow_raw(raw_fd)
}
}
}

#[cfg(windows)]
#[cfg_attr(docsrs, doc(cfg(windows)))]
impl AsRawSocket for Socket {
Expand Down Expand Up @@ -801,7 +815,10 @@ mod tests {
#[test]
#[cfg(unix)]
fn socket_messages() {
use std::{io, os::unix::io::AsRawFd};
use std::{
io,
os::unix::io::{AsRawFd, FromRawFd, OwnedFd},
};

use super::Socket;
use crate::{prelude::*, Cancellable, UnixFDMessage};
Expand All @@ -813,8 +830,8 @@ mod tests {
panic!("{}", io::Error::last_os_error());
}
(
Socket::from_fd(fds[0]).unwrap(),
Socket::from_fd(fds[1]).unwrap(),
Socket::from_fd(OwnedFd::from_raw_fd(fds[0])).unwrap(),
Socket::from_fd(OwnedFd::from_raw_fd(fds[1])).unwrap(),
)
};

Expand Down
24 changes: 15 additions & 9 deletions gio/src/unix_input_stream.rs
Original file line number Diff line number Diff line change
@@ -1,27 +1,24 @@
// Take a look at the license at the top of the repository in the LICENSE file.

#[cfg(unix)]
use std::os::unix::io::{AsRawFd, IntoRawFd, RawFd};
use std::os::unix::io::{AsFd, AsRawFd, BorrowedFd, IntoRawFd, OwnedFd, RawFd};

use glib::{prelude::*, translate::*};
#[cfg(all(not(unix), docsrs))]
use socket::{AsRawFd, IntoRawFd, RawFd};
use socket::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd};

use crate::{ffi, InputStream, UnixInputStream};

impl UnixInputStream {
// rustdoc-stripper-ignore-next
/// Creates a new [`Self`] that takes ownership of the passed in fd.
///
/// # Safety
/// You must not close the fd unless you've previously called [`UnixInputStreamExtManual::set_close_fd`]
/// with `true` on this stream. At which point you may only do so when all references to this
/// stream have been dropped.
#[doc(alias = "g_unix_input_stream_new")]
pub unsafe fn take_fd(fd: impl IntoRawFd) -> UnixInputStream {
pub fn take_fd(fd: OwnedFd) -> UnixInputStream {
let fd = fd.into_raw_fd();
let close_fd = true.into_glib();
InputStream::from_glib_full(ffi::g_unix_input_stream_new(fd, close_fd)).unsafe_cast()
unsafe {
InputStream::from_glib_full(ffi::g_unix_input_stream_new(fd, close_fd)).unsafe_cast()
}
}

// rustdoc-stripper-ignore-next
Expand All @@ -43,6 +40,15 @@ impl AsRawFd for UnixInputStream {
}
}

impl AsFd for UnixInputStream {
fn as_fd(&self) -> BorrowedFd<'_> {
unsafe {
let raw_fd = self.as_raw_fd();
BorrowedFd::borrow_raw(raw_fd)
}
}
}

pub trait UnixInputStreamExtManual: IsA<UnixInputStream> + Sized {
// rustdoc-stripper-ignore-next
/// Sets whether the fd of this stream will be closed when the stream is closed.
Expand Down
24 changes: 15 additions & 9 deletions gio/src/unix_output_stream.rs
Original file line number Diff line number Diff line change
@@ -1,27 +1,24 @@
// Take a look at the license at the top of the repository in the LICENSE file.

#[cfg(unix)]
use std::os::unix::io::{AsRawFd, IntoRawFd, RawFd};
use std::os::unix::io::{AsFd, AsRawFd, BorrowedFd, IntoRawFd, OwnedFd, RawFd};

use glib::{prelude::*, translate::*};
#[cfg(all(not(unix), docsrs))]
use socket::{AsRawFd, IntoRawFd, RawFd};
use socket::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd};

use crate::{ffi, OutputStream, UnixOutputStream};

impl UnixOutputStream {
// rustdoc-stripper-ignore-next
/// Creates a new [`Self`] that takes ownership of the passed in fd.
///
/// # Safety
/// You must not close the fd unless you've previously called [`UnixOutputStreamExtManual::set_close_fd`]
/// on this stream. At which point you may only do so when all references to this stream have
/// been dropped.
#[doc(alias = "g_unix_output_stream_new")]
pub unsafe fn take_fd(fd: impl IntoRawFd) -> UnixOutputStream {
pub fn take_fd(fd: OwnedFd) -> UnixOutputStream {
let fd = fd.into_raw_fd();
let close_fd = true.into_glib();
OutputStream::from_glib_full(ffi::g_unix_output_stream_new(fd, close_fd)).unsafe_cast()
unsafe {
OutputStream::from_glib_full(ffi::g_unix_output_stream_new(fd, close_fd)).unsafe_cast()
}
}

// rustdoc-stripper-ignore-next
Expand All @@ -43,6 +40,15 @@ impl AsRawFd for UnixOutputStream {
}
}

impl AsFd for UnixOutputStream {
fn as_fd(&self) -> BorrowedFd<'_> {
unsafe {
let raw_fd = self.as_raw_fd();
BorrowedFd::borrow_raw(raw_fd)
}
}
}

pub trait UnixOutputStreamExtManual: IsA<UnixOutputStream> + Sized {
// rustdoc-stripper-ignore-next
/// Sets whether the fd of this stream will be closed when the stream is closed.
Expand Down
6 changes: 3 additions & 3 deletions gio/tests/dbus_peer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ fn test_gdbus_peer_connection() {
prelude::*,
DBusConnection, DBusConnectionFlags, DBusNodeInfo, Socket,
};
use std::os::{fd::IntoRawFd, unix::net::UnixStream};
use std::os::unix::net::UnixStream;

const EXAMPLE_XML: &str = r#"
<node>
Expand All @@ -23,7 +23,7 @@ fn test_gdbus_peer_connection() {
"#;

pub async fn spawn_server(fd: UnixStream) -> DBusConnection {
let socket = unsafe { Socket::from_fd(fd.into_raw_fd()) }.unwrap();
let socket = Socket::from_fd(fd.into()).unwrap();
let socket_connection = socket.connection_factory_create_connection();

let guid = gio::dbus_generate_guid();
Expand Down Expand Up @@ -112,7 +112,7 @@ fn test_gdbus_peer_connection() {
}

pub async fn spawn_client(fd: UnixStream) -> DBusConnection {
let socket_client = unsafe { Socket::from_fd(fd.into_raw_fd()) }.unwrap();
let socket_client = Socket::from_fd(fd.into()).unwrap();
let socket_connection_client = socket_client.connection_factory_create_connection();

dbg!("client connecting");
Expand Down
19 changes: 11 additions & 8 deletions glib/src/functions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use std::boxed::Box as Box_;
use std::mem;
#[cfg(not(windows))]
#[cfg(feature = "v2_58")]
use std::os::unix::io::AsRawFd;
use std::os::unix::io::{AsFd, AsRawFd};
#[cfg(not(windows))]
use std::os::unix::io::{FromRawFd, IntoRawFd, RawFd};
use std::ptr;
Expand All @@ -24,15 +24,15 @@ use crate::{Error, Pid, SpawnFlags};
#[cfg_attr(docsrs, doc(cfg(all(feature = "v2_58", not(windows)))))]
#[allow(clippy::too_many_arguments)]
#[doc(alias = "g_spawn_async_with_fds")]
pub fn spawn_async_with_fds<P: AsRef<std::path::Path>, T: AsRawFd, U: AsRawFd, V: AsRawFd>(
pub fn spawn_async_with_fds<P: AsRef<std::path::Path>>(
working_directory: P,
argv: &[&str],
envp: &[&str],
flags: SpawnFlags,
child_setup: Option<Box_<dyn FnOnce() + 'static>>,
stdin_fd: T,
stdout_fd: U,
stderr_fd: V,
stdin_fd: Option<impl AsFd>,
stdout_fd: Option<impl AsFd>,
stderr_fd: Option<impl AsFd>,
) -> Result<Pid, Error> {
let child_setup_data: Box_<Option<Box_<dyn FnOnce() + 'static>>> = Box_::new(child_setup);
unsafe extern "C" fn child_setup_func(user_data: ffi::gpointer) {
Expand All @@ -47,6 +47,9 @@ pub fn spawn_async_with_fds<P: AsRef<std::path::Path>, T: AsRawFd, U: AsRawFd, V
None
};
let super_callback0: Box_<Option<Box_<dyn FnOnce() + 'static>>> = child_setup_data;
let stdin_raw_fd = stdin_fd.map_or(-1, |fd| fd.as_fd().as_raw_fd());
let stdout_raw_fd = stdout_fd.map_or(-1, |fd| fd.as_fd().as_raw_fd());
let stderr_raw_fd = stderr_fd.map_or(-1, |fd| fd.as_fd().as_raw_fd());
unsafe {
let mut child_pid = mem::MaybeUninit::uninit();
let mut error = ptr::null_mut();
Expand All @@ -58,9 +61,9 @@ pub fn spawn_async_with_fds<P: AsRef<std::path::Path>, T: AsRawFd, U: AsRawFd, V
child_setup,
Box_::into_raw(super_callback0) as *mut _,
child_pid.as_mut_ptr(),
stdin_fd.as_raw_fd(),
stdout_fd.as_raw_fd(),
stderr_fd.as_raw_fd(),
stdin_raw_fd,
stdout_raw_fd,
stderr_raw_fd,
&mut error,
);
let child_pid = from_glib(child_pid.assume_init());
Expand Down
14 changes: 9 additions & 5 deletions glib/src/log.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Take a look at the license at the top of the repository in the LICENSE file.

#[cfg(unix)]
use std::os::unix::io::AsRawFd;
use std::os::unix::io::{AsFd, AsRawFd};
use std::{
boxed::Box as Box_,
sync::{Arc, Mutex, OnceLock},
Expand Down Expand Up @@ -972,16 +972,20 @@ pub fn log_variant(log_domain: Option<&str>, log_level: LogLevel, fields: &crate
#[cfg_attr(docsrs, doc(cfg(unix)))]
#[doc(alias = "g_log_writer_supports_color")]
#[inline]
pub fn log_writer_supports_color<T: AsRawFd>(output_fd: T) -> bool {
unsafe { from_glib(ffi::g_log_writer_supports_color(output_fd.as_raw_fd())) }
pub fn log_writer_supports_color(output_fd: impl AsFd) -> bool {
unsafe {
from_glib(ffi::g_log_writer_supports_color(
output_fd.as_fd().as_raw_fd(),
))
}
}

#[cfg(unix)]
#[cfg_attr(docsrs, doc(cfg(unix)))]
#[doc(alias = "g_log_writer_is_journald")]
#[inline]
pub fn log_writer_is_journald<T: AsRawFd>(output_fd: T) -> bool {
unsafe { from_glib(ffi::g_log_writer_is_journald(output_fd.as_raw_fd())) }
pub fn log_writer_is_journald(output_fd: impl AsFd) -> bool {
unsafe { from_glib(ffi::g_log_writer_is_journald(output_fd.as_fd().as_raw_fd())) }
}

#[doc(alias = "g_log_writer_format_fields")]
Expand Down
Loading