From 76084c1451bec014f8e0140bbe9cc3de85016268 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Sat, 21 Aug 2021 10:09:47 -0700 Subject: [PATCH] Add an option to use the new I/O safety types and traits in std. I/O safety is now [in Rust Nightly]; add a mode to io-lifetimes to use std's types and traits. See the blurb in README.md for more details. [in Rust Nightly]: https://github.com/rust-lang/rust/pull/87329 --- .github/workflows/main.yml | 27 ++ README.md | 26 ++ examples/easy-conversions.rs | 2 + examples/flexible-apis.rs | 2 + examples/hello.rs | 1 + examples/owning-wrapper.rs | 2 + examples/portable-views.rs | 2 + src/impls_std.rs | 624 ++++++++++++++++++++++++++++++++++ src/lib.rs | 106 +++++- src/traits.rs | 635 +---------------------------------- tests/api.rs | 1 + tests/ffi.rs | 1 + tests/niche-optimizations.rs | 1 + 13 files changed, 811 insertions(+), 619 deletions(-) create mode 100644 src/impls_std.rs diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 9d083e6..a711caa 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -47,3 +47,30 @@ jobs: with: toolchain: ${{ matrix.rust }} - run: cargo test --workspace --all-features + + test_use_std: + name: Test with std's types and traits + runs-on: ${{ matrix.os }} + strategy: + matrix: + build: [ubuntu-nightly, windows-nightly] + include: + - build: ubuntu-nightly + os: ubuntu-latest + rust: nightly + - build: windows-nightly + os: windows-latest + rust: nightly + + env: + RUSTFLAGS: --cfg io_lifetimes_use_std + RUSTDOCFLAGS: --cfg io_lifetimes_use_std + + steps: + - uses: actions/checkout@v2 + with: + submodules: true + - uses: ./.github/actions/install-rust + with: + toolchain: ${{ matrix.rust }} + - run: cargo test --workspace --all-features diff --git a/README.md b/README.md index 93ab365..f1d1077 100644 --- a/README.md +++ b/README.md @@ -99,6 +99,32 @@ is what motivates having `BorrowedFd` instead of just using `&OwnedFd`. Note the use of `Option` as the return value of `open`, representing the fact that it can either succeed or fail. +## I/O Safety in Rust Nightly + +The I/O Safety +[implementation PR](https://github.com/rust-lang/rust/pull/87329) has now +landed and is available on Rust Nightly. It can be used directly, or through +io-lifetimes: when `io_lifetimes_use_std` mode is enabled, such as by setting +`RUSTFLAGS=--cfg=io_lifetimes_use_std`, io-lifetimes uses the std's `OwnedFd`, +`BorrowedFd`, and `AsFd` instead of defining its own. + +The code in `std` uses `From` and `Into` instead of `FromFd` +and `IntoFd`. io-lifetimes is unable to provide impls for these for third-party +types, so it continues to provide `FromFd` and `IntoFd` for now, with default +impls that forward to `From` and `Into` in +`io_lifetimes_use_std` mode. + +io-lifetimes also includes several features which are not (yet?) in std, +including the portability traits `AsFilelike`/`AsSocketlike`/etc., the +`from_into_*` functions in the `From*` traits, and [views]. + +If you test a crate with the std I/O safety types and traits, or io-lifetimes +in `io_lifetimes_use_std` mode, please post a note about it in the +[I/O safety tracking issue] as an example of usage. + +[I/O safety tracking issue]: https://github.com/rust-lang/rust/issues/87074 +[views]: https://docs.rs/io-lifetimes/*/io_lifetimes/views/index.html + ## Prior Art There are several similar crates: [fd](https://crates.io/crates/fd), diff --git a/examples/easy-conversions.rs b/examples/easy-conversions.rs index 56c7a24..87481c1 100644 --- a/examples/easy-conversions.rs +++ b/examples/easy-conversions.rs @@ -2,6 +2,8 @@ //! implementing `IntoFilelike` and `FromSocketlike` to types implementing //! `FromFilelike` and `IntoSocketlike`, respectively. +#![cfg_attr(io_lifetimes_use_std, feature(io_safety))] + use io_lifetimes::FromFilelike; use std::fs::File; use std::io::{self, Read}; diff --git a/examples/flexible-apis.rs b/examples/flexible-apis.rs index 3f54121..b3a51c5 100644 --- a/examples/flexible-apis.rs +++ b/examples/flexible-apis.rs @@ -4,6 +4,8 @@ //! The following uses the POSIX-ish `Fd` types; similar considerations //! apply to the Windows and portable types. +#![cfg_attr(io_lifetimes_use_std, feature(io_safety))] + #[cfg(all(feature = "close", not(windows)))] use io_lifetimes::{AsFd, BorrowedFd, IntoFd, OwnedFd}; diff --git a/examples/hello.rs b/examples/hello.rs index 6301431..dc698df 100644 --- a/examples/hello.rs +++ b/examples/hello.rs @@ -2,6 +2,7 @@ //! the io-lifetimes API. #![cfg_attr(not(rustc_attrs), allow(unused_imports))] +#![cfg_attr(io_lifetimes_use_std, feature(io_safety))] #[cfg(feature = "close")] use io_lifetimes::example_ffi::*; diff --git a/examples/owning-wrapper.rs b/examples/owning-wrapper.rs index 6dcf570..59f7687 100644 --- a/examples/owning-wrapper.rs +++ b/examples/owning-wrapper.rs @@ -1,5 +1,7 @@ //! A simple example implementing the main traits for a type. +#![cfg_attr(io_lifetimes_use_std, feature(io_safety))] + use io_lifetimes::OwnedFilelike; #[cfg(not(windows))] use io_lifetimes::{AsFd, BorrowedFd, FromFd, IntoFd, OwnedFd}; diff --git a/examples/portable-views.rs b/examples/portable-views.rs index 074cd99..410b4c2 100644 --- a/examples/portable-views.rs +++ b/examples/portable-views.rs @@ -1,6 +1,8 @@ //! io-lifetimes provides safe, convenient, and portable ways to temporarily //! view an I/O resource as a `File`, `Socket`, or other types. +#![cfg_attr(io_lifetimes_use_std, feature(io_safety))] + use io_lifetimes::AsFilelike; use std::fs::File; use std::io::{self, stdout}; diff --git a/src/impls_std.rs b/src/impls_std.rs new file mode 100644 index 0000000..308ae6d --- /dev/null +++ b/src/impls_std.rs @@ -0,0 +1,624 @@ +#[cfg(any(unix, target_os = "wasi"))] +use crate::{AsFd, FromFd, IntoFd}; +#[cfg(windows)] +use crate::{AsHandle, AsSocket, FromHandle, FromSocket, IntoHandle, IntoSocket}; +#[cfg(any(unix, target_os = "wasi"))] +use crate::{BorrowedFd, OwnedFd}; +#[cfg(windows)] +use crate::{BorrowedHandle, BorrowedSocket, HandleOrInvalid, OwnedHandle, OwnedSocket}; +#[cfg(unix)] +use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd}; +#[cfg(target_os = "wasi")] +use std::os::wasi::io::{AsRawFd, FromRawFd, IntoRawFd}; +#[cfg(windows)] +use std::os::windows::io::{ + AsRawHandle, AsRawSocket, FromRawHandle, FromRawSocket, IntoRawHandle, IntoRawSocket, +}; + +#[cfg(any(unix, target_os = "wasi"))] +impl AsFd for BorrowedFd<'_> { + #[inline] + fn as_fd(&self) -> BorrowedFd<'_> { + unsafe { BorrowedFd::borrow_raw_fd(self.as_raw_fd()) } + } +} + +#[cfg(windows)] +impl AsHandle for BorrowedHandle<'_> { + #[inline] + fn as_handle(&self) -> BorrowedHandle<'_> { + unsafe { BorrowedHandle::borrow_raw_handle(self.as_raw_handle()) } + } +} + +#[cfg(windows)] +impl AsSocket for BorrowedSocket<'_> { + #[inline] + fn as_socket(&self) -> BorrowedSocket<'_> { + unsafe { BorrowedSocket::borrow_raw_socket(self.as_raw_socket()) } + } +} + +#[cfg(any(unix, target_os = "wasi"))] +impl AsFd for OwnedFd { + #[inline] + fn as_fd(&self) -> BorrowedFd<'_> { + unsafe { BorrowedFd::borrow_raw_fd(self.as_raw_fd()) } + } +} + +#[cfg(windows)] +impl AsHandle for OwnedHandle { + #[inline] + fn as_handle(&self) -> BorrowedHandle<'_> { + unsafe { BorrowedHandle::borrow_raw_handle(self.as_raw_handle()) } + } +} + +#[cfg(windows)] +impl AsSocket for OwnedSocket { + #[inline] + fn as_socket(&self) -> BorrowedSocket<'_> { + unsafe { BorrowedSocket::borrow_raw_socket(self.as_raw_socket()) } + } +} + +#[cfg(any(unix, target_os = "wasi"))] +impl IntoFd for OwnedFd { + #[inline] + fn into_fd(self) -> OwnedFd { + unsafe { Self::from_raw_fd(self.into_raw_fd()) } + } +} + +#[cfg(windows)] +impl IntoHandle for OwnedHandle { + #[inline] + fn into_handle(self) -> OwnedHandle { + unsafe { Self::from_raw_handle(self.into_raw_handle()) } + } +} + +#[cfg(windows)] +impl IntoSocket for OwnedSocket { + #[inline] + fn into_socket(self) -> OwnedSocket { + unsafe { Self::from_raw_socket(self.into_raw_socket()) } + } +} + +#[cfg(any(unix, target_os = "wasi"))] +impl FromFd for OwnedFd { + #[inline] + fn from_fd(owned: OwnedFd) -> Self { + unsafe { Self::from_raw_fd(owned.into_raw_fd()) } + } +} + +#[cfg(windows)] +impl FromHandle for OwnedHandle { + #[inline] + fn from_handle(owned: OwnedHandle) -> Self { + unsafe { Self::from_raw_handle(owned.into_raw_handle()) } + } +} + +#[cfg(windows)] +impl FromSocket for OwnedSocket { + #[inline] + fn from_socket(owned: OwnedSocket) -> Self { + unsafe { Self::from_raw_socket(owned.into_raw_socket()) } + } +} + +#[cfg(windows)] +impl FromHandle for HandleOrInvalid { + #[inline] + fn from_handle(owned: OwnedHandle) -> Self { + unsafe { Self::from_raw_handle(owned.into_raw_handle()) } + } +} + +#[cfg(any(unix, target_os = "wasi"))] +impl AsFd for std::fs::File { + #[inline] + fn as_fd(&self) -> BorrowedFd<'_> { + unsafe { BorrowedFd::borrow_raw_fd(self.as_raw_fd()) } + } +} + +#[cfg(windows)] +impl AsHandle for std::fs::File { + #[inline] + fn as_handle(&self) -> BorrowedHandle<'_> { + unsafe { BorrowedHandle::borrow_raw_handle(self.as_raw_handle()) } + } +} + +#[cfg(any(unix, target_os = "wasi"))] +impl IntoFd for std::fs::File { + #[inline] + fn into_fd(self) -> OwnedFd { + unsafe { OwnedFd::from_raw_fd(self.into_raw_fd()) } + } +} + +#[cfg(windows)] +impl IntoHandle for std::fs::File { + #[inline] + fn into_handle(self) -> OwnedHandle { + unsafe { OwnedHandle::from_raw_handle(self.into_raw_handle()) } + } +} + +#[cfg(any(unix, target_os = "wasi"))] +impl FromFd for std::fs::File { + #[inline] + fn from_fd(owned: OwnedFd) -> Self { + unsafe { Self::from_raw_fd(owned.into_raw_fd()) } + } +} + +#[cfg(windows)] +impl FromHandle for std::fs::File { + #[inline] + fn from_handle(owned: OwnedHandle) -> Self { + unsafe { Self::from_raw_handle(owned.into_raw_handle()) } + } +} + +#[cfg(any(unix, target_os = "wasi"))] +impl AsFd for std::net::TcpStream { + #[inline] + fn as_fd(&self) -> BorrowedFd<'_> { + unsafe { BorrowedFd::borrow_raw_fd(self.as_raw_fd()) } + } +} + +#[cfg(windows)] +impl AsSocket for std::net::TcpStream { + #[inline] + fn as_socket(&self) -> BorrowedSocket<'_> { + unsafe { BorrowedSocket::borrow_raw_socket(self.as_raw_socket()) } + } +} + +#[cfg(any(unix, target_os = "wasi"))] +impl IntoFd for std::net::TcpStream { + #[inline] + fn into_fd(self) -> OwnedFd { + unsafe { OwnedFd::from_raw_fd(self.into_raw_fd()) } + } +} + +#[cfg(windows)] +impl IntoSocket for std::net::TcpStream { + #[inline] + fn into_socket(self) -> OwnedSocket { + unsafe { OwnedSocket::from_raw_socket(self.into_raw_socket()) } + } +} + +#[cfg(any(unix, target_os = "wasi"))] +impl FromFd for std::net::TcpStream { + #[inline] + fn from_fd(owned: OwnedFd) -> Self { + unsafe { Self::from_raw_fd(owned.into_raw_fd()) } + } +} + +#[cfg(windows)] +impl FromSocket for std::net::TcpStream { + #[inline] + fn from_socket(owned: OwnedSocket) -> Self { + unsafe { Self::from_raw_socket(owned.into_raw_socket()) } + } +} + +#[cfg(any(unix, target_os = "wasi"))] +impl AsFd for std::net::TcpListener { + #[inline] + fn as_fd(&self) -> BorrowedFd<'_> { + unsafe { BorrowedFd::borrow_raw_fd(self.as_raw_fd()) } + } +} + +#[cfg(windows)] +impl AsSocket for std::net::TcpListener { + #[inline] + fn as_socket(&self) -> BorrowedSocket<'_> { + unsafe { BorrowedSocket::borrow_raw_socket(self.as_raw_socket()) } + } +} + +#[cfg(any(unix, target_os = "wasi"))] +impl IntoFd for std::net::TcpListener { + #[inline] + fn into_fd(self) -> OwnedFd { + unsafe { OwnedFd::from_raw_fd(self.into_raw_fd()) } + } +} + +#[cfg(windows)] +impl IntoSocket for std::net::TcpListener { + #[inline] + fn into_socket(self) -> OwnedSocket { + unsafe { OwnedSocket::from_raw_socket(self.into_raw_socket()) } + } +} + +#[cfg(any(unix, target_os = "wasi"))] +impl FromFd for std::net::TcpListener { + #[inline] + fn from_fd(owned: OwnedFd) -> Self { + unsafe { Self::from_raw_fd(owned.into_raw_fd()) } + } +} + +#[cfg(windows)] +impl FromSocket for std::net::TcpListener { + #[inline] + fn from_socket(owned: OwnedSocket) -> Self { + unsafe { Self::from_raw_socket(owned.into_raw_socket()) } + } +} + +#[cfg(any(unix, target_os = "wasi"))] +impl AsFd for std::net::UdpSocket { + #[inline] + fn as_fd(&self) -> BorrowedFd<'_> { + unsafe { BorrowedFd::borrow_raw_fd(self.as_raw_fd()) } + } +} + +#[cfg(windows)] +impl AsSocket for std::net::UdpSocket { + #[inline] + fn as_socket(&self) -> BorrowedSocket { + unsafe { BorrowedSocket::borrow_raw_socket(self.as_raw_socket()) } + } +} + +#[cfg(any(unix, target_os = "wasi"))] +impl IntoFd for std::net::UdpSocket { + #[inline] + fn into_fd(self) -> OwnedFd { + unsafe { OwnedFd::from_raw_fd(self.into_raw_fd()) } + } +} + +#[cfg(windows)] +impl IntoSocket for std::net::UdpSocket { + #[inline] + fn into_socket(self) -> OwnedSocket { + unsafe { OwnedSocket::from_raw_socket(self.into_raw_socket()) } + } +} + +#[cfg(any(unix, target_os = "wasi"))] +impl FromFd for std::net::UdpSocket { + #[inline] + fn from_fd(owned: OwnedFd) -> Self { + unsafe { Self::from_raw_fd(owned.into_raw_fd()) } + } +} + +#[cfg(windows)] +impl FromSocket for std::net::UdpSocket { + #[inline] + fn from_socket(owned: OwnedSocket) -> Self { + unsafe { Self::from_raw_socket(owned.into_raw_socket()) } + } +} + +#[cfg(any(unix, target_os = "wasi"))] +impl AsFd for std::io::Stdin { + #[inline] + fn as_fd(&self) -> BorrowedFd<'_> { + unsafe { BorrowedFd::borrow_raw_fd(self.as_raw_fd()) } + } +} + +#[cfg(windows)] +impl AsHandle for std::io::Stdin { + #[inline] + fn as_handle(&self) -> BorrowedHandle<'_> { + unsafe { BorrowedHandle::borrow_raw_handle(self.as_raw_handle()) } + } +} + +#[cfg(any(unix, target_os = "wasi"))] +impl<'a> AsFd for std::io::StdinLock<'a> { + #[inline] + fn as_fd(&self) -> BorrowedFd<'_> { + unsafe { BorrowedFd::borrow_raw_fd(self.as_raw_fd()) } + } +} + +#[cfg(windows)] +impl<'a> AsHandle for std::io::StdinLock<'a> { + #[inline] + fn as_handle(&self) -> BorrowedHandle<'_> { + unsafe { BorrowedHandle::borrow_raw_handle(self.as_raw_handle()) } + } +} + +#[cfg(any(unix, target_os = "wasi"))] +impl AsFd for std::io::Stdout { + #[inline] + fn as_fd(&self) -> BorrowedFd<'_> { + unsafe { BorrowedFd::borrow_raw_fd(self.as_raw_fd()) } + } +} + +#[cfg(windows)] +impl AsHandle for std::io::Stdout { + #[inline] + fn as_handle(&self) -> BorrowedHandle<'_> { + unsafe { BorrowedHandle::borrow_raw_handle(self.as_raw_handle()) } + } +} + +#[cfg(any(unix, target_os = "wasi"))] +impl<'a> AsFd for std::io::StdoutLock<'a> { + #[inline] + fn as_fd(&self) -> BorrowedFd<'_> { + unsafe { BorrowedFd::borrow_raw_fd(self.as_raw_fd()) } + } +} + +#[cfg(windows)] +impl<'a> AsHandle for std::io::StdoutLock<'a> { + #[inline] + fn as_handle(&self) -> BorrowedHandle<'_> { + unsafe { BorrowedHandle::borrow_raw_handle(self.as_raw_handle()) } + } +} + +#[cfg(any(unix, target_os = "wasi"))] +impl AsFd for std::io::Stderr { + #[inline] + fn as_fd(&self) -> BorrowedFd<'_> { + unsafe { BorrowedFd::borrow_raw_fd(self.as_raw_fd()) } + } +} + +#[cfg(windows)] +impl AsHandle for std::io::Stderr { + #[inline] + fn as_handle(&self) -> BorrowedHandle<'_> { + unsafe { BorrowedHandle::borrow_raw_handle(self.as_raw_handle()) } + } +} + +#[cfg(any(unix, target_os = "wasi"))] +impl<'a> AsFd for std::io::StderrLock<'a> { + #[inline] + fn as_fd(&self) -> BorrowedFd<'_> { + unsafe { BorrowedFd::borrow_raw_fd(self.as_raw_fd()) } + } +} + +#[cfg(windows)] +impl<'a> AsHandle for std::io::StderrLock<'a> { + #[inline] + fn as_handle(&self) -> BorrowedHandle<'_> { + unsafe { BorrowedHandle::borrow_raw_handle(self.as_raw_handle()) } + } +} + +#[cfg(unix)] +impl AsFd for std::process::ChildStdin { + #[inline] + fn as_fd(&self) -> BorrowedFd<'_> { + unsafe { BorrowedFd::borrow_raw_fd(self.as_raw_fd()) } + } +} + +#[cfg(windows)] +impl AsHandle for std::process::ChildStdin { + #[inline] + fn as_handle(&self) -> BorrowedHandle<'_> { + unsafe { BorrowedHandle::borrow_raw_handle(self.as_raw_handle()) } + } +} + +#[cfg(unix)] +impl IntoFd for std::process::ChildStdin { + #[inline] + fn into_fd(self) -> OwnedFd { + unsafe { OwnedFd::from_raw_fd(self.into_raw_fd()) } + } +} + +#[cfg(windows)] +impl IntoHandle for std::process::ChildStdin { + #[inline] + fn into_handle(self) -> OwnedHandle { + unsafe { OwnedHandle::from_raw_handle(self.into_raw_handle()) } + } +} + +#[cfg(unix)] +impl AsFd for std::process::ChildStdout { + #[inline] + fn as_fd(&self) -> BorrowedFd<'_> { + unsafe { BorrowedFd::borrow_raw_fd(self.as_raw_fd()) } + } +} + +#[cfg(windows)] +impl AsHandle for std::process::ChildStdout { + #[inline] + fn as_handle(&self) -> BorrowedHandle<'_> { + unsafe { BorrowedHandle::borrow_raw_handle(self.as_raw_handle()) } + } +} + +#[cfg(unix)] +impl IntoFd for std::process::ChildStdout { + #[inline] + fn into_fd(self) -> OwnedFd { + unsafe { OwnedFd::from_raw_fd(self.into_raw_fd()) } + } +} + +#[cfg(windows)] +impl IntoHandle for std::process::ChildStdout { + #[inline] + fn into_handle(self) -> OwnedHandle { + unsafe { OwnedHandle::from_raw_handle(self.into_raw_handle()) } + } +} + +#[cfg(unix)] +impl AsFd for std::process::ChildStderr { + #[inline] + fn as_fd(&self) -> BorrowedFd<'_> { + unsafe { BorrowedFd::borrow_raw_fd(self.as_raw_fd()) } + } +} + +#[cfg(windows)] +impl AsHandle for std::process::ChildStderr { + #[inline] + fn as_handle(&self) -> BorrowedHandle<'_> { + unsafe { BorrowedHandle::borrow_raw_handle(self.as_raw_handle()) } + } +} + +#[cfg(unix)] +impl IntoFd for std::process::ChildStderr { + #[inline] + fn into_fd(self) -> OwnedFd { + unsafe { OwnedFd::from_raw_fd(self.into_raw_fd()) } + } +} + +#[cfg(windows)] +impl IntoHandle for std::process::ChildStderr { + #[inline] + fn into_handle(self) -> OwnedHandle { + unsafe { OwnedHandle::from_raw_handle(self.into_raw_handle()) } + } +} + +#[cfg(unix)] +impl FromFd for std::process::Stdio { + #[inline] + fn from_fd(owned: OwnedFd) -> Self { + unsafe { Self::from_raw_fd(owned.into_raw_fd()) } + } +} + +#[cfg(windows)] +impl FromHandle for std::process::Stdio { + #[inline] + fn from_handle(owned: OwnedHandle) -> Self { + unsafe { Self::from_raw_handle(owned.into_raw_handle()) } + } +} + +#[cfg(windows)] +impl AsHandle for std::process::Child { + #[inline] + fn as_handle(&self) -> BorrowedHandle<'_> { + unsafe { BorrowedHandle::borrow_raw_handle(self.as_raw_handle()) } + } +} + +#[cfg(windows)] +impl IntoHandle for std::process::Child { + #[inline] + fn into_handle(self) -> OwnedHandle { + unsafe { OwnedHandle::from_raw_handle(self.into_raw_handle()) } + } +} + +#[cfg(unix)] +impl AsFd for std::os::unix::net::UnixStream { + #[inline] + fn as_fd(&self) -> BorrowedFd<'_> { + unsafe { BorrowedFd::borrow_raw_fd(self.as_raw_fd()) } + } +} + +#[cfg(unix)] +impl IntoFd for std::os::unix::net::UnixStream { + #[inline] + fn into_fd(self) -> OwnedFd { + unsafe { OwnedFd::from_raw_fd(self.into_raw_fd()) } + } +} + +#[cfg(unix)] +impl FromFd for std::os::unix::net::UnixStream { + #[inline] + fn from_fd(owned: OwnedFd) -> Self { + unsafe { Self::from_raw_fd(owned.into_raw_fd()) } + } +} + +#[cfg(unix)] +impl AsFd for std::os::unix::net::UnixListener { + #[inline] + fn as_fd(&self) -> BorrowedFd<'_> { + unsafe { BorrowedFd::borrow_raw_fd(self.as_raw_fd()) } + } +} + +#[cfg(unix)] +impl IntoFd for std::os::unix::net::UnixListener { + #[inline] + fn into_fd(self) -> OwnedFd { + unsafe { OwnedFd::from_raw_fd(self.into_raw_fd()) } + } +} + +#[cfg(unix)] +impl FromFd for std::os::unix::net::UnixListener { + #[inline] + fn from_fd(owned: OwnedFd) -> Self { + unsafe { Self::from_raw_fd(owned.into_raw_fd()) } + } +} + +#[cfg(unix)] +impl AsFd for std::os::unix::net::UnixDatagram { + #[inline] + fn as_fd(&self) -> BorrowedFd<'_> { + unsafe { BorrowedFd::borrow_raw_fd(self.as_raw_fd()) } + } +} + +#[cfg(unix)] +impl IntoFd for std::os::unix::net::UnixDatagram { + #[inline] + fn into_fd(self) -> OwnedFd { + unsafe { OwnedFd::from_raw_fd(self.into_raw_fd()) } + } +} + +#[cfg(unix)] +impl FromFd for std::os::unix::net::UnixDatagram { + #[inline] + fn from_fd(owned: OwnedFd) -> Self { + unsafe { Self::from_raw_fd(owned.into_raw_fd()) } + } +} + +#[cfg(windows)] +impl AsHandle for std::thread::JoinHandle { + #[inline] + fn as_handle(&self) -> BorrowedHandle<'_> { + unsafe { BorrowedHandle::borrow_raw_handle(self.as_raw_handle()) } + } +} + +#[cfg(windows)] +impl IntoHandle for std::thread::JoinHandle { + #[inline] + fn into_handle(self) -> OwnedHandle { + unsafe { OwnedHandle::from_raw_handle(self.into_raw_handle()) } + } +} diff --git a/src/lib.rs b/src/lib.rs index 386ebdb..bec443f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -30,21 +30,117 @@ #![deny(missing_docs)] #![cfg_attr(rustc_attrs, feature(rustc_attrs))] #![cfg_attr(target_os = "wasi", feature(wasi_ext))] +#![cfg_attr(io_lifetimes_use_std, feature(io_safety))] mod portability; mod traits; +#[cfg(not(io_lifetimes_use_std))] mod types; +#[cfg(not(io_lifetimes_use_std))] +mod impls_std; + +#[cfg(not(io_lifetimes_use_std))] +#[cfg(any(unix, target_os = "wasi"))] +pub use traits::AsFd; +#[cfg(not(io_lifetimes_use_std))] +#[cfg(windows)] +pub use traits::{AsHandle, AsSocket}; #[cfg(any(unix, target_os = "wasi"))] -pub use traits::{AsFd, FromFd, IntoFd}; +pub use traits::{FromFd, IntoFd}; #[cfg(windows)] -pub use traits::{AsHandle, AsSocket, FromHandle, FromSocket, IntoHandle, IntoSocket}; +pub use traits::{FromHandle, FromSocket, IntoHandle, IntoSocket}; +#[cfg(not(io_lifetimes_use_std))] #[cfg(any(unix, target_os = "wasi"))] pub use types::{BorrowedFd, OwnedFd}; +#[cfg(not(io_lifetimes_use_std))] #[cfg(windows)] pub use types::{BorrowedHandle, BorrowedSocket, HandleOrInvalid, OwnedHandle, OwnedSocket}; +#[cfg(io_lifetimes_use_std)] +#[cfg(unix)] +pub use std::os::unix::io::{AsFd, BorrowedFd, OwnedFd}; +#[cfg(io_lifetimes_use_std)] +#[cfg(target_os = "wasi")] +pub use std::os::wasi::io::{AsFd, BorrowedFd, OwnedFd}; +#[cfg(io_lifetimes_use_std)] +#[cfg(windows)] +pub use std::os::windows::io::{ + AsHandle, AsSocket, BorrowedHandle, BorrowedSocket, HandleOrInvalid, OwnedHandle, OwnedSocket, +}; + +// io-lifetimes defined `FromFd`/`IntoFd` traits instead of just using +// `From`/`Into` because that allowed it to implement them for foreign types, +// including std types like File and TcpStream, and popular third-party types. +// +// std just uses `From`/`Into`, because it defines those traits itself so it +// can implement them for std types itself, and std won't be implementing them +// for third-party types. However, this means that until `OwnedFd` et al are +// stabilized, there will be no impls for third-party traits. +// +// So we define `FromFd`/`IntoFd` traits, and implement them in terms of +// `From`/`Into`, +#[cfg(io_lifetimes_use_std)] +#[cfg(any(unix, target_os = "wasi"))] +impl> FromFd for T { + #[inline] + fn from_fd(owned_fd: OwnedFd) -> Self { + owned_fd.into() + } +} +#[cfg(io_lifetimes_use_std)] +#[cfg(any(unix, target_os = "wasi"))] +impl IntoFd for T +where + OwnedFd: From, +{ + #[inline] + fn into_fd(self) -> OwnedFd { + self.into() + } +} + +#[cfg(io_lifetimes_use_std)] +#[cfg(windows)] +impl> FromHandle for T { + #[inline] + fn from_handle(owned_handle: OwnedHandle) -> Self { + owned_handle.into() + } +} +#[cfg(io_lifetimes_use_std)] +#[cfg(windows)] +impl IntoHandle for T +where + OwnedHandle: From, +{ + #[inline] + fn into_handle(self) -> OwnedHandle { + self.into() + } +} + +#[cfg(io_lifetimes_use_std)] +#[cfg(windows)] +impl> FromSocket for T { + #[inline] + fn from_socket(owned_socket: OwnedSocket) -> Self { + owned_socket.into() + } +} +#[cfg(io_lifetimes_use_std)] +#[cfg(windows)] +impl IntoSocket for T +where + OwnedSocket: From, +{ + #[inline] + fn into_socket(self) -> OwnedSocket { + self.into() + } +} + pub use portability::{ AsFilelike, AsSocketlike, BorrowedFilelike, BorrowedSocketlike, FromFilelike, FromSocketlike, IntoFilelike, IntoSocketlike, OwnedFilelike, OwnedSocketlike, @@ -56,15 +152,21 @@ pub mod views; // Ideally, we'd want crates to implement our traits themselves. But for now, // while we're prototyping, we provide a few impls on foreign types. +#[cfg(not(io_lifetimes_use_std))] #[cfg(feature = "async-std")] mod impls_async_std; +#[cfg(not(io_lifetimes_use_std))] #[cfg(feature = "fs-err")] mod impls_fs_err; +#[cfg(not(io_lifetimes_use_std))] #[cfg(feature = "mio")] mod impls_mio; +#[cfg(not(io_lifetimes_use_std))] #[cfg(feature = "os_pipe")] mod impls_os_pipe; +#[cfg(not(io_lifetimes_use_std))] #[cfg(feature = "socket2")] mod impls_socket2; +#[cfg(not(io_lifetimes_use_std))] #[cfg(feature = "tokio")] mod impls_tokio; diff --git a/src/traits.rs b/src/traits.rs index 8420160..e6464c8 100644 --- a/src/traits.rs +++ b/src/traits.rs @@ -1,21 +1,20 @@ +#[cfg(not(io_lifetimes_use_std))] #[cfg(any(unix, target_os = "wasi"))] -use crate::{BorrowedFd, OwnedFd}; +use crate::BorrowedFd; +#[cfg(any(unix, target_os = "wasi"))] +use crate::OwnedFd; +#[cfg(not(io_lifetimes_use_std))] #[cfg(windows)] -use crate::{BorrowedHandle, BorrowedSocket, HandleOrInvalid, OwnedHandle, OwnedSocket}; -#[cfg(unix)] -use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd}; -#[cfg(target_os = "wasi")] -use std::os::wasi::io::{AsRawFd, FromRawFd, IntoRawFd}; +use crate::{BorrowedHandle, BorrowedSocket}; #[cfg(windows)] -use std::os::windows::io::{ - AsRawHandle, AsRawSocket, FromRawHandle, FromRawSocket, IntoRawHandle, IntoRawSocket, -}; +use crate::{OwnedHandle, OwnedSocket}; /// A trait to borrow the file descriptor from an underlying object. /// /// This is only available on unix platforms and must be imported in order to /// call the method. Windows platforms have a corresponding `AsHandle` and /// `AsSocket` set of traits. +#[cfg(not(io_lifetimes_use_std))] #[cfg(any(unix, target_os = "wasi"))] pub trait AsFd { /// Borrows the file descriptor. @@ -23,6 +22,7 @@ pub trait AsFd { /// # Example /// /// ```rust,no_run + /// # #![cfg_attr(io_lifetimes_use_std, feature(io_safety))] /// use std::fs::File; /// # use std::io; /// use io_lifetimes::{AsFd, BorrowedFd}; @@ -35,6 +35,7 @@ pub trait AsFd { } /// A trait to borrow the handle from an underlying object. +#[cfg(not(io_lifetimes_use_std))] #[cfg(windows)] pub trait AsHandle { /// Borrows the handle. @@ -42,6 +43,7 @@ pub trait AsHandle { /// # Example /// /// ```rust,no_run + /// # #![cfg_attr(io_lifetimes_use_std, feature(io_safety))] /// use std::fs::File; /// # use std::io; /// use io_lifetimes::{AsHandle, BorrowedHandle}; @@ -54,6 +56,7 @@ pub trait AsHandle { } /// A trait to borrow the socket from an underlying object. +#[cfg(not(io_lifetimes_use_std))] #[cfg(windows)] pub trait AsSocket { /// Borrows the socket. @@ -69,6 +72,7 @@ pub trait IntoFd { /// # Example /// /// ```rust,no_run + /// # #![cfg_attr(io_lifetimes_use_std, feature(io_safety))] /// use std::fs::File; /// # use std::io; /// use io_lifetimes::{IntoFd, OwnedFd}; @@ -89,6 +93,7 @@ pub trait IntoHandle { /// # Example /// /// ```rust,no_run + /// # #![cfg_attr(io_lifetimes_use_std, feature(io_safety))] /// use std::fs::File; /// # use std::io; /// use io_lifetimes::{IntoHandle, OwnedHandle}; @@ -117,6 +122,7 @@ pub trait FromFd { /// # Example /// /// ```rust,no_run + /// # #![cfg_attr(io_lifetimes_use_std, feature(io_safety))] /// use std::fs::File; /// # use std::io; /// use io_lifetimes::{FromFd, IntoFd, OwnedFd}; @@ -134,6 +140,7 @@ pub trait FromFd { /// # Example /// /// ```rust,no_run + /// # #![cfg_attr(io_lifetimes_use_std, feature(io_safety))] /// use std::fs::File; /// # use std::io; /// use io_lifetimes::{FromFd, IntoFd}; @@ -159,6 +166,7 @@ pub trait FromHandle { /// # Example /// /// ```rust,no_run + /// # #![cfg_attr(io_lifetimes_use_std, feature(io_safety))] /// use std::fs::File; /// # use std::io; /// use io_lifetimes::{FromHandle, IntoHandle, OwnedHandle}; @@ -176,6 +184,7 @@ pub trait FromHandle { /// # Example /// /// ```rust,no_run + /// # #![cfg_attr(io_lifetimes_use_std, feature(io_safety))] /// use std::fs::File; /// # use std::io; /// use io_lifetimes::{FromHandle, IntoHandle}; @@ -209,611 +218,3 @@ pub trait FromSocket { Self::from_socket(into_owned.into_socket()) } } - -#[cfg(any(unix, target_os = "wasi"))] -impl AsFd for BorrowedFd<'_> { - #[inline] - fn as_fd(&self) -> BorrowedFd<'_> { - unsafe { BorrowedFd::borrow_raw_fd(self.as_raw_fd()) } - } -} - -#[cfg(windows)] -impl AsHandle for BorrowedHandle<'_> { - #[inline] - fn as_handle(&self) -> BorrowedHandle<'_> { - unsafe { BorrowedHandle::borrow_raw_handle(self.as_raw_handle()) } - } -} - -#[cfg(windows)] -impl AsSocket for BorrowedSocket<'_> { - #[inline] - fn as_socket(&self) -> BorrowedSocket<'_> { - unsafe { BorrowedSocket::borrow_raw_socket(self.as_raw_socket()) } - } -} - -#[cfg(any(unix, target_os = "wasi"))] -impl AsFd for OwnedFd { - #[inline] - fn as_fd(&self) -> BorrowedFd<'_> { - unsafe { BorrowedFd::borrow_raw_fd(self.as_raw_fd()) } - } -} - -#[cfg(windows)] -impl AsHandle for OwnedHandle { - #[inline] - fn as_handle(&self) -> BorrowedHandle<'_> { - unsafe { BorrowedHandle::borrow_raw_handle(self.as_raw_handle()) } - } -} - -#[cfg(windows)] -impl AsSocket for OwnedSocket { - #[inline] - fn as_socket(&self) -> BorrowedSocket<'_> { - unsafe { BorrowedSocket::borrow_raw_socket(self.as_raw_socket()) } - } -} - -#[cfg(any(unix, target_os = "wasi"))] -impl IntoFd for OwnedFd { - #[inline] - fn into_fd(self) -> OwnedFd { - unsafe { Self::from_raw_fd(self.into_raw_fd()) } - } -} - -#[cfg(windows)] -impl IntoHandle for OwnedHandle { - #[inline] - fn into_handle(self) -> OwnedHandle { - unsafe { Self::from_raw_handle(self.into_raw_handle()) } - } -} - -#[cfg(windows)] -impl IntoSocket for OwnedSocket { - #[inline] - fn into_socket(self) -> OwnedSocket { - unsafe { Self::from_raw_socket(self.into_raw_socket()) } - } -} - -#[cfg(any(unix, target_os = "wasi"))] -impl FromFd for OwnedFd { - #[inline] - fn from_fd(owned: OwnedFd) -> Self { - unsafe { Self::from_raw_fd(owned.into_raw_fd()) } - } -} - -#[cfg(windows)] -impl FromHandle for OwnedHandle { - #[inline] - fn from_handle(owned: OwnedHandle) -> Self { - unsafe { Self::from_raw_handle(owned.into_raw_handle()) } - } -} - -#[cfg(windows)] -impl FromSocket for OwnedSocket { - #[inline] - fn from_socket(owned: OwnedSocket) -> Self { - unsafe { Self::from_raw_socket(owned.into_raw_socket()) } - } -} - -#[cfg(windows)] -impl FromHandle for HandleOrInvalid { - #[inline] - fn from_handle(owned: OwnedHandle) -> Self { - unsafe { Self::from_raw_handle(owned.into_raw_handle()) } - } -} - -#[cfg(any(unix, target_os = "wasi"))] -impl AsFd for std::fs::File { - #[inline] - fn as_fd(&self) -> BorrowedFd<'_> { - unsafe { BorrowedFd::borrow_raw_fd(self.as_raw_fd()) } - } -} - -#[cfg(windows)] -impl AsHandle for std::fs::File { - #[inline] - fn as_handle(&self) -> BorrowedHandle<'_> { - unsafe { BorrowedHandle::borrow_raw_handle(self.as_raw_handle()) } - } -} - -#[cfg(any(unix, target_os = "wasi"))] -impl IntoFd for std::fs::File { - #[inline] - fn into_fd(self) -> OwnedFd { - unsafe { OwnedFd::from_raw_fd(self.into_raw_fd()) } - } -} - -#[cfg(windows)] -impl IntoHandle for std::fs::File { - #[inline] - fn into_handle(self) -> OwnedHandle { - unsafe { OwnedHandle::from_raw_handle(self.into_raw_handle()) } - } -} - -#[cfg(any(unix, target_os = "wasi"))] -impl FromFd for std::fs::File { - #[inline] - fn from_fd(owned: OwnedFd) -> Self { - unsafe { Self::from_raw_fd(owned.into_raw_fd()) } - } -} - -#[cfg(windows)] -impl FromHandle for std::fs::File { - #[inline] - fn from_handle(owned: OwnedHandle) -> Self { - unsafe { Self::from_raw_handle(owned.into_raw_handle()) } - } -} - -#[cfg(any(unix, target_os = "wasi"))] -impl AsFd for std::net::TcpStream { - #[inline] - fn as_fd(&self) -> BorrowedFd<'_> { - unsafe { BorrowedFd::borrow_raw_fd(self.as_raw_fd()) } - } -} - -#[cfg(windows)] -impl AsSocket for std::net::TcpStream { - #[inline] - fn as_socket(&self) -> BorrowedSocket<'_> { - unsafe { BorrowedSocket::borrow_raw_socket(self.as_raw_socket()) } - } -} - -#[cfg(any(unix, target_os = "wasi"))] -impl IntoFd for std::net::TcpStream { - #[inline] - fn into_fd(self) -> OwnedFd { - unsafe { OwnedFd::from_raw_fd(self.into_raw_fd()) } - } -} - -#[cfg(windows)] -impl IntoSocket for std::net::TcpStream { - #[inline] - fn into_socket(self) -> OwnedSocket { - unsafe { OwnedSocket::from_raw_socket(self.into_raw_socket()) } - } -} - -#[cfg(any(unix, target_os = "wasi"))] -impl FromFd for std::net::TcpStream { - #[inline] - fn from_fd(owned: OwnedFd) -> Self { - unsafe { Self::from_raw_fd(owned.into_raw_fd()) } - } -} - -#[cfg(windows)] -impl FromSocket for std::net::TcpStream { - #[inline] - fn from_socket(owned: OwnedSocket) -> Self { - unsafe { Self::from_raw_socket(owned.into_raw_socket()) } - } -} - -#[cfg(any(unix, target_os = "wasi"))] -impl AsFd for std::net::TcpListener { - #[inline] - fn as_fd(&self) -> BorrowedFd<'_> { - unsafe { BorrowedFd::borrow_raw_fd(self.as_raw_fd()) } - } -} - -#[cfg(windows)] -impl AsSocket for std::net::TcpListener { - #[inline] - fn as_socket(&self) -> BorrowedSocket<'_> { - unsafe { BorrowedSocket::borrow_raw_socket(self.as_raw_socket()) } - } -} - -#[cfg(any(unix, target_os = "wasi"))] -impl IntoFd for std::net::TcpListener { - #[inline] - fn into_fd(self) -> OwnedFd { - unsafe { OwnedFd::from_raw_fd(self.into_raw_fd()) } - } -} - -#[cfg(windows)] -impl IntoSocket for std::net::TcpListener { - #[inline] - fn into_socket(self) -> OwnedSocket { - unsafe { OwnedSocket::from_raw_socket(self.into_raw_socket()) } - } -} - -#[cfg(any(unix, target_os = "wasi"))] -impl FromFd for std::net::TcpListener { - #[inline] - fn from_fd(owned: OwnedFd) -> Self { - unsafe { Self::from_raw_fd(owned.into_raw_fd()) } - } -} - -#[cfg(windows)] -impl FromSocket for std::net::TcpListener { - #[inline] - fn from_socket(owned: OwnedSocket) -> Self { - unsafe { Self::from_raw_socket(owned.into_raw_socket()) } - } -} - -#[cfg(any(unix, target_os = "wasi"))] -impl AsFd for std::net::UdpSocket { - #[inline] - fn as_fd(&self) -> BorrowedFd<'_> { - unsafe { BorrowedFd::borrow_raw_fd(self.as_raw_fd()) } - } -} - -#[cfg(windows)] -impl AsSocket for std::net::UdpSocket { - #[inline] - fn as_socket(&self) -> BorrowedSocket { - unsafe { BorrowedSocket::borrow_raw_socket(self.as_raw_socket()) } - } -} - -#[cfg(any(unix, target_os = "wasi"))] -impl IntoFd for std::net::UdpSocket { - #[inline] - fn into_fd(self) -> OwnedFd { - unsafe { OwnedFd::from_raw_fd(self.into_raw_fd()) } - } -} - -#[cfg(windows)] -impl IntoSocket for std::net::UdpSocket { - #[inline] - fn into_socket(self) -> OwnedSocket { - unsafe { OwnedSocket::from_raw_socket(self.into_raw_socket()) } - } -} - -#[cfg(any(unix, target_os = "wasi"))] -impl FromFd for std::net::UdpSocket { - #[inline] - fn from_fd(owned: OwnedFd) -> Self { - unsafe { Self::from_raw_fd(owned.into_raw_fd()) } - } -} - -#[cfg(windows)] -impl FromSocket for std::net::UdpSocket { - #[inline] - fn from_socket(owned: OwnedSocket) -> Self { - unsafe { Self::from_raw_socket(owned.into_raw_socket()) } - } -} - -#[cfg(any(unix, target_os = "wasi"))] -impl AsFd for std::io::Stdin { - #[inline] - fn as_fd(&self) -> BorrowedFd<'_> { - unsafe { BorrowedFd::borrow_raw_fd(self.as_raw_fd()) } - } -} - -#[cfg(windows)] -impl AsHandle for std::io::Stdin { - #[inline] - fn as_handle(&self) -> BorrowedHandle<'_> { - unsafe { BorrowedHandle::borrow_raw_handle(self.as_raw_handle()) } - } -} - -#[cfg(any(unix, target_os = "wasi"))] -impl<'a> AsFd for std::io::StdinLock<'a> { - #[inline] - fn as_fd(&self) -> BorrowedFd<'_> { - unsafe { BorrowedFd::borrow_raw_fd(self.as_raw_fd()) } - } -} - -#[cfg(windows)] -impl<'a> AsHandle for std::io::StdinLock<'a> { - #[inline] - fn as_handle(&self) -> BorrowedHandle<'_> { - unsafe { BorrowedHandle::borrow_raw_handle(self.as_raw_handle()) } - } -} - -#[cfg(any(unix, target_os = "wasi"))] -impl AsFd for std::io::Stdout { - #[inline] - fn as_fd(&self) -> BorrowedFd<'_> { - unsafe { BorrowedFd::borrow_raw_fd(self.as_raw_fd()) } - } -} - -#[cfg(windows)] -impl AsHandle for std::io::Stdout { - #[inline] - fn as_handle(&self) -> BorrowedHandle<'_> { - unsafe { BorrowedHandle::borrow_raw_handle(self.as_raw_handle()) } - } -} - -#[cfg(any(unix, target_os = "wasi"))] -impl<'a> AsFd for std::io::StdoutLock<'a> { - #[inline] - fn as_fd(&self) -> BorrowedFd<'_> { - unsafe { BorrowedFd::borrow_raw_fd(self.as_raw_fd()) } - } -} - -#[cfg(windows)] -impl<'a> AsHandle for std::io::StdoutLock<'a> { - #[inline] - fn as_handle(&self) -> BorrowedHandle<'_> { - unsafe { BorrowedHandle::borrow_raw_handle(self.as_raw_handle()) } - } -} - -#[cfg(any(unix, target_os = "wasi"))] -impl AsFd for std::io::Stderr { - #[inline] - fn as_fd(&self) -> BorrowedFd<'_> { - unsafe { BorrowedFd::borrow_raw_fd(self.as_raw_fd()) } - } -} - -#[cfg(windows)] -impl AsHandle for std::io::Stderr { - #[inline] - fn as_handle(&self) -> BorrowedHandle<'_> { - unsafe { BorrowedHandle::borrow_raw_handle(self.as_raw_handle()) } - } -} - -#[cfg(any(unix, target_os = "wasi"))] -impl<'a> AsFd for std::io::StderrLock<'a> { - #[inline] - fn as_fd(&self) -> BorrowedFd<'_> { - unsafe { BorrowedFd::borrow_raw_fd(self.as_raw_fd()) } - } -} - -#[cfg(windows)] -impl<'a> AsHandle for std::io::StderrLock<'a> { - #[inline] - fn as_handle(&self) -> BorrowedHandle<'_> { - unsafe { BorrowedHandle::borrow_raw_handle(self.as_raw_handle()) } - } -} - -#[cfg(unix)] -impl AsFd for std::process::ChildStdin { - #[inline] - fn as_fd(&self) -> BorrowedFd<'_> { - unsafe { BorrowedFd::borrow_raw_fd(self.as_raw_fd()) } - } -} - -#[cfg(windows)] -impl AsHandle for std::process::ChildStdin { - #[inline] - fn as_handle(&self) -> BorrowedHandle<'_> { - unsafe { BorrowedHandle::borrow_raw_handle(self.as_raw_handle()) } - } -} - -#[cfg(unix)] -impl IntoFd for std::process::ChildStdin { - #[inline] - fn into_fd(self) -> OwnedFd { - unsafe { OwnedFd::from_raw_fd(self.into_raw_fd()) } - } -} - -#[cfg(windows)] -impl IntoHandle for std::process::ChildStdin { - #[inline] - fn into_handle(self) -> OwnedHandle { - unsafe { OwnedHandle::from_raw_handle(self.into_raw_handle()) } - } -} - -#[cfg(unix)] -impl AsFd for std::process::ChildStdout { - #[inline] - fn as_fd(&self) -> BorrowedFd<'_> { - unsafe { BorrowedFd::borrow_raw_fd(self.as_raw_fd()) } - } -} - -#[cfg(windows)] -impl AsHandle for std::process::ChildStdout { - #[inline] - fn as_handle(&self) -> BorrowedHandle<'_> { - unsafe { BorrowedHandle::borrow_raw_handle(self.as_raw_handle()) } - } -} - -#[cfg(unix)] -impl IntoFd for std::process::ChildStdout { - #[inline] - fn into_fd(self) -> OwnedFd { - unsafe { OwnedFd::from_raw_fd(self.into_raw_fd()) } - } -} - -#[cfg(windows)] -impl IntoHandle for std::process::ChildStdout { - #[inline] - fn into_handle(self) -> OwnedHandle { - unsafe { OwnedHandle::from_raw_handle(self.into_raw_handle()) } - } -} - -#[cfg(unix)] -impl AsFd for std::process::ChildStderr { - #[inline] - fn as_fd(&self) -> BorrowedFd<'_> { - unsafe { BorrowedFd::borrow_raw_fd(self.as_raw_fd()) } - } -} - -#[cfg(windows)] -impl AsHandle for std::process::ChildStderr { - #[inline] - fn as_handle(&self) -> BorrowedHandle<'_> { - unsafe { BorrowedHandle::borrow_raw_handle(self.as_raw_handle()) } - } -} - -#[cfg(unix)] -impl IntoFd for std::process::ChildStderr { - #[inline] - fn into_fd(self) -> OwnedFd { - unsafe { OwnedFd::from_raw_fd(self.into_raw_fd()) } - } -} - -#[cfg(windows)] -impl IntoHandle for std::process::ChildStderr { - #[inline] - fn into_handle(self) -> OwnedHandle { - unsafe { OwnedHandle::from_raw_handle(self.into_raw_handle()) } - } -} - -#[cfg(unix)] -impl FromFd for std::process::Stdio { - #[inline] - fn from_fd(owned: OwnedFd) -> Self { - unsafe { Self::from_raw_fd(owned.into_raw_fd()) } - } -} - -#[cfg(windows)] -impl FromHandle for std::process::Stdio { - #[inline] - fn from_handle(owned: OwnedHandle) -> Self { - unsafe { Self::from_raw_handle(owned.into_raw_handle()) } - } -} - -#[cfg(windows)] -impl AsHandle for std::process::Child { - #[inline] - fn as_handle(&self) -> BorrowedHandle<'_> { - unsafe { BorrowedHandle::borrow_raw_handle(self.as_raw_handle()) } - } -} - -#[cfg(windows)] -impl IntoHandle for std::process::Child { - #[inline] - fn into_handle(self) -> OwnedHandle { - unsafe { OwnedHandle::from_raw_handle(self.into_raw_handle()) } - } -} - -#[cfg(unix)] -impl AsFd for std::os::unix::net::UnixStream { - #[inline] - fn as_fd(&self) -> BorrowedFd<'_> { - unsafe { BorrowedFd::borrow_raw_fd(self.as_raw_fd()) } - } -} - -#[cfg(unix)] -impl IntoFd for std::os::unix::net::UnixStream { - #[inline] - fn into_fd(self) -> OwnedFd { - unsafe { OwnedFd::from_raw_fd(self.into_raw_fd()) } - } -} - -#[cfg(unix)] -impl FromFd for std::os::unix::net::UnixStream { - #[inline] - fn from_fd(owned: OwnedFd) -> Self { - unsafe { Self::from_raw_fd(owned.into_raw_fd()) } - } -} - -#[cfg(unix)] -impl AsFd for std::os::unix::net::UnixListener { - #[inline] - fn as_fd(&self) -> BorrowedFd<'_> { - unsafe { BorrowedFd::borrow_raw_fd(self.as_raw_fd()) } - } -} - -#[cfg(unix)] -impl IntoFd for std::os::unix::net::UnixListener { - #[inline] - fn into_fd(self) -> OwnedFd { - unsafe { OwnedFd::from_raw_fd(self.into_raw_fd()) } - } -} - -#[cfg(unix)] -impl FromFd for std::os::unix::net::UnixListener { - #[inline] - fn from_fd(owned: OwnedFd) -> Self { - unsafe { Self::from_raw_fd(owned.into_raw_fd()) } - } -} - -#[cfg(unix)] -impl AsFd for std::os::unix::net::UnixDatagram { - #[inline] - fn as_fd(&self) -> BorrowedFd<'_> { - unsafe { BorrowedFd::borrow_raw_fd(self.as_raw_fd()) } - } -} - -#[cfg(unix)] -impl IntoFd for std::os::unix::net::UnixDatagram { - #[inline] - fn into_fd(self) -> OwnedFd { - unsafe { OwnedFd::from_raw_fd(self.into_raw_fd()) } - } -} - -#[cfg(unix)] -impl FromFd for std::os::unix::net::UnixDatagram { - #[inline] - fn from_fd(owned: OwnedFd) -> Self { - unsafe { Self::from_raw_fd(owned.into_raw_fd()) } - } -} - -#[cfg(windows)] -impl AsHandle for std::thread::JoinHandle { - #[inline] - fn as_handle(&self) -> BorrowedHandle<'_> { - unsafe { BorrowedHandle::borrow_raw_handle(self.as_raw_handle()) } - } -} - -#[cfg(windows)] -impl IntoHandle for std::thread::JoinHandle { - #[inline] - fn into_handle(self) -> OwnedHandle { - unsafe { OwnedHandle::from_raw_handle(self.into_raw_handle()) } - } -} diff --git a/tests/api.rs b/tests/api.rs index 5bb4fa5..7193511 100644 --- a/tests/api.rs +++ b/tests/api.rs @@ -1,5 +1,6 @@ #![cfg_attr(target_os = "wasi", feature(wasi_ext))] #![cfg(feature = "close")] +#![cfg_attr(io_lifetimes_use_std, feature(io_safety))] use io_lifetimes::{ AsFilelike, AsSocketlike, BorrowedFilelike, FromFilelike, FromSocketlike, IntoFilelike, diff --git a/tests/ffi.rs b/tests/ffi.rs index 9d5d600..8678f6c 100644 --- a/tests/ffi.rs +++ b/tests/ffi.rs @@ -1,5 +1,6 @@ #![cfg_attr(not(rustc_attrs), allow(unused_imports))] #![cfg(feature = "close")] +#![cfg_attr(io_lifetimes_use_std, feature(io_safety))] #[cfg(any(unix, windows))] use io_lifetimes::example_ffi::*; diff --git a/tests/niche-optimizations.rs b/tests/niche-optimizations.rs index 0199e11..4bf9956 100644 --- a/tests/niche-optimizations.rs +++ b/tests/niche-optimizations.rs @@ -1,5 +1,6 @@ #![cfg_attr(not(rustc_attrs), allow(unused_imports))] #![cfg_attr(target_os = "wasi", feature(wasi_ext))] +#![cfg_attr(io_lifetimes_use_std, feature(io_safety))] use std::mem::size_of;