summaryrefslogtreecommitdiffstats
path: root/tokio
diff options
context:
space:
mode:
authorAlice Ryhl <alice@ryhl.io>2020-01-07 18:17:01 +0100
committerCarl Lerche <me@carllerche.com>2020-01-07 09:17:01 -0800
commit780d6f91a0b56c9cbfca01a9a4694f21eb670f96 (patch)
treef95d4d7d6d61fd1b68f32536750cc7c0b86fc465 /tokio
parent45da5f3510a61599c89dc458ecc859f13a81e255 (diff)
docs: improve tokio::io API documentation (#2060)
* Links are added where missing and examples are improved. * Improve `stdin`, `stdout`, and `stderr` documentation by going into more details regarding what can go wrong in concurrent situations and provide examples for `stdout` and `stderr`.
Diffstat (limited to 'tokio')
-rw-r--r--tokio/src/io/async_buf_read.rs8
-rw-r--r--tokio/src/io/async_seek.rs11
-rw-r--r--tokio/src/io/async_write.rs21
-rw-r--r--tokio/src/io/split.rs8
-rw-r--r--tokio/src/io/stderr.rs43
-rw-r--r--tokio/src/io/stdin.rs8
-rw-r--r--tokio/src/io/stdout.rs51
-rw-r--r--tokio/src/io/util/async_buf_read_ext.rs4
-rw-r--r--tokio/src/io/util/copy.rs4
-rw-r--r--tokio/src/io/util/empty.rs22
-rw-r--r--tokio/src/io/util/repeat.rs20
-rw-r--r--tokio/src/io/util/sink.rs29
12 files changed, 174 insertions, 55 deletions
diff --git a/tokio/src/io/async_buf_read.rs b/tokio/src/io/async_buf_read.rs
index 1499bd4f..18127351 100644
--- a/tokio/src/io/async_buf_read.rs
+++ b/tokio/src/io/async_buf_read.rs
@@ -7,9 +7,15 @@ use std::task::{Context, Poll};
/// Read bytes asynchronously.
///
-/// This trait inherits from `std::io::BufRead` and indicates that an I/O object is
+/// This trait inherits from [`std::io::BufRead`] and indicates that an I/O object is
/// **non-blocking**. All non-blocking I/O objects must return an error when
/// bytes are unavailable instead of blocking the current thread.
+///
+/// Utilities for working with `AsyncBufRead` values are provided by
+/// [`AsyncBufReadExt`].
+///
+/// [`std::io::BufRead`]: std::io::BufRead
+/// [`AsyncBufReadExt`]: crate::io::AsyncBufReadExt
pub trait AsyncBufRead: AsyncRead {
/// Attempt to return the contents of the internal buffer, filling it with more data
/// from the inner reader if it is empty.
diff --git a/tokio/src/io/async_seek.rs b/tokio/src/io/async_seek.rs
index d36d404f..f3e6fcdc 100644
--- a/tokio/src/io/async_seek.rs
+++ b/tokio/src/io/async_seek.rs
@@ -5,9 +5,16 @@ use std::task::{Context, Poll};
/// Seek bytes asynchronously.
///
-/// This trait is analogous to the `std::io::Seek` trait, but integrates
+/// This trait is analogous to the [`std::io::Seek`] trait, but integrates
/// with the asynchronous task system. In particular, the `start_seek`
-/// method, unlike `Seek::seek`, will not block the calling thread.
+/// method, unlike [`Seek::seek`], will not block the calling thread.
+///
+/// Utilities for working with `AsyncSeek` values are provided by
+/// [`AsyncSeekExt`].
+///
+/// [`std::io::Seek`]: std::io::Seek
+/// [`Seek::seek`]: std::io::Seek::seek()
+/// [`AsyncSeekExt`]: crate::io::AsyncSeekExt
pub trait AsyncSeek {
/// Attempt to seek to an offset, in bytes, in a stream.
///
diff --git a/tokio/src/io/async_write.rs b/tokio/src/io/async_write.rs
index 2d5e4578..8ae7cf84 100644
--- a/tokio/src/io/async_write.rs
+++ b/tokio/src/io/async_write.rs
@@ -6,11 +6,11 @@ use std::task::{Context, Poll};
/// Writes bytes asynchronously.
///
-/// The trait inherits from `std::io::Write` and indicates that an I/O object is
+/// The trait inherits from [`std::io::Write`] and indicates that an I/O object is
/// **nonblocking**. All non-blocking I/O objects must return an error when
/// bytes cannot be written instead of blocking the current thread.
///
-/// Specifically, this means that the `poll_write` function will return one of
+/// Specifically, this means that the [`poll_write`] function will return one of
/// the following:
///
/// * `Poll::Ready(Ok(n))` means that `n` bytes of data was immediately
@@ -26,14 +26,23 @@ use std::task::{Context, Poll};
/// * `Poll::Ready(Err(e))` for other errors are standard I/O errors coming from the
/// underlying object.
///
-/// This trait importantly means that the `write` method only works in the
-/// context of a future's task. The object may panic if used outside of a task.
+/// This trait importantly means that the [`write`][stdwrite] method only works in
+/// the context of a future's task. The object may panic if used outside of a task.
///
-/// Note that this trait also represents that the `Write::flush` method works
-/// very similarly to the `write` method, notably that `Ok(())` means that the
+/// Note that this trait also represents that the [`Write::flush`][stdflush] method
+/// works very similarly to the `write` method, notably that `Ok(())` means that the
/// writer has successfully been flushed, a "would block" error means that the
/// current task is ready to receive a notification when flushing can make more
/// progress, and otherwise normal errors can happen as well.
+///
+/// Utilities for working with `AsyncWrite` values are provided by
+/// [`AsyncWriteExt`].
+///
+/// [`std::io::Write`]: std::io::Write
+/// [`poll_write`]: AsyncWrite::poll_write()
+/// [stdwrite]: std::io::Write::write()
+/// [stdflush]: std::io::Write::flush()
+/// [`AsyncWriteExt`]: crate::io::AsyncWriteExt
pub trait AsyncWrite {
/// Attempt to write bytes from `buf` into the object.
///
diff --git a/tokio/src/io/split.rs b/tokio/src/io/split.rs
index 50cd498c..7f21533e 100644
--- a/tokio/src/io/split.rs
+++ b/tokio/src/io/split.rs
@@ -17,12 +17,12 @@ use std::sync::Arc;
use std::task::{Context, Poll};
cfg_io_util! {
- /// The readable half of a value returned from `split`.
+ /// The readable half of a value returned from [`split`](split()).
pub struct ReadHalf<T> {
inner: Arc<Inner<T>>,
}
- /// The writable half of a value returned from `split`.
+ /// The writable half of a value returned from [`split`](split()).
pub struct WriteHalf<T> {
inner: Arc<Inner<T>>,
}
@@ -30,8 +30,8 @@ cfg_io_util! {
/// 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`.
+ /// To restore this read/write object from its `ReadHalf` and
+ /// `WriteHalf` use [`unsplit`](ReadHalf::unsplit()).
pub fn split<T>(stream: T) -> (ReadHalf<T>, WriteHalf<T>)
where
T: AsyncRead + AsyncWrite,
diff --git a/tokio/src/io/stderr.rs b/tokio/src/io/stderr.rs
index d91dd481..fa5d0fbd 100644
--- a/tokio/src/io/stderr.rs
+++ b/tokio/src/io/stderr.rs
@@ -9,13 +9,30 @@ use std::task::Poll;
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.
+ /// Concurrent writes to stderr must be executed with care: Only individual
+ /// writes to this [`AsyncWrite`] are guaranteed to be intact. In particular
+ /// you should be aware that writes using [`write_all`] are not guaranteed
+ /// to occur as a single write, so multiple threads writing data with
+ /// [`write_all`] may result in interleaved output.
///
/// Created by the [`stderr`] function.
///
/// [`stderr`]: stderr()
/// [`AsyncWrite`]: AsyncWrite
+ /// [`write_all`]: crate::io::AsyncWriteExt::write_all()
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use tokio::io::{self, AsyncWriteExt};
+ ///
+ /// #[tokio::main]
+ /// async fn main() -> io::Result<()> {
+ /// let mut stderr = io::stdout();
+ /// stderr.write_all(b"Print some error here.").await?;
+ /// Ok(())
+ /// }
+ /// ```
#[derive(Debug)]
pub struct Stderr {
std: Blocking<std::io::Stderr>,
@@ -25,6 +42,28 @@ cfg_io_std! {
///
/// The returned handle allows writing to standard error from the within the
/// Tokio runtime.
+ ///
+ /// Concurrent writes to stderr must be executed with care: Only individual
+ /// writes to this [`AsyncWrite`] are guaranteed to be intact. In particular
+ /// you should be aware that writes using [`write_all`] are not guaranteed
+ /// to occur as a single write, so multiple threads writing data with
+ /// [`write_all`] may result in interleaved output.
+ ///
+ /// [`AsyncWrite`]: AsyncWrite
+ /// [`write_all`]: crate::io::AsyncWriteExt::write_all()
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use tokio::io::{self, AsyncWriteExt};
+ ///
+ /// #[tokio::main]
+ /// async fn main() -> io::Result<()> {
+ /// let mut stderr = io::stdout();
+ /// stderr.write_all(b"Print some error here.").await?;
+ /// Ok(())
+ /// }
+ /// ```
pub fn stderr() -> Stderr {
let std = io::stderr();
Stderr {
diff --git a/tokio/src/io/stdin.rs b/tokio/src/io/stdin.rs
index 81bc5abb..6c937447 100644
--- a/tokio/src/io/stdin.rs
+++ b/tokio/src/io/stdin.rs
@@ -13,7 +13,7 @@ cfg_io_std! {
/// 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
+ /// 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.
@@ -31,6 +31,12 @@ cfg_io_std! {
///
/// The returned handle allows reading from standard input from the within the
/// Tokio runtime.
+ ///
+ /// 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.
pub fn stdin() -> Stdin {
let std = io::stdin();
Stdin {
diff --git a/tokio/src/io/stdout.rs b/tokio/src/io/stdout.rs
index 86de1c58..ff1bfd5d 100644
--- a/tokio/src/io/stdout.rs
+++ b/tokio/src/io/stdout.rs
@@ -9,13 +9,30 @@ use std::task::Poll;
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.
+ /// Concurrent writes to stdout must be executed with care: Only individual
+ /// writes to this [`AsyncWrite`] are guaranteed to be intact. In particular
+ /// you should be aware that writes using [`write_all`] are not guaranteed
+ /// to occur as a single write, so multiple threads writing data with
+ /// [`write_all`] may result in interleaved output.
///
/// Created by the [`stdout`] function.
///
- /// [`stdout`]: fn.stdout.html
- /// [`AsyncWrite`]: trait.AsyncWrite.html
+ /// [`stdout`]: stdout()
+ /// [`AsyncWrite`]: AsyncWrite
+ /// [`write_all`]: crate::io::AsyncWriteExt::write_all()
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use tokio::io::{self, AsyncWriteExt};
+ ///
+ /// #[tokio::main]
+ /// async fn main() -> io::Result<()> {
+ /// let mut stdout = io::stdout();
+ /// stdout.write_all(b"Hello world!").await?;
+ /// Ok(())
+ /// }
+ /// ```
#[derive(Debug)]
pub struct Stdout {
std: Blocking<std::io::Stdout>,
@@ -23,8 +40,30 @@ cfg_io_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.
+ /// The returned handle allows writing to standard out from the within the
+ /// Tokio runtime.
+ ///
+ /// Concurrent writes to stdout must be executed with care: Only individual
+ /// writes to this [`AsyncWrite`] are guaranteed to be intact. In particular
+ /// you should be aware that writes using [`write_all`] are not guaranteed
+ /// to occur as a single write, so multiple threads writing data with
+ /// [`write_all`] may result in interleaved output.
+ ///
+ /// [`AsyncWrite`]: AsyncWrite
+ /// [`write_all`]: crate::io::AsyncWriteExt::write_all()
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use tokio::io::{self, AsyncWriteExt};
+ ///
+ /// #[tokio::main]
+ /// async fn main() -> io::Result<()> {
+ /// let mut stdout = io::stdout();
+ /// stdout.write_all(b"Hello world!").await?;
+ /// Ok(())
+ /// }
+ /// ```
pub fn stdout() -> Stdout {
let std = io::stdout();
Stdout {
diff --git a/tokio/src/io/util/async_buf_read_ext.rs b/tokio/src/io/util/async_buf_read_ext.rs
index b2930652..90789744 100644
--- a/tokio/src/io/util/async_buf_read_ext.rs
+++ b/tokio/src/io/util/async_buf_read_ext.rs
@@ -5,7 +5,9 @@ use crate::io::util::split::{split, Split};
use crate::io::AsyncBufRead;
cfg_io_util! {
- /// An extension trait which adds utility methods to `AsyncBufRead` types.
+ /// An extension trait which adds utility methods to [`AsyncBufRead`] types.
+ ///
+ /// [`AsyncBufRead`]: crate::io::AsyncBufRead
pub trait AsyncBufReadExt: AsyncBufRead {
/// Read all bytes into `buf` until the delimiter `byte` or EOF is reached.
///
diff --git a/tokio/src/io/util/copy.rs b/tokio/src/io/util/copy.rs
index 0a2aea73..8e0058c1 100644
--- a/tokio/src/io/util/copy.rs
+++ b/tokio/src/io/util/copy.rs
@@ -36,6 +36,8 @@ cfg_io_util! {
///
/// This is an asynchronous version of [`std::io::copy`][std].
///
+ /// [std]: std::io::copy
+ ///
/// # Errors
///
/// The returned future will finish with an error will return an error
@@ -56,8 +58,6 @@ cfg_io_util! {
/// # Ok(())
/// # }
/// ```
- ///
- /// [std]: std::io::copy
pub fn copy<'a, R, W>(reader: &'a mut R, writer: &'a mut W) -> Copy<'a, R, W>
where
R: AsyncRead + Unpin + ?Sized,
diff --git a/tokio/src/io/util/empty.rs b/tokio/src/io/util/empty.rs
index 054d8e60..7075612f 100644
--- a/tokio/src/io/util/empty.rs
+++ b/tokio/src/io/util/empty.rs
@@ -6,7 +6,7 @@ use std::pin::Pin;
use std::task::{Context, Poll};
cfg_io_util! {
- // An async reader which is always at EOF.
+ /// 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.
@@ -14,7 +14,7 @@ cfg_io_util! {
/// 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
+ /// [std]: std::io::empty
pub struct Empty {
_p: (),
}
@@ -25,20 +25,22 @@ cfg_io_util! {
///
/// This is an asynchronous version of [`std::io::empty`][std].
///
+ /// [std]: std::io::empty
+ ///
/// # 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());
- /// # }
/// ```
+ /// use tokio::io::{self, AsyncReadExt};
///
- /// [std]: https://doc.rust-lang.org/std/io/fn.empty.html
+ /// #[tokio::main]
+ /// async fn main() {
+ /// let mut buffer = String::new();
+ /// io::empty().read_to_string(&mut buffer).await.unwrap();
+ /// assert!(buffer.is_empty());
+ /// }
+ /// ```
pub fn empty() -> Empty {
Empty { _p: () }
}
diff --git a/tokio/src/io/util/repeat.rs b/tokio/src/io/util/repeat.rs
index a74a153b..064775ee 100644
--- a/tokio/src/io/util/repeat.rs
+++ b/tokio/src/io/util/repeat.rs
@@ -14,7 +14,7 @@ cfg_io_util! {
/// 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
+ /// [std]: std::io::Repeat
#[derive(Debug)]
pub struct Repeat {
byte: u8,
@@ -27,18 +27,20 @@ cfg_io_util! {
///
/// This is an asynchronous version of [`std::io::repeat`][std].
///
+ /// [std]: std::io::repeat
+ ///
/// # 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]);
- /// # }
- /// ```
+ /// use tokio::io::{self, AsyncReadExt};
///
- /// [std]: https://doc.rust-lang.org/std/io/fn.repeat.html
+ /// #[tokio::main]
+ /// async fn main() {
+ /// let mut buffer = [0; 3];
+ /// io::repeat(0b101).read_exact(&mut buffer).await.unwrap();
+ /// assert_eq!(buffer, [0b101, 0b101, 0b101]);
+ /// }
+ /// ```
pub fn repeat(byte: u8) -> Repeat {
Repeat { byte }
}
diff --git a/tokio/src/io/util/sink.rs b/tokio/src/io/util/sink.rs
index 74802f97..05ee773f 100644
--- a/tokio/src/io/util/sink.rs
+++ b/tokio/src/io/util/sink.rs
@@ -11,9 +11,10 @@ cfg_io_util! {
/// 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`.
+ /// This is an asynchronous version of [`std::io::Sink`][std].
///
- /// [sink]: fn.sink.html
+ /// [sink]: sink()
+ /// [std]: std::io::Sink
pub struct Sink {
_p: (),
}
@@ -21,21 +22,27 @@ cfg_io_util! {
/// Creates an instance of an async writer which will successfully consume all
/// data.
///
- /// All calls to `poll_write` on the returned instance will return
+ /// 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`.
+ /// This is an asynchronous version of [`std::io::sink`][std].
+ ///
+ /// [`poll_write`]: crate::io::AsyncWrite::poll_write()
+ /// [std]: 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);
- /// # }
+ /// ```
+ /// use tokio::io::{self, AsyncWriteExt};
+ ///
+ /// #[tokio::main]
+ /// async fn main() -> io::Result<()> {
+ /// let buffer = vec![1, 2, 3, 5, 8];
+ /// let num_bytes = io::sink().write(&buffer).await?;
+ /// assert_eq!(num_bytes, 5);
+ /// Ok(())
+ /// }
/// ```
pub fn sink() -> Sink {
Sink { _p: () }