Repository: gtk-rs/gtk-rs-core
Pull request #1699: gio: Use `OwnedSocket` / `BorrowedSocket` for Windows APIs on GSocket
Author: login: sdroege
Created: 2025-04-05T11:02:06Z | Merged: 2025-04-06T14:26:51Z

CC @A6GibKm 


Diff:
diff --git a/cairo/src/surface.rs b/cairo/src/surface.rs
index 8ea7034913e7..2868742b81ff 100644
--- a/cairo/src/surface.rs
+++ b/cairo/src/surface.rs
@@ -78,14 +78,16 @@ impl Surface {
     #[doc(alias = "cairo_surface_get_mime_data")]
     #[doc(alias = "get_mime_data")]
     pub fn mime_data(&self, mime_type: &str) -> Option<Vec<u8>> {
-        let data_ptr: *mut u8 = ptr::null_mut();
+        let mut data_ptr: *mut u8 = ptr::null_mut();
         let mut length: c_ulong = 0;
+        // The function actually needs a mutable pointer
+        #[allow(clippy::unnecessary_mut_passed)]
         unsafe {
             let mime_type = CString::new(mime_type).unwrap();
             ffi::cairo_surface_get_mime_data(
                 self.to_raw_none(),
                 mime_type.as_ptr(),
-                &data_ptr,
+                &mut data_ptr,
                 &mut length,
             );
             if !data_ptr.is_null() && length != 0 {
@@ -99,15 +101,19 @@ impl Surface {
     #[doc(alias = "cairo_surface_get_mime_data")]
     #[doc(alias = "get_mime_data_raw")]
     pub unsafe fn mime_data_raw(&self, mime_type: &str) -> Option<&[u8]> {
-        let data_ptr: *mut u8 = ptr::null_mut();
+        let mut data_ptr: *mut u8 = ptr::null_mut();
         let mut length: c_ulong = 0;
         let mime_type = CString::new(mime_type).unwrap();
-        ffi::cairo_surface_get_mime_data(
-            self.to_raw_none(),
-            mime_type.as_ptr(),
-            &data_ptr,
-            &mut length,
-        );
+        // The function actually needs a mutable pointer
+        #[allow(clippy::unnecessary_mut_passed)]
+        {
+            ffi::cairo_surface_get_mime_data(
+                self.to_raw_none(),
+                mime_type.as_ptr(),
+                &mut data_ptr,
+                &mut length,
+            );
+        }
         if !data_ptr.is_null() && length != 0 {
             Some(slice::from_raw_parts(
                 data_ptr as *const u8,
diff --git a/gdk-pixbuf/src/pixbuf.rs b/gdk-pixbuf/src/pixbuf.rs
index 17c5ee0ee8f6..a48f2e6cf660 100644
--- a/gdk-pixbuf/src/pixbuf.rs
+++ b/gdk-pixbuf/src/pixbuf.rs
@@ -35,7 +35,7 @@ impl Pixbuf {
         let bits_per_sample = bits_per_sample as usize;
 
         let n_channels = if has_alpha { 4 } else { 3 };
-        let last_row_len = width * ((n_channels * bits_per_sample + 7) / 8);
+        let last_row_len = width * (n_channels * bits_per_sample).div_ceil(8);
 
         let mut data: Box<T> = Box::new(data);
 
diff --git a/gio/src/input_stream.rs b/gio/src/input_stream.rs
index fb874f96f2b9..fcced64e768f 100644
--- a/gio/src/input_stream.rs
+++ b/gio/src/input_stream.rs
@@ -417,7 +417,7 @@ impl<T: IsA<InputStream>> InputStreamAsyncBufRead<T> {
 
     fn set_has_data(&mut self, buffer: Vec<u8>, valid: (usize, usize)) {
         match self.state {
-            State::Reading { .. } | State::Transitioning { .. } => {
+            State::Reading { .. } | State::Transitioning => {
                 self.state = State::HasData { buffer, valid }
             }
             _ => panic!("Invalid state"),
diff --git a/gio/src/socket.rs b/gio/src/socket.rs
index da27490d8499..738a6840bef8 100644
--- a/gio/src/socket.rs
+++ b/gio/src/socket.rs
@@ -3,7 +3,9 @@
 #[cfg(unix)]
 use std::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd};
 #[cfg(windows)]
-use std::os::windows::io::{AsRawSocket, FromRawSocket, IntoRawSocket, RawSocket};
+use std::os::windows::io::{
+    AsRawSocket, AsSocket, BorrowedSocket, FromRawSocket, IntoRawSocket, OwnedSocket, RawSocket,
+};
 #[cfg(feature = "v2_60")]
 use std::time::Duration;
 use std::{cell::RefCell, marker::PhantomData, mem::transmute, pin::Pin, ptr};
@@ -27,22 +29,24 @@ impl Socket {
             if error.is_null() {
                 Ok(from_glib_full(ret))
             } else {
-                libc::close(fd);
+                let _ = OwnedFd::from_raw_fd(fd);
                 Err(from_glib_full(error))
             }
         }
     }
     #[cfg(windows)]
     #[cfg_attr(docsrs, doc(cfg(windows)))]
-    #[allow(clippy::missing_safety_doc)]
-    pub unsafe fn from_socket(socket: impl IntoRawSocket) -> Result<Socket, glib::Error> {
+    pub fn from_socket(socket: OwnedSocket) -> Result<Socket, glib::Error> {
         let socket = socket.into_raw_socket();
         let mut error = ptr::null_mut();
-        let ret = ffi::g_socket_new_from_fd(socket as i32, &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(socket as i32, &mut error);
+            if error.is_null() {
+                Ok(from_glib_full(ret))
+            } else {
+                let _ = OwnedSocket::from_raw_socket(socket);
+                Err(from_glib_full(error))
+            }
         }
     }
 }
@@ -74,6 +78,17 @@ impl AsRawSocket for Socket {
     }
 }
 
+#[cfg(windows)]
+#[cfg_attr(docsrs, doc(cfg(windows)))]
+impl AsSocket for Socket {
+    fn as_socket(&self) -> BorrowedSocket<'_> {
+        unsafe {
+            let raw_socket = self.as_raw_socket();
+            BorrowedSocket::borrow_raw(raw_socket)
+        }
+    }
+}
+
 #[doc(alias = "GInputVector")]
 #[repr(transparent)]
 #[derive(Debug)]
@@ -646,18 +661,16 @@ pub trait SocketExtManual: IsA<Socket> + Sized {
     #[cfg_attr(docsrs, doc(cfg(unix)))]
     #[doc(alias = "get_fd")]
     #[doc(alias = "g_socket_get_fd")]
-    fn fd<T: FromRawFd>(&self) -> T {
-        unsafe { FromRawFd::from_raw_fd(ffi::g_socket_get_fd(self.as_ref().to_glib_none().0)) }
+    fn fd(&self) -> BorrowedFd<'_> {
+        self.as_ref().as_fd()
     }
 
     #[cfg(windows)]
     #[cfg_attr(docsrs, doc(cfg(windows)))]
     #[doc(alias = "get_socket")]
     #[doc(alias = "g_socket_get_fd")]
-    fn socket<T: FromRawSocket>(&self) -> T {
-        unsafe {
-            FromRawSocket::from_raw_socket(ffi::g_socket_get_fd(self.as_ref().to_glib_none().0) as _)
-        }
+    fn socket(&self) -> BorrowedSocket<'_> {
+        self.as_ref().as_socket()
     }
 
     #[doc(alias = "g_socket_create_source")]


Reviews:
user: login: A6GibKm
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-05T12:41:56Z
user: login: sdroege
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-05T15:10:04Z
user: login: sdroege
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-05T15:10:31Z
user: login: sdroege
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-05T15:31:23Z
user: login: A6GibKm
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-06T15:52:22Z
user: login: sdroege
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-06T15:58:14Z
user: login: A6GibKm
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-06T16:00:29Z
user: login: sdroege
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-06T16:06:38Z

Review comments:
diff_hunk: @@ -27,22 +29,24 @@ impl Socket {
             if error.is_null() {
                 Ok(from_glib_full(ret))
             } else {
-                libc::close(fd);
+                let _ = OwnedFd::from_raw_fd(fd);
path: gio/src/socket.rs
user: login: A6GibKm
body: Ultimately, `Drop` on OwnedFd does libc::close, no strong opinion though.

https://doc.rust-lang.org/src/std/os/fd/owned.rs.html#182
created_at: 2025-04-05T12:10:34Z
author_association: CONTRIBUTOR
diff_hunk: @@ -27,22 +29,24 @@ impl Socket {
             if error.is_null() {
                 Ok(from_glib_full(ret))
             } else {
-                libc::close(fd);
+                let _ = OwnedFd::from_raw_fd(fd);
                 Err(from_glib_full(error))
             }
         }
     }
     #[cfg(windows)]
     #[cfg_attr(docsrs, doc(cfg(windows)))]
-    #[allow(clippy::missing_safety_doc)]
-    pub unsafe fn from_socket(socket: impl IntoRawSocket) -> Result<Socket, glib::Error> {
+    pub fn from_socket(socket: OwnedSocket) -> Result<Socket, glib::Error> {
         let socket = socket.into_raw_socket();
path: gio/src/socket.rs
user: login: A6GibKm
body: Did we implement `Into<OwnedFd>` for Socket?
created_at: 2025-04-05T12:38:40Z
author_association: CONTRIBUTOR
diff_hunk: @@ -27,22 +29,24 @@ impl Socket {
             if error.is_null() {
                 Ok(from_glib_full(ret))
             } else {
-                libc::close(fd);
+                let _ = OwnedFd::from_raw_fd(fd);
path: gio/src/socket.rs
user: login: sdroege
body: It does, yes. But it seems more symmetric to close it via `OwnedFd` if we got it from there :)
created_at: 2025-04-05T15:10:04Z
author_association: MEMBER
diff_hunk: @@ -27,22 +29,24 @@ impl Socket {
             if error.is_null() {
                 Ok(from_glib_full(ret))
             } else {
-                libc::close(fd);
+                let _ = OwnedFd::from_raw_fd(fd);
                 Err(from_glib_full(error))
             }
         }
     }
     #[cfg(windows)]
     #[cfg_attr(docsrs, doc(cfg(windows)))]
-    #[allow(clippy::missing_safety_doc)]
-    pub unsafe fn from_socket(socket: impl IntoRawSocket) -> Result<Socket, glib::Error> {
+    pub fn from_socket(socket: OwnedSocket) -> Result<Socket, glib::Error> {
         let socket = socket.into_raw_socket();
path: gio/src/socket.rs
user: login: sdroege
body: No, we can't really. We can't steal the fd from the socket.
created_at: 2025-04-05T15:10:31Z
author_association: MEMBER
diff_hunk: @@ -78,14 +78,14 @@ impl Surface {
     #[doc(alias = "cairo_surface_get_mime_data")]
     #[doc(alias = "get_mime_data")]
     pub fn mime_data(&self, mime_type: &str) -> Option<Vec<u8>> {
-        let data_ptr: *mut u8 = ptr::null_mut();
+        let mut data_ptr: *mut u8 = ptr::null_mut();
         let mut length: c_ulong = 0;
         unsafe {
             let mime_type = CString::new(mime_type).unwrap();
             ffi::cairo_surface_get_mime_data(
                 self.to_raw_none(),
                 mime_type.as_ptr(),
-                &data_ptr,
+                &mut data_ptr,
path: cairo/src/surface.rs
user: login: sdroege
body: Actually not a false positive. That code was completely broken
created_at: 2025-04-05T15:31:23Z
author_association: MEMBER
diff_hunk: @@ -35,7 +35,7 @@ impl Pixbuf {
         let bits_per_sample = bits_per_sample as usize;
 
         let n_channels = if has_alpha { 4 } else { 3 };
-        let last_row_len = width * ((n_channels * bits_per_sample + 7) / 8);
+        let last_row_len = width * (n_channels * bits_per_sample).div_ceil(8);
path: gdk-pixbuf/src/pixbuf.rs
user: login: A6GibKm
body: This is missing a 7 isn't it?
created_at: 2025-04-06T15:52:12Z
author_association: CONTRIBUTOR
diff_hunk: @@ -35,7 +35,7 @@ impl Pixbuf {
         let bits_per_sample = bits_per_sample as usize;
 
         let n_channels = if has_alpha { 4 } else { 3 };
-        let last_row_len = width * ((n_channels * bits_per_sample + 7) / 8);
+        let last_row_len = width * (n_channels * bits_per_sample).div_ceil(8);
path: gdk-pixbuf/src/pixbuf.rs
user: login: sdroege
body: No, why?
created_at: 2025-04-06T15:58:14Z
author_association: MEMBER
diff_hunk: @@ -35,7 +35,7 @@ impl Pixbuf {
         let bits_per_sample = bits_per_sample as usize;
 
         let n_channels = if has_alpha { 4 } else { 3 };
-        let last_row_len = width * ((n_channels * bits_per_sample + 7) / 8);
+        let last_row_len = width * (n_channels * bits_per_sample).div_ceil(8);
path: gdk-pixbuf/src/pixbuf.rs
user: login: A6GibKm
body: There was a +7 before and that change seemed unrelated to clippy fixes.
created_at: 2025-04-06T16:00:29Z
author_association: CONTRIBUTOR
diff_hunk: @@ -35,7 +35,7 @@ impl Pixbuf {
         let bits_per_sample = bits_per_sample as usize;
 
         let n_channels = if has_alpha { 4 } else { 3 };
-        let last_row_len = width * ((n_channels * bits_per_sample + 7) / 8);
+        let last_row_len = width * (n_channels * bits_per_sample).div_ceil(8);
path: gdk-pixbuf/src/pixbuf.rs
user: login: sdroege
body: That `(x + 7) / 8` is the same as dividing by 8 and rounding up (which is what `div_ceil()` does)
created_at: 2025-04-06T16:06:38Z
author_association: MEMBER

PR comments:
user: login: sdroege
created_at: 2025-04-05T11:06:02Z
body: CI failure is a false positive compiler error with latest nightly...
author_association: MEMBER
user: login: sdroege
created_at: 2025-04-05T15:41:21Z
body: CI finally passing
author_association: MEMBER