Rollup merge of #82420 - sunfishcode:wasi-docs, r=alexcrichton

Enable API documentation for `std::os::wasi`.

This adds API documentation support for `std::os::wasi` modeled after
how `std::os::unix` works, so that WASI can be documented [here] along
with the other platforms.

[here]: https://doc.rust-lang.org/stable/std/os/index.html

Two changes of particular interest:

 - This changes the `AsRawFd` for `io::Stdin` for WASI to return
   `libc::STDIN_FILENO` instead of `sys::stdio::Stdin.as_raw_fd()` (and
   similar for `Stdout` and `Stderr`), which matches how the `unix`
   version works. `STDIN_FILENO` etc. may not always be explicitly
   reserved at the WASI level, but as long as we have Rust's `std` and
   `libc`, I think it's reasonable to guarantee that we'll always use
   `libc::STDIN_FILENO` for stdin.

 - This duplicates the `osstr2str` utility function, rather than
   trying to share it across all the configurations that need it.

r? ```@alexcrichton```
This commit is contained in:
Dylan DPC 2021-02-27 02:34:27 +01:00 committed by GitHub
commit f5b68a4444
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 91 additions and 29 deletions

View File

@ -3,7 +3,7 @@
#![stable(feature = "os", since = "1.0.0")] #![stable(feature = "os", since = "1.0.0")]
#![allow(missing_docs, nonstandard_style, missing_debug_implementations)] #![allow(missing_docs, nonstandard_style, missing_debug_implementations)]
// When documenting libstd we want to show unix/windows/linux modules as these are the "main // When documenting libstd we want to show unix/windows/linux/wasi modules as these are the "main
// modules" that are used across platforms, so all modules are enabled when `cfg(doc)` is set. // modules" that are used across platforms, so all modules are enabled when `cfg(doc)` is set.
// This should help show platform-specific functionality in a hopefully cross-platform way in the // This should help show platform-specific functionality in a hopefully cross-platform way in the
// documentation. // documentation.
@ -22,6 +22,9 @@ pub use crate::sys::windows_ext as windows;
#[doc(cfg(target_os = "linux"))] #[doc(cfg(target_os = "linux"))]
pub mod linux; pub mod linux;
#[cfg(doc)]
pub use crate::sys::wasi_ext as wasi;
// If we're not documenting libstd then we just expose the main modules as we otherwise would. // If we're not documenting libstd then we just expose the main modules as we otherwise would.
#[cfg(not(doc))] #[cfg(not(doc))]
@ -38,6 +41,10 @@ pub use crate::sys::ext as windows;
#[cfg(any(target_os = "linux", target_os = "l4re"))] #[cfg(any(target_os = "linux", target_os = "l4re"))]
pub mod linux; pub mod linux;
#[cfg(not(doc))]
#[cfg(target_os = "wasi")]
pub mod wasi;
#[cfg(target_os = "android")] #[cfg(target_os = "android")]
pub mod android; pub mod android;
#[cfg(target_os = "dragonfly")] #[cfg(target_os = "dragonfly")]
@ -68,7 +75,5 @@ pub mod redox;
pub mod solaris; pub mod solaris;
#[cfg(target_os = "vxworks")] #[cfg(target_os = "vxworks")]
pub mod vxworks; pub mod vxworks;
#[cfg(target_os = "wasi")]
pub mod wasi;
pub mod raw; pub mod raw;

View File

