Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 2739397

Browse files
committedAug 21, 2021
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]: rust-lang/rust#87329
1 parent 5f68afb commit 2739397

13 files changed

+803
-619
lines changed
 

‎.github/workflows/main.yml

+27
Original file line numberDiff line numberDiff line change
@@ -47,3 +47,30 @@ jobs:
4747
with:
4848
toolchain: ${{ matrix.rust }}
4949
- run: cargo test --workspace --all-features
50+
51+
test_use_std:
52+
name: Test with std's types and traits
53+
runs-on: ${{ matrix.os }}
54+
strategy:
55+
matrix:
56+
build: [ubuntu-nightly, windows-nightly]
57+
include:
58+
- build: ubuntu-nightly
59+
os: ubuntu-latest
60+
rust: nightly
61+
- build: windows-nightly
62+
os: windows-latest
63+
rust: nightly
64+
65+
env:
66+
RUSTFLAGS: --cfg io_lifetimes_use_std
67+
RUSTDOCFLAGS: --cfg io_lifetimes_use_std
68+
69+
steps:
70+
- uses: actions/checkout@v2
71+
with:
72+
submodules: true
73+
- uses: ./.github/actions/install-rust
74+
with:
75+
toolchain: ${{ matrix.rust }}
76+
- run: cargo test --workspace --all-features

‎README.md

+26
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,32 @@ is what motivates having `BorrowedFd` instead of just using `&OwnedFd`.
9999
Note the use of `Option<OwnedFd>` as the return value of `open`, representing
100100
the fact that it can either succeed or fail.
101101

