Module tokio::io[][src]

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.

Structs

BufReader

The BufReader struct adds buffering to any reader.

BufStream

Wraps a type that is AsyncWrite and AsyncRead, and buffers its input and output.

BufWriter

Wraps a writer and buffers its output.

Copy

A future that asynchronously copies the entire contents of a reader into a writer.

DuplexStream

A bidirectional pipe to read and write bytes in memory.

Empty

An async reader which is always at EOF.

Error

The error type for I/O operations of the Read, Write, Seek, and associated traits.

Lines

Stream for the lines method.

PollEvented

Associates an I/O resource that implements the std::io::Read and/or std::io::Write traits with the reactor that drives it.

ReadHalf

The readable half of a value returned from split.

ReaderStream

Convert an AsyncRead implementor into a Stream of Result<Bytes, std::io::Error>. After first error it will stop. Additionally, this stream is fused: after it returns None at some moment, it is guaranteed that further next(), poll_next() and similar functions will instantly return None.

Registration

Associates an I/O resource with the reactor instance that drives it.

Repeat

An async reader which yields one byte over and over and over and over and over and…

Seek

Future for the seek method.

Sink

An async writer which will move data into the void.

Split

Stream for the split method.

StreamReader

Convert a stream of byte chunks into an AsyncRead.

Take

Stream for the take method.

WriteHalf

The writable half of a value returned from split.

Enums

ErrorKind

A list specifying general categories of I/O error.

SeekFrom

Enumeration of possible methods to seek within an I/O object.

Traits

AsyncBufRead

Reads bytes asynchronously.

AsyncBufReadExt

An extension trait which adds utility methods to AsyncBufRead types.

AsyncRead

Reads bytes from a source.

AsyncReadExt

Reads bytes from a source.

AsyncSeek

Seek bytes asynchronously.

AsyncSeekExt

An extension trait which adds utility methods to AsyncSeek types.

AsyncWrite

Writes bytes asynchronously.

AsyncWriteExt

Writes bytes to a sink.

Functions

copy

Asynchronously copies the entire contents of a reader into a writer.

duplex

Create a new pair of DuplexStreams that act like a pair of connected sockets.

empty

Creates a new empty async reader.

reader_stream

Convert an AsyncRead implementor into a Stream of Result<Bytes, std::io::Error>.

repeat

Creates an instance of an async reader that infinitely repeats one byte.

sink

Creates an instance of an async writer which will successfully consume all data.

split

Splits a single value implementing AsyncRead + AsyncWrite into separate AsyncRead and AsyncWrite handles.

stream_reader

Convert a stream of byte chunks into an AsyncRead.

Type Definitions

Result

A specialized Result type for I/O operations.