From 5fb0c89ecc7c79d44dfef9115fe87b1e8d29b637 Mon Sep 17 00:00:00 2001 From: Carl Lerche Date: Fri, 22 Nov 2019 21:41:52 -0800 Subject: [PATCH 1/5] docs: improve tokio::io API documentation Adds method level documentation for `AsyncReadExt`. --- tokio/src/io/async_read.rs | 18 +- tokio/src/io/mod.rs | 27 ++- tokio/src/io/util/async_read_ext.rs | 314 ++++++++++++++++++++++++---- 3 files changed, 309 insertions(+), 50 deletions(-) diff --git a/tokio/src/io/async_read.rs b/tokio/src/io/async_read.rs index d7e703d46de..d28280a5124 100644 --- a/tokio/src/io/async_read.rs +++ b/tokio/src/io/async_read.rs @@ -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. diff --git a/tokio/src/io/mod.rs b/tokio/src/io/mod.rs index 627e643fce1..29d700b1fb8 100644 --- a/tokio/src/io/mod.rs +++ b/tokio/src/io/mod.rs @@ -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<()> { diff --git a/tokio/src/io/util/async_read_ext.rs b/tokio/src/io/util/async_read_ext.rs index faac42d93f8..2872b202d56 100644 --- a/tokio/src/io/util/async_read_ext.rs +++ b/tokio/src/io/util/async_read_ext.rs @@ -1,20 +1,71 @@ 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::io; + /// 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(self, next: R) -> Chain where Self: Sized, @@ -23,56 +74,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; + /// ``` + /// + /// 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 /// - /// 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> + /// 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; + /// ``` + /// + /// 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`. + /// + /// Equivalent to: + /// + /// ```ignore + /// async fn read_to_end(&mut self, buf: &mut Vec) -> io::Result; + /// ``` + /// + /// 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`. /// - /// 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> + /// # 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) -> 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`. + /// + /// Equivalent to: + /// + /// ```ignore + /// async fn read_to_string(&mut self, buf: &mut String) -> io::Result; + /// ``` /// - /// On success the total number of bytes read is returned. + /// 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 +297,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 where Self: Sized, From a967575b0b3dbd110539c0bfc1b045c7032d7dc5 Mon Sep 17 00:00:00 2001 From: Carl Lerche Date: Fri, 22 Nov 2019 22:48:42 -0800 Subject: [PATCH 2/5] more docs --- tokio/src/io/util/async_read_ext.rs | 1 - tokio/src/io/util/async_write_ext.rs | 174 ++++++++++++++++++++++++++- tokio/src/prelude.rs | 2 +- tokio/tests/tcp_shutdown.rs | 4 +- 4 files changed, 172 insertions(+), 9 deletions(-) diff --git a/tokio/src/io/util/async_read_ext.rs b/tokio/src/io/util/async_read_ext.rs index 2872b202d56..fe1e646eee2 100644 --- a/tokio/src/io/util/async_read_ext.rs +++ b/tokio/src/io/util/async_read_ext.rs @@ -17,7 +17,6 @@ cfg_io_util! { /// /// ```no_run /// use tokio::fs::File; - /// use tokio::io; /// use tokio::prelude::*; /// /// #[tokio::main] diff --git a/tokio/src/io/util/async_write_ext.rs b/tokio/src/io/util/async_write_ext.rs index 65374428eac..82de2576e77 100644 --- a/tokio/src/io/util/async_write_ext.rs +++ b/tokio/src/io/util/async_write_ext.rs @@ -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; + /// ``` + /// + /// 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, diff --git a/tokio/src/prelude.rs b/tokio/src/prelude.rs index 7e482892295..d4e790be72f 100644 --- a/tokio/src/prelude.rs +++ b/tokio/src/prelude.rs @@ -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)] diff --git a/tokio/tests/tcp_shutdown.rs b/tokio/tests/tcp_shutdown.rs index cc5ea26f409..bd43e143b8d 100644 --- a/tokio/tests/tcp_shutdown.rs +++ b/tokio/tests/tcp_shutdown.rs @@ -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); } From d6274e8b9339b55c69c371e25744545e7eadf4c2 Mon Sep 17 00:00:00 2001 From: Carl Lerche Date: Fri, 22 Nov 2019 23:07:29 -0800 Subject: [PATCH 3/5] fix examples --- examples/proxy.rs | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/examples/proxy.rs b/examples/proxy.rs index 4314d1b9551..3d75d7a97c4 100644 --- a/examples/proxy.rs +++ b/examples/proxy.rs @@ -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::FutureExt; +use futures::future::try_join; +use std::env; +use std::error::Error; #[tokio::main] async fn main() -> Result<(), Box> { @@ -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?; From 15a691a1a881167562f7da9dca2c648b8455a1f6 Mon Sep 17 00:00:00 2001 From: Carl Lerche Date: Fri, 22 Nov 2019 23:16:43 -0800 Subject: [PATCH 4/5] fix tests --- tokio/tests/buffered.rs | 2 +- tokio/tests/io_copy.rs | 5 ++--- tokio/tests/tcp_echo.rs | 2 +- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/tokio/tests/buffered.rs b/tokio/tests/buffered.rs index 7ce3d01cf27..595f855a0f7 100644 --- a/tokio/tests/buffered.rs +++ b/tokio/tests/buffered.rs @@ -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(); diff --git a/tokio/tests/io_copy.rs b/tokio/tests/io_copy.rs index 75d77435828..c1c6df4eb34 100644 --- a/tokio/tests/io_copy.rs +++ b/tokio/tests/io_copy.rs @@ -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"); } diff --git a/tokio/tests/tcp_echo.rs b/tokio/tests/tcp_echo.rs index 38377702d08..1feba63ee73 100644 --- a/tokio/tests/tcp_echo.rs +++ b/tokio/tests/tcp_echo.rs @@ -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); From 718ca40f7d8411ed6c72e45009120d0e22445df6 Mon Sep 17 00:00:00 2001 From: Carl Lerche Date: Fri, 22 Nov 2019 23:23:59 -0800 Subject: [PATCH 5/5] fmt --- examples/proxy.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/proxy.rs b/examples/proxy.rs index 3d75d7a97c4..48f8f05721e 100644 --- a/examples/proxy.rs +++ b/examples/proxy.rs @@ -25,8 +25,8 @@ use tokio::io; use tokio::net::{TcpListener, TcpStream}; -use futures::FutureExt; use futures::future::try_join; +use futures::FutureExt; use std::env; use std::error::Error;