|
1 | 1 | // Take a look at the license at the top of the repository in the LICENSE file.
|
2 | 2 |
|
3 | 3 | #[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}; |
5 | 5 | use std::{mem, ptr};
|
6 | 6 |
|
7 | 7 | use glib::{prelude::*, translate::*};
|
8 | 8 | #[cfg(all(not(unix), docsrs))]
|
9 |
| -use socket::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd}; |
| 9 | +use socket::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd}; |
10 | 10 |
|
11 | 11 | use crate::{ffi, UnixFDList};
|
12 | 12 |
|
@@ -74,16 +74,80 @@ pub trait UnixFDListExtManual: sealed::Sealed + IsA<UnixFDList> + Sized {
|
74 | 74 | }
|
75 | 75 |
|
76 | 76 | #[doc(alias = "g_unix_fd_list_steal_fds")]
|
77 |
| - fn steal_fds(&self) -> Vec<OwnedFd> { |
| 77 | + fn steal_fds(&self) -> FdArray { |
78 | 78 | unsafe {
|
79 | 79 | 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 | + } |
85 | 88 | }
|
86 | 89 | }
|
87 | 90 | }
|
88 | 91 |
|
89 | 92 | 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