@ -61,9 +61,9 @@ cfg_if::cfg_if! {
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub use self::ext as unix_ext; pub use self::ext as unix_ext;
} else if #[cfg(any(target_os = "hermit", } else if #[cfg(any(target_os = "hermit",
target_arch = "wasm32", all(target_arch = "wasm32", not(target_os = "wasi")),
all(target_vendor = "fortanix", target_env = "sgx")))] { all(target_vendor = "fortanix", target_env = "sgx")))] {
// On wasm right now the module below doesn't compile // On non-WASI wasm right now the module below doesn't compile
// (missing things in `libc` which is empty) so just omit everything // (missing things in `libc` which is empty) so just omit everything
// with an empty module // with an empty module
#[unstable(issue = "none", feature = "std_internals")] #[unstable(issue = "none", feature = "std_internals")]
@ -85,9 +85,9 @@ cfg_if::cfg_if! {
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub use self::ext as windows_ext; pub use self::ext as windows_ext;
} else if #[cfg(any(target_os = "hermit", } else if #[cfg(any(target_os = "hermit",
target_arch = "wasm32", all(target_arch = "wasm32", not(target_os = "wasi")),
all(target_vendor = "fortanix", target_env = "sgx")))] { all(target_vendor = "fortanix", target_env = "sgx")))] {
// On wasm right now the shim below doesn't compile, so // On non-WASI wasm right now the shim below doesn't compile, so
// just omit it // just omit it
#[unstable(issue = "none", feature = "std_internals")] #[unstable(issue = "none", feature = "std_internals")]
#[allow(missing_docs)] #[allow(missing_docs)]
@ -106,3 +106,25 @@ cfg_if::cfg_if! {
pub mod windows_ext; pub mod windows_ext;
} }
} }
#[cfg(doc)]
cfg_if::cfg_if! {
if #[cfg(target_os = "wasi")] {
// On WASI we'll document what's already available
#[stable(feature = "rust1", since = "1.0.0")]
pub use self::ext as wasi_ext;
} else if #[cfg(any(target_os = "hermit",
target_arch = "wasm32",
all(target_vendor = "fortanix", target_env = "sgx")))] {
// On non-WASI wasm right now the module below doesn't compile
// (missing things in `libc` which is empty) so just omit everything
// with an empty module
#[unstable(issue = "none", feature = "std_internals")]
#[allow(missing_docs)]
pub mod wasi_ext {}
} else {
// On other platforms like Windows document the bare bones of WASI
#[path = "wasi/ext/mod.rs"]
pub mod wasi_ext;
}
}

View File

