mirror of https://github.com/rust-lang/rust.git
kmc-solid: Add `std::os::solid::io::{BorrowedFd,OwnedFd,AsFd}`
It's mostly based on `std::os::fd::owned`.
This commit is contained in:
parent
ff0b4b6091
commit
5d3aefe58d
|
@ -3,6 +3,9 @@
|
|||
#![deny(unsafe_op_in_unsafe_fn)]
|
||||
#![unstable(feature = "solid_ext", issue = "none")]
|
||||
|
||||
use crate::fmt;
|
||||
use crate::marker::PhantomData;
|
||||
use crate::mem::forget;
|
||||
use crate::net;
|
||||
use crate::sys;
|
||||
use crate::sys_common::{self, AsInner, FromInner, IntoInner};
|
||||
|
@ -10,6 +13,194 @@ use crate::sys_common::{self, AsInner, FromInner, IntoInner};
|
|||
/// Raw file descriptors.
|
||||
pub type RawFd = i32;
|
||||
|
||||
/// A borrowed SOLID Sockets file descriptor.
|
||||
///
|
||||
/// This has a lifetime parameter to tie it to the lifetime of something that
|
||||
/// owns the socket.
|
||||
///
|
||||
/// This uses `repr(transparent)` and has the representation of a host file
|
||||
/// descriptor, so it can be used in FFI in places where a socket is passed as
|
||||
/// an argument, it is not captured or consumed, and it never has the value
|
||||
/// `SOLID_NET_INVALID_FD`.
|
||||
///
|
||||
/// This type's `.to_owned()` implementation returns another `BorrowedFd`
|
||||
/// rather than an `OwnedFd`. It just makes a trivial copy of the raw
|
||||
/// socket, which is then borrowed under the same lifetime.
|
||||
#[derive(Copy, Clone)]
|
||||
#[repr(transparent)]
|
||||
#[rustc_layout_scalar_valid_range_start(0)]
|
||||
// This is -2, in two's complement. -1 is `SOLID_NET_INVALID_FD`.
|
||||
#[rustc_layout_scalar_valid_range_end(0xFF_FF_FF_FE)]
|
||||
#[rustc_nonnull_optimization_guaranteed]
|
||||
pub struct BorrowedFd<'socket> {
|
||||
fd: RawFd,
|
||||
_phantom: PhantomData<&'socket OwnedFd>,
|
||||
}
|
||||
|
||||
/// An owned SOLID Sockets file descriptor.
|
||||
///
|
||||
/// This closes the file descriptor on drop.
|
||||
///
|
||||
/// This uses `repr(transparent)` and has the representation of a host file
|
||||
/// descriptor, so it can be used in FFI in places where a socket is passed as
|
||||
/// an argument, it is not captured or consumed, and it never has the value
|
||||
/// `SOLID_NET_INVALID_FD`.
|
||||
#[repr(transparent)]
|
||||
#[rustc_layout_scalar_valid_range_start(0)]
|
||||
// This is -2, in two's complement. -1 is `SOLID_NET_INVALID_FD`.
|
||||
#[rustc_layout_scalar_valid_range_end(0xFF_FF_FF_FE)]
|
||||
#[rustc_nonnull_optimization_guaranteed]
|
||||
pub struct OwnedFd {
|
||||
fd: RawFd,
|
||||
}
|
||||
|
||||
impl BorrowedFd<'_> {
|
||||
/// Return a `BorrowedFd` holding the given raw file descriptor.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The resource pointed to by `fd` must remain open for the duration of
|
||||
/// the returned `BorrowedFd`, and it must not have the value
|
||||
/// `SOLID_NET_INVALID_FD`.
|
||||
#[inline]
|
||||
pub const unsafe fn borrow_raw(fd: RawFd) -> Self {
|
||||
assert!(fd != -1 as RawFd);
|
||||
// SAFETY: we just asserted that the value is in the valid range and
|
||||
// isn't `-1` (the only value bigger than `0xFF_FF_FF_FE` unsigned)
|
||||
unsafe { Self { fd, _phantom: PhantomData } }
|
||||
}
|
||||
}
|
||||
|
||||
impl OwnedFd {
|
||||
/// Creates a new `OwnedFd` instance that shares the same underlying file
|
||||
/// description as the existing `OwnedFd` instance.
|
||||
pub fn try_clone(&self) -> crate::io::Result<Self> {
|
||||
self.as_fd().try_clone_to_owned()
|
||||
}
|
||||
}
|
||||
|
||||
impl BorrowedFd<'_> {
|
||||
/// Creates a new `OwnedFd` instance that shares the same underlying file
|
||||
/// description as the existing `BorrowedFd` instance.
|
||||
pub fn try_clone_to_owned(&self) -> crate::io::Result<OwnedFd> {
|
||||
let fd = sys::net::cvt(unsafe { sys::net::netc::dup(self.as_raw_fd()) })?;
|
||||
Ok(unsafe { OwnedFd::from_raw_fd(fd) })
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRawFd for BorrowedFd<'_> {
|
||||
#[inline]
|
||||
fn as_raw_fd(&self) -> RawFd {
|
||||
self.fd
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRawFd for OwnedFd {
|
||||
#[inline]
|
||||
fn as_raw_fd(&self) -> RawFd {
|
||||
self.fd
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoRawFd for OwnedFd {
|
||||
#[inline]
|
||||
fn into_raw_fd(self) -> RawFd {
|
||||
let fd = self.fd;
|
||||
forget(self);
|
||||
fd
|
||||
}
|
||||
}
|
||||
|
||||
impl FromRawFd for OwnedFd {
|
||||
/// Constructs a new instance of `Self` from the given raw file descriptor.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The resource pointed to by `fd` must be open and suitable for assuming
|
||||
/// ownership. The resource must not require any cleanup other than `close`.
|
||||
#[inline]
|
||||
unsafe fn from_raw_fd(fd: RawFd) -> Self {
|
||||
assert_ne!(fd, -1 as RawFd);
|
||||
// SAFETY: we just asserted that the value is in the valid range and
|
||||
// isn't `-1` (the only value bigger than `0xFF_FF_FF_FE` unsigned)
|
||||
unsafe { Self { fd } }
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for OwnedFd {
|
||||
#[inline]
|
||||
fn drop(&mut self) {
|
||||
unsafe { sys::net::netc::close(self.fd) };
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for BorrowedFd<'_> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("BorrowedFd").field("fd", &self.fd).finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for OwnedFd {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("OwnedFd").field("fd", &self.fd).finish()
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! impl_is_terminal {
|
||||
($($t:ty),*$(,)?) => {$(
|
||||
#[unstable(feature = "sealed", issue = "none")]
|
||||
impl crate::sealed::Sealed for $t {}
|
||||
|
||||
#[stable(feature = "is_terminal", since = "1.70.0")]
|
||||
impl crate::io::IsTerminal for $t {
|
||||
#[inline]
|
||||
fn is_terminal(&self) -> bool {
|
||||
crate::sys::io::is_terminal(self)
|
||||
}
|
||||
}
|
||||
)*}
|
||||
}
|
||||
|
||||
impl_is_terminal!(BorrowedFd<'_>, OwnedFd);
|
||||
|
||||
/// A trait to borrow the SOLID Sockets file descriptor from an underlying
|
||||
/// object.
|
||||
pub trait AsFd {
|
||||
/// Borrows the file descriptor.
|
||||
fn as_fd(&self) -> BorrowedFd<'_>;
|
||||
}
|
||||
|
||||
impl<T: AsFd> AsFd for &T {
|
||||
#[inline]
|
||||
fn as_fd(&self) -> BorrowedFd<'_> {
|
||||
T::as_fd(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: AsFd> AsFd for &mut T {
|
||||
#[inline]
|
||||
fn as_fd(&self) -> BorrowedFd<'_> {
|
||||
T::as_fd(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl AsFd for BorrowedFd<'_> {
|
||||
#[inline]
|
||||
fn as_fd(&self) -> BorrowedFd<'_> {
|
||||
*self
|
||||
}
|
||||
}
|
||||
|
||||
impl AsFd for OwnedFd {
|
||||
#[inline]
|
||||
fn as_fd(&self) -> BorrowedFd<'_> {
|
||||
// Safety: `OwnedFd` and `BorrowedFd` have the same validity
|
||||
// invariants, and the `BorrowedFd` is bounded by the lifetime
|
||||
// of `&self`.
|
||||
unsafe { BorrowedFd::borrow_raw(self.as_raw_fd()) }
|
||||
}
|
||||
}
|
||||
|
||||
/// A trait to extract the raw SOLID Sockets file descriptor from an underlying
|
||||
/// object.
|
||||
pub trait AsRawFd {
|
||||
|
|
Loading…
Reference in New Issue