1 | //! Traits, helpers, and type definitions for asynchronous I/O functionality. |
2 | //! |
3 | //! This module is the asynchronous version of `std::io`. Primarily, it |
4 | //! defines two traits, [`AsyncRead`] and [`AsyncWrite`], which are asynchronous |
5 | //! versions of the [`Read`] and [`Write`] traits in the standard library. |
6 | //! |
7 | //! # `AsyncRead` and `AsyncWrite` |
8 | //! |
9 | //! Like the standard library's [`Read`] and [`Write`] traits, [`AsyncRead`] and |
10 | //! [`AsyncWrite`] provide the most general interface for reading and writing |
11 | //! input and output. Unlike the standard library's traits, however, they are |
12 | //! _asynchronous_ — meaning that reading from or writing to a `tokio::io` |
13 | //! type will _yield_ to the Tokio scheduler when IO is not ready, rather than |
14 | //! blocking. This allows other tasks to run while waiting on IO. |
15 | //! |
16 | //! Another difference is that `AsyncRead` and `AsyncWrite` only contain |
17 | //! core methods needed to provide asynchronous reading and writing |
18 | //! functionality. Instead, utility methods are defined in the [`AsyncReadExt`] |
19 | //! and [`AsyncWriteExt`] extension traits. These traits are automatically |
20 | //! implemented for all values that implement `AsyncRead` and `AsyncWrite` |
21 | //! respectively. |
22 | //! |
23 | //! End users will rarely interact directly with `AsyncRead` and |
24 | //! `AsyncWrite`. Instead, they will use the async functions defined in the |
25 | //! extension traits. Library authors are expected to implement `AsyncRead` |
26 | //! and `AsyncWrite` in order to provide types that behave like byte streams. |
27 | //! |
28 | //! Even with these differences, Tokio's `AsyncRead` and `AsyncWrite` traits |
29 | //! can be used in almost exactly the same manner as the standard library's |
30 | //! `Read` and `Write`. Most types in the standard library that implement `Read` |
31 | //! and `Write` have asynchronous equivalents in `tokio` that implement |
32 | //! `AsyncRead` and `AsyncWrite`, such as [`File`] and [`TcpStream`]. |
33 | //! |
34 | //! For example, the standard library documentation introduces `Read` by |
35 | //! [demonstrating][std_example] reading some bytes from a [`std::fs::File`]. We |
36 | //! can do the same with [`tokio::fs::File`][`File`]: |
37 | //! |
38 | //! ```no_run |
39 | //! use tokio::io::{self, AsyncReadExt}; |
40 | //! use tokio::fs::File; |
41 | //! |
42 | //! #[tokio::main] |
43 | //! async fn main() -> io::Result<()> { |
44 | //! let mut f = File::open("foo.txt" ).await?; |
45 | //! let mut buffer = [0; 10]; |
46 | //! |
47 | //! // read up to 10 bytes |
48 | //! let n = f.read(&mut buffer).await?; |
49 | //! |
50 | //! println!("The bytes: {:?}" , &buffer[..n]); |
51 | //! Ok(()) |
52 | //! } |
53 | //! ``` |
54 | //! |
55 | //! [`File`]: crate::fs::File |
56 | //! [`TcpStream`]: crate::net::TcpStream |
57 | //! [`std::fs::File`]: std::fs::File |
58 | //! [std_example]: std::io#read-and-write |
59 | //! |
60 | //! ## Buffered Readers and Writers |
61 | //! |
62 | //! Byte-based interfaces are unwieldy and can be inefficient, as we'd need to be |
63 | //! making near-constant calls to the operating system. To help with this, |
64 | //! `std::io` comes with [support for _buffered_ readers and writers][stdbuf], |
65 | //! and therefore, `tokio::io` does as well. |
66 | //! |
67 | //! Tokio provides an async version of the [`std::io::BufRead`] trait, |
68 | //! [`AsyncBufRead`]; and async [`BufReader`] and [`BufWriter`] structs, which |
69 | //! wrap readers and writers. These wrappers use a buffer, reducing the number |
70 | //! of calls and providing nicer methods for accessing exactly what you want. |
71 | //! |
72 | //! For example, [`BufReader`] works with the [`AsyncBufRead`] trait to add |
73 | //! extra methods to any async reader: |
74 | //! |
75 | //! ```no_run |
76 | //! use tokio::io::{self, BufReader, AsyncBufReadExt}; |
77 | //! use tokio::fs::File; |
78 | //! |
79 | //! #[tokio::main] |
80 | //! async fn main() -> io::Result<()> { |
81 | //! let f = File::open("foo.txt" ).await?; |
82 | //! let mut reader = BufReader::new(f); |
83 | //! let mut buffer = String::new(); |
84 | //! |
85 | //! // read a line into buffer |
86 | //! reader.read_line(&mut buffer).await?; |
87 | //! |
88 | //! println!("{}" , buffer); |
89 | //! Ok(()) |
90 | //! } |
91 | //! ``` |
92 | //! |
93 | //! [`BufWriter`] doesn't add any new ways of writing; it just buffers every call |
94 | //! to [`write`](crate::io::AsyncWriteExt::write). However, you **must** flush |
95 | //! [`BufWriter`] to ensure that any buffered data is written. |
96 | //! |
97 | //! ```no_run |
98 | //! use tokio::io::{self, BufWriter, AsyncWriteExt}; |
99 | //! use tokio::fs::File; |
100 | //! |
101 | //! #[tokio::main] |
102 | //! async fn main() -> io::Result<()> { |
103 | //! let f = File::create("foo.txt" ).await?; |
104 | //! { |
105 | //! let mut writer = BufWriter::new(f); |
106 | //! |
107 | //! // Write a byte to the buffer. |
108 | //! writer.write(&[42u8]).await?; |
109 | //! |
110 | //! // Flush the buffer before it goes out of scope. |
111 | //! writer.flush().await?; |
112 | //! |
113 | //! } // Unless flushed or shut down, the contents of the buffer is discarded on drop. |
114 | //! |
115 | //! Ok(()) |
116 | //! } |
117 | //! ``` |
118 | //! |
119 | //! [stdbuf]: std::io#bufreader-and-bufwriter |
120 | //! [`std::io::BufRead`]: std::io::BufRead |
121 | //! [`AsyncBufRead`]: crate::io::AsyncBufRead |
122 | //! [`BufReader`]: crate::io::BufReader |
123 | //! [`BufWriter`]: crate::io::BufWriter |
124 | //! |
125 | //! ## Implementing `AsyncRead` and `AsyncWrite` |
126 | //! |
127 | //! Because they are traits, we can implement [`AsyncRead`] and [`AsyncWrite`] for |
128 | //! our own types, as well. Note that these traits must only be implemented for |
129 | //! non-blocking I/O types that integrate with the futures type system. In |
130 | //! other words, these types must never block the thread, and instead the |
131 | //! current task is notified when the I/O resource is ready. |
132 | //! |
133 | //! ## Conversion to and from Stream/Sink |
134 | //! |
135 | //! It is often convenient to encapsulate the reading and writing of bytes in a |
136 | //! [`Stream`] or [`Sink`] of data. |
137 | //! |
138 | //! Tokio provides simple wrappers for converting [`AsyncRead`] to [`Stream`] |
139 | //! and vice-versa in the [tokio-util] crate, see [`ReaderStream`] and |
140 | //! [`StreamReader`]. |
141 | //! |
142 | //! There are also utility traits that abstract the asynchronous buffering |
143 | //! necessary to write your own adaptors for encoding and decoding bytes to/from |
144 | //! your structured data, allowing to transform something that implements |
145 | //! [`AsyncRead`]/[`AsyncWrite`] into a [`Stream`]/[`Sink`], see [`Decoder`] and |
146 | //! [`Encoder`] in the [tokio-util::codec] module. |
147 | //! |
148 | //! [tokio-util]: https://docs.rs/tokio-util |
149 | //! [tokio-util::codec]: https://docs.rs/tokio-util/latest/tokio_util/codec/index.html |
150 | //! |
151 | //! # Standard input and output |
152 | //! |
153 | //! Tokio provides asynchronous APIs to standard [input], [output], and [error]. |
154 | //! These APIs are very similar to the ones provided by `std`, but they also |
155 | //! implement [`AsyncRead`] and [`AsyncWrite`]. |
156 | //! |
157 | //! Note that the standard input / output APIs **must** be used from the |
158 | //! context of the Tokio runtime, as they require Tokio-specific features to |
159 | //! function. Calling these functions outside of a Tokio runtime will panic. |
160 | //! |
161 | //! [input]: fn@stdin |
162 | //! [output]: fn@stdout |
163 | //! [error]: fn@stderr |
164 | //! |
165 | //! # `std` re-exports |
166 | //! |
167 | //! Additionally, [`Error`], [`ErrorKind`], [`Result`], and [`SeekFrom`] are |
168 | //! re-exported from `std::io` for ease of use. |
169 | //! |
170 | //! [`AsyncRead`]: trait@AsyncRead |
171 | //! [`AsyncWrite`]: trait@AsyncWrite |
172 | //! [`AsyncReadExt`]: trait@AsyncReadExt |
173 | //! [`AsyncWriteExt`]: trait@AsyncWriteExt |
174 | //! ["codec"]: https://docs.rs/tokio-util/latest/tokio_util/codec/index.html |
175 | //! [`Encoder`]: https://docs.rs/tokio-util/latest/tokio_util/codec/trait.Encoder.html |
176 | //! [`Decoder`]: https://docs.rs/tokio-util/latest/tokio_util/codec/trait.Decoder.html |
177 | //! [`ReaderStream`]: https://docs.rs/tokio-util/latest/tokio_util/io/struct.ReaderStream.html |
178 | //! [`StreamReader`]: https://docs.rs/tokio-util/latest/tokio_util/io/struct.StreamReader.html |
179 | //! [`Error`]: struct@Error |
180 | //! [`ErrorKind`]: enum@ErrorKind |
181 | //! [`Result`]: type@Result |
182 | //! [`Read`]: std::io::Read |
183 | //! [`SeekFrom`]: enum@SeekFrom |
184 | //! [`Sink`]: https://docs.rs/futures/0.3/futures/sink/trait.Sink.html |
185 | //! [`Stream`]: https://docs.rs/futures/0.3/futures/stream/trait.Stream.html |
186 | //! [`Write`]: std::io::Write |
187 | |
188 | #![cfg_attr ( |
189 | not(all(feature = "rt" , feature = "net" )), |
190 | allow(dead_code, unused_imports) |
191 | )] |
192 | |
193 | cfg_io_blocking! { |
194 | pub(crate) mod blocking; |
195 | } |
196 | |
197 | mod async_buf_read; |
198 | pub use self::async_buf_read::AsyncBufRead; |
199 | |
200 | mod async_read; |
201 | pub use self::async_read::AsyncRead; |
202 | |
203 | mod async_seek; |
204 | pub use self::async_seek::AsyncSeek; |
205 | |
206 | mod async_write; |
207 | pub use self::async_write::AsyncWrite; |
208 | |
209 | mod read_buf; |
210 | pub use self::read_buf::ReadBuf; |
211 | |
212 | // Re-export some types from `std::io` so that users don't have to deal |
213 | // with conflicts when `use`ing `tokio::io` and `std::io`. |
214 | #[doc (no_inline)] |
215 | pub use std::io::{Error, ErrorKind, Result, SeekFrom}; |
216 | |
217 | cfg_io_driver_impl! { |
218 | pub(crate) mod interest; |
219 | pub(crate) mod ready; |
220 | |
221 | cfg_net! { |
222 | pub use interest::Interest; |
223 | pub use ready::Ready; |
224 | } |
225 | |
226 | #[cfg_attr (target_os = "wasi" , allow(unused_imports))] |
227 | mod poll_evented; |
228 | |
229 | #[cfg (not(loom))] |
230 | #[cfg_attr (target_os = "wasi" , allow(unused_imports))] |
231 | pub(crate) use poll_evented::PollEvented; |
232 | } |
233 | |
234 | cfg_aio! { |
235 | /// BSD-specific I/O types. |
236 | pub mod bsd { |
237 | mod poll_aio; |
238 | |
239 | pub use poll_aio::{Aio, AioEvent, AioSource}; |
240 | } |
241 | } |
242 | |
243 | cfg_net_unix! { |
244 | mod async_fd; |
245 | |
246 | pub mod unix { |
247 | //! Asynchronous IO structures specific to Unix-like operating systems. |
248 | pub use super::async_fd::{AsyncFd, AsyncFdReadyGuard, AsyncFdReadyMutGuard, TryIoError}; |
249 | } |
250 | } |
251 | |
252 | cfg_io_std! { |
253 | mod stdio_common; |
254 | |
255 | mod stderr; |
256 | pub use stderr::{stderr, Stderr}; |
257 | |
258 | mod stdin; |
259 | pub use stdin::{stdin, Stdin}; |
260 | |
261 | mod stdout; |
262 | pub use stdout::{stdout, Stdout}; |
263 | } |
264 | |
265 | cfg_io_util! { |
266 | mod split; |
267 | pub use split::{split, ReadHalf, WriteHalf}; |
268 | mod join; |
269 | pub use join::{join, Join}; |
270 | |
271 | pub(crate) mod seek; |
272 | pub(crate) mod util; |
273 | pub use util::{ |
274 | copy, copy_bidirectional, copy_buf, duplex, empty, repeat, sink, AsyncBufReadExt, AsyncReadExt, AsyncSeekExt, AsyncWriteExt, |
275 | BufReader, BufStream, BufWriter, DuplexStream, Empty, Lines, Repeat, Sink, Split, Take, |
276 | }; |
277 | } |
278 | |
279 | cfg_not_io_util! { |
280 | cfg_process! { |
281 | pub(crate) mod util; |
282 | } |
283 | } |
284 | |
285 | cfg_io_blocking! { |
286 | /// Types in this module can be mocked out in tests. |
287 | mod sys { |
288 | // TODO: don't rename |
289 | pub(crate) use crate::blocking::spawn_blocking as run; |
290 | pub(crate) use crate::blocking::JoinHandle as Blocking; |
291 | } |
292 | } |
293 | |