Skip to content

Commit

Permalink
wip: unix_fd_list: Use custom iterator for steal_fds
Browse files Browse the repository at this point in the history
  • Loading branch information
A6GibKm committed Jun 10, 2024
1 parent bf6f65d commit c82d4c4
Showing 1 changed file with 71 additions and 8 deletions.
79 changes: 71 additions & 8 deletions gio/src/unix_fd_list.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
// Take a look at the license at the top of the repository in the LICENSE file.

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

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

use crate::{ffi, UnixFDList};

Expand Down Expand Up @@ -74,16 +74,79 @@ pub trait UnixFDListExtManual: sealed::Sealed + IsA<UnixFDList> + Sized {
}

#[doc(alias = "g_unix_fd_list_steal_fds")]
fn steal_fds(&self) -> Vec<OwnedFd> {
fn steal_fds(&self) -> FdArray {
unsafe {
let mut length = mem::MaybeUninit::uninit();
let ret: Vec<RawFd> = FromGlibContainer::from_glib_full_num(
ffi::g_unix_fd_list_steal_fds(self.as_ref().to_glib_none().0, length.as_mut_ptr()),
length.assume_init() as usize,
);
ret.into_iter().map(|fd| OwnedFd::from_raw_fd(fd)).collect()

let ptr =
ffi::g_unix_fd_list_steal_fds(self.as_ref().to_glib_none().0, length.as_mut_ptr());

FdArray {
ptr: ptr::NonNull::new(ptr).unwrap(),
len: length.assume_init() as usize,
}
}
}
}

impl<O: IsA<UnixFDList>> UnixFDListExtManual for O {}

pub struct FdArray {
ptr: ptr::NonNull<libc::c_int>,
len: usize,
}

pub struct FdIterator {
ptr: ptr::NonNull<libc::c_int>,
len: usize,
}

impl Iterator for FdIterator {
type Item = OwnedFd;

fn next(&mut self) -> Option<Self::Item> {
if self.len > 0 {
let current = self.ptr.as_ptr();
if self.len > 1 {
let next = unsafe { self.ptr.as_ptr().add(1) };
self.ptr = ptr::NonNull::new(next).unwrap();
}
self.len -= 1;
Some(unsafe { OwnedFd::from_raw_fd(*current) })
} else {
None
}
}
}

impl Drop for FdArray {
fn drop(&mut self) {
while self.len > 0 {
unsafe {
let current = self.ptr.as_ptr();
libc::close(*current);
}
if self.len > 1 {
let next = unsafe { self.ptr.as_ptr().add(1) };
self.ptr = ptr::NonNull::new(next).unwrap();
}
self.len -= 1;
}
}
}

impl std::iter::IntoIterator for FdArray {
type Item = OwnedFd;
type IntoIter = FdIterator;

fn into_iter(mut self) -> Self::IntoIter {
let len = std::mem::take(&mut self.len);
FdIterator { len, ptr: self.ptr }
}
}

impl FdArray {
pub fn as_slice(&self) -> &[BorrowedFd<'_>] {
unsafe { std::slice::from_raw_parts(self.ptr.as_ptr() as *const BorrowedFd, self.len) }
}
}

0 comments on commit c82d4c4

Please sign in to comment.