Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add an option to use the new I/O safety types and traits in std.
Browse files Browse the repository at this point in the history
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]: rust-lang/rust#87329
sunfishcode committed Aug 21, 2021
1 parent 5f68afb commit 2739397
Showing 13 changed files with 803 additions and 619 deletions.
27 changes: 27 additions & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
@@ -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
26 changes: 26 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -99,6 +99,32 @@ is what motivates having `BorrowedFd` instead of just using `&OwnedFd`.
Note the use of `Option<OwnedFd>` 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<OwnedFd>` and `Into<OwnedFd>` 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<OwnedFd>` and `Into<OwnedFd>` 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),
2 changes: 2 additions & 0 deletions examples/easy-conversions.rs
Original file line number Diff line number Diff line change
@@ -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};
2 changes: 2 additions & 0 deletions examples/flexible-apis.rs
Original file line number Diff line number Diff line change
@@ -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};

1 change: 1 addition & 0 deletions examples/hello.rs
Original file line number Diff line number Diff line change
@@ -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::*;
2 changes: 2 additions & 0 deletions examples/owning-wrapper.rs
Original file line number Diff line number Diff line change
@@ -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};
2 changes: 2 additions & 0 deletions examples/portable-views.rs
Original file line number Diff line number Diff line change
@@ -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};
624 changes: 624 additions & 0 deletions src/impls_std.rs

Large diffs are not rendered by default.

106 changes: 104 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -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<T: From<OwnedFd>> 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<T> IntoFd for T
where
OwnedFd: From<T>,
{
#[inline]
fn into_fd(self) -> OwnedFd {
self.into()
}
}

#[cfg(io_lifetimes_use_std)]
#[cfg(windows)]
impl<T: From<OwnedHandle>> FromHandle for T {
#[inline]
fn from_handle(owned_handle: OwnedHandle) -> Self {
owned_handle.into()
}
}
#[cfg(io_lifetimes_use_std)]
#[cfg(windows)]
impl<T> IntoHandle for T
where
OwnedHandle: From<T>,
{
#[inline]
fn into_handle(self) -> OwnedHandle {
self.into()
}
}

#[cfg(io_lifetimes_use_std)]
#[cfg(windows)]
impl<T: From<OwnedSocket>> FromSocket for T {
#[inline]
fn from_socket(owned_socket: OwnedSocket) -> Self {
owned_socket.into()
}
}
#[cfg(io_lifetimes_use_std)]
#[cfg(windows)]
impl<T> IntoSocket for T
where
OwnedSocket: From<T>,
{
#[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;
627 changes: 10 additions & 617 deletions src/traits.rs

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions tests/api.rs
Original file line number Diff line number Diff line change
@@ -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,
1 change: 1 addition & 0 deletions tests/ffi.rs
Original file line number Diff line number Diff line change
@@ -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::*;
1 change: 1 addition & 0 deletions tests/niche-optimizations.rs
Original file line number Diff line number Diff line change
@@ -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;

0 comments on commit 2739397

Please sign in to comment.