Skip to content

Commit 5d3aefe

Browse files
committed
kmc-solid: Add std::os::solid::io::{BorrowedFd,OwnedFd,AsFd}
It's mostly based on `std::os::fd::owned`.
1 parent ff0b4b6 commit 5d3aefe

File tree

1 file changed

+191
-0
lines changed
  • library/std/src/os/solid

1 file changed

+191
-0
lines changed

library/std/src/os/solid/io.rs

Lines changed: 191 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,204 @@
33
#![deny(unsafe_op_in_unsafe_fn)]
44
#![unstable(feature = "solid_ext", issue = "none")]
55

6+
use crate::fmt;
7+
use crate::marker::PhantomData;
8+
use crate::mem::forget;
69
use crate::net;
710
use crate::sys;
811
use crate::sys_common::{self, AsInner, FromInner, IntoInner};
912

1013
/// Raw file descriptors.
1114
pub type RawFd = i32;
1215

16+
/// A borrowed SOLID Sockets file descriptor.
17+
///
18+
/// This has a lifetime parameter to tie it to the lifetime of something that
19+
/// owns the socket.
20+
///
21+
/// This uses `repr(transparent)` and has the representation of a host file
22+
/// descriptor, so it can be used in FFI in places where a socket is passed as
23+
/// an argument, it is not captured or consumed, and it never has the value
24+
/// `SOLID_NET_INVALID_FD`.
25+
///
26+
/// This type's `.to_owned()` implementation returns another `BorrowedFd`
27+
/// rather than an `OwnedFd`. It just makes a trivial copy of the raw
28+
/// socket, which is then borrowed under the same lifetime.
29+
#[derive(Copy, Clone)]
30+
#[repr(transparent)]
31+
#[rustc_layout_scalar_valid_range_start(0)]
32+
// This is -2, in two's complement. -1 is `SOLID_NET_INVALID_FD`.
33+
#[rustc_layout_scalar_valid_range_end(0xFF_FF_FF_FE)]
34+
#[rustc_nonnull_optimization_guaranteed]
35+
pub struct BorrowedFd<'socket> {
36+
fd: RawFd,
37+
_phantom: PhantomData<&'socket OwnedFd>,
38+
}
39+
40+
/// An owned SOLID Sockets file descriptor.
41+
///
42+
/// This closes the file descriptor on drop.
43+
///
44+
/// This uses `repr(transparent)` and has the representation of a host file
45+
/// descriptor, so it can be used in FFI in places where a socket is passed as
46+
/// an argument, it is not captured or consumed, and it never has the value
47+
/// `SOLID_NET_INVALID_FD`.
48+
#[repr(transparent)]
49+
#[rustc_layout_scalar_valid_range_start(0)]
50+
// This is -2, in two's complement. -1 is `SOLID_NET_INVALID_FD`.
51+
#[rustc_layout_scalar_valid_range_end(0xFF_FF_FF_FE)]
52+
#[rustc_nonnull_optimization_guaranteed]
53+
pub struct OwnedFd {
54+
fd: RawFd,
55+
}
56+
57+
impl BorrowedFd<'_> {
58+
/// Return a `BorrowedFd` holding the given raw file descriptor.
59+
///
60+
/// # Safety
61+
///
62+
/// The resource pointed to by `fd` must remain open for the duration of
63+
/// the returned `BorrowedFd`, and it must not have the value
64+
/// `SOLID_NET_INVALID_FD`.
65+
#[inline]
66+
pub const unsafe fn borrow_raw(fd: RawFd) -> Self {
67+
assert!(fd != -1 as RawFd);
68+
// SAFETY: we just asserted that the value is in the valid range and
69+
// isn't `-1` (the only value bigger than `0xFF_FF_FF_FE` unsigned)
70+
unsafe { Self { fd, _phantom: PhantomData } }
71+
}
72+
}
73+
74+
impl OwnedFd {
75+
/// Creates a new `OwnedFd` instance that shares the same underlying file
76+
/// description as the existing `OwnedFd` instance.
77+
pub fn try_clone(&self) -> crate::io::Result<Self> {
78+
self.as_fd().try_clone_to_owned()
79+
}
80+
}
81+
82+
impl BorrowedFd<'_> {
83+
/// Creates a new `OwnedFd` instance that shares the same underlying file
84+
/// description as the existing `BorrowedFd` instance.
85+
pub fn try_clone_to_owned(&self) -> crate::io::Result<OwnedFd> {
86+
let fd = sys::net::cvt(unsafe { sys::net::netc::dup(self.as_raw_fd()) })?;
87+
Ok(unsafe { OwnedFd::from_raw_fd(fd) })
88+
}
89+
}
90+
91+
impl AsRawFd for BorrowedFd<'_> {
92+
#[inline]
93+
fn as_raw_fd(&self) -> RawFd {
94+
self.fd
95+
}
96+
}
97+
98+
impl AsRawFd for OwnedFd {
99+
#[inline]
100+
fn as_raw_fd(&self) -> RawFd {
101+
self.fd
102+
}
103+
}
104+
105+
impl IntoRawFd for OwnedFd {
106+
#[inline]
107+
fn into_raw_fd(self) -> RawFd {
108+
let fd = self.fd;
109+
forget(self);
110+
fd
111+
}
112+
}
113+
114+
impl FromRawFd for OwnedFd {
115+
/// Constructs a new instance of `Self` from the given raw file descriptor.
116+
///
117+
/// # Safety
118+
///
119+
/// The resource pointed to by `fd` must be open and suitable for assuming
120+
/// ownership. The resource must not require any cleanup other than `close`.
121+
#[inline]
122+
unsafe fn from_raw_fd(fd: RawFd) -> Self {
123+
assert_ne!(fd, -1 as RawFd);
124+
// SAFETY: we just asserted that the value is in the valid range and
125+
// isn't `-1` (the only value bigger than `0xFF_FF_FF_FE` unsigned)
126+
unsafe { Self { fd } }
127+
}
128+
}
129+
130+
impl Drop for OwnedFd {
131+
#[inline]
132+
fn drop(&mut self) {
133+
unsafe { sys::net::netc::close(self.fd) };
134+
}
135+
}
136+
137+
impl fmt::Debug for BorrowedFd<'_> {
138+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
139+
f.debug_struct("BorrowedFd").field("fd", &self.fd).finish()
140+
}
141+
}
142+
143+
impl fmt::Debug for OwnedFd {
144+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
145+
f.debug_struct("OwnedFd").field("fd", &self.fd).finish()
146+
}
147+
}
148+
149+
macro_rules! impl_is_terminal {
150+
($($t:ty),*$(,)?) => {$(
151+
#[unstable(feature = "sealed", issue = "none")]
152+
impl crate::sealed::Sealed for $t {}
153+
154+
#[stable(feature = "is_terminal", since = "1.70.0")]
155+
impl crate::io::IsTerminal for $t {
156+
#[inline]
157+
fn is_terminal(&self) -> bool {
158+
crate::sys::io::is_terminal(self)
159+
}
160+
}
161+
)*}
162+
}
163+
164+
impl_is_terminal!(BorrowedFd<'_>, OwnedFd);
165+
166+
/// A trait to borrow the SOLID Sockets file descriptor from an underlying
167+
/// object.
168+
pub trait AsFd {
169+
/// Borrows the file descriptor.
170+
fn as_fd(&self) -> BorrowedFd<'_>;
171+
}
172+
173+
impl<T: AsFd> AsFd for &T {
174+
#[inline]
175+
fn as_fd(&self) -> BorrowedFd<'_> {
176+
T::as_fd(self)
177+
}
178+
}
179+
180+
impl<T: AsFd> AsFd for &mut T {
181+
#[inline]
182+
fn as_fd(&self) -> BorrowedFd<'_> {
183+
T::as_fd(self)
184+
}
185+
}
186+
187+
impl AsFd for BorrowedFd<'_> {
188+
#[inline]
189+
fn as_fd(&self) -> BorrowedFd<'_> {
190+
*self
191+
}
192+
}
193+
194+
impl AsFd for OwnedFd {
195+
#[inline]
196+
fn as_fd(&self) -> BorrowedFd<'_> {
197+
// Safety: `OwnedFd` and `BorrowedFd` have the same validity
198+
// invariants, and the `BorrowedFd` is bounded by the lifetime
199+
// of `&self`.
200+
unsafe { BorrowedFd::borrow_raw(self.as_raw_fd()) }
201+
}
202+
}
203+
13204
/// A trait to extract the raw SOLID Sockets file descriptor from an underlying
14205
/// object.
15206
pub trait AsRawFd {

0 commit comments

Comments
 (0)