|
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, FromRawFd, IntoRawFd, OwnedFd, RawFd}; |
| 4 | +use std::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd}; |
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, FromRawFd, IntoRawFd, OwnedFd, RawFd}; |
| 9 | +use socket::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd}; |
10 | 10 |
|
11 | 11 | use crate::{ffi, UnixFDList};
|
12 | 12 |
|
@@ -69,16 +69,79 @@ pub trait UnixFDListExtManual: IsA<UnixFDList> + Sized {
|
69 | 69 | }
|
70 | 70 |
|
71 | 71 | #[doc(alias = "g_unix_fd_list_steal_fds")]
|
72 |
| - fn steal_fds(&self) -> Vec<RawFd> { |
| 72 | + fn steal_fds(&self) -> FdArray { |
73 | 73 | unsafe {
|
74 | 74 | 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 | + } |
80 | 83 | }
|
81 | 84 | }
|
82 | 85 | }
|
83 | 86 |
|
84 | 87 | 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