From 9b2aa14bb185f552f0842319e7fbbfe0bd9b3dc6 Mon Sep 17 00:00:00 2001 From: Carl Lerche Date: Fri, 22 Nov 2019 09:56:08 -0800 Subject: [PATCH] docs: annotate io mod with doc_cfg (#1808) Annotates types in `tokio::io` module with their required feature flag. This annotation is included in generated documentation. Notes: * The annotation must be on the type or function itself. Annotating just the re-export is not sufficient. * The annotation must be **inside** the `pin_project!` macro or it is lost. --- tokio/Cargo.toml | 1 + tokio/src/io/poll_evented.rs | 187 ++++++++++---------- tokio/src/io/registration.rs | 71 ++++---- tokio/src/io/split.rs | 62 +++---- tokio/src/io/stderr.rs | 44 ++--- tokio/src/io/stdin.rs | 56 +++--- tokio/src/io/stdout.rs | 44 ++--- tokio/src/io/util/async_buf_read_ext.rs | 220 ++++++++++++------------ tokio/src/io/util/async_read_ext.rs | 148 ++++++++-------- tokio/src/io/util/async_write_ext.rs | 60 +++---- tokio/src/io/util/buf_reader.rs | 2 +- tokio/src/io/util/buf_stream.rs | 1 + tokio/src/io/util/buf_writer.rs | 2 +- tokio/src/io/util/chain.rs | 1 + tokio/src/io/util/copy.rs | 130 +++++++------- tokio/src/io/util/empty.rs | 70 ++++---- tokio/src/io/util/flush.rs | 14 +- tokio/src/io/util/lines.rs | 1 + tokio/src/io/util/read.rs | 20 ++- tokio/src/io/util/read_exact.rs | 22 +-- tokio/src/io/util/read_line.rs | 18 +- tokio/src/io/util/read_to_end.rs | 1 + tokio/src/io/util/read_to_string.rs | 18 +- tokio/src/io/util/read_until.rs | 18 +- tokio/src/io/util/repeat.rs | 72 ++++---- tokio/src/io/util/shutdown.rs | 14 +- tokio/src/io/util/sink.rs | 66 +++---- tokio/src/io/util/split.rs | 1 + tokio/src/io/util/take.rs | 1 + tokio/src/io/util/write.rs | 14 +- tokio/src/io/util/write_all.rs | 12 +- tokio/src/lib.rs | 3 +- tokio/src/macros/cfg.rs | 45 ++++- tokio/src/process/mod.rs | 8 +- 34 files changed, 768 insertions(+), 679 deletions(-) diff --git a/tokio/Cargo.toml b/tokio/Cargo.toml index fdec4695624..320e5b38738 100644 --- a/tokio/Cargo.toml +++ b/tokio/Cargo.toml @@ -126,3 +126,4 @@ tempfile = "3.1.0" [package.metadata.docs.rs] all-features = true +rustdoc-args = ["--cfg", "docsrs"] diff --git a/tokio/src/io/poll_evented.rs b/tokio/src/io/poll_evented.rs index d1644ca20a0..bbd60259d31 100644 --- a/tokio/src/io/poll_evented.rs +++ b/tokio/src/io/poll_evented.rs @@ -10,98 +10,101 @@ use std::sync::atomic::AtomicUsize; use std::sync::atomic::Ordering::Relaxed; use std::task::{Context, Poll}; -/// Associates an I/O resource that implements the [`std::io::Read`] and/or -/// [`std::io::Write`] traits with the reactor that drives it. -/// -/// `PollEvented` uses [`Registration`] internally to take a type that -/// implements [`mio::Evented`] as well as [`std::io::Read`] and or -/// [`std::io::Write`] and associate it with a reactor that will drive it. -/// -/// Once the [`mio::Evented`] type is wrapped by `PollEvented`, it can be -/// used from within the future's execution model. As such, the `PollEvented` -/// type provides [`AsyncRead`] and [`AsyncWrite`] implementations using the -/// underlying I/O resource as well as readiness events provided by the reactor. -/// -/// **Note**: While `PollEvented` is `Sync` (if the underlying I/O type is -/// `Sync`), the caller must ensure that there are at most two tasks that use a -/// `PollEvented` instance concurrently. One for reading and one for writing. -/// While violating this requirement is "safe" from a Rust memory model point of -/// view, it will result in unexpected behavior in the form of lost -/// notifications and tasks hanging. -/// -/// ## Readiness events -/// -/// Besides just providing [`AsyncRead`] and [`AsyncWrite`] implementations, -/// this type also supports access to the underlying readiness event stream. -/// While similar in function to what [`Registration`] provides, the semantics -/// are a bit different. -/// -/// Two functions are provided to access the readiness events: -/// [`poll_read_ready`] and [`poll_write_ready`]. These functions return the -/// current readiness state of the `PollEvented` instance. If -/// [`poll_read_ready`] indicates read readiness, immediately calling -/// [`poll_read_ready`] again will also indicate read readiness. -/// -/// When the operation is attempted and is unable to succeed due to the I/O -/// resource not being ready, the caller must call [`clear_read_ready`] or -/// [`clear_write_ready`]. This clears the readiness state until a new readiness -/// event is received. -/// -/// This allows the caller to implement additional functions. For example, -/// [`TcpListener`] implements poll_accept by using [`poll_read_ready`] and -/// [`clear_read_ready`]. -/// -/// ```rust -/// use tokio::io::PollEvented; -/// -/// use futures::ready; -/// use mio::Ready; -/// use mio::net::{TcpStream, TcpListener}; -/// use std::io; -/// use std::task::{Context, Poll}; -/// -/// struct MyListener { -/// poll_evented: PollEvented, -/// } -/// -/// impl MyListener { -/// pub fn poll_accept(&mut self, cx: &mut Context<'_>) -> Poll> { -/// let ready = Ready::readable(); -/// -/// ready!(self.poll_evented.poll_read_ready(cx, ready))?; -/// -/// match self.poll_evented.get_ref().accept() { -/// Ok((socket, _)) => Poll::Ready(Ok(socket)), -/// Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => { -/// self.poll_evented.clear_read_ready(cx, ready)?; -/// Poll::Pending -/// } -/// Err(e) => Poll::Ready(Err(e)), -/// } -/// } -/// } -/// ``` -/// -/// ## Platform-specific events -/// -/// `PollEvented` also allows receiving platform-specific `mio::Ready` events. -/// These events are included as part of the read readiness event stream. The -/// write readiness event stream is only for `Ready::writable()` events. -/// -/// [`std::io::Read`]: https://doc.rust-lang.org/std/io/trait.Read.html -/// [`std::io::Write`]: https://doc.rust-lang.org/std/io/trait.Write.html -/// [`AsyncRead`]: ../io/trait.AsyncRead.html -/// [`AsyncWrite`]: ../io/trait.AsyncWrite.html -/// [`mio::Evented`]: https://docs.rs/mio/0.6/mio/trait.Evented.html -/// [`Registration`]: struct.Registration.html -/// [`TcpListener`]: ../net/struct.TcpListener.html -/// [`clear_read_ready`]: #method.clear_read_ready -/// [`clear_write_ready`]: #method.clear_write_ready -/// [`poll_read_ready`]: #method.poll_read_ready -/// [`poll_write_ready`]: #method.poll_write_ready -pub struct PollEvented { - io: Option, - inner: Inner, +cfg_io_driver! { + /// Associates an I/O resource that implements the [`std::io::Read`] and/or + /// [`std::io::Write`] traits with the reactor that drives it. + /// + /// `PollEvented` uses [`Registration`] internally to take a type that + /// implements [`mio::Evented`] as well as [`std::io::Read`] and or + /// [`std::io::Write`] and associate it with a reactor that will drive it. + /// + /// Once the [`mio::Evented`] type is wrapped by `PollEvented`, it can be + /// used from within the future's execution model. As such, the + /// `PollEvented` type provides [`AsyncRead`] and [`AsyncWrite`] + /// implementations using the underlying I/O resource as well as readiness + /// events provided by the reactor. + /// + /// **Note**: While `PollEvented` is `Sync` (if the underlying I/O type is + /// `Sync`), the caller must ensure that there are at most two tasks that + /// use a `PollEvented` instance concurrently. One for reading and one for + /// writing. While violating this requirement is "safe" from a Rust memory + /// model point of view, it will result in unexpected behavior in the form + /// of lost notifications and tasks hanging. + /// + /// ## Readiness events + /// + /// Besides just providing [`AsyncRead`] and [`AsyncWrite`] implementations, + /// this type also supports access to the underlying readiness event stream. + /// While similar in function to what [`Registration`] provides, the + /// semantics are a bit different. + /// + /// Two functions are provided to access the readiness events: + /// [`poll_read_ready`] and [`poll_write_ready`]. These functions return the + /// current readiness state of the `PollEvented` instance. If + /// [`poll_read_ready`] indicates read readiness, immediately calling + /// [`poll_read_ready`] again will also indicate read readiness. + /// + /// When the operation is attempted and is unable to succeed due to the I/O + /// resource not being ready, the caller must call [`clear_read_ready`] or + /// [`clear_write_ready`]. This clears the readiness state until a new + /// readiness event is received. + /// + /// This allows the caller to implement additional functions. For example, + /// [`TcpListener`] implements poll_accept by using [`poll_read_ready`] and + /// [`clear_read_ready`]. + /// + /// ```rust + /// use tokio::io::PollEvented; + /// + /// use futures::ready; + /// use mio::Ready; + /// use mio::net::{TcpStream, TcpListener}; + /// use std::io; + /// use std::task::{Context, Poll}; + /// + /// struct MyListener { + /// poll_evented: PollEvented, + /// } + /// + /// impl MyListener { + /// pub fn poll_accept(&mut self, cx: &mut Context<'_>) -> Poll> { + /// let ready = Ready::readable(); + /// + /// ready!(self.poll_evented.poll_read_ready(cx, ready))?; + /// + /// match self.poll_evented.get_ref().accept() { + /// Ok((socket, _)) => Poll::Ready(Ok(socket)), + /// Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => { + /// self.poll_evented.clear_read_ready(cx, ready)?; + /// Poll::Pending + /// } + /// Err(e) => Poll::Ready(Err(e)), + /// } + /// } + /// } + /// ``` + /// + /// ## Platform-specific events + /// + /// `PollEvented` also allows receiving platform-specific `mio::Ready` events. + /// These events are included as part of the read readiness event stream. The + /// write readiness event stream is only for `Ready::writable()` events. + /// + /// [`std::io::Read`]: https://doc.rust-lang.org/std/io/trait.Read.html + /// [`std::io::Write`]: https://doc.rust-lang.org/std/io/trait.Write.html + /// [`AsyncRead`]: ../io/trait.AsyncRead.html + /// [`AsyncWrite`]: ../io/trait.AsyncWrite.html + /// [`mio::Evented`]: https://docs.rs/mio/0.6/mio/trait.Evented.html + /// [`Registration`]: struct.Registration.html + /// [`TcpListener`]: ../net/struct.TcpListener.html + /// [`clear_read_ready`]: #method.clear_read_ready + /// [`clear_write_ready`]: #method.clear_write_ready + /// [`poll_read_ready`]: #method.poll_read_ready + /// [`poll_write_ready`]: #method.poll_write_ready + pub struct PollEvented { + io: Option, + inner: Inner, + } } struct Inner { diff --git a/tokio/src/io/registration.rs b/tokio/src/io/registration.rs index 1a8db6d79f0..e8f9794dc49 100644 --- a/tokio/src/io/registration.rs +++ b/tokio/src/io/registration.rs @@ -5,40 +5,43 @@ use mio::{self, Evented}; use std::task::{Context, Poll}; use std::io; -/// Associates an I/O resource with the reactor instance that drives it. -/// -/// A registration represents an I/O resource registered with a Reactor such -/// that it will receive task notifications on readiness. This is the lowest -/// level API for integrating with a reactor. -/// -/// The association between an I/O resource is made by calling [`new`]. Once -/// the association is established, it remains established until the -/// registration instance is dropped. -/// -/// A registration instance represents two separate readiness streams. One for -/// the read readiness and one for write readiness. These streams are -/// independent and can be consumed from separate tasks. -/// -/// **Note**: while `Registration` is `Sync`, the caller must ensure that there -/// are at most two tasks that use a registration instance concurrently. One -/// task for [`poll_read_ready`] and one task for [`poll_write_ready`]. While -/// violating this requirement is "safe" from a Rust memory safety point of -/// view, it will result in unexpected behavior in the form of lost -/// notifications and tasks hanging. -/// -/// ## Platform-specific events -/// -/// `Registration` also allows receiving platform-specific `mio::Ready` events. -/// These events are included as part of the read readiness event stream. The -/// write readiness event stream is only for `Ready::writable()` events. -/// -/// [`new`]: #method.new -/// [`poll_read_ready`]: #method.poll_read_ready`] -/// [`poll_write_ready`]: #method.poll_write_ready`] -#[derive(Debug)] -pub struct Registration { - handle: Handle, - address: Address, +cfg_io_driver! { + /// Associates an I/O resource with the reactor instance that drives it. + /// + /// A registration represents an I/O resource registered with a Reactor such + /// that it will receive task notifications on readiness. This is the lowest + /// level API for integrating with a reactor. + /// + /// The association between an I/O resource is made by calling [`new`]. Once + /// the association is established, it remains established until the + /// registration instance is dropped. + /// + /// A registration instance represents two separate readiness streams. One + /// for the read readiness and one for write readiness. These streams are + /// independent and can be consumed from separate tasks. + /// + /// **Note**: while `Registration` is `Sync`, the caller must ensure that + /// there are at most two tasks that use a registration instance + /// concurrently. One task for [`poll_read_ready`] and one task for + /// [`poll_write_ready`]. While violating this requirement is "safe" from a + /// Rust memory safety point of view, it will result in unexpected behavior + /// in the form of lost notifications and tasks hanging. + /// + /// ## Platform-specific events + /// + /// `Registration` also allows receiving platform-specific `mio::Ready` + /// events. These events are included as part of the read readiness event + /// stream. The write readiness event stream is only for `Ready::writable()` + /// events. + /// + /// [`new`]: #method.new + /// [`poll_read_ready`]: #method.poll_read_ready`] + /// [`poll_write_ready`]: #method.poll_write_ready`] + #[derive(Debug)] + pub struct Registration { + handle: Handle, + address: Address, + } } // ===== impl Registration ===== diff --git a/tokio/src/io/split.rs b/tokio/src/io/split.rs index 388ee4ed2ef..a01ceef264f 100644 --- a/tokio/src/io/split.rs +++ b/tokio/src/io/split.rs @@ -16,14 +16,39 @@ use std::sync::atomic::Ordering::{Acquire, Release}; use std::sync::Arc; use std::task::{Context, Poll}; -/// The readable half of a value returned from `split`. -pub struct ReadHalf { - inner: Arc>, -} +cfg_io_util! { + /// The readable half of a value returned from `split`. + pub struct ReadHalf { + inner: Arc>, + } + + /// The writable half of a value returned from `split`. + pub struct WriteHalf { + inner: Arc>, + } -/// The writable half of a value returned from `split`. -pub struct WriteHalf { - inner: Arc>, + /// Split a single value implementing `AsyncRead + AsyncWrite` into separate + /// `AsyncRead` and `AsyncWrite` handles. + /// + /// To restore this read/write object from its `split::ReadHalf` and + /// `split::WriteHalf` use `unsplit`. + pub fn split(stream: T) -> (ReadHalf, WriteHalf) + where + T: AsyncRead + AsyncWrite, + { + let inner = Arc::new(Inner { + locked: AtomicBool::new(false), + stream: UnsafeCell::new(stream), + }); + + let rd = ReadHalf { + inner: inner.clone(), + }; + + let wr = WriteHalf { inner }; + + (rd, wr) + } } struct Inner { @@ -35,29 +60,6 @@ struct Guard<'a, T> { inner: &'a Inner, } -/// Split a single value implementing `AsyncRead + AsyncWrite` into separate -/// `AsyncRead` and `AsyncWrite` handles. -/// -/// To restore this read/write object from its `split::ReadHalf` and -/// `split::WriteHalf` use `unsplit`. -pub fn split(stream: T) -> (ReadHalf, WriteHalf) -where - T: AsyncRead + AsyncWrite, -{ - let inner = Arc::new(Inner { - locked: AtomicBool::new(false), - stream: UnsafeCell::new(stream), - }); - - let rd = ReadHalf { - inner: inner.clone(), - }; - - let wr = WriteHalf { inner }; - - (rd, wr) -} - impl ReadHalf { /// Reunite with a previously split `WriteHalf`. /// diff --git a/tokio/src/io/stderr.rs b/tokio/src/io/stderr.rs index 9e3f2e9b695..231941f298f 100644 --- a/tokio/src/io/stderr.rs +++ b/tokio/src/io/stderr.rs @@ -6,28 +6,30 @@ use std::pin::Pin; use std::task::Context; use std::task::Poll; -/// A handle to the standard error stream of a process. -/// -/// The handle implements the [`AsyncWrite`] trait, but beware that concurrent -/// writes to `Stderr` must be executed with care. -/// -/// Created by the [`stderr`] function. -/// -/// [`stderr`]: fn.stderr.html -/// [`AsyncWrite`]: trait.AsyncWrite.html -#[derive(Debug)] -pub struct Stderr { - std: Blocking, -} +cfg_io_std! { + /// A handle to the standard error stream of a process. + /// + /// The handle implements the [`AsyncWrite`] trait, but beware that concurrent + /// writes to `Stderr` must be executed with care. + /// + /// Created by the [`stderr`] function. + /// + /// [`stderr`]: fn.stderr.html + /// [`AsyncWrite`]: trait.AsyncWrite.html + #[derive(Debug)] + pub struct Stderr { + std: Blocking, + } -/// Constructs a new handle to the standard error of the current process. -/// -/// The returned handle allows writing to standard error from the within the -/// Tokio runtime. -pub fn stderr() -> Stderr { - let std = io::stderr(); - Stderr { - std: Blocking::new(std), + /// Constructs a new handle to the standard error of the current process. + /// + /// The returned handle allows writing to standard error from the within the + /// Tokio runtime. + pub fn stderr() -> Stderr { + let std = io::stderr(); + Stderr { + std: Blocking::new(std), + } } } diff --git a/tokio/src/io/stdin.rs b/tokio/src/io/stdin.rs index 58b1908261c..81bc5abbbe9 100644 --- a/tokio/src/io/stdin.rs +++ b/tokio/src/io/stdin.rs @@ -6,34 +6,36 @@ use std::pin::Pin; use std::task::Context; use std::task::Poll; -/// A handle to the standard input stream of a process. -/// -/// The handle implements the [`AsyncRead`] trait, but beware that concurrent -/// reads of `Stdin` must be executed with care. -/// -/// As an additional caveat, reading from the handle may block the calling -/// future indefinitely, if there is not enough data available. This makes this -/// handle unsuitable for use in any circumstance where immediate reaction to -/// available data is required, e.g. interactive use or when implementing a -/// subprocess driven by requests on the standard input. -/// -/// Created by the [`stdin`] function. -/// -/// [`stdin`]: fn.stdin.html -/// [`AsyncRead`]: trait.AsyncRead.html -#[derive(Debug)] -pub struct Stdin { - std: Blocking, -} +cfg_io_std! { + /// A handle to the standard input stream of a process. + /// + /// The handle implements the [`AsyncRead`] trait, but beware that concurrent + /// reads of `Stdin` must be executed with care. + /// + /// As an additional caveat, reading from the handle may block the calling + /// future indefinitely, if there is not enough data available. This makes this + /// handle unsuitable for use in any circumstance where immediate reaction to + /// available data is required, e.g. interactive use or when implementing a + /// subprocess driven by requests on the standard input. + /// + /// Created by the [`stdin`] function. + /// + /// [`stdin`]: fn.stdin.html + /// [`AsyncRead`]: trait.AsyncRead.html + #[derive(Debug)] + pub struct Stdin { + std: Blocking, + } -/// Constructs a new handle to the standard input of the current process. -/// -/// The returned handle allows reading from standard input from the within the -/// Tokio runtime. -pub fn stdin() -> Stdin { - let std = io::stdin(); - Stdin { - std: Blocking::new(std), + /// Constructs a new handle to the standard input of the current process. + /// + /// The returned handle allows reading from standard input from the within the + /// Tokio runtime. + pub fn stdin() -> Stdin { + let std = io::stdin(); + Stdin { + std: Blocking::new(std), + } } } diff --git a/tokio/src/io/stdout.rs b/tokio/src/io/stdout.rs index c06c7d3866f..86de1c58dbe 100644 --- a/tokio/src/io/stdout.rs +++ b/tokio/src/io/stdout.rs @@ -6,28 +6,30 @@ use std::pin::Pin; use std::task::Context; use std::task::Poll; -/// A handle to the standard output stream of a process. -/// -/// The handle implements the [`AsyncWrite`] trait, but beware that concurrent -/// writes to `Stdout` must be executed with care. -/// -/// Created by the [`stdout`] function. -/// -/// [`stdout`]: fn.stdout.html -/// [`AsyncWrite`]: trait.AsyncWrite.html -#[derive(Debug)] -pub struct Stdout { - std: Blocking, -} +cfg_io_std! { + /// A handle to the standard output stream of a process. + /// + /// The handle implements the [`AsyncWrite`] trait, but beware that concurrent + /// writes to `Stdout` must be executed with care. + /// + /// Created by the [`stdout`] function. + /// + /// [`stdout`]: fn.stdout.html + /// [`AsyncWrite`]: trait.AsyncWrite.html + #[derive(Debug)] + pub struct Stdout { + std: Blocking, + } -/// Constructs a new handle to the standard output of the current process. -/// -/// The returned handle allows writing to standard out from the within the Tokio -/// runtime. -pub fn stdout() -> Stdout { - let std = io::stdout(); - Stdout { - std: Blocking::new(std), + /// Constructs a new handle to the standard output of the current process. + /// + /// The returned handle allows writing to standard out from the within the Tokio + /// runtime. + pub fn stdout() -> Stdout { + let std = io::stdout(); + Stdout { + std: Blocking::new(std), + } } } diff --git a/tokio/src/io/util/async_buf_read_ext.rs b/tokio/src/io/util/async_buf_read_ext.rs index 7567d72ed9b..86d09dd33b6 100644 --- a/tokio/src/io/util/async_buf_read_ext.rs +++ b/tokio/src/io/util/async_buf_read_ext.rs @@ -4,118 +4,120 @@ use crate::io::util::read_until::{read_until, ReadUntil}; use crate::io::util::split::{split, Split}; use crate::io::AsyncBufRead; -/// An extension trait which adds utility methods to `AsyncBufRead` types. -pub trait AsyncBufReadExt: AsyncBufRead { - /// Creates a future which will read all the bytes associated with this I/O - /// object into `buf` until the delimiter `byte` or EOF is reached. - /// This method is the async equivalent to [`BufRead::read_until`](std::io::BufRead::read_until). - /// - /// This function will read bytes from the underlying stream until the - /// delimiter or EOF is found. Once found, all bytes up to, and including, - /// the delimiter (if found) will be appended to `buf`. - /// - /// The returned future will resolve to the number of bytes read once the read - /// operation is completed. - /// - /// In the case of an error the buffer and the object will be discarded, with - /// the error yielded. - fn read_until<'a>(&'a mut self, byte: u8, buf: &'a mut Vec) -> ReadUntil<'a, Self> - where - Self: Unpin, - { - read_until(self, byte, buf) - } +cfg_io_util! { + /// An extension trait which adds utility methods to `AsyncBufRead` types. + pub trait AsyncBufReadExt: AsyncBufRead { + /// Creates a future which will read all the bytes associated with this I/O + /// object into `buf` until the delimiter `byte` or EOF is reached. + /// This method is the async equivalent to [`BufRead::read_until`](std::io::BufRead::read_until). + /// + /// This function will read bytes from the underlying stream until the + /// delimiter or EOF is found. Once found, all bytes up to, and including, + /// the delimiter (if found) will be appended to `buf`. + /// + /// The returned future will resolve to the number of bytes read once the read + /// operation is completed. + /// + /// In the case of an error the buffer and the object will be discarded, with + /// the error yielded. + fn read_until<'a>(&'a mut self, byte: u8, buf: &'a mut Vec) -> ReadUntil<'a, Self> + where + Self: Unpin, + { + read_until(self, byte, buf) + } - /// Creates a future which will read all the bytes associated with this I/O - /// object into `buf` until a newline (the 0xA byte) or EOF is reached, - /// This method is the async equivalent to [`BufRead::read_line`](std::io::BufRead::read_line). - /// - /// This function will read bytes from the underlying stream until the - /// newline delimiter (the 0xA byte) or EOF is found. Once found, all bytes - /// up to, and including, the delimiter (if found) will be appended to - /// `buf`. - /// - /// The returned future will resolve to the number of bytes read once the read - /// operation is completed. - /// - /// In the case of an error the buffer and the object will be discarded, with - /// the error yielded. - /// - /// # Errors - /// - /// This function has the same error semantics as [`read_until`] and will - /// also return an error if the read bytes are not valid UTF-8. If an I/O - /// error is encountered then `buf` may contain some bytes already read in - /// the event that all data read so far was valid UTF-8. - /// - /// [`read_until`]: AsyncBufReadExt::read_until - fn read_line<'a>(&'a mut self, buf: &'a mut String) -> ReadLine<'a, Self> - where - Self: Unpin, - { - read_line(self, buf) - } + /// Creates a future which will read all the bytes associated with this I/O + /// object into `buf` until a newline (the 0xA byte) or EOF is reached, + /// This method is the async equivalent to [`BufRead::read_line`](std::io::BufRead::read_line). + /// + /// This function will read bytes from the underlying stream until the + /// newline delimiter (the 0xA byte) or EOF is found. Once found, all bytes + /// up to, and including, the delimiter (if found) will be appended to + /// `buf`. + /// + /// The returned future will resolve to the number of bytes read once the read + /// operation is completed. + /// + /// In the case of an error the buffer and the object will be discarded, with + /// the error yielded. + /// + /// # Errors + /// + /// This function has the same error semantics as [`read_until`] and will + /// also return an error if the read bytes are not valid UTF-8. If an I/O + /// error is encountered then `buf` may contain some bytes already read in + /// the event that all data read so far was valid UTF-8. + /// + /// [`read_until`]: AsyncBufReadExt::read_until + fn read_line<'a>(&'a mut self, buf: &'a mut String) -> ReadLine<'a, Self> + where + Self: Unpin, + { + read_line(self, buf) + } - /// Returns a stream of the contents of this reader split on the byte - /// `byte`. - /// - /// This method is the asynchronous equivalent to - /// [`BufRead::split`](std::io::BufRead::split). - /// - /// The stream returned from this function will yield instances of - /// [`io::Result`]`<`[`Vec`]`>`. Each vector returned will *not* have - /// the delimiter byte at the end. - /// - /// [`io::Result`]: std::io::Result - /// [`Vec`]: std::vec::Vec - /// - /// # Errors - /// - /// Each item of the stream has the same error semantics as - /// [`AsyncBufReadExt::read_until`](AsyncBufReadExt::read_until). - /// - /// # Examples - /// - /// ``` - /// # use tokio::io::AsyncBufRead; - /// use tokio::io::AsyncBufReadExt; - /// - /// # async fn dox(my_buf_read: impl AsyncBufRead + Unpin) -> std::io::Result<()> { - /// let mut segments = my_buf_read.split(b'f'); - /// - /// while let Some(segment) = segments.next_segment().await? { - /// println!("length = {}", segment.len()) - /// } - /// # Ok(()) - /// # } - /// ``` - fn split(self, byte: u8) -> Split - where - Self: Sized + Unpin, - { - split(self, byte) - } + /// Returns a stream of the contents of this reader split on the byte + /// `byte`. + /// + /// This method is the asynchronous equivalent to + /// [`BufRead::split`](std::io::BufRead::split). + /// + /// The stream returned from this function will yield instances of + /// [`io::Result`]`<`[`Vec`]`>`. Each vector returned will *not* have + /// the delimiter byte at the end. + /// + /// [`io::Result`]: std::io::Result + /// [`Vec`]: std::vec::Vec + /// + /// # Errors + /// + /// Each item of the stream has the same error semantics as + /// [`AsyncBufReadExt::read_until`](AsyncBufReadExt::read_until). + /// + /// # Examples + /// + /// ``` + /// # use tokio::io::AsyncBufRead; + /// use tokio::io::AsyncBufReadExt; + /// + /// # async fn dox(my_buf_read: impl AsyncBufRead + Unpin) -> std::io::Result<()> { + /// let mut segments = my_buf_read.split(b'f'); + /// + /// while let Some(segment) = segments.next_segment().await? { + /// println!("length = {}", segment.len()) + /// } + /// # Ok(()) + /// # } + /// ``` + fn split(self, byte: u8) -> Split + where + Self: Sized + Unpin, + { + split(self, byte) + } - /// Returns a stream over the lines of this reader. - /// This method is the async equivalent to [`BufRead::lines`](std::io::BufRead::lines). - /// - /// The stream returned from this function will yield instances of - /// [`io::Result`]`<`[`String`]`>`. Each string returned will *not* have a newline - /// byte (the 0xA byte) or CRLF (0xD, 0xA bytes) at the end. - /// - /// [`io::Result`]: std::io::Result - /// [`String`]: String - /// - /// # Errors - /// - /// Each line of the stream has the same error semantics as [`AsyncBufReadExt::read_line`]. - /// - /// [`AsyncBufReadExt::read_line`]: AsyncBufReadExt::read_line - fn lines(self) -> Lines - where - Self: Sized, - { - lines(self) + /// Returns a stream over the lines of this reader. + /// This method is the async equivalent to [`BufRead::lines`](std::io::BufRead::lines). + /// + /// The stream returned from this function will yield instances of + /// [`io::Result`]`<`[`String`]`>`. Each string returned will *not* have a newline + /// byte (the 0xA byte) or CRLF (0xD, 0xA bytes) at the end. + /// + /// [`io::Result`]: std::io::Result + /// [`String`]: String + /// + /// # Errors + /// + /// Each line of the stream has the same error semantics as [`AsyncBufReadExt::read_line`]. + /// + /// [`AsyncBufReadExt::read_line`]: AsyncBufReadExt::read_line + fn lines(self) -> Lines + where + Self: Sized, + { + lines(self) + } } } diff --git a/tokio/src/io/util/async_read_ext.rs b/tokio/src/io/util/async_read_ext.rs index 0b7cdbf1394..faac42d93f8 100644 --- a/tokio/src/io/util/async_read_ext.rs +++ b/tokio/src/io/util/async_read_ext.rs @@ -7,85 +7,87 @@ use crate::io::util::read_to_string::{read_to_string, ReadToString}; use crate::io::util::take::{take, Take}; use crate::io::{AsyncRead, AsyncWrite}; -/// An extension trait which adds utility methods to `AsyncRead` types. -pub trait AsyncReadExt: AsyncRead { - /// Creates an adaptor which will chain this stream with another. - /// - /// The returned `AsyncRead` instance will first read all bytes from this object - /// until EOF is encountered. Afterwards the output is equivalent to the - /// output of `next`. - fn chain(self, next: R) -> Chain - where - Self: Sized, - R: AsyncRead, - { - chain(self, next) - } +cfg_io_util! { + /// An extension trait which adds utility methods to `AsyncRead` types. + pub trait AsyncReadExt: AsyncRead { + /// Creates an adaptor which will chain this stream with another. + /// + /// The returned `AsyncRead` instance will first read all bytes from this object + /// until EOF is encountered. Afterwards the output is equivalent to the + /// output of `next`. + fn chain(self, next: R) -> Chain + where + Self: Sized, + R: AsyncRead, + { + chain(self, next) + } - /// Copy all data from `self` into the provided `AsyncWrite`. - /// - /// The returned future will copy all the bytes read from `reader` into the - /// `writer` specified. This future will only complete once the `reader` - /// has hit EOF and all bytes have been written to and flushed from the - /// `writer` provided. - /// - /// On success the number of bytes is returned and the `reader` and `writer` - /// are consumed. On error the error is returned and the I/O objects are - /// consumed as well. - fn copy<'a, W>(&'a mut self, dst: &'a mut W) -> Copy<'a, Self, W> - where - Self: Unpin, - W: AsyncWrite + Unpin + ?Sized, - { - copy(self, dst) - } + /// Copy all data from `self` into the provided `AsyncWrite`. + /// + /// The returned future will copy all the bytes read from `reader` into the + /// `writer` specified. This future will only complete once the `reader` + /// has hit EOF and all bytes have been written to and flushed from the + /// `writer` provided. + /// + /// On success the number of bytes is returned and the `reader` and `writer` + /// are consumed. On error the error is returned and the I/O objects are + /// consumed as well. + fn copy<'a, W>(&'a mut self, dst: &'a mut W) -> Copy<'a, Self, W> + where + Self: Unpin, + W: AsyncWrite + Unpin + ?Sized, + { + copy(self, dst) + } - /// Read data into the provided buffer. - /// - /// The returned future will resolve to the number of bytes read once the - /// read operation is completed. - fn read<'a>(&'a mut self, dst: &'a mut [u8]) -> Read<'a, Self> - where - Self: Unpin, - { - read(self, dst) - } + /// Read data into the provided buffer. + /// + /// The returned future will resolve to the number of bytes read once the + /// read operation is completed. + fn read<'a>(&'a mut self, dst: &'a mut [u8]) -> Read<'a, Self> + where + Self: Unpin, + { + read(self, dst) + } - /// Read exactly the amount of data needed to fill the provided buffer. - fn read_exact<'a>(&'a mut self, dst: &'a mut [u8]) -> ReadExact<'a, Self> - where - Self: Unpin, - { - read_exact(self, dst) - } + /// Read exactly the amount of data needed to fill the provided buffer. + fn read_exact<'a>(&'a mut self, dst: &'a mut [u8]) -> ReadExact<'a, Self> + where + Self: Unpin, + { + read_exact(self, dst) + } - /// Read all bytes until EOF in this source, placing them into `dst`. - /// - /// On success the total number of bytes read is returned. - fn read_to_end<'a>(&'a mut self, dst: &'a mut Vec) -> ReadToEnd<'a, Self> - where - Self: Unpin, - { - read_to_end(self, dst) - } + /// Read all bytes until EOF in this source, placing them into `dst`. + /// + /// On success the total number of bytes read is returned. + fn read_to_end<'a>(&'a mut self, dst: &'a mut Vec) -> ReadToEnd<'a, Self> + where + Self: Unpin, + { + read_to_end(self, dst) + } - /// Read all bytes until EOF in this source, placing them into `dst`. - /// - /// On success the total number of bytes read is returned. - fn read_to_string<'a>(&'a mut self, dst: &'a mut String) -> ReadToString<'a, Self> - where - Self: Unpin, - { - read_to_string(self, dst) - } + /// Read all bytes until EOF in this source, placing them into `dst`. + /// + /// On success the total number of bytes read is returned. + fn read_to_string<'a>(&'a mut self, dst: &'a mut String) -> ReadToString<'a, Self> + where + Self: Unpin, + { + read_to_string(self, dst) + } - /// Creates an AsyncRead adapter which will read at most `limit` bytes - /// from the underlying reader. - fn take(self, limit: u64) -> Take - where - Self: Sized, - { - take(self, limit) + /// Creates an AsyncRead adapter which will read at most `limit` bytes + /// from the underlying reader. + fn take(self, limit: u64) -> Take + where + Self: Sized, + { + take(self, limit) + } } } diff --git a/tokio/src/io/util/async_write_ext.rs b/tokio/src/io/util/async_write_ext.rs index 9e40e2594aa..65374428eac 100644 --- a/tokio/src/io/util/async_write_ext.rs +++ b/tokio/src/io/util/async_write_ext.rs @@ -4,38 +4,40 @@ use crate::io::util::write::{write, Write}; use crate::io::util::write_all::{write_all, WriteAll}; use crate::io::AsyncWrite; -/// An extension trait which adds utility methods to `AsyncWrite` types. -pub trait AsyncWriteExt: AsyncWrite { - /// Write a buffer into this writter, returning how many bytes were written. - fn write<'a>(&'a mut self, src: &'a [u8]) -> Write<'a, Self> - where - Self: Unpin, - { - write(self, src) - } +cfg_io_util! { + /// An extension trait which adds utility methods to `AsyncWrite` types. + pub trait AsyncWriteExt: AsyncWrite { + /// Write a buffer into this writter, returning how many bytes were written. + fn write<'a>(&'a mut self, src: &'a [u8]) -> Write<'a, Self> + where + Self: Unpin, + { + write(self, src) + } - /// Attempt to write an entire buffer into this writter. - fn write_all<'a>(&'a mut self, src: &'a [u8]) -> WriteAll<'a, Self> - where - Self: Unpin, - { - write_all(self, src) - } + /// Attempt to write an entire buffer into this writter. + fn write_all<'a>(&'a mut self, src: &'a [u8]) -> WriteAll<'a, Self> + where + Self: Unpin, + { + write_all(self, src) + } - /// Flush the contents of this writer. - fn flush(&mut self) -> Flush<'_, Self> - where - Self: Unpin, - { - flush(self) - } + /// Flush the contents of this writer. + fn flush(&mut self) -> Flush<'_, Self> + where + Self: Unpin, + { + flush(self) + } - /// Shutdown this writer. - fn shutdown(&mut self) -> Shutdown<'_, Self> - where - Self: Unpin, - { - shutdown(self) + /// Shutdown this writer. + fn shutdown(&mut self) -> Shutdown<'_, Self> + where + Self: Unpin, + { + shutdown(self) + } } } diff --git a/tokio/src/io/util/buf_reader.rs b/tokio/src/io/util/buf_reader.rs index 5cf2c179fee..0177c0e344a 100644 --- a/tokio/src/io/util/buf_reader.rs +++ b/tokio/src/io/util/buf_reader.rs @@ -24,7 +24,7 @@ pin_project! { /// When the `BufReader` is dropped, the contents of its buffer will be /// discarded. Creating multiple instances of a `BufReader` on the same /// stream can cause data loss. - // TODO: Examples + #[cfg_attr(docsrs, doc(cfg(feature = "io-util")))] pub struct BufReader { #[pin] pub(super) inner: R, diff --git a/tokio/src/io/util/buf_stream.rs b/tokio/src/io/util/buf_stream.rs index a1676c29a49..d83310e3d67 100644 --- a/tokio/src/io/util/buf_stream.rs +++ b/tokio/src/io/util/buf_stream.rs @@ -16,6 +16,7 @@ pin_project! { /// types aid with these problems respectively, but do so in only one direction. `BufStream` wraps /// one in the other so that both directions are buffered. See their documentation for details. #[derive(Debug)] + #[cfg_attr(docsrs, doc(cfg(feature = "io-util")))] pub struct BufStream { #[pin] inner: BufReader>, diff --git a/tokio/src/io/util/buf_writer.rs b/tokio/src/io/util/buf_writer.rs index e7ae57a0ee7..efd053ebac6 100644 --- a/tokio/src/io/util/buf_writer.rs +++ b/tokio/src/io/util/buf_writer.rs @@ -29,7 +29,7 @@ pin_project! { /// [`AsyncWrite`]: AsyncWrite /// [`flush`]: super::AsyncWriteExt::flush /// - // TODO: Examples + #[cfg_attr(docsrs, doc(cfg(feature = "io-util")))] pub struct BufWriter { #[pin] pub(super) inner: W, diff --git a/tokio/src/io/util/chain.rs b/tokio/src/io/util/chain.rs index 2b3531e78ba..bc76af341da 100644 --- a/tokio/src/io/util/chain.rs +++ b/tokio/src/io/util/chain.rs @@ -9,6 +9,7 @@ use std::task::{Context, Poll}; pin_project! { /// Stream for the [`chain`](super::AsyncReadExt::chain) method. #[must_use = "streams do nothing unless polled"] + #[cfg_attr(docsrs, doc(cfg(feature = "io-util")))] pub struct Chain { #[pin] first: T, diff --git a/tokio/src/io/util/copy.rs b/tokio/src/io/util/copy.rs index 65dfa9587b7..312ff3605b0 100644 --- a/tokio/src/io/util/copy.rs +++ b/tokio/src/io/util/copy.rs @@ -5,71 +5,73 @@ use std::io; use std::pin::Pin; use std::task::{Context, Poll}; -/// A future that asynchronously copies the entire contents of a reader into a -/// writer. -/// -/// This struct is generally created by calling [`copy`][copy]. Please -/// see the documentation of `copy()` for more details. -/// -/// [copy]: fn.copy.html -#[derive(Debug)] -#[must_use = "futures do nothing unless you `.await` or poll them"] -pub struct Copy<'a, R: ?Sized, W: ?Sized> { - reader: &'a mut R, - read_done: bool, - writer: &'a mut W, - pos: usize, - cap: usize, - amt: u64, - buf: Box<[u8]>, -} +cfg_io_util! { + /// A future that asynchronously copies the entire contents of a reader into a + /// writer. + /// + /// This struct is generally created by calling [`copy`][copy]. Please + /// see the documentation of `copy()` for more details. + /// + /// [copy]: fn.copy.html + #[derive(Debug)] + #[must_use = "futures do nothing unless you `.await` or poll them"] + pub struct Copy<'a, R: ?Sized, W: ?Sized> { + reader: &'a mut R, + read_done: bool, + writer: &'a mut W, + pos: usize, + cap: usize, + amt: u64, + buf: Box<[u8]>, + } -/// Asynchronously copies the entire contents of a reader into a writer. -/// -/// This function returns a future that will continuously read data from -/// `reader` and then write it into `writer` in a streaming fashion until -/// `reader` returns EOF. -/// -/// On success, the total number of bytes that were copied from -/// `reader` to `writer` is returned. -/// -/// This is an asynchronous version of [`std::io::copy`][std]. -/// -/// # Errors -/// -/// The returned future will finish with an error will return an error -/// immediately if any call to `poll_read` or `poll_write` returns an error. -/// -/// # Examples -/// -/// ``` -/// use tokio::io; -/// -/// # async fn dox() -> std::io::Result<()> { -/// let mut reader: &[u8] = b"hello"; -/// let mut writer: Vec = vec![]; -/// -/// io::copy(&mut reader, &mut writer).await?; -/// -/// assert_eq!(&b"hello"[..], &writer[..]); -/// # Ok(()) -/// # } -/// ``` -/// -/// [std]: https://doc.rust-lang.org/std/io/fn.copy.html -pub fn copy<'a, R, W>(reader: &'a mut R, writer: &'a mut W) -> Copy<'a, R, W> -where - R: AsyncRead + Unpin + ?Sized, - W: AsyncWrite + Unpin + ?Sized, -{ - Copy { - reader, - read_done: false, - writer, - amt: 0, - pos: 0, - cap: 0, - buf: Box::new([0; 2048]), + /// Asynchronously copies the entire contents of a reader into a writer. + /// + /// This function returns a future that will continuously read data from + /// `reader` and then write it into `writer` in a streaming fashion until + /// `reader` returns EOF. + /// + /// On success, the total number of bytes that were copied from `reader` to + /// `writer` is returned. + /// + /// This is an asynchronous version of [`std::io::copy`][std]. + /// + /// # Errors + /// + /// The returned future will finish with an error will return an error + /// immediately if any call to `poll_read` or `poll_write` returns an error. + /// + /// # Examples + /// + /// ``` + /// use tokio::io; + /// + /// # async fn dox() -> std::io::Result<()> { + /// let mut reader: &[u8] = b"hello"; + /// let mut writer: Vec = vec![]; + /// + /// io::copy(&mut reader, &mut writer).await?; + /// + /// assert_eq!(&b"hello"[..], &writer[..]); + /// # Ok(()) + /// # } + /// ``` + /// + /// [std]: https://doc.rust-lang.org/std/io/fn.copy.html + pub fn copy<'a, R, W>(reader: &'a mut R, writer: &'a mut W) -> Copy<'a, R, W> + where + R: AsyncRead + Unpin + ?Sized, + W: AsyncWrite + Unpin + ?Sized, + { + Copy { + reader, + read_done: false, + writer, + amt: 0, + pos: 0, + cap: 0, + buf: Box::new([0; 2048]), + } } } diff --git a/tokio/src/io/util/empty.rs b/tokio/src/io/util/empty.rs index 3868eb6d08b..054d8e6023d 100644 --- a/tokio/src/io/util/empty.rs +++ b/tokio/src/io/util/empty.rs @@ -5,41 +5,43 @@ use std::io; use std::pin::Pin; use std::task::{Context, Poll}; -// An async reader which is always at EOF. -/// -/// This struct is generally created by calling [`empty`]. Please see -/// the documentation of [`empty()`][`empty`] for more details. -/// -/// This is an asynchronous version of [`std::io::empty`][std]. -/// -/// [`empty`]: fn.empty.html -/// [std]: https://doc.rust-lang.org/std/io/struct.Empty.html -pub struct Empty { - _p: (), -} +cfg_io_util! { + // An async reader which is always at EOF. + /// + /// This struct is generally created by calling [`empty`]. Please see + /// the documentation of [`empty()`][`empty`] for more details. + /// + /// This is an asynchronous version of [`std::io::empty`][std]. + /// + /// [`empty`]: fn.empty.html + /// [std]: https://doc.rust-lang.org/std/io/struct.Empty.html + pub struct Empty { + _p: (), + } -/// Creates a new empty async reader. -/// -/// All reads from the returned reader will return `Poll::Ready(Ok(0))`. -/// -/// This is an asynchronous version of [`std::io::empty`][std]. -/// -/// # Examples -/// -/// A slightly sad example of not reading anything into a buffer: -/// -/// ```rust -/// # use tokio::io::{self, AsyncReadExt}; -/// # async fn dox() { -/// let mut buffer = String::new(); -/// io::empty().read_to_string(&mut buffer).await.unwrap(); -/// assert!(buffer.is_empty()); -/// # } -/// ``` -/// -/// [std]: https://doc.rust-lang.org/std/io/fn.empty.html -pub fn empty() -> Empty { - Empty { _p: () } + /// Creates a new empty async reader. + /// + /// All reads from the returned reader will return `Poll::Ready(Ok(0))`. + /// + /// This is an asynchronous version of [`std::io::empty`][std]. + /// + /// # Examples + /// + /// A slightly sad example of not reading anything into a buffer: + /// + /// ```rust + /// # use tokio::io::{self, AsyncReadExt}; + /// # async fn dox() { + /// let mut buffer = String::new(); + /// io::empty().read_to_string(&mut buffer).await.unwrap(); + /// assert!(buffer.is_empty()); + /// # } + /// ``` + /// + /// [std]: https://doc.rust-lang.org/std/io/fn.empty.html + pub fn empty() -> Empty { + Empty { _p: () } + } } impl AsyncRead for Empty { diff --git a/tokio/src/io/util/flush.rs b/tokio/src/io/util/flush.rs index 61253ab5ba2..1465f304486 100644 --- a/tokio/src/io/util/flush.rs +++ b/tokio/src/io/util/flush.rs @@ -5,12 +5,14 @@ use std::io; use std::pin::Pin; use std::task::{Context, Poll}; -/// A future used to fully flush an I/O object. -/// -/// Created by the [`AsyncWriteExt::flush`] function. -#[derive(Debug)] -pub struct Flush<'a, A: ?Sized> { - a: &'a mut A, +cfg_io_util! { + /// A future used to fully flush an I/O object. + /// + /// Created by the [`AsyncWriteExt::flush`] function. + #[derive(Debug)] + pub struct Flush<'a, A: ?Sized> { + a: &'a mut A, + } } /// Creates a future which will entirely flush an I/O object. diff --git a/tokio/src/io/util/lines.rs b/tokio/src/io/util/lines.rs index 96c0cc27a95..0f1d946a805 100644 --- a/tokio/src/io/util/lines.rs +++ b/tokio/src/io/util/lines.rs @@ -11,6 +11,7 @@ pin_project! { /// Stream for the [`lines`](crate::io::AsyncBufReadExt::lines) method. #[derive(Debug)] #[must_use = "streams do nothing unless polled"] + #[cfg_attr(docsrs, doc(cfg(feature = "io-util")))] pub struct Lines { #[pin] reader: R, diff --git a/tokio/src/io/util/read.rs b/tokio/src/io/util/read.rs index 1fb8c8c8457..a8ca370ea87 100644 --- a/tokio/src/io/util/read.rs +++ b/tokio/src/io/util/read.rs @@ -18,15 +18,17 @@ where Read { reader, buf } } -/// A future which can be used to easily read available number of bytes to fill -/// a buffer. -/// -/// Created by the [`read`] function. -#[derive(Debug)] -#[must_use = "futures do nothing unless you `.await` or poll them"] -pub struct Read<'a, R: ?Sized> { - reader: &'a mut R, - buf: &'a mut [u8], +cfg_io_util! { + /// A future which can be used to easily read available number of bytes to fill + /// a buffer. + /// + /// Created by the [`read`] function. + #[derive(Debug)] + #[must_use = "futures do nothing unless you `.await` or poll them"] + pub struct Read<'a, R: ?Sized> { + reader: &'a mut R, + buf: &'a mut [u8], + } } impl Future for Read<'_, R> diff --git a/tokio/src/io/util/read_exact.rs b/tokio/src/io/util/read_exact.rs index 545b993009b..d6983c99530 100644 --- a/tokio/src/io/util/read_exact.rs +++ b/tokio/src/io/util/read_exact.rs @@ -21,16 +21,18 @@ where } } -/// Creates a future which will read exactly enough bytes to fill `buf`, -/// returning an error if EOF is hit sooner. -/// -/// On success the number of bytes is returned -#[derive(Debug)] -#[must_use = "futures do nothing unless you `.await` or poll them"] -pub struct ReadExact<'a, A: ?Sized> { - reader: &'a mut A, - buf: &'a mut [u8], - pos: usize, +cfg_io_util! { + /// Creates a future which will read exactly enough bytes to fill `buf`, + /// returning an error if EOF is hit sooner. + /// + /// On success the number of bytes is returned + #[derive(Debug)] + #[must_use = "futures do nothing unless you `.await` or poll them"] + pub struct ReadExact<'a, A: ?Sized> { + reader: &'a mut A, + buf: &'a mut [u8], + pos: usize, + } } fn eof() -> io::Error { diff --git a/tokio/src/io/util/read_line.rs b/tokio/src/io/util/read_line.rs index b917bd41fac..c5ee597486f 100644 --- a/tokio/src/io/util/read_line.rs +++ b/tokio/src/io/util/read_line.rs @@ -8,14 +8,16 @@ use std::pin::Pin; use std::str; use std::task::{Context, Poll}; -/// Future for the [`read_line`](crate::io::AsyncBufReadExt::read_line) method. -#[derive(Debug)] -#[must_use = "futures do nothing unless you `.await` or poll them"] -pub struct ReadLine<'a, R: ?Sized> { - reader: &'a mut R, - buf: &'a mut String, - bytes: Vec, - read: usize, +cfg_io_util! { + /// Future for the [`read_line`](crate::io::AsyncBufReadExt::read_line) method. + #[derive(Debug)] + #[must_use = "futures do nothing unless you `.await` or poll them"] + pub struct ReadLine<'a, R: ?Sized> { + reader: &'a mut R, + buf: &'a mut String, + bytes: Vec, + read: usize, + } } pub(crate) fn read_line<'a, R>(reader: &'a mut R, buf: &'a mut String) -> ReadLine<'a, R> diff --git a/tokio/src/io/util/read_to_end.rs b/tokio/src/io/util/read_to_end.rs index 0cd91f841c6..a2cd99bed09 100644 --- a/tokio/src/io/util/read_to_end.rs +++ b/tokio/src/io/util/read_to_end.rs @@ -8,6 +8,7 @@ use std::task::{Context, Poll}; #[derive(Debug)] #[must_use = "futures do nothing unless you `.await` or poll them"] +#[cfg_attr(docsrs, doc(cfg(feature = "io-util")))] pub struct ReadToEnd<'a, R: ?Sized> { reader: &'a mut R, buf: &'a mut Vec, diff --git a/tokio/src/io/util/read_to_string.rs b/tokio/src/io/util/read_to_string.rs index 0526d5ea1f6..e77d836dee9 100644 --- a/tokio/src/io/util/read_to_string.rs +++ b/tokio/src/io/util/read_to_string.rs @@ -6,14 +6,16 @@ use std::pin::Pin; use std::task::{Context, Poll}; use std::{io, mem, str}; -/// Future for the [`read_to_string`](super::AsyncReadExt::read_to_string) method. -#[derive(Debug)] -#[must_use = "futures do nothing unless you `.await` or poll them"] -pub struct ReadToString<'a, R: ?Sized> { - reader: &'a mut R, - buf: &'a mut String, - bytes: Vec, - start_len: usize, +cfg_io_util! { + /// Future for the [`read_to_string`](super::AsyncReadExt::read_to_string) method. + #[derive(Debug)] + #[must_use = "futures do nothing unless you `.await` or poll them"] + pub struct ReadToString<'a, R: ?Sized> { + reader: &'a mut R, + buf: &'a mut String, + bytes: Vec, + start_len: usize, + } } pub(crate) fn read_to_string<'a, R>(reader: &'a mut R, buf: &'a mut String) -> ReadToString<'a, R> diff --git a/tokio/src/io/util/read_until.rs b/tokio/src/io/util/read_until.rs index bdf1928bda1..1adeda66f05 100644 --- a/tokio/src/io/util/read_until.rs +++ b/tokio/src/io/util/read_until.rs @@ -6,14 +6,16 @@ use std::mem; use std::pin::Pin; use std::task::{Context, Poll}; -/// Future for the [`read_until`](crate::io::AsyncBufReadExt::read_until) method. -#[derive(Debug)] -#[must_use = "futures do nothing unless you `.await` or poll them"] -pub struct ReadUntil<'a, R: ?Sized> { - reader: &'a mut R, - byte: u8, - buf: &'a mut Vec, - read: usize, +cfg_io_util! { + /// Future for the [`read_until`](crate::io::AsyncBufReadExt::read_until) method. + #[derive(Debug)] + #[must_use = "futures do nothing unless you `.await` or poll them"] + pub struct ReadUntil<'a, R: ?Sized> { + reader: &'a mut R, + byte: u8, + buf: &'a mut Vec, + read: usize, + } } pub(crate) fn read_until<'a, R>( diff --git a/tokio/src/io/util/repeat.rs b/tokio/src/io/util/repeat.rs index 22e62a9377d..a74a153b5d4 100644 --- a/tokio/src/io/util/repeat.rs +++ b/tokio/src/io/util/repeat.rs @@ -4,42 +4,44 @@ use std::io; use std::pin::Pin; use std::task::{Context, Poll}; -/// An async reader which yields one byte over and over and over and over and -/// over and... -/// -/// This struct is generally created by calling [`repeat`][repeat]. Please -/// see the documentation of `repeat()` for more details. -/// -/// This is an asynchronous version of [`std::io::Repeat`][std]. -/// -/// [repeat]: fn.repeat.html -/// [std]: https://doc.rust-lang.org/std/io/struct.Repeat.html -#[derive(Debug)] -pub struct Repeat { - byte: u8, -} +cfg_io_util! { + /// An async reader which yields one byte over and over and over and over and + /// over and... + /// + /// This struct is generally created by calling [`repeat`][repeat]. Please + /// see the documentation of `repeat()` for more details. + /// + /// This is an asynchronous version of [`std::io::Repeat`][std]. + /// + /// [repeat]: fn.repeat.html + /// [std]: https://doc.rust-lang.org/std/io/struct.Repeat.html + #[derive(Debug)] + pub struct Repeat { + byte: u8, + } -/// Creates an instance of an async reader that infinitely repeats one byte. -/// -/// All reads from this reader will succeed by filling the specified buffer with -/// the given byte. -/// -/// This is an asynchronous version of [`std::io::repeat`][std]. -/// -/// # Examples -/// -/// ``` -/// # use tokio::io::{self, AsyncReadExt}; -/// # async fn dox() { -/// let mut buffer = [0; 3]; -/// io::repeat(0b101).read_exact(&mut buffer).await.unwrap(); -/// assert_eq!(buffer, [0b101, 0b101, 0b101]); -/// # } -/// ``` -/// -/// [std]: https://doc.rust-lang.org/std/io/fn.repeat.html -pub fn repeat(byte: u8) -> Repeat { - Repeat { byte } + /// Creates an instance of an async reader that infinitely repeats one byte. + /// + /// All reads from this reader will succeed by filling the specified buffer with + /// the given byte. + /// + /// This is an asynchronous version of [`std::io::repeat`][std]. + /// + /// # Examples + /// + /// ``` + /// # use tokio::io::{self, AsyncReadExt}; + /// # async fn dox() { + /// let mut buffer = [0; 3]; + /// io::repeat(0b101).read_exact(&mut buffer).await.unwrap(); + /// assert_eq!(buffer, [0b101, 0b101, 0b101]); + /// # } + /// ``` + /// + /// [std]: https://doc.rust-lang.org/std/io/fn.repeat.html + pub fn repeat(byte: u8) -> Repeat { + Repeat { byte } + } } impl AsyncRead for Repeat { diff --git a/tokio/src/io/util/shutdown.rs b/tokio/src/io/util/shutdown.rs index ee7f4592fd8..f24e2885414 100644 --- a/tokio/src/io/util/shutdown.rs +++ b/tokio/src/io/util/shutdown.rs @@ -5,12 +5,14 @@ use std::io; use std::pin::Pin; use std::task::{Context, Poll}; -/// A future used to shutdown an I/O object. -/// -/// Created by the [`AsyncWriteExt::shutdown`] function. -#[derive(Debug)] -pub struct Shutdown<'a, A: ?Sized> { - a: &'a mut A, +cfg_io_util! { + /// A future used to shutdown an I/O object. + /// + /// Created by the [`AsyncWriteExt::shutdown`] function. + #[derive(Debug)] + pub struct Shutdown<'a, A: ?Sized> { + a: &'a mut A, + } } /// Creates a future which will shutdown an I/O object. diff --git a/tokio/src/io/util/sink.rs b/tokio/src/io/util/sink.rs index 483636589c7..74802f979e7 100644 --- a/tokio/src/io/util/sink.rs +++ b/tokio/src/io/util/sink.rs @@ -5,39 +5,41 @@ use std::io; use std::pin::Pin; use std::task::{Context, Poll}; -/// An async writer which will move data into the void. -/// -/// This struct is generally created by calling [`sink`][sink]. Please -/// see the documentation of `sink()` for more details. -/// -/// This is an asynchronous version of `std::io::Sink`. -/// -/// [sink]: fn.sink.html -pub struct Sink { - _p: (), -} +cfg_io_util! { + /// An async writer which will move data into the void. + /// + /// This struct is generally created by calling [`sink`][sink]. Please + /// see the documentation of `sink()` for more details. + /// + /// This is an asynchronous version of `std::io::Sink`. + /// + /// [sink]: fn.sink.html + pub struct Sink { + _p: (), + } -/// Creates an instance of an async writer which will successfully consume all -/// data. -/// -/// All calls to `poll_write` on the returned instance will return -/// `Poll::Ready(Ok(buf.len()))` and the contents of the buffer will not be -/// inspected. -/// -/// This is an asynchronous version of `std::io::sink`. -/// -/// # Examples -/// -/// ```rust -/// # use tokio::io::{self, AsyncWriteExt}; -/// # async fn dox() { -/// let buffer = vec![1, 2, 3, 5, 8]; -/// let num_bytes = io::sink().write(&buffer).await.unwrap(); -/// assert_eq!(num_bytes, 5); -/// # } -/// ``` -pub fn sink() -> Sink { - Sink { _p: () } + /// Creates an instance of an async writer which will successfully consume all + /// data. + /// + /// All calls to `poll_write` on the returned instance will return + /// `Poll::Ready(Ok(buf.len()))` and the contents of the buffer will not be + /// inspected. + /// + /// This is an asynchronous version of `std::io::sink`. + /// + /// # Examples + /// + /// ```rust + /// # use tokio::io::{self, AsyncWriteExt}; + /// # async fn dox() { + /// let buffer = vec![1, 2, 3, 5, 8]; + /// let num_bytes = io::sink().write(&buffer).await.unwrap(); + /// assert_eq!(num_bytes, 5); + /// # } + /// ``` + pub fn sink() -> Sink { + Sink { _p: () } + } } impl AsyncWrite for Sink { diff --git a/tokio/src/io/util/split.rs b/tokio/src/io/util/split.rs index be66f70c3f8..a2e168de12d 100644 --- a/tokio/src/io/util/split.rs +++ b/tokio/src/io/util/split.rs @@ -11,6 +11,7 @@ pin_project! { /// Stream for the [`split`](crate::io::AsyncBufReadExt::split) method. #[derive(Debug)] #[must_use = "streams do nothing unless polled"] + #[cfg_attr(docsrs, doc(cfg(feature = "io-util")))] pub struct Split { #[pin] reader: R, diff --git a/tokio/src/io/util/take.rs b/tokio/src/io/util/take.rs index 18332603682..5d6bd90aa31 100644 --- a/tokio/src/io/util/take.rs +++ b/tokio/src/io/util/take.rs @@ -10,6 +10,7 @@ pin_project! { /// Stream for the [`take`](super::AsyncReadExt::take) method. #[derive(Debug)] #[must_use = "streams do nothing unless you `.await` or poll them"] + #[cfg_attr(docsrs, doc(cfg(feature = "io-util")))] pub struct Take { #[pin] inner: R, diff --git a/tokio/src/io/util/write.rs b/tokio/src/io/util/write.rs index 42e59848b0f..758f8dbcc10 100644 --- a/tokio/src/io/util/write.rs +++ b/tokio/src/io/util/write.rs @@ -5,12 +5,14 @@ use std::io; use std::pin::Pin; use std::task::{Context, Poll}; -/// A future to write some of the buffer to an `AsyncWrite`. -#[derive(Debug)] -#[must_use = "futures do nothing unless you `.await` or poll them"] -pub struct Write<'a, W: ?Sized> { - writer: &'a mut W, - buf: &'a [u8], +cfg_io_util! { + /// A future to write some of the buffer to an `AsyncWrite`. + #[derive(Debug)] + #[must_use = "futures do nothing unless you `.await` or poll them"] + pub struct Write<'a, W: ?Sized> { + writer: &'a mut W, + buf: &'a [u8], + } } /// Tries to write some bytes from the given `buf` to the writer in an diff --git a/tokio/src/io/util/write_all.rs b/tokio/src/io/util/write_all.rs index d336e65db47..898006c56ca 100644 --- a/tokio/src/io/util/write_all.rs +++ b/tokio/src/io/util/write_all.rs @@ -6,11 +6,13 @@ use std::mem; use std::pin::Pin; use std::task::{Context, Poll}; -#[derive(Debug)] -#[must_use = "futures do nothing unless you `.await` or poll them"] -pub struct WriteAll<'a, W: ?Sized> { - writer: &'a mut W, - buf: &'a [u8], +cfg_io_util! { + #[derive(Debug)] + #[must_use = "futures do nothing unless you `.await` or poll them"] + pub struct WriteAll<'a, W: ?Sized> { + writer: &'a mut W, + buf: &'a [u8], + } } pub(crate) fn write_all<'a, W>(writer: &'a mut W, buf: &'a [u8]) -> WriteAll<'a, W> diff --git a/tokio/src/lib.rs b/tokio/src/lib.rs index a0f1c194406..c213ee89091 100644 --- a/tokio/src/lib.rs +++ b/tokio/src/lib.rs @@ -10,6 +10,7 @@ no_crate_inject, attr(deny(warnings, rust_2018_idioms), allow(dead_code, unused_variables)) ))] +#![cfg_attr(docsrs, feature(doc_cfg))] //! A runtime for writing reliable, asynchronous, and slim applications. //! @@ -71,7 +72,7 @@ //! [`tokio::task`]: crate::task //! [`spawn`]: crate::task::spawn() //! [`JoinHandle`]: crate::task::JoinHandle -//! [`blocking`]: task/index.html#blocking-and-yielding +//! [blocking]: task/index.html#blocking-and-yielding //! //! The [`tokio::sync`] module contains synchronization primitives to use when //! need to communicate or share data. These include: diff --git a/tokio/src/macros/cfg.rs b/tokio/src/macros/cfg.rs index a3146688d37..1e660d8f0ba 100644 --- a/tokio/src/macros/cfg.rs +++ b/tokio/src/macros/cfg.rs @@ -12,7 +12,11 @@ macro_rules! cfg_resource_drivers { macro_rules! cfg_blocking { ($($item:item)*) => { - $( #[cfg(feature = "blocking")] $item )* + $( + #[cfg(feature = "blocking")] + #[cfg_attr(docsrs, doc(cfg(feature = "blocking")))] + $item + )* } } @@ -50,12 +54,22 @@ macro_rules! cfg_not_blocking_impl { macro_rules! cfg_dns { ($($item:item)*) => { - $( #[cfg(feature = "dns")] $item )* + $( + #[cfg(feature = "dns")] + #[cfg_attr(docsrs, doc(cfg(feature = "dns")))] + $item + )* } } macro_rules! cfg_fs { - ($($item:item)*) => { $( #[cfg(feature = "fs")] $item )* } + ($($item:item)*) => { + $( + #[cfg(feature = "fs")] + #[cfg_attr(docsrs, doc(cfg(feature = "fs")))] + $item + )* + } } macro_rules! cfg_io_blocking { @@ -66,25 +80,40 @@ macro_rules! cfg_io_blocking { macro_rules! cfg_io_driver { ($($item:item)*) => { - $( #[cfg(feature = "io-driver")] $item )* + $( + #[cfg(feature = "io-driver")] + #[cfg_attr(docsrs, doc(cfg(feature = "io-driver")))] + $item + )* } } macro_rules! cfg_not_io_driver { ($($item:item)*) => { - $( #[cfg(not(feature = "io-driver"))] $item )* + $( + #[cfg(not(feature = "io-driver"))] + $item + )* } } macro_rules! cfg_io_std { ($($item:item)*) => { - $( #[cfg(feature = "io-std")] $item )* + $( + #[cfg(feature = "io-std")] + #[cfg_attr(docsrs, doc(cfg(feature = "io-std")))] + $item + )* } } macro_rules! cfg_io_util { ($($item:item)*) => { - $( #[cfg(feature = "io-util")] $item )* + $( + #[cfg(feature = "io-util")] + #[cfg_attr(docsrs, doc(cfg(feature = "io-util")))] + $item + )* } } @@ -110,6 +139,7 @@ macro_rules! cfg_macros { ($($item:item)*) => { $( #[cfg(feature = "macros")] + #[cfg_attr(docsrs, doc(cfg(feature = "macros")))] #[doc(inline)] $item )* @@ -120,6 +150,7 @@ macro_rules! cfg_process { ($($item:item)*) => { $( #[cfg(feature = "process")] + #[cfg_attr(docsrs, doc(cfg(feature = "process")))] #[cfg(not(loom))] $item )* diff --git a/tokio/src/process/mod.rs b/tokio/src/process/mod.rs index 63d6f19eb27..439b1d110ff 100644 --- a/tokio/src/process/mod.rs +++ b/tokio/src/process/mod.rs @@ -101,10 +101,14 @@ //! While similar to the standard library, this crate's `Child` type differs //! importantly in the behavior of `drop`. In the standard library, a child //! process will continue running after the instance of [`std::process::Child`] -//! is dropped. In this crate, however, because [`tokio::process::Child`][Child] is a +//! is dropped. In this crate, however, because [`tokio::process::Child`] is a //! future of the child's `ExitStatus`, a child process is terminated if //! `tokio::process::Child` is dropped. The behavior of the standard library can -//! be regained with the [`Child::forget`](crate::process::Child::forget) method. +//! be regained with the [`Child::forget`](crate::process::Child::forget) +//! method. +//! +//! [`Command`]: crate::process::Command +//! [`tokio::process::Child`]: crate::process::Child #[path = "unix/mod.rs"] #[cfg(unix)]