diff --git a/.travis.yml b/.travis.yml index 9664ed9ce..a554b0a00 100644 --- a/.travis.yml +++ b/.travis.yml @@ -32,8 +32,11 @@ matrix: - name: docs rust: nightly os: linux + before_script: + - test -x $HOME/.cargo/bin/cargo-deadlinks || ./ci/install-cargo-deadlinks.sh script: - cargo doc --features docs + - cargo deadlinks --check-http - name: book rust: nightly diff --git a/ci/install-cargo-deadlinks.sh b/ci/install-cargo-deadlinks.sh new file mode 100755 index 000000000..ea758092b --- /dev/null +++ b/ci/install-cargo-deadlinks.sh @@ -0,0 +1,19 @@ +set -euxo pipefail + +# Based on the Rust-Embedded WG's book CI +# https://github.com/rust-embedded/book/blob/master/ci/install.sh + +main() { + # Note - this will only accept releases tagged with v0.4.x + local tag=$(git ls-remote --tags --refs --exit-code \ + https://github.com/deadlinks/cargo-deadlinks \ + | cut -d/ -f3 \ + | grep -E '^0\.4\.[0-9]+$' \ + | sort --version-sort \ + | tail -n1) + + curl -LSfs https://japaric.github.io/trust/install.sh | \ + sh -s -- --git deadlinks/cargo-deadlinks --tag $tag +} + +main diff --git a/src/fs/mod.rs b/src/fs/mod.rs index 8d9833020..7140a6a74 100644 --- a/src/fs/mod.rs +++ b/src/fs/mod.rs @@ -27,7 +27,7 @@ pub use open_options::OpenOptions; pub use read_dir::ReadDir; #[doc(inline)] -pub use std::fs::{FileType, Metadata, Permissions}; +pub use std::fs::{FileType, Metadata}; pub use canonicalize::canonicalize; pub use copy::copy; @@ -68,3 +68,26 @@ mod rename; mod set_permissions; mod symlink_metadata; mod write; + +use cfg_if::cfg_if; + +cfg_if! { + if #[cfg(feature = "docs")] { + /// Representation of the various permissions on a file. + /// + /// This module only currently provides one bit of information, [`readonly`], + /// which is exposed on all currently supported platforms. Unix-specific + /// functionality, such as mode bits, is available through the + /// [`PermissionsExt`] trait. + /// + /// [`readonly`]: struct.Permissions.html#method.readonly + /// [`PermissionsExt`]: ../os/unix/fs/trait.PermissionsExt.html + #[derive(Clone, PartialEq, Eq, Debug)] + pub struct Permissions { + _private: () + } + } else { + #[doc(inline)] + pub use std::fs::Permissions; + } +} diff --git a/src/io/mod.rs b/src/io/mod.rs index fd4158782..0337d663a 100644 --- a/src/io/mod.rs +++ b/src/io/mod.rs @@ -21,7 +21,7 @@ //! ``` #[doc(inline)] -pub use std::io::{Error, ErrorKind, Result, SeekFrom}; +pub use std::io::SeekFrom; pub use buf_read::{BufRead, Lines}; pub use buf_reader::BufReader; @@ -48,3 +48,151 @@ mod stdin; mod stdout; mod timeout; mod write; + +use cfg_if::cfg_if; + +cfg_if! { + if #[cfg(feature = "docs")] { + /// The error type for I/O operations of the [`Read`], [`Write`], [`Seek`], and + /// associated traits. + /// + /// Errors mostly originate from the underlying OS, but custom instances of + /// `Error` can be created with crafted error messages and a particular value of + /// [`ErrorKind`]. + /// + /// [`Read`]: ../io/trait.Read.html + /// [`Write`]: ../io/trait.Write.html + /// [`Seek`]: ../io/trait.Seek.html + /// [`ErrorKind`]: enum.ErrorKind.html + pub struct Error { + _private: () + } + } else { + #[doc(inline)] + pub use std::io::Error; + } +} + +cfg_if! { + if #[cfg(feature = "docs")] { + /// A list specifying general categories of I/O error. + /// + /// This list is intended to grow over time and it is not recommended to + /// exhaustively match against it. + /// + /// It is used with the [`io::Error`] type. + /// + /// [`io::Error`]: struct.Error.html + #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] + pub enum ErrorKind { + /// An entity was not found, often a file. + NotFound, + /// The operation lacked the necessary privileges to complete. + PermissionDenied, + /// The connection was refused by the remote server. + ConnectionRefused, + /// The connection was reset by the remote server. + ConnectionReset, + /// The connection was aborted (terminated) by the remote server. + ConnectionAborted, + /// The network operation failed because it was not connected yet. + NotConnected, + /// A socket address could not be bound because the address is already in + /// use elsewhere. + AddrInUse, + /// A nonexistent interface was requested or the requested address was not + /// local. + AddrNotAvailable, + /// The operation failed because a pipe was closed. + BrokenPipe, + /// An entity already exists, often a file. + AlreadyExists, + /// The operation needs to block to complete, but the blocking operation was + /// requested to not occur. + WouldBlock, + /// A parameter was incorrect. + InvalidInput, + /// Data not valid for the operation were encountered. + /// + /// Unlike [`InvalidInput`], this typically means that the operation + /// parameters were valid, however the error was caused by malformed + /// input data. + /// + /// For example, a function that reads a file into a string will error with + /// `InvalidData` if the file's contents are not valid UTF-8. + /// + /// [`InvalidInput`]: #variant.InvalidInput + InvalidData, + /// The I/O operation's timeout expired, causing it to be canceled. + TimedOut, + /// An error returned when an operation could not be completed because a + /// call to [`write`] returned [`Ok(0)`]. + /// + /// This typically means that an operation could only succeed if it wrote a + /// particular number of bytes but only a smaller number of bytes could be + /// written. + /// + /// [`write`]: ../io/trait.Write.html#tymethod.write + /// [`Ok(0)`]: ../io/type.Result.html + WriteZero, + /// This operation was interrupted. + /// + /// Interrupted operations can typically be retried. + Interrupted, + /// Any I/O error not part of this list. + Other, + /// An error returned when an operation could not be completed because an + /// "end of file" was reached prematurely. + /// + /// This typically means that an operation could only succeed if it read a + /// particular number of bytes but only a smaller number of bytes could be + /// read. + UnexpectedEof, + } + } else { + #[doc(inline)] + pub use std::io::ErrorKind; + } +} + +cfg_if! { + if #[cfg(feature = "docs")] { + /// A specialized [`Result`] type for I/O + /// operations. + /// + /// This type is broadly used across [`std::io`] for any operation which may + /// produce an error. + /// + /// This typedef is generally used to avoid writing out [`io::Error`] directly and + /// is otherwise a direct mapping to [`Result`]. + /// + /// While usual Rust style is to import types directly, aliases of [`Result`] + /// often are not, to make it easier to distinguish between them. [`Result`] is + /// generally assumed to be [`std::result::Result`][`Result`], and so users of this alias + /// will generally use `io::Result` instead of shadowing the prelude's import + /// of [`std::result::Result`][`Result`]. + /// + /// [`std::io`]: ../io/index.html + /// [`io::Error`]: ../io/struct.Error.html + /// + /// # Examples + /// + /// A convenience function that bubbles an `io::Result` to its caller: + /// + /// ``` + /// use std::io; + /// + /// fn get_string() -> io::Result { + /// let mut buffer = String::new(); + /// + /// io::stdin().read_line(&mut buffer)?; + /// + /// Ok(buffer) + /// } + /// ``` + pub type Result = std::result::Result; + } else { + #[doc(inline)] + pub use std::io::Result; + } +} diff --git a/src/net/tcp/stream.rs b/src/net/tcp/stream.rs index b63b7f2e4..967dafee9 100644 --- a/src/net/tcp/stream.rs +++ b/src/net/tcp/stream.rs @@ -62,11 +62,9 @@ impl TcpStream { /// Creates a new TCP stream connected to the specified address. /// /// This method will create a new TCP socket and attempt to connect it to the `addr` - /// provided. The [returned future] will be resolved once the stream has successfully + /// provided. The returned future will be resolved once the stream has successfully /// connected, or it will return an error if one occurs. /// - /// [returned future]: struct.Connect.html - /// /// # Examples /// /// ```no_run diff --git a/src/os/unix/fs.rs b/src/os/unix/fs.rs index 16d7cab78..6374e396c 100644 --- a/src/os/unix/fs.rs +++ b/src/os/unix/fs.rs @@ -40,14 +40,25 @@ cfg_if! { /// `0o777`. fn mode(&mut self, mode: u32) -> &mut Self; } + } else { + #[doc(inline)] + pub use std::os::unix::fs::DirBuilderExt; + } +} +cfg_if! { + if #[cfg(feature = "docs")] { /// Unix-specific extension methods for `DirEntry`. pub trait DirEntryExt { /// Returns the underlying `d_ino` field in the contained `dirent` /// structure. fn ino(&self) -> u64; } + } +} +cfg_if! { + if #[cfg(feature = "docs")] { /// Unix-specific extensions to `OpenOptions`. pub trait OpenOptionsExt { /// Sets the mode bits that a new file will be created with. @@ -70,6 +81,68 @@ cfg_if! { } } else { #[doc(inline)] - pub use std::os::unix::fs::{DirBuilderExt, OpenOptionsExt}; + pub use std::os::unix::fs::OpenOptionsExt; + } +} + +cfg_if! { + if #[cfg(feature = "docs")] { + /// Unix-specific extensions to [`fs::Permissions`]. + /// + /// [`fs::Permissions`]: ../../../fs/struct.Permissions.html + pub trait PermissionsExt { + /// Returns the underlying raw `st_mode` bits that contain the standard + /// Unix permissions for this file. + /// + /// # Examples + /// + /// ```no_run + /// use std::fs::File; + /// use std::os::unix::fs::PermissionsExt; + /// + /// fn main() -> std::io::Result<()> { + /// let f = File::create("foo.txt")?; + /// let metadata = f.metadata()?; + /// let permissions = metadata.permissions(); + /// + /// println!("permissions: {:o}", permissions.mode()); + /// Ok(()) } + /// ``` + fn mode(&self) -> u32; + + /// Sets the underlying raw bits for this set of permissions. + /// + /// # Examples + /// + /// ```no_run + /// use std::fs::File; + /// use std::os::unix::fs::PermissionsExt; + /// + /// fn main() -> std::io::Result<()> { + /// let f = File::create("foo.txt")?; + /// let metadata = f.metadata()?; + /// let mut permissions = metadata.permissions(); + /// + /// permissions.set_mode(0o644); // Read/write for owner and read for others. + /// assert_eq!(permissions.mode(), 0o644); + /// Ok(()) } + /// ``` + fn set_mode(&mut self, mode: u32); + + /// Creates a new instance of `Permissions` from the given set of Unix + /// permission bits. + /// + /// # Examples + /// + /// ``` + /// use std::fs::Permissions; + /// use std::os::unix::fs::PermissionsExt; + /// + /// // Read/write for owner and read for others. + /// let permissions = Permissions::from_mode(0o644); + /// assert_eq!(permissions.mode(), 0o644); + /// ``` + fn from_mode(mode: u32) -> Self; + } } } diff --git a/src/task/mod.rs b/src/task/mod.rs index eef72846a..02842e008 100644 --- a/src/task/mod.rs +++ b/src/task/mod.rs @@ -22,7 +22,7 @@ //! ``` #[doc(inline)] -pub use std::task::{Context, Poll, Waker}; +pub use std::task::{Context, Poll}; pub use block_on::block_on; pub use local::{AccessError, LocalKey}; @@ -37,3 +37,23 @@ mod sleep; mod task; pub(crate) mod blocking; + +use cfg_if::cfg_if; + +cfg_if! { + if #[cfg(feature = "docs")] { + /// A `Waker` is a handle for waking up a task by notifying its executor + /// that it is ready to be run. + /// + /// This handle encapsulates a [`RawWaker`][`std::task::RawWaker`] + /// instance, which defines the executor-specific wakeup behavior. + /// + /// Implements [`Clone`], [`trait@Send`], and [`trait@Sync`]. + pub struct Waker { + _private: (), + } + } else { + #[doc(inline)] + pub use std::task::Waker; + } +}