mirror of
https://github.com/tokio-rs/tokio.git
synced 2026-08-07 00:00:09 +02:00
docs: improve tokio::io API documentation (#1815)
Adds method level documentation for `tokio::io`.
This commit is contained in:
+9
-8
@@ -22,12 +22,13 @@
|
||||
|
||||
#![warn(rust_2018_idioms)]
|
||||
|
||||
use futures::{future::try_join, FutureExt};
|
||||
use std::{env, error::Error};
|
||||
use tokio::{
|
||||
io::AsyncReadExt,
|
||||
net::{TcpListener, TcpStream},
|
||||
};
|
||||
use tokio::io;
|
||||
use tokio::net::{TcpListener, TcpStream};
|
||||
|
||||
use futures::future::try_join;
|
||||
use futures::FutureExt;
|
||||
use std::env;
|
||||
use std::error::Error;
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<(), Box<dyn Error>> {
|
||||
@@ -58,8 +59,8 @@ async fn transfer(mut inbound: TcpStream, proxy_addr: String) -> Result<(), Box<
|
||||
let (mut ri, mut wi) = inbound.split();
|
||||
let (mut ro, mut wo) = outbound.split();
|
||||
|
||||
let client_to_server = ri.copy(&mut wo);
|
||||
let server_to_client = ro.copy(&mut wi);
|
||||
let client_to_server = io::copy(&mut ri, &mut wo);
|
||||
let server_to_client = io::copy(&mut ro, &mut wi);
|
||||
|
||||
try_join(client_to_server, server_to_client).await?;
|
||||
|
||||
|
||||
@@ -5,11 +5,13 @@ use std::ops::DerefMut;
|
||||
use std::pin::Pin;
|
||||
use std::task::{Context, Poll};
|
||||
|
||||
/// Read bytes asynchronously.
|
||||
/// Read bytes from a source.
|
||||
///
|
||||
/// This trait inherits from `std::io::Read` 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.
|
||||
/// This trait is analogous to the [`std::io::Read`] trait, but integrates with
|
||||
/// the asynchronous task system. In particular, the [`poll_read`] method,
|
||||
/// unlike [`Read::read`], will automatically queue the current task for wakeup
|
||||
/// and return if data is not yet available, rather than blocking the calling
|
||||
/// thread.
|
||||
///
|
||||
/// Specifically, this means that the `poll_read` function will return one of
|
||||
/// the following:
|
||||
@@ -30,6 +32,14 @@ use std::task::{Context, Poll};
|
||||
///
|
||||
/// This trait importantly means that the `read` method only works in the
|
||||
/// context of a future's task. The object may panic if used outside of a task.
|
||||
///
|
||||
/// Utilities for working with `AsyncRead` values are provided by
|
||||
/// [`AsyncReadExt`].
|
||||
///
|
||||
/// [`poll_read`]: AsyncRead::poll_read
|
||||
/// [`std::io::Read`]: std::io::Read
|
||||
/// [`Read::read`]: std::io::Read::read
|
||||
/// [`AsyncReadExt`]: crate::io::AsyncReadExt
|
||||
pub trait AsyncRead {
|
||||
/// Prepares an uninitialized buffer to be safe to pass to `read`. Returns
|
||||
/// `true` if the supplied buffer was zeroed out.
|
||||
|
||||
+17
-10
@@ -1,6 +1,6 @@
|
||||
#![cfg_attr(loom, allow(dead_code, unreachable_pub))]
|
||||
|
||||
//! Asynchronous I/O.
|
||||
//! Traits, helpers, and type definitions for asynchronous I/O functionality.
|
||||
//!
|
||||
//! This module is the asynchronous version of `std::io`. Primarily, it
|
||||
//! defines two traits, [`AsyncRead`] and [`AsyncWrite`], which are asynchronous
|
||||
@@ -15,7 +15,19 @@
|
||||
//! type will _yield_ to the Tokio scheduler when IO is not ready, rather than
|
||||
//! blocking. This allows other tasks to run while waiting on IO.
|
||||
//!
|
||||
//! In asynchronous programs, Tokio's [`AsyncRead`] and [`AsyncWrite`] traits
|
||||
//! Another difference is that [`AsyncRead`] and [`AsyncWrite`] only contain
|
||||
//! core methods needed to provide asynchronous reading and writing
|
||||
//! functionality. Instead, utility methods are defined in the [`AsyncReadExt`]
|
||||
//! and [`AsyncWriteExt`] extension traits. These traits are automatically
|
||||
//! implemented for all values that implement [`AsyncRead`] and [`AsyncWrite`]
|
||||
//! respectively.
|
||||
//!
|
||||
//! End users will rarely interact directly with [`AsyncRead`] and
|
||||
//! [`AsyncWrite`]. Instead, they will use the async functions defined in the
|
||||
//! extension traits. Library authors are expected to implement [`AsyncRead`]
|
||||
//! and [`AsyncWrite`] in order to provide types that behave like byte streams.
|
||||
//!
|
||||
//! Even with these differences, Tokio's [`AsyncRead`] and [`AsyncWrite`] traits
|
||||
//! can be used in almost exactly the same manner as the standard library's
|
||||
//! `Read` and `Write`. Most types in the standard library that implement `Read`
|
||||
//! and `Write` have asynchronous equivalents in `tokio` that implement
|
||||
@@ -26,8 +38,7 @@
|
||||
//! can do the same with [`tokio::fs::File`][`File`]:
|
||||
//!
|
||||
//! ```no_run
|
||||
//! use tokio::io;
|
||||
//! use tokio::prelude::*;
|
||||
//! use tokio::io::{self, AsyncReadExt};
|
||||
//! use tokio::fs::File;
|
||||
//!
|
||||
//! #[tokio::main]
|
||||
@@ -64,10 +75,8 @@
|
||||
//! extra methods to any async reader:
|
||||
//!
|
||||
//! ```no_run
|
||||
//! use tokio::io;
|
||||
//! use tokio::io::BufReader;
|
||||
//! use tokio::io::{self, BufReader, AsyncBufReadExt};
|
||||
//! use tokio::fs::File;
|
||||
//! use tokio::prelude::*;
|
||||
//!
|
||||
//! #[tokio::main]
|
||||
//! async fn main() -> io::Result<()> {
|
||||
@@ -87,10 +96,8 @@
|
||||
//! to [`write`](crate::io::AsyncWriteExt::write):
|
||||
//!
|
||||
//! ```no_run
|
||||
//! use tokio::io;
|
||||
//! use tokio::io::BufWriter;
|
||||
//! use tokio::io::{self, BufWriter, AsyncWriteExt};
|
||||
//! use tokio::fs::File;
|
||||
//! use tokio::prelude::*;
|
||||
//!
|
||||
//! #[tokio::main]
|
||||
//! async fn main() -> io::Result<()> {
|
||||
|
||||
@@ -1,20 +1,70 @@
|
||||
use crate::io::util::chain::{chain, Chain};
|
||||
use crate::io::util::copy::{copy, Copy};
|
||||
use crate::io::util::read::{read, Read};
|
||||
use crate::io::util::read_exact::{read_exact, ReadExact};
|
||||
use crate::io::util::read_to_end::{read_to_end, ReadToEnd};
|
||||
use crate::io::util::read_to_string::{read_to_string, ReadToString};
|
||||
use crate::io::util::take::{take, Take};
|
||||
use crate::io::{AsyncRead, AsyncWrite};
|
||||
use crate::io::AsyncRead;
|
||||
|
||||
cfg_io_util! {
|
||||
/// An extension trait which adds utility methods to `AsyncRead` types.
|
||||
/// Read bytes from a source.
|
||||
///
|
||||
/// Implemented as an extention trait, adding utility methods to all
|
||||
/// [`AsyncRead`] types. Callers will tend to import this trait instead of
|
||||
/// [`AsyncRead`].
|
||||
///
|
||||
/// As a convenience, this trait may be imported using the [`prelude`]:
|
||||
///
|
||||
/// ```no_run
|
||||
/// use tokio::fs::File;
|
||||
/// use tokio::prelude::*;
|
||||
///
|
||||
/// #[tokio::main]
|
||||
/// async fn main() -> io::Result<()> {
|
||||
/// let mut f = File::open("foo.txt").await?;
|
||||
/// let mut buffer = [0; 10];
|
||||
///
|
||||
/// // The `read` method is defined by this trait.
|
||||
/// let n = f.read(&mut buffer[..]).await?;
|
||||
///
|
||||
/// Ok(())
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// See [module][crate::io] documentation for more details.
|
||||
///
|
||||
/// [`AsyncRead`]: AsyncRead
|
||||
/// [`prelude`]: crate::prelude
|
||||
pub trait AsyncReadExt: AsyncRead {
|
||||
/// Creates an adaptor which will chain this stream with another.
|
||||
/// Create a new `AsyncRead` instance that chains this stream with
|
||||
/// `next`.
|
||||
///
|
||||
/// 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`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// [`File`][crate::fs::File]s implement `AsyncRead`:
|
||||
///
|
||||
/// ```no_run
|
||||
/// use tokio::fs::File;
|
||||
/// use tokio::io::{self, AsyncReadExt};
|
||||
///
|
||||
/// #[tokio::main]
|
||||
/// async fn main() -> io::Result<()> {
|
||||
/// let f1 = File::open("foo.txt").await?;
|
||||
/// let f2 = File::open("bar.txt").await?;
|
||||
///
|
||||
/// let mut handle = f1.chain(f2);
|
||||
/// let mut buffer = String::new();
|
||||
///
|
||||
/// // read the value into a String. We could use any AsyncRead
|
||||
/// // method here, this is just one example.
|
||||
/// handle.read_to_string(&mut buffer).await?;
|
||||
/// Ok(())
|
||||
/// }
|
||||
/// ```
|
||||
fn chain<R>(self, next: R) -> Chain<Self, R>
|
||||
where
|
||||
Self: Sized,
|
||||
@@ -23,56 +73,222 @@ cfg_io_util! {
|
||||
chain(self, next)
|
||||
}
|
||||
|
||||
/// Copy all data from `self` into the provided `AsyncWrite`.
|
||||
/// Pull some bytes from this source into the specified buffer,
|
||||
/// returning how many bytes were read.
|
||||
///
|
||||
/// 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.
|
||||
/// Equivalent to:
|
||||
///
|
||||
/// 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.
|
||||
/// ```ignore
|
||||
/// async fn read(&mut self, buf: &mut [u8]) -> io::Result<usize>;
|
||||
/// ```
|
||||
///
|
||||
/// 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>
|
||||
/// This function does not provide any guarantees about whether it
|
||||
/// completes immediately or asynchronously
|
||||
///
|
||||
/// If the return value of this method is `Ok(n)`, then it must be
|
||||
/// guaranteed that `0 <= n <= buf.len()`. A nonzero `n` value indicates
|
||||
/// that the buffer `buf` has been filled in with `n` bytes of data from
|
||||
/// this source. If `n` is `0`, then it can indicate one of two
|
||||
/// scenarios:
|
||||
///
|
||||
/// 1. This reader has reached its "end of file" and will likely no longer
|
||||
/// be able to produce bytes. Note that this does not mean that the
|
||||
/// reader will *always* no longer be able to produce bytes.
|
||||
/// 2. The buffer specified was 0 bytes in length.
|
||||
///
|
||||
/// No guarantees are provided about the contents of `buf` when this
|
||||
/// function is called, implementations cannot rely on any property of the
|
||||
/// contents of `buf` being true. It is recommended that *implementations*
|
||||
/// only write data to `buf` instead of reading its contents.
|
||||
///
|
||||
/// Correspondingly, however, *callers* of this method may not assume
|
||||
/// any guarantees about how the implementation uses `buf`. It is
|
||||
/// possible that the code that's supposed to write to the buffer might
|
||||
/// also read from it. It is your responsibility to make sure that `buf`
|
||||
/// is initialized before calling `read`.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// If this function encounters any form of I/O or other error, an error
|
||||
/// variant will be returned. If an error is returned then it must be
|
||||
/// guaranteed that no bytes were read.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// [`File`][crate::fs::File]s implement `Read`:
|
||||
///
|
||||
/// ```no_run
|
||||
/// use tokio::fs::File;
|
||||
/// use tokio::io::{self, AsyncReadExt};
|
||||
///
|
||||
/// #[tokio::main]
|
||||
/// async fn main() -> io::Result<()> {
|
||||
/// let mut f = File::open("foo.txt").await?;
|
||||
/// let mut buffer = [0; 10];
|
||||
///
|
||||
/// // read up to 10 bytes
|
||||
/// let n = f.read(&mut buffer[..]).await?;
|
||||
///
|
||||
/// println!("The bytes: {:?}", &buffer[..n]);
|
||||
/// Ok(())
|
||||
/// }
|
||||
/// ```
|
||||
fn read<'a>(&'a mut self, buf: &'a mut [u8]) -> Read<'a, Self>
|
||||
where
|
||||
Self: Unpin,
|
||||
{
|
||||
read(self, dst)
|
||||
read(self, buf)
|
||||
}
|
||||
|
||||
/// 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>
|
||||
/// Read the exact number of bytes required to fill `buf`.
|
||||
///
|
||||
/// Equivalent to:
|
||||
///
|
||||
/// ```ignore
|
||||
/// async fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<usize>;
|
||||
/// ```
|
||||
///
|
||||
/// This function reads as many bytes as necessary to completely fill
|
||||
/// the specified buffer `buf`.
|
||||
///
|
||||
/// No guarantees are provided about the contents of `buf` when this
|
||||
/// function is called, implementations cannot rely on any property of
|
||||
/// the contents of `buf` being true. It is recommended that
|
||||
/// implementations only write data to `buf` instead of reading its
|
||||
/// contents.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// If the operation encounters an "end of file" before completely
|
||||
/// filling the buffer, it returns an error of the kind
|
||||
/// [`ErrorKind::UnexpectedEof`]. The contents of `buf` are unspecified
|
||||
/// in this case.
|
||||
///
|
||||
/// If any other read error is encountered then the operation
|
||||
/// immediately returns. The contents of `buf` are unspecified in this
|
||||
/// case.
|
||||
///
|
||||
/// If this operation returns an error, it is unspecified how many bytes
|
||||
/// it has read, but it will never read more than would be necessary to
|
||||
/// completely fill the buffer.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// [`File`][crate::fs::File]s implement `Read`:
|
||||
///
|
||||
/// ```no_run
|
||||
/// use tokio::fs::File;
|
||||
/// use tokio::io::{self, AsyncReadExt};
|
||||
///
|
||||
/// #[tokio::main]
|
||||
/// async fn main() -> io::Result<()> {
|
||||
/// let mut f = File::open("foo.txt").await?;
|
||||
/// let mut buffer = [0; 10];
|
||||
///
|
||||
/// // read exactly 10 bytes
|
||||
/// f.read_exact(&mut buffer).await?;
|
||||
/// Ok(())
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// [`ErrorKind::UnexpectedEof`]: std::io::ErrorKind::UnexpectedEof
|
||||
fn read_exact<'a>(&'a mut self, buf: &'a mut [u8]) -> ReadExact<'a, Self>
|
||||
where
|
||||
Self: Unpin,
|
||||
{
|
||||
read_exact(self, dst)
|
||||
read_exact(self, buf)
|
||||
}
|
||||
|
||||
/// Read all bytes until EOF in this source, placing them into `dst`.
|
||||
/// Read all bytes until EOF in this source, placing them into `buf`.
|
||||
///
|
||||
/// On success the total number of bytes read is returned.
|
||||
fn read_to_end<'a>(&'a mut self, dst: &'a mut Vec<u8>) -> ReadToEnd<'a, Self>
|
||||
/// Equivalent to:
|
||||
///
|
||||
/// ```ignore
|
||||
/// async fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize>;
|
||||
/// ```
|
||||
///
|
||||
/// All bytes read from this source will be appended to the specified
|
||||
/// buffer `buf`. This function will continuously call [`read()`] to
|
||||
/// append more data to `buf` until [`read()`][read] returns `Ok(0)`.
|
||||
///
|
||||
/// If successful, the total number of bytes read is returned.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// If a read error is encountered then the `read_to_end` operation
|
||||
/// immediately completes. Any bytes which have already been read will
|
||||
/// be appended to `buf`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// [`File`][crate::fs::File]s implement `Read`:
|
||||
///
|
||||
/// ```no_run
|
||||
/// use tokio::io::{self, AsyncReadExt};
|
||||
/// use tokio::fs::File;
|
||||
///
|
||||
/// #[tokio::main]
|
||||
/// async fn main() -> io::Result<()> {
|
||||
/// let mut f = File::open("foo.txt").await?;
|
||||
/// let mut buffer = Vec::new();
|
||||
///
|
||||
/// // read the whole file
|
||||
/// f.read_to_end(&mut buffer).await?;
|
||||
/// Ok(())
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// (See also the [`tokio::fs::read`] convenience function for reading from a
|
||||
/// file.)
|
||||
///
|
||||
/// [`tokio::fs::read`]: crate::fs::read::read
|
||||
fn read_to_end<'a>(&'a mut self, buf: &'a mut Vec<u8>) -> ReadToEnd<'a, Self>
|
||||
where
|
||||
Self: Unpin,
|
||||
{
|
||||
read_to_end(self, dst)
|
||||
read_to_end(self, buf)
|
||||
}
|
||||
|
||||
/// Read all bytes until EOF in this source, placing them into `dst`.
|
||||
/// Read all bytes until EOF in this source, appending them to `buf`.
|
||||
///
|
||||
/// On success the total number of bytes read is returned.
|
||||
/// Equivalent to:
|
||||
///
|
||||
/// ```ignore
|
||||
/// async fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize>;
|
||||
/// ```
|
||||
///
|
||||
/// If successful, the number of bytes which were read and appended to
|
||||
/// `buf` is returned.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// If the data in this stream is *not* valid UTF-8 then an error is
|
||||
/// returned and `buf` is unchanged.
|
||||
///
|
||||
/// See [`read_to_end`][AsyncReadExt::read_to_end] for other error semantics.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// [`File`][crate::fs::File]s implement `Read`:
|
||||
///
|
||||
/// ```no_run
|
||||
/// use tokio::io::{self, AsyncReadExt};
|
||||
/// use tokio::fs::File;
|
||||
///
|
||||
/// #[tokio::main]
|
||||
/// async fn main() -> io::Result<()> {
|
||||
/// let mut f = File::open("foo.txt").await?;
|
||||
/// let mut buffer = String::new();
|
||||
///
|
||||
/// f.read_to_string(&mut buffer).await?;
|
||||
/// Ok(())
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// (See also the [`crate::fs::read_to_string`] convenience function for
|
||||
/// reading from a file.)
|
||||
///
|
||||
/// [`crate::fs::read_to_string`]: crate::fs::read_to_string::read_to_string
|
||||
fn read_to_string<'a>(&'a mut self, dst: &'a mut String) -> ReadToString<'a, Self>
|
||||
where
|
||||
Self: Unpin,
|
||||
@@ -80,8 +296,33 @@ cfg_io_util! {
|
||||
read_to_string(self, dst)
|
||||
}
|
||||
|
||||
/// Creates an AsyncRead adapter which will read at most `limit` bytes
|
||||
/// from the underlying reader.
|
||||
/// Creates an adaptor which reads at most `limit` bytes from it.
|
||||
///
|
||||
/// This function returns a new instance of `AsyncRead` which will read
|
||||
/// at most `limit` bytes, after which it will always return EOF
|
||||
/// (`Ok(0)`). Any read errors will not count towards the number of
|
||||
/// bytes read and future calls to [`read()`][read] may succeed.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// [`File`][crate::fs::File]s implement `Read`:
|
||||
///
|
||||
/// ```no_run
|
||||
/// use tokio::io::{self, AsyncReadExt};
|
||||
/// use tokio::fs::File;
|
||||
///
|
||||
/// #[tokio::main]
|
||||
/// async fn main() -> io::Result<()> {
|
||||
/// let f = File::open("foo.txt").await?;
|
||||
/// let mut buffer = [0; 5];
|
||||
///
|
||||
/// // read at most five bytes
|
||||
/// let mut handle = f.take(5);
|
||||
///
|
||||
/// handle.read(&mut buffer).await?;
|
||||
/// Ok(())
|
||||
/// }
|
||||
/// ```
|
||||
fn take(self, limit: u64) -> Take<Self>
|
||||
where
|
||||
Self: Sized,
|
||||
|
||||
@@ -5,9 +5,83 @@ use crate::io::util::write_all::{write_all, WriteAll};
|
||||
use crate::io::AsyncWrite;
|
||||
|
||||
cfg_io_util! {
|
||||
/// An extension trait which adds utility methods to `AsyncWrite` types.
|
||||
/// Write bytes to a sink.
|
||||
///
|
||||
/// Implemented as an extention trait, adding utility methods to all
|
||||
/// [`AsyncWrite`] types. Callers will tend to import this trait instead of
|
||||
/// [`AsyncWrite`].
|
||||
///
|
||||
/// As a convenience, this trait may be imported using the [`prelude`]:
|
||||
///
|
||||
/// ```no_run
|
||||
/// use tokio::prelude::*;
|
||||
/// use tokio::fs::File;
|
||||
///
|
||||
/// #[tokio::main]
|
||||
/// async fn main() -> io::Result<()> {
|
||||
/// let data = b"some bytes";
|
||||
///
|
||||
/// let mut pos = 0;
|
||||
/// let mut buffer = File::create("foo.txt").await?;
|
||||
///
|
||||
/// while pos < data.len() {
|
||||
/// let bytes_written = buffer.write(&data[pos..]).await?;
|
||||
/// pos += bytes_written;
|
||||
/// }
|
||||
///
|
||||
/// Ok(())
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// See [module][crate::io] documentation for more details.
|
||||
///
|
||||
/// [`AsyncWrite`]: AsyncWrite
|
||||
/// [`prelude`]: crate::prelude
|
||||
pub trait AsyncWriteExt: AsyncWrite {
|
||||
/// Write a buffer into this writter, returning how many bytes were written.
|
||||
/// Write a buffer into this writer, returning how many bytes were
|
||||
/// written.
|
||||
///
|
||||
/// Equivalent to:
|
||||
///
|
||||
/// ```ignore
|
||||
/// async fn write(&mut self, buf: &[u8]) -> io::Result<usize>;
|
||||
/// ```
|
||||
///
|
||||
/// This function will attempt to write the entire contents of `buf`, but
|
||||
/// the entire write may not succeed, or the write may also generate an
|
||||
/// error. A call to `write` represents *at most one* attempt to write to
|
||||
/// any wrapped object.
|
||||
///
|
||||
/// If the return value is `Ok(n)` then it must be guaranteed that `n <=
|
||||
/// buf.len()`. A return value of `0` typically means that the
|
||||
/// underlying object is no longer able to accept bytes and will likely
|
||||
/// not be able to in the future as well, or that the buffer provided is
|
||||
/// empty.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// Each call to `write` may generate an I/O error indicating that the
|
||||
/// operation could not be completed. If an error is returned then no bytes
|
||||
/// in the buffer were written to this writer.
|
||||
///
|
||||
/// It is **not** considered an error if the entire buffer could not be
|
||||
/// written to this writer.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use tokio::io::{self, AsyncWriteExt};
|
||||
/// use tokio::fs::File;
|
||||
///
|
||||
/// #[tokio::main]
|
||||
/// async fn main() -> io::Result<()> {
|
||||
/// let mut buffer = File::create("foo.txt").await?;
|
||||
///
|
||||
/// // Writes some prefix of the byte string, not necessarily all of it.
|
||||
/// buffer.write(b"some bytes").await?;
|
||||
/// Ok(())
|
||||
/// }
|
||||
/// ```
|
||||
fn write<'a>(&'a mut self, src: &'a [u8]) -> Write<'a, Self>
|
||||
where
|
||||
Self: Unpin,
|
||||
@@ -15,7 +89,39 @@ cfg_io_util! {
|
||||
write(self, src)
|
||||
}
|
||||
|
||||
/// Attempt to write an entire buffer into this writter.
|
||||
/// Attempts to write an entire buffer into this writer.
|
||||
///
|
||||
/// Equivalent to:
|
||||
///
|
||||
/// ```ignore
|
||||
/// async fn write_all(&mut self, buf: &[u8]) -> io::Result<()>;
|
||||
/// ```
|
||||
///
|
||||
/// This method will continuously call [`write`] until there is no more data
|
||||
/// to be written. This method will not return until the entire buffer
|
||||
/// has been successfully written or such an error occurs. The first
|
||||
/// error generated from this method will be returned.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// This function will return the first error that [`write`] returns.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use tokio::io::{self, AsyncWriteExt};
|
||||
/// use tokio::fs::File;
|
||||
///
|
||||
/// #[tokio::main]
|
||||
/// async fn main() -> io::Result<()> {
|
||||
/// let mut buffer = File::create("foo.txt").await?;
|
||||
///
|
||||
/// buffer.write_all(b"some bytes").await?;
|
||||
/// Ok(())
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// [`write`]: AsyncWriteExt::write
|
||||
fn write_all<'a>(&'a mut self, src: &'a [u8]) -> WriteAll<'a, Self>
|
||||
where
|
||||
Self: Unpin,
|
||||
@@ -23,7 +129,36 @@ cfg_io_util! {
|
||||
write_all(self, src)
|
||||
}
|
||||
|
||||
/// Flush the contents of this writer.
|
||||
/// Flush this output stream, ensuring that all intermediately buffered
|
||||
/// contents reach their destination.
|
||||
///
|
||||
/// Equivalent to:
|
||||
///
|
||||
/// ```ignore
|
||||
/// async fn flush(&mut self) -> io::Result<()>;
|
||||
/// ```
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// It is considered an error if not all bytes could be written due to
|
||||
/// I/O errors or EOF being reached.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use tokio::io::{self, BufWriter, AsyncWriteExt};
|
||||
/// use tokio::fs::File;
|
||||
///
|
||||
/// #[tokio::main]
|
||||
/// async fn main() -> io::Result<()> {
|
||||
/// let f = File::create("foo.txt").await?;
|
||||
/// let mut buffer = BufWriter::new(f);
|
||||
///
|
||||
/// buffer.write_all(b"some bytes").await?;
|
||||
/// buffer.flush().await?;
|
||||
/// Ok(())
|
||||
/// }
|
||||
/// ```
|
||||
fn flush(&mut self) -> Flush<'_, Self>
|
||||
where
|
||||
Self: Unpin,
|
||||
@@ -31,7 +166,36 @@ cfg_io_util! {
|
||||
flush(self)
|
||||
}
|
||||
|
||||
/// Shutdown this writer.
|
||||
/// Shuts down the output stream, ensuring that the value can be dropped
|
||||
/// cleanly.
|
||||
///
|
||||
/// Equivalent to:
|
||||
///
|
||||
/// ```ignore
|
||||
/// async fn shutdown(&mut self) -> io::Result<()>;
|
||||
/// ```
|
||||
///
|
||||
/// Similar to [`flush`], all intermediately buffered is written to the
|
||||
/// underlying stream. Once the operation completes, the caller should
|
||||
/// no longer attempt to write to the stream. For example, the
|
||||
/// `TcpStream` implementation will issue a `shutdown(Write)` sys call.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use tokio::io::{self, BufWriter, AsyncWriteExt};
|
||||
/// use tokio::fs::File;
|
||||
///
|
||||
/// #[tokio::main]
|
||||
/// async fn main() -> io::Result<()> {
|
||||
/// let f = File::create("foo.txt").await?;
|
||||
/// let mut buffer = BufWriter::new(f);
|
||||
///
|
||||
/// buffer.write_all(b"some bytes").await?;
|
||||
/// buffer.shutdown().await?;
|
||||
/// Ok(())
|
||||
/// }
|
||||
/// ```
|
||||
fn shutdown(&mut self) -> Shutdown<'_, Self>
|
||||
where
|
||||
Self: Unpin,
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
//!
|
||||
//! The prelude may grow over time as additional items see ubiquitous use.
|
||||
|
||||
pub use crate::io::{AsyncBufRead, AsyncRead, AsyncWrite};
|
||||
pub use crate::io::{self, AsyncBufRead, AsyncRead, AsyncWrite};
|
||||
|
||||
cfg_io_util! {
|
||||
#[doc(no_inline)]
|
||||
|
||||
@@ -41,7 +41,7 @@ async fn echo_server() {
|
||||
let (mut a, _) = assert_ok!(srv.accept().await);
|
||||
let (mut b, _) = assert_ok!(srv.accept().await);
|
||||
|
||||
let n = assert_ok!(a.copy(&mut b).await);
|
||||
let n = assert_ok!(io::copy(&mut a, &mut b).await);
|
||||
|
||||
let (expected, t2) = t.join().unwrap();
|
||||
let actual = t2.join().unwrap();
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
#![warn(rust_2018_idioms)]
|
||||
#![cfg(feature = "full")]
|
||||
|
||||
use tokio::io::{AsyncRead, AsyncReadExt};
|
||||
use tokio::io::{self, AsyncRead};
|
||||
use tokio_test::assert_ok;
|
||||
|
||||
use std::io;
|
||||
use std::pin::Pin;
|
||||
use std::task::{Context, Poll};
|
||||
|
||||
@@ -31,7 +30,7 @@ async fn copy() {
|
||||
let mut rd = Rd(true);
|
||||
let mut wr = Vec::new();
|
||||
|
||||
let n = assert_ok!(rd.copy(&mut wr).await);
|
||||
let n = assert_ok!(io::copy(&mut rd, &mut wr).await);
|
||||
assert_eq!(n, 11);
|
||||
assert_eq!(wr, b"hello world");
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ async fn echo_server() {
|
||||
let (mut stream, _) = assert_ok!(srv.accept().await);
|
||||
let (mut rd, mut wr) = stream.split();
|
||||
|
||||
let n = assert_ok!(rd.copy(&mut wr).await);
|
||||
let n = assert_ok!(io::copy(&mut rd, &mut wr).await);
|
||||
assert_eq!(n, (ITER * msg.len()) as u64);
|
||||
|
||||
assert_ok!(rx.await);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#![warn(rust_2018_idioms)]
|
||||
#![cfg(feature = "full")]
|
||||
|
||||
use tokio::io::AsyncWriteExt;
|
||||
use tokio::io::{self, AsyncWriteExt};
|
||||
use tokio::net::{TcpListener, TcpStream};
|
||||
use tokio::prelude::*;
|
||||
use tokio_test::assert_ok;
|
||||
@@ -24,6 +24,6 @@ async fn shutdown() {
|
||||
let (mut stream, _) = assert_ok!(srv.accept().await);
|
||||
let (mut rd, mut wr) = stream.split();
|
||||
|
||||
let n = assert_ok!(rd.copy(&mut wr).await);
|
||||
let n = assert_ok!(io::copy(&mut rd, &mut wr).await);
|
||||
assert_eq!(n, 0);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user