Expand description
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
versions of the Read
and Write
traits in the standard library.
AsyncRead and AsyncWrite
Like the standard library’s Read
and Write
traits, AsyncRead
and
AsyncWrite
provide the most general interface for reading and writing
input and output. Unlike the standard library’s traits, however, they are
asynchronous — meaning that reading from or writing to a tokio::io
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.
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
AsyncRead
and AsyncWrite
, such as File
and TcpStream
.
For example, the standard library documentation introduces Read
by
demonstrating reading some bytes from a std::fs::File
. We
can do the same with tokio::fs::File
:
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 = [0; 10];
// read up to 10 bytes
let n = f.read(&mut buffer).await?;
println!("The bytes: {:?}", &buffer[..n]);
Ok(())
}
Buffered Readers and Writers
Byte-based interfaces are unwieldy and can be inefficient, as we’d need to be
making near-constant calls to the operating system. To help with this,
std::io
comes with support for buffered readers and writers,
and therefore, tokio::io
does as well.
Tokio provides an async version of the std::io::BufRead
trait,
AsyncBufRead
; and async BufReader
and BufWriter
structs, which
wrap readers and writers. These wrappers use a buffer, reducing the number
of calls and providing nicer methods for accessing exactly what you want.
For example, BufReader
works with the AsyncBufRead
trait to add
extra methods to any async reader:
use tokio::io::{self, BufReader, AsyncBufReadExt};
use tokio::fs::File;
#[tokio::main]
async fn main() -> io::Result<()> {
let f = File::open("foo.txt").await?;
let mut reader = BufReader::new(f);
let mut buffer = String::new();
// read a line into buffer
reader.read_line(&mut buffer).await?;
println!("{}", buffer);
Ok(())
}
BufWriter
doesn’t add any new ways of writing; it just buffers every call
to write
. However, you must flush
BufWriter
to ensure that any buffered data is written.
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 writer = BufWriter::new(f);
// Write a byte to the buffer.
writer.write(&[42u8]).await?;
// Flush the buffer before it goes out of scope.
writer.flush().await?;
} // Unless flushed or shut down, the contents of the buffer is discarded on drop.
Ok(())
}
Implementing AsyncRead and AsyncWrite
Because they are traits, we can implement AsyncRead
and AsyncWrite
for
our own types, as well. Note that these traits must only be implemented for
non-blocking I/O types that integrate with the futures type system. In
other words, these types must never block the thread, and instead the
current task is notified when the I/O resource is ready.
Conversion to and from Sink/Stream
It is often convenient to encapsulate the reading and writing of
bytes and instead work with a Sink
or Stream
of some data
type that is encoded as bytes and/or decoded from bytes. Tokio
provides some utility traits in the tokio-util crate that
abstract the asynchronous buffering that is required and allows
you to write Encoder
and Decoder
functions working with a
buffer of bytes, and then use that “codec” to transform anything
that implements AsyncRead
and AsyncWrite
into a Sink
/Stream
of
your structured data.
Standard input and output
Tokio provides asynchronous APIs to standard input, output, and error.
These APIs are very similar to the ones provided by std
, but they also
implement AsyncRead
and AsyncWrite
.
Note that the standard input / output APIs must be used from the context of the Tokio runtime, as they require Tokio-specific features to function. Calling these functions outside of a Tokio runtime will panic.
std
re-exports
Additionally, Error
, ErrorKind
, Result
, and SeekFrom
are
re-exported from std::io
for ease of use.
Re-exports
pub use std::io::Error;
pub use std::io::ErrorKind;
pub use std::io::Result;
pub use std::io::SeekFrom;
Modules
- bsdFreeBSD and
net
BSD-specific I/O types. - unixUnix and
net
Asynchronous IO structures specific to Unix-like operating systems.
Structs
- BufReader
io-util
TheBufReader
struct adds buffering to any reader. - BufStream
io-util
Wraps a type that isAsyncWrite
andAsyncRead
, and buffers its input and output. - BufWriter
io-util
Wraps a writer and buffers its output. - DuplexStream
io-util
A bidirectional pipe to read and write bytes in memory. - Empty
io-util
An async reader which is always at EOF. - Interest
net
Readiness event interest. - Lines
io-util
Reads lines from anAsyncBufRead
. - A wrapper around a byte buffer that is incrementally filled and initialized.
- ReadHalf
io-util
The readable half of a value returned fromsplit
. - Ready
net
Describes the readiness state of an I/O resources. - Repeat
io-util
An async reader which yields one byte over and over and over and over and over and… - Sink
io-util
An async writer which will move data into the void. - Split
io-util
Splitter for thesplit
method. - Stderr
io-std
A handle to the standard error stream of a process. - Stdin
io-std
A handle to the standard input stream of a process. - Stdout
io-std
A handle to the standard output stream of a process. - Take
io-util
Stream for thetake
method. - WriteHalf
io-util
The writable half of a value returned fromsplit
.
Traits
- Reads bytes asynchronously.
- AsyncBufReadExt
io-util
An extension trait which adds utility methods toAsyncBufRead
types. - Reads bytes from a source.
- AsyncReadExt
io-util
Reads bytes from a source. - Seek bytes asynchronously.
- AsyncSeekExt
io-util
An extension trait that adds utility methods toAsyncSeek
types. - Writes bytes asynchronously.
- AsyncWriteExt
io-util
Writes bytes to a sink.
Functions
- copy
io-util
Asynchronously copies the entire contents of a reader into a writer. - copy_bidirectional
io-util
Copies data in both directions betweena
andb
. - copy_buf
io-util
Asynchronously copies the entire contents of a reader into a writer. - duplex
io-util
Create a new pair ofDuplexStream
s that act like a pair of connected sockets. - empty
io-util
Creates a new empty async reader. - repeat
io-util
Creates an instance of an async reader that infinitely repeats one byte. - sink
io-util
Creates an instance of an async writer which will successfully consume all data. - split
io-util
Splits a single value implementingAsyncRead + AsyncWrite
into separateAsyncRead
andAsyncWrite
handles. - stderr
io-std
Constructs a new handle to the standard error of the current process. - stdin
io-std
Constructs a new handle to the standard input of the current process. - stdout
io-std
Constructs a new handle to the standard output of the current process.