about summary refs log tree commit diff
path: root/library/std/src/os/solid/io.rs
diff options
context:
space:
mode:
authorTomoaki Kawada <kawada@kmckk.co.jp>2023-08-23 14:46:28 +0900
committerTomoaki Kawada <kawada@kmckk.co.jp>2023-11-08 10:48:49 +0900
commit5d3aefe58d2148d277a1b28e29caed0e48858a9f (patch)
treece98291cfe0ec8765f8defb67554299a9f9f72a4 /library/std/src/os/solid/io.rs
parentff0b4b6091a75ad840035a991426c8bc9fbd93bb (diff)
downloadrust-5d3aefe58d2148d277a1b28e29caed0e48858a9f.tar.gz
rust-5d3aefe58d2148d277a1b28e29caed0e48858a9f.zip
kmc-solid: Add `std::os::solid::io::{BorrowedFd,OwnedFd,AsFd}`
It's mostly based on `std::os::fd::owned`.
Diffstat (limited to 'library/std/src/os/solid/io.rs')
-rw-r--r--library/std/src/os/solid/io.rs191
1 files changed, 191 insertions, 0 deletions
diff --git a/library/std/src/os/solid/io.rs b/library/std/src/os/solid/io.rs
index f82034663d4..ab17a01e411 100644
--- a/library/std/src/os/solid/io.rs
+++ b/library/std/src/os/solid/io.rs
@@ -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 {