Skip to content

Commit 696197e

Browse files
committed
wip: unix_fd_list: Use custom iterator for steal_fds
1 parent 1d6321d commit 696197e

File tree

1 file changed

+71
-8
lines changed

1 file changed

+71
-8
lines changed

gio/src/unix_fd_list.rs

Lines changed: 71 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, FromRawFd, IntoRawFd, OwnedFd, RawFd};
4+
use std::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd};
55
use std::{mem, ptr};
66

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

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

@@ -69,16 +69,79 @@ pub trait UnixFDListExtManual: IsA<UnixFDList> + Sized {
6969
}
7070

7171
#[doc(alias = "g_unix_fd_list_steal_fds")]
72-
fn steal_fds(&self) -> Vec<RawFd> {
72+
fn steal_fds(&self) -> FdArray {
7373
unsafe {
7474
let mut length = mem::MaybeUninit::uninit();
75-
let ret = FromGlibContainer::from_glib_full_num(
76-
ffi::g_unix_fd_list_steal_fds(self.as_ref().to_glib_none().0, length.as_mut_ptr()),
77-
length.assume_init() as usize,
78-
);
79-
ret
75+
76+
let ptr =
77+
ffi::g_unix_fd_list_steal_fds(self.as_ref().to_glib_none().0, length.as_mut_ptr());
78+
79+
FdArray {
80+
ptr: ptr::NonNull::new(ptr).unwrap(),
81+
len: length.assume_init() as usize,
82+
}
8083
}
8184
}
8285
}
8386

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

0 commit comments

Comments
 (0)