@ -3,11 +3,14 @@
#![deny(unsafe_op_in_unsafe_fn)] #![deny(unsafe_op_in_unsafe_fn)]
#![unstable(feature = "wasi_ext", issue = "none")] #![unstable(feature = "wasi_ext", issue = "none")]
use crate::ffi::OsStr;
use crate::fs::{self, File, Metadata, OpenOptions}; use crate::fs::{self, File, Metadata, OpenOptions};
use crate::io::{self, IoSlice, IoSliceMut}; use crate::io::{self, IoSlice, IoSliceMut};
use crate::path::{Path, PathBuf}; use crate::path::{Path, PathBuf};
use crate::sys::fs::osstr2str;
use crate::sys_common::{AsInner, AsInnerMut, FromInner}; use crate::sys_common::{AsInner, AsInnerMut, FromInner};
// Used for `File::read` on intra-doc links
#[allow(unused_imports)]
use io::{Read, Write};
/// WASI-specific extensions to [`File`]. /// WASI-specific extensions to [`File`].
pub trait FileExt { pub trait FileExt {
@ -54,11 +57,11 @@ pub trait FileExt {
/// # Errors /// # Errors
/// ///
/// If this function encounters an error of the kind /// If this function encounters an error of the kind
/// [`ErrorKind::Interrupted`] then the error is ignored and the operation /// [`io::ErrorKind::Interrupted`] then the error is ignored and the operation
/// will continue. /// will continue.
/// ///
/// If this function encounters an "end of file" before completely filling /// If this function encounters an "end of file" before completely filling
/// the buffer, it returns an error of the kind [`ErrorKind::UnexpectedEof`]. /// the buffer, it returns an error of the kind [`io::ErrorKind::UnexpectedEof`].
/// The contents of `buf` are unspecified in this case. /// The contents of `buf` are unspecified in this case.
/// ///
/// If any other read error is encountered then this function immediately /// If any other read error is encountered then this function immediately
@ -131,16 +134,16 @@ pub trait FileExt {
/// The current file cursor is not affected by this function. /// The current file cursor is not affected by this function.
/// ///
/// This method will continuously call [`write_at`] until there is no more data /// This method will continuously call [`write_at`] until there is no more data
/// to be written or an error of non-[`ErrorKind::Interrupted`] kind is /// to be written or an error of non-[`io::ErrorKind::Interrupted`] kind is
/// returned. This method will not return until the entire buffer has been /// returned. This method will not return until the entire buffer has been
/// successfully written or such an error occurs. The first error that is /// successfully written or such an error occurs. The first error that is
/// not of [`ErrorKind::Interrupted`] kind generated from this method will be /// not of [`io::ErrorKind::Interrupted`] kind generated from this method will be
/// returned. /// returned.
/// ///
/// # Errors /// # Errors
/// ///
/// This function will return the first error of /// This function will return the first error of
/// non-[`ErrorKind::Interrupted`] kind that [`write_at`] returns. /// non-[`io::ErrorKind::Interrupted`] kind that [`write_at`] returns.
/// ///
/// [`write_at`]: FileExt::write_at /// [`write_at`]: FileExt::write_at
#[stable(feature = "rw_exact_all_at", since = "1.33.0")] #[stable(feature = "rw_exact_all_at", since = "1.33.0")]
@ -426,7 +429,7 @@ impl MetadataExt for fs::Metadata {
} }
} }
/// WASI-specific extensions for [`FileType`]. /// WASI-specific extensions for [`fs::FileType`].
/// ///
/// Adds support for special WASI file types such as block/character devices, /// Adds support for special WASI file types such as block/character devices,
/// pipes, and sockets. /// pipes, and sockets.
@ -517,8 +520,12 @@ pub fn symlink<P: AsRef<Path>, U: AsRef<Path>>(
/// Create a symbolic link. /// Create a symbolic link.
/// ///
/// This is a convenience API similar to [`std::os::unix::fs::symlink`] and /// This is a convenience API similar to `std::os::unix::fs::symlink` and
/// [`std::os::windows::fs::symlink_file`] and [`symlink_dir`](std::os::windows::fs::symlink_dir). /// `std::os::windows::fs::symlink_file` and `std::os::windows::fs::symlink_dir`.
pub fn symlink_path<P: AsRef<Path>, U: AsRef<Path>>(old_path: P, new_path: U) -> io::Result<()> { pub fn symlink_path<P: AsRef<Path>, U: AsRef<Path>>(old_path: P, new_path: U) -> io::Result<()> {
crate::sys::fs::symlink(old_path.as_ref(), new_path.as_ref()) crate::sys::fs::symlink(old_path.as_ref(), new_path.as_ref())
} }
fn osstr2str(f: &OsStr) -> io::Result<&str> {
f.to_str().ok_or_else(|| io::Error::new(io::ErrorKind::Other, "input must be utf-8"))
}

View File

@ -145,36 +145,36 @@ impl IntoRawFd for fs::File {
impl AsRawFd for io::Stdin { impl AsRawFd for io::Stdin {
fn as_raw_fd(&self) -> RawFd { fn as_raw_fd(&self) -> RawFd {
sys::stdio::Stdin.as_raw_fd() libc::STDIN_FILENO as RawFd
} }
} }
impl AsRawFd for io::Stdout { impl AsRawFd for io::Stdout {
fn as_raw_fd(&self) -> RawFd { fn as_raw_fd(&self) -> RawFd {
sys::stdio::Stdout.as_raw_fd() libc::STDOUT_FILENO as RawFd
} }
} }
impl AsRawFd for io::Stderr { impl AsRawFd for io::Stderr {
fn as_raw_fd(&self) -> RawFd { fn as_raw_fd(&self) -> RawFd {
sys::stdio::Stderr.as_raw_fd() libc::STDERR_FILENO as RawFd
} }
} }
impl<'a> AsRawFd for io::StdinLock<'a> { impl<'a> AsRawFd for io::StdinLock<'a> {
fn as_raw_fd(&self) -> RawFd { fn as_raw_fd(&self) -> RawFd {
sys::stdio::Stdin.as_raw_fd() libc::STDIN_FILENO as RawFd
} }
} }
impl<'a> AsRawFd for io::StdoutLock<'a> { impl<'a> AsRawFd for io::StdoutLock<'a> {
fn as_raw_fd(&self) -> RawFd { fn as_raw_fd(&self) -> RawFd {
sys::stdio::Stdout.as_raw_fd() libc::STDOUT_FILENO as RawFd
} }
} }
impl<'a> AsRawFd for io::StderrLock<'a> { impl<'a> AsRawFd for io::StderrLock<'a> {
fn as_raw_fd(&self) -> RawFd { fn as_raw_fd(&self) -> RawFd {
sys::stdio::Stderr.as_raw_fd() libc::STDERR_FILENO as RawFd
} }
} }

View File

@ -1,4 +1,32 @@
//! Platform-specific extensions to `std` for WASI.
//!
//! Provides access to platform-level information on WASI, and exposes
//! WASI-specific functions that would otherwise be inappropriate as
//! part of the core `std` library.
//!
//! It exposes more ways to deal with platform-specific strings (`OsStr`,
//! `OsString`), allows to set permissions more granularly, extract low-level
//! file descriptors from files and sockets, and has platform-specific helpers
//! for spawning processes.
//!
//! # Examples
//!
//! ```no_run
//! use std::fs::File;
//! use std::os::wasi::prelude::*;
//!
//! fn main() -> std::io::Result<()> {
//! let f = File::create("foo.txt")?;
//! let fd = f.as_raw_fd();
//!
//! // use fd with native WASI bindings
//!
//! Ok(())
//! }
//! ```
#![deny(unsafe_op_in_unsafe_fn)] #![deny(unsafe_op_in_unsafe_fn)]
#![doc(cfg(target_os = "wasi"))]
pub mod ffi; pub mod ffi;
pub mod fs; pub mod fs;
@ -11,14 +39,14 @@ pub mod io;
pub mod prelude { pub mod prelude {
#[doc(no_inline)] #[doc(no_inline)]
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub use crate::sys::ext::ffi::{OsStrExt, OsStringExt}; pub use super::ffi::{OsStrExt, OsStringExt};
#[doc(no_inline)] #[doc(no_inline)]
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub use crate::sys::ext::fs::FileTypeExt; pub use super::fs::FileTypeExt;
#[doc(no_inline)] #[doc(no_inline)]
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub use crate::sys::ext::fs::{DirEntryExt, FileExt, MetadataExt, OpenOptionsExt}; pub use super::fs::{DirEntryExt, FileExt, MetadataExt, OpenOptionsExt};
#[doc(no_inline)] #[doc(no_inline)]
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub use crate::sys::ext::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd}; pub use super::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
} }

View File

@ -1,5 +1,6 @@
#![deny(unsafe_op_in_unsafe_fn)] #![deny(unsafe_op_in_unsafe_fn)]
use super::fd::WasiFd;
use crate::ffi::{CStr, CString, OsStr, OsString}; use crate::ffi::{CStr, CString, OsStr, OsString};
use crate::fmt; use crate::fmt;
use crate::io::{self, IoSlice, IoSliceMut, SeekFrom}; use crate::io::{self, IoSlice, IoSliceMut, SeekFrom};
@ -9,7 +10,6 @@ use crate::os::wasi::ffi::{OsStrExt, OsStringExt};
use crate::path::{Path, PathBuf}; use crate::path::{Path, PathBuf};
use crate::ptr; use crate::ptr;
use crate::sync::Arc; use crate::sync::Arc;
use crate::sys::fd::WasiFd;
use crate::sys::time::SystemTime; use crate::sys::time::SystemTime;
use crate::sys::unsupported; use crate::sys::unsupported;
use crate::sys_common::FromInner; use crate::sys_common::FromInner;

View File

@ -1,10 +1,10 @@
#![deny(unsafe_op_in_unsafe_fn)] #![deny(unsafe_op_in_unsafe_fn)]
use super::fd::WasiFd;
use crate::convert::TryFrom; use crate::convert::TryFrom;
use crate::fmt; use crate::fmt;
use crate::io::{self, IoSlice, IoSliceMut}; use crate::io::{self, IoSlice, IoSliceMut};
use crate::net::{Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr}; use crate::net::{Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr};
use crate::sys::fd::WasiFd;
use crate::sys::{unsupported, Void}; use crate::sys::{unsupported, Void};
use crate::sys_common::FromInner; use crate::sys_common::FromInner;
use crate::time::Duration; use crate::time::Duration;

View File

@ -1,8 +1,8 @@
#![deny(unsafe_op_in_unsafe_fn)] #![deny(unsafe_op_in_unsafe_fn)]
use super::fd::WasiFd;
use crate::io::{self, IoSlice, IoSliceMut}; use crate::io::{self, IoSlice, IoSliceMut};
use crate::mem::ManuallyDrop; use crate::mem::ManuallyDrop;
use crate::sys::fd::WasiFd;
pub struct Stdin; pub struct Stdin;
pub struct Stdout; pub struct Stdout;