Skip to content

Commit 0e306d3

Browse files
committed
unix_fd_list: Use custom iterator for steal_fds
1 parent e816303 commit 0e306d3

File tree

1 file changed

+72
-8
lines changed

1 file changed

+72
-8
lines changed

gio/src/unix_fd_list.rs

Lines changed: 72 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
// Take a look at the license at the top of the repository in the LICENSE file.
22

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

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

1111
use crate::{ffi, UnixFDList};
1212

@@ -74,16 +74,80 @@ pub trait UnixFDListExtManual: sealed::Sealed + IsA<UnixFDList> + Sized {
7474
}
7575

7676
#[doc(alias = "g_unix_fd_list_steal_fds")]
77-
fn steal_fds(&self) -> Vec<OwnedFd> {
77+
fn steal_fds(&self) -> FdArray {
7878
unsafe {
7979
let mut length = mem::MaybeUninit::uninit();
80-
let ret: Vec<RawFd> = FromGlibContainer::from_glib_full_num(
81-
ffi::g_unix_fd_list_steal_fds(self.as_ref().to_glib_none().0, length.as_mut_ptr()),
82-
length.assume_init() as usize,
83-
);
84-
ret.into_iter().map(|fd| OwnedFd::from_raw_fd(fd)).collect()
80+
81+
let ptr =
82+
ffi::g_unix_fd_list_steal_fds(self.as_ref().to_glib_none().0, length.as_mut_ptr());
83+
84+
FdArray {
85+
ptr: ptr::NonNull::new(ptr).unwrap(),
86+
len: length.assume_init() as usize,
87+
}
8588
}
8689
}
8790
}
8891

8992
impl<O: IsA<UnixFDList>> UnixFDListExtManual for O {}
93+
94+
pub struct FdArray {
95+
ptr: ptr::NonNull<libc::c_int>,
96+
len: usize,
97+
}
98+
99+
pub struct FdIterator {
100+
ptr: ptr::NonNull<libc::c_int>,
101+
len: usize,
102+
}
103+
104+
impl Iterator for FdIterator {
105+
type Item = OwnedFd;
106+
107+
fn next(&mut self) -> Option<Self::Item> {
108+
if self.len > 0 {
109+
let current = self.ptr.as_ptr();
110+
if self.len > 1 {
111+
let next = unsafe { self.ptr.as_ptr().add(1) };
112+
self.ptr = ptr::NonNull::new(next).unwrap();
113+
}
114+
self.len -= 1;
115+
Some(unsafe { OwnedFd::from_raw_fd(*current) })
116+
} else {
117+
None
118+
}
119+
}
120+
}
121+
122+
impl Drop for FdArray {
123+
fn drop(&mut self) {
124+
while self.len > 0 {
125+
unsafe {
126+
let current = self.ptr.as_ptr();
127+
libc::close(*current);
128+
}
129+
if self.len > 1 {
130+
let next = unsafe { self.ptr.as_ptr().add(1) };
131+
self.ptr = ptr::NonNull::new(next).unwrap();
132+
}
133+
self.len -= 1;
134+
}
135+
}
136+
}
137+
138+
impl std::iter::IntoIterator for FdArray {
139+
type Item = OwnedFd;
140+
type IntoIter = FdIterator;
141+
142+
fn into_iter(mut self) -> Self::IntoIter {
143+
// Can I .take() the ptr and set it to null here?
144+
let len = std::mem::take(&mut self.len);
145+
FdIterator { len, ptr: self.ptr }
146+
}
147+
}
148+
149+
impl FdArray {
150+
pub fn as_slice(&self) -> &[BorrowedFd<'_>] {
151+
unsafe { std::slice::from_raw_parts(self.ptr.as_ptr() as *const BorrowedFd, self.len) }
152+
}
153+
}

0 commit comments

Comments
 (0)