102+
## I/O Safety in Rust Nightly
103+
104+
The I/O Safety
105+
[implementation PR](https://github.com/rust-lang/rust/pull/87329) has now
106+
landed and is available on Rust Nightly. It can be used directly, or through
107+
io-lifetimes: when `io_lifetimes_use_std` mode is enabled, such as by setting
108+
`RUSTFLAGS=--cfg=io_lifetimes_use_std`, io-lifetimes uses the std's `OwnedFd`,
109+
`BorrowedFd`, and `AsFd` instead of defining its own.
110+
111+
The code in `std` uses `From<OwnedFd>` and `Into<OwnedFd>` instead of `FromFd`
112+
and `IntoFd`. io-lifetimes is unable to provide impls for these for third-party
113+
types, so it continues to provide `FromFd` and `IntoFd` for now, with default
114+
impls that forward to `From<OwnedFd>` and `Into<OwnedFd>` in
115+
`io_lifetimes_use_std` mode.
116+
117+
io-lifetimes also includes several features which are not (yet?) in std,
118+
including the portability traits `AsFilelike`/`AsSocketlike`/etc., the
119+
`from_into_*` functions in the `From*` traits, and [views].
120+
121+
If you test a crate with the std I/O safety types and traits, or io-lifetimes
122+
in `io_lifetimes_use_std` mode, please post a note about it in the
123+
[I/O safety tracking issue] as an example of usage.
124+
125+
[I/O safety tracking issue]: https://github.com/rust-lang/rust/issues/87074
126+
[views]: https://docs.rs/io-lifetimes/*/io_lifetimes/views/index.html
127+
102128
## Prior Art
103129

104130
There are several similar crates: [fd](https://crates.io/crates/fd),

‎examples/easy-conversions.rs

+2
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
//! implementing `IntoFilelike` and `FromSocketlike` to types implementing
33
//! `FromFilelike` and `IntoSocketlike`, respectively.
44
5+
#![cfg_attr(io_lifetimes_use_std, feature(io_safety))]
6+
57
use io_lifetimes::FromFilelike;
68
use std::fs::File;
79
use std::io::{self, Read};

‎examples/flexible-apis.rs

+2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
//! The following uses the POSIX-ish `Fd` types; similar considerations
55
//! apply to the Windows and portable types.
66
7+
#![cfg_attr(io_lifetimes_use_std, feature(io_safety))]
8+
79
#[cfg(all(feature = "close", not(windows)))]
810
use io_lifetimes::{AsFd, BorrowedFd, IntoFd, OwnedFd};
911

‎examples/hello.rs

+1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
//! the io-lifetimes API.
33
44
#![cfg_attr(not(rustc_attrs), allow(unused_imports))]
5+
#![cfg_attr(io_lifetimes_use_std, feature(io_safety))]
56

67
#[cfg(feature = "close")]
78
use io_lifetimes::example_ffi::*;

‎examples/owning-wrapper.rs

+2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
//! A simple example implementing the main traits for a type.
22
3+
#![cfg_attr(io_lifetimes_use_std, feature(io_safety))]
4+
35
use io_lifetimes::OwnedFilelike;
46
#[cfg(not(windows))]
57
use io_lifetimes::{AsFd, BorrowedFd, FromFd, IntoFd, OwnedFd};

‎examples/portable-views.rs

+2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
//! io-lifetimes provides safe, convenient, and portable ways to temporarily
22
//! view an I/O resource as a `File`, `Socket`, or other types.
33
4+
#![cfg_attr(io_lifetimes_use_std, feature(io_safety))]
5+
46
use io_lifetimes::AsFilelike;
57
use std::fs::File;
68
use std::io::{self, stdout};

‎src/impls_std.rs

+624
Large diffs are not rendered by default.

‎src/lib.rs

+104-2
Original file line numberDiff line numberDiff line change
@@ -30,21 +30,117 @@
3030
#![deny(missing_docs)]
3131
#![cfg_attr(rustc_attrs, feature(rustc_attrs))]
3232
#![cfg_attr(target_os = "wasi", feature(wasi_ext))]
33+
#![cfg_attr(io_lifetimes_use_std, feature(io_safety))]
3334

3435
mod portability;
3536
mod traits;
37+
#[cfg(not(io_lifetimes_use_std))]
3638
mod types;
3739

40+
#[cfg(not(io_lifetimes_use_std))]
41+
mod impls_std;
42+
43+
#[cfg(not(io_lifetimes_use_std))]
44+
#[cfg(any(unix, target_os = "wasi"))]
45+
pub use traits::AsFd;
46+
#[cfg(not(io_lifetimes_use_std))]
47+
#[cfg(windows)]
48+
pub use traits::{AsHandle, AsSocket};
3849
#[cfg(any(unix, target_os = "wasi"))]
39-
pub use traits::{AsFd, FromFd, IntoFd};
50+
pub use traits::{FromFd, IntoFd};
4051
#[cfg(windows)]
41-
pub use traits::{AsHandle, AsSocket, FromHandle, FromSocket, IntoHandle, IntoSocket};
52+
pub use traits::{FromHandle, FromSocket, IntoHandle, IntoSocket};
4253

54+
#[cfg(not(io_lifetimes_use_std))]
4355
#[cfg(any(unix, target_os = "wasi"))]
4456
pub use types::{BorrowedFd, OwnedFd};
57+
#[cfg(not(io_lifetimes_use_std))]
4558
#[cfg(windows)]
4659
pub use types::{BorrowedHandle, BorrowedSocket, HandleOrInvalid, OwnedHandle, OwnedSocket};
4760

61+
#[cfg(io_lifetimes_use_std)]
62+
#[cfg(unix)]
63+
pub use std::os::unix::io::{AsFd, BorrowedFd, OwnedFd};
64+
#[cfg(io_lifetimes_use_std)]
65+
#[cfg(target_os = "wasi")]
66+
pub use std::os::wasi::io::{AsFd, BorrowedFd, OwnedFd};
67+
#[cfg(io_lifetimes_use_std)]
68+
#[cfg(windows)]
69+
pub use std::os::windows::io::{
70+
AsHandle, AsSocket, BorrowedHandle, BorrowedSocket, HandleOrInvalid, OwnedHandle, OwnedSocket,
71+
};
72+
73+
// io-lifetimes defined `FromFd`/`IntoFd` traits instead of just using
74+
// `From`/`Into` because that allowed it to implement them for foreign types,
75+
// including std types like File and TcpStream, and popular third-party types.
76+
//
77+
// std just uses `From`/`Into`, because it defines those traits itself so it
78+
// can implement them for std types itself, and std won't be implementing them
79+
// for third-party types. However, this means that until `OwnedFd` et al are
80+
// stabilized, there will be no impls for third-party traits.
81+
//
82+
// So we define `FromFd`/`IntoFd` traits, and implement them in terms of
83+
// `From`/`Into`,
84+
#[cfg(io_lifetimes_use_std)]
85+
#[cfg(any(unix, target_os = "wasi"))]
86+
impl<T: From<OwnedFd>> FromFd for T {
87+
#[inline]
88+
fn from_fd(owned_fd: OwnedFd) -> Self {
89+
owned_fd.into()
90+
}
91+
}
92+
#[cfg(io_lifetimes_use_std)]
93+
#[cfg(any(unix, target_os = "wasi"))]
94+
impl<T> IntoFd for T
95+
where
96+
OwnedFd: From<T>,
97+
{
98+
#[inline]
99+
fn into_fd(self) -> OwnedFd {
100+
self.into()
101+
}
102+
}
103+
104+
#[cfg(io_lifetimes_use_std)]
105+
#[cfg(windows)]
106+
impl<T: From<OwnedHandle>> FromHandle for T {
107+
#[inline]
108+
fn from_handle(owned_handle: OwnedHandle) -> Self {
109+
owned_handle.into()
110+
}
111+
}
112+
#[cfg(io_lifetimes_use_std)]
113+
#[cfg(windows)]
114+
impl<T> IntoHandle for T
115+
where
116+
OwnedHandle: From<T>,
117+
{
118+
#[inline]
119+
fn into_handle(self) -> OwnedHandle {
120+
self.into()
121+
}
122+
}
123+
124+
#[cfg(io_lifetimes_use_std)]
125+
#[cfg(windows)]
126+
impl<T: From<OwnedSocket>> FromSocket for T {
127+
#[inline]
128+
fn from_socket(owned_socket: OwnedSocket) -> Self {
129+
owned_socket.into()
130+
}
131+
}
132+
#[cfg(io_lifetimes_use_std)]
133+
#[cfg(windows)]
134+
impl<T> IntoSocket for T
135+
where
136+
OwnedSocket: From<T>,
137+
{
138+
#[inline]
139+
fn into_socket(self) -> OwnedSocket {
140+
self.into()
141+
}
142+
}
143+
48144
pub use portability::{
49145
AsFilelike, AsSocketlike, BorrowedFilelike, BorrowedSocketlike, FromFilelike, FromSocketlike,
50146
IntoFilelike, IntoSocketlike, OwnedFilelike, OwnedSocketlike,
@@ -56,15 +152,21 @@ pub mod views;
56152

57153
// Ideally, we'd want crates to implement our traits themselves. But for now,
58154
// while we're prototyping, we provide a few impls on foreign types.
155+
#[cfg(not(io_lifetimes_use_std))]
59156
#[cfg(feature = "async-std")]
60157
mod impls_async_std;
158+
#[cfg(not(io_lifetimes_use_std))]
61159
#[cfg(feature = "fs-err")]
62160
mod impls_fs_err;
161+
#[cfg(not(io_lifetimes_use_std))]
63162
#[cfg(feature = "mio")]
64163
mod impls_mio;
164+
#[cfg(not(io_lifetimes_use_std))]
65165
#[cfg(feature = "os_pipe")]
66166
mod impls_os_pipe;
167+
#[cfg(not(io_lifetimes_use_std))]
67168
#[cfg(feature = "socket2")]
68169
mod impls_socket2;
170+
#[cfg(not(io_lifetimes_use_std))]
69171
#[cfg(feature = "tokio")]
70172
mod impls_tokio;

‎src/traits.rs

+10-617
Large diffs are not rendered by default.

‎tests/api.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#![cfg_attr(target_os = "wasi", feature(wasi_ext))]
22
#![cfg(feature = "close")]
3+
#![cfg_attr(io_lifetimes_use_std, feature(io_safety))]
34

45
use io_lifetimes::{
56
AsFilelike, AsSocketlike, BorrowedFilelike, FromFilelike, FromSocketlike, IntoFilelike,

‎tests/ffi.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#![cfg_attr(not(rustc_attrs), allow(unused_imports))]
22
#![cfg(feature = "close")]
3+
#![cfg_attr(io_lifetimes_use_std, feature(io_safety))]
34

45
#[cfg(any(unix, windows))]
56
use io_lifetimes::example_ffi::*;

‎tests/niche-optimizations.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#![cfg_attr(not(rustc_attrs), allow(unused_imports))]
22
#![cfg_attr(target_os = "wasi", feature(wasi_ext))]
3+
#![cfg_attr(io_lifetimes_use_std, feature(io_safety))]
34

45
use std::mem::size_of;
56

0 commit comments

Comments
 (0)
Please sign in to comment.