mirror of
https://github.com/async-rs/async-std.git
synced 2025-02-06 20:55:33 +00:00
Merge pull request #1036 from notgull/main
Implement I/O-safe traits on types
This commit is contained in:
commit
7c95bce535
15 changed files with 371 additions and 6 deletions
15
.github/workflows/ci.yml
vendored
15
.github/workflows/ci.yml
vendored
|
@ -108,6 +108,21 @@ jobs:
|
|||
with:
|
||||
command: check
|
||||
args: --all --features tokio02
|
||||
|
||||
check_io_safety_feature:
|
||||
name: Check io_safety feature
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest, windows-latest]
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: check io_safety
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: check
|
||||
args: --all --features io_safety
|
||||
|
||||
|
||||
cross:
|
||||
name: Cross compile
|
||||
|
|
|
@ -58,6 +58,7 @@ alloc = [
|
|||
tokio1 = ["async-global-executor/tokio"]
|
||||
tokio02 = ["async-global-executor/tokio02"]
|
||||
tokio03 = ["async-global-executor/tokio03"]
|
||||
io_safety = []
|
||||
|
||||
[dependencies]
|
||||
async-attributes = { version = "1.1.1", optional = true }
|
||||
|
|
|
@ -15,6 +15,8 @@ use crate::prelude::*;
|
|||
use crate::task::{spawn_blocking, Context, Poll, Waker};
|
||||
use crate::utils::Context as _;
|
||||
|
||||
const ARC_TRY_UNWRAP_EXPECT: &str = "cannot acquire ownership of the file handle after drop";
|
||||
|
||||
/// An open file on the filesystem.
|
||||
///
|
||||
/// Depending on what options the file was opened with, this type can be used for reading and/or
|
||||
|
@ -415,6 +417,15 @@ impl From<std::fs::File> for File {
|
|||
cfg_unix! {
|
||||
use crate::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
|
||||
|
||||
impl File {
|
||||
fn into_std_file(self) -> std::fs::File {
|
||||
let file = self.file.clone();
|
||||
drop(self);
|
||||
Arc::try_unwrap(file)
|
||||
.expect(ARC_TRY_UNWRAP_EXPECT)
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRawFd for File {
|
||||
fn as_raw_fd(&self) -> RawFd {
|
||||
self.file.as_raw_fd()
|
||||
|
@ -429,11 +440,29 @@ cfg_unix! {
|
|||
|
||||
impl IntoRawFd for File {
|
||||
fn into_raw_fd(self) -> RawFd {
|
||||
let file = self.file.clone();
|
||||
drop(self);
|
||||
Arc::try_unwrap(file)
|
||||
.expect("cannot acquire ownership of the file handle after drop")
|
||||
.into_raw_fd()
|
||||
self.into_std_file().into_raw_fd()
|
||||
}
|
||||
}
|
||||
|
||||
cfg_io_safety! {
|
||||
use crate::os::unix::io::{AsFd, BorrowedFd, OwnedFd};
|
||||
|
||||
impl AsFd for File {
|
||||
fn as_fd(&self) -> BorrowedFd<'_> {
|
||||
self.file.as_fd()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<OwnedFd> for File {
|
||||
fn from(fd: OwnedFd) -> Self {
|
||||
std::fs::File::from(fd).into()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<File> for OwnedFd {
|
||||
fn from(val: File) -> OwnedFd {
|
||||
self.into_std_file().into()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -458,10 +487,36 @@ cfg_windows! {
|
|||
let file = self.file.clone();
|
||||
drop(self);
|
||||
Arc::try_unwrap(file)
|
||||
.expect("cannot acquire ownership of the file handle after drop")
|
||||
.expect(ARC_TRY_UNWRAP_EXPECT)
|
||||
.into_raw_handle()
|
||||
}
|
||||
}
|
||||
|
||||
cfg_io_safety! {
|
||||
use crate::os::windows::io::{AsHandle, BorrowedHandle, OwnedHandle};
|
||||
|
||||
impl AsHandle for File {
|
||||
fn as_handle(&self) -> BorrowedHandle<'_> {
|
||||
self.file.as_handle()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<OwnedHandle> for File {
|
||||
fn from(handle: OwnedHandle) -> Self {
|
||||
std::fs::File::from(handle).into()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<File> for OwnedHandle {
|
||||
fn from(val: File) -> OwnedHandle {
|
||||
let file = val.file.clone();
|
||||
drop(val);
|
||||
Arc::try_unwrap(file)
|
||||
.expect(ARC_TRY_UNWRAP_EXPECT)
|
||||
.into()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// An async mutex with non-borrowing lock guards.
|
||||
|
|
|
@ -180,6 +180,16 @@ cfg_unix! {
|
|||
std::io::stderr().as_raw_fd()
|
||||
}
|
||||
}
|
||||
|
||||
cfg_io_safety! {
|
||||
use crate::os::unix::io::{AsFd, BorrowedFd};
|
||||
|
||||
impl AsFd for Stderr {
|
||||
fn as_fd(&self) -> BorrowedFd<'_> {
|
||||
std::io::stderr().as_fd()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cfg_windows! {
|
||||
|
@ -190,4 +200,14 @@ cfg_windows! {
|
|||
std::io::stderr().as_raw_handle()
|
||||
}
|
||||
}
|
||||
|
||||
cfg_io_safety! {
|
||||
use crate::os::unix::io::{AsHandle, BorrowedHandle};
|
||||
|
||||
impl AsHandle for Stderr {
|
||||
fn as_handle(&self) -> BorrowedHandle<'_> {
|
||||
std::io::stderr().as_handle()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -206,6 +206,16 @@ cfg_unix! {
|
|||
std::io::stdin().as_raw_fd()
|
||||
}
|
||||
}
|
||||
|
||||
cfg_io_safety! {
|
||||
use crate::os::unix::io::{AsFd, BorrowedFd};
|
||||
|
||||
impl AsFd for Stderr {
|
||||
fn as_fd(&self) -> BorrowedFd<'_> {
|
||||
std::io::stdin().as_fd()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cfg_windows! {
|
||||
|
@ -216,4 +226,14 @@ cfg_windows! {
|
|||
std::io::stdin().as_raw_handle()
|
||||
}
|
||||
}
|
||||
|
||||
cfg_io_safety! {
|
||||
use crate::os::unix::io::{AsFd, BorrowedFd};
|
||||
|
||||
impl AsFd for Stdin {
|
||||
fn as_fd(&self) -> BorrowedFd<'_> {
|
||||
std::io::stdin().as_fd()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -180,6 +180,16 @@ cfg_unix! {
|
|||
std::io::stdout().as_raw_fd()
|
||||
}
|
||||
}
|
||||
|
||||
cfg_io_safety! {
|
||||
use crate::os::unix::io::{AsFd, BorrowedFd};
|
||||
|
||||
impl AsFd for Stdout {
|
||||
fn as_fd(&self) -> BorrowedFd<'_> {
|
||||
std::io::stdout().as_fd()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cfg_windows! {
|
||||
|
@ -190,4 +200,14 @@ cfg_windows! {
|
|||
std::io::stdout().as_raw_handle()
|
||||
}
|
||||
}
|
||||
|
||||
cfg_io_safety! {
|
||||
use crate::os::unix::io::{AsHandle, BorrowedHandle};
|
||||
|
||||
impl AsHandle for Stdout {
|
||||
fn as_handle(&self) -> BorrowedHandle<'_> {
|
||||
std::io::stdout().as_handle()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -282,6 +282,28 @@ cfg_unix! {
|
|||
self.watcher.into_inner().unwrap().into_raw_fd()
|
||||
}
|
||||
}
|
||||
|
||||
cfg_io_safety! {
|
||||
use crate::os::unix::io::{AsFd, BorrowedFd, OwnedFd};
|
||||
|
||||
impl AsFd for TcpListener {
|
||||
fn as_fd(&self) -> BorrowedFd<'_> {
|
||||
self.watcher.get_ref().as_fd()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<OwnedFd> for TcpListener {
|
||||
fn from(fd: OwnedFd) -> TcpListener {
|
||||
std::net::TcpListener::from(fd).into()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<TcpListener> for OwnedFd {
|
||||
fn from(listener: TcpListener) -> OwnedFd {
|
||||
listener.watcher.into_inner().unwrap().into()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cfg_windows! {
|
||||
|
@ -306,4 +328,26 @@ cfg_windows! {
|
|||
self.watcher.into_inner().unwrap().into_raw_socket()
|
||||
}
|
||||
}
|
||||
|
||||
cfg_io_safety! {
|
||||
use crate::os::windows::io::{AsSocket, BorrowedSocket, OwnedSocket};
|
||||
|
||||
impl AsSocket for TcpListener {
|
||||
fn as_socket(&self) -> BorrowedSocket<'_> {
|
||||
self.watcher.get_ref().as_socket()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<OwnedSocket> for TcpListener {
|
||||
fn from(fd: OwnedSocket) -> TcpListener {
|
||||
std::net::TcpListener::from(fd).into()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<TcpListener> for OwnedSocket {
|
||||
fn from(listener: TcpListener) -> OwnedSocket {
|
||||
listener.watcher.into_inner().unwrap().into()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -416,6 +416,28 @@ cfg_unix! {
|
|||
self.as_raw_fd()
|
||||
}
|
||||
}
|
||||
|
||||
cfg_io_safety! {
|
||||
use crate::os::unix::io::{AsFd, BorrowedFd, OwnedFd};
|
||||
|
||||
impl AsFd for TcpStream {
|
||||
fn as_fd(&self) -> BorrowedFd<'_> {
|
||||
self.watcher.get_ref().as_fd()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<OwnedFd> for TcpStream {
|
||||
fn from(fd: OwnedFd) -> TcpStream {
|
||||
std::net::TcpStream::from(fd).into()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<TcpStream> for OwnedFd {
|
||||
fn from(stream: TcpStream) -> OwnedFd {
|
||||
stream.watcher.into_inner().unwrap().into()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cfg_windows! {
|
||||
|
@ -443,4 +465,26 @@ cfg_windows! {
|
|||
self.as_raw_socket()
|
||||
}
|
||||
}
|
||||
|
||||
cfg_io_safety! {
|
||||
use crate::os::windows::io::{AsSocket, BorrowedSocket, OwnedSocket};
|
||||
|
||||
impl AsSocket for TcpStream {
|
||||
fn as_socket(&self) -> BorrowedSocket<'_> {
|
||||
self.watcher.get_ref().as_socket()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<OwnedSocket> for TcpStream {
|
||||
fn from(fd: OwnedSocket) -> TcpStream {
|
||||
std::net::TcpListener::from(fd).into()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<TcpStream> for OwnedSocket {
|
||||
fn from(stream: TcpStream) -> OwnedSocket {
|
||||
stream.watcher.into_inner().unwrap().into()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -562,6 +562,28 @@ cfg_unix! {
|
|||
self.watcher.into_inner().unwrap().into_raw_fd()
|
||||
}
|
||||
}
|
||||
|
||||
cfg_io_safety! {
|
||||
use crate::os::unix::io::{AsFd, BorrowedFd, OwnedFd};
|
||||
|
||||
impl AsFd for UdpSocket {
|
||||
fn as_fd(&self) -> BorrowedFd<'_> {
|
||||
self.watcher.get_ref().as_fd()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<OwnedFd> for UdpSocket {
|
||||
fn from(fd: OwnedFd) -> UdpSocket {
|
||||
std::net::TcpStream::from(fd).into()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<UdpSocket> for OwnedFd {
|
||||
fn from(stream: UdpSocket) -> OwnedFd {
|
||||
stream.watcher.into_inner().unwrap().into()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cfg_windows! {
|
||||
|
@ -586,4 +608,26 @@ cfg_windows! {
|
|||
self.watcher.into_inner().unwrap().into_raw_socket()
|
||||
}
|
||||
}
|
||||
|
||||
cfg_io_safety! {
|
||||
use crate::os::windows::io::{AsSocket, BorrowedSocket, OwnedSocket};
|
||||
|
||||
impl AsSocket for UdpSocket {
|
||||
fn as_socket(&self) -> BorrowedSocket<'_> {
|
||||
self.watcher.get_ref().as_socket()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<OwnedSocket> for UdpSocket {
|
||||
fn from(fd: OwnedSocket) -> UdpSocket {
|
||||
std::net::TcpListener::from(fd).into()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<UdpSocket> for OwnedSocket {
|
||||
fn from(stream: UdpSocket) -> OwnedSocket {
|
||||
stream.watcher.into_inner().unwrap().into()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,10 @@
|
|||
|
||||
cfg_not_docs! {
|
||||
pub use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
|
||||
|
||||
cfg_io_safety! {
|
||||
pub use std::os::unix::io::{AsFd, BorrowedFd, OwnedFd};
|
||||
}
|
||||
}
|
||||
|
||||
cfg_docs! {
|
||||
|
@ -51,4 +55,9 @@ cfg_docs! {
|
|||
/// and must close the descriptor once it's no longer needed.
|
||||
fn into_raw_fd(self) -> RawFd;
|
||||
}
|
||||
|
||||
cfg_io_safety! {
|
||||
#[doc(inline)]
|
||||
pub use std::os::unix::io::{AsFd, BorrowedFd, OwnedFd};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -340,3 +340,25 @@ impl IntoRawFd for UnixDatagram {
|
|||
self.watcher.into_inner().unwrap().into_raw_fd()
|
||||
}
|
||||
}
|
||||
|
||||
cfg_io_safety! {
|
||||
use crate::os::unix::io::{AsFd, BorrowedFd, OwnedFd};
|
||||
|
||||
impl AsFd for UnixDatagram {
|
||||
fn as_fd(&self) -> BorrowedFd<'_> {
|
||||
self.watcher.get_ref().as_fd()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<OwnedFd> for UnixDatagram {
|
||||
fn from(fd: OwnedFd) -> UnixDatagram {
|
||||
std::net::TcpStream::from(fd).into()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<UnixDatagram> for OwnedFd {
|
||||
fn from(stream: UnixDatagram) -> OwnedFd {
|
||||
stream.watcher.into_inner().unwrap().into()
|
||||
}
|
||||
}
|
||||
}
|
|
@ -233,3 +233,25 @@ impl IntoRawFd for UnixListener {
|
|||
self.watcher.into_inner().unwrap().into_raw_fd()
|
||||
}
|
||||
}
|
||||
|
||||
cfg_io_safety! {
|
||||
use crate::os::unix::io::{AsFd, BorrowedFd, OwnedFd};
|
||||
|
||||
impl AsFd for UnixListener {
|
||||
fn as_fd(&self) -> BorrowedFd<'_> {
|
||||
self.watcher.get_ref().as_fd()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<OwnedFd> for UnixListener {
|
||||
fn from(fd: OwnedFd) -> UnixListener {
|
||||
std::net::TcpStream::from(fd).into()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<UnixListener> for OwnedFd {
|
||||
fn from(stream: UnixListener) -> OwnedFd {
|
||||
stream.watcher.into_inner().unwrap().into()
|
||||
}
|
||||
}
|
||||
}
|
|
@ -264,3 +264,25 @@ impl IntoRawFd for UnixStream {
|
|||
(*self.watcher).get_ref().try_clone().unwrap().into_raw_fd()
|
||||
}
|
||||
}
|
||||
|
||||
cfg_io_safety! {
|
||||
use crate::os::unix::io::{AsFd, BorrowedFd, OwnedFd};
|
||||
|
||||
impl AsFd for UnixStream {
|
||||
fn as_fd(&self) -> BorrowedFd<'_> {
|
||||
self.watcher.get_ref().as_fd()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<OwnedFd> for UnixStream {
|
||||
fn from(fd: OwnedFd) -> UnixStream {
|
||||
std::net::TcpStream::from(fd).into()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<UnixStream> for OwnedFd {
|
||||
fn from(stream: UnixStream) -> OwnedFd {
|
||||
stream.watcher.into_inner().unwrap().into()
|
||||
}
|
||||
}
|
||||
}
|
|
@ -5,6 +5,13 @@ cfg_not_docs! {
|
|||
AsRawHandle, FromRawHandle, IntoRawHandle, RawHandle,
|
||||
AsRawSocket, FromRawSocket, IntoRawSocket, RawSocket,
|
||||
};
|
||||
|
||||
cfg_io_safety! {
|
||||
pub use std::os::windows::io::{
|
||||
AsHandle, BorrowedHandle, OwnedHandle,
|
||||
AsSocket, BorrowedSocket, OwnedSocket,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
cfg_docs! {
|
||||
|
@ -75,4 +82,12 @@ cfg_docs! {
|
|||
/// it once it's no longer needed.
|
||||
fn into_raw_socket(self) -> RawSocket;
|
||||
}
|
||||
|
||||
cfg_io_safety! {
|
||||
#[doc(inline)]
|
||||
pub use std::os::windows::io::{
|
||||
AsHandle, BorrowedHandle, OwnedHandle,
|
||||
AsSocket, BorrowedSocket, OwnedSocket,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
12
src/utils.rs
12
src/utils.rs
|
@ -239,3 +239,15 @@ macro_rules! cfg_default {
|
|||
)*
|
||||
}
|
||||
}
|
||||
|
||||
/// Declares items that use I/O safety.
|
||||
#[allow(unused_macros)]
|
||||
#[doc(hidden)]
|
||||
macro_rules! cfg_io_safety {
|
||||
($($item:item)*) => {
|
||||
$(
|
||||
#[cfg(feature = "io-safety")]
|
||||
$item
|
||||
)*
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue