1 | //! Traits, helpers, and type definitions for core I/O functionality. |
2 | //! |
3 | //! The `async_std::io` module contains a number of common things you'll need |
4 | //! when doing input and output. The most core part of this module is |
5 | //! the [`Read`] and [`Write`] traits, which provide the |
6 | //! most general interface for reading and writing input and output. |
7 | //! |
8 | //! This module is an async version of [`std::io`]. |
9 | //! |
10 | //! [`std::io`]: https://doc.rust-lang.org/std/io/index.html |
11 | //! |
12 | //! # Read and Write |
13 | //! |
14 | //! Because they are traits, [`Read`] and [`Write`] are implemented by a number |
15 | //! of other types, and you can implement them for your types too. As such, |
16 | //! you'll see a few different types of I/O throughout the documentation in |
17 | //! this module: [`File`]s, [`TcpStream`]s, and sometimes even [`Vec<T>`]s. For |
18 | //! example, [`Read`] adds a [`read`][`Read::read`] method, which we can use on |
19 | //! [`File`]s: |
20 | //! |
21 | //! ```no_run |
22 | //! use async_std::fs::File; |
23 | //! use async_std::prelude::*; |
24 | //! |
25 | //! # fn main() -> std::io::Result<()> { async_std::task::block_on(async { |
26 | //! # |
27 | //! let mut f = File::open("foo.txt" ).await?; |
28 | //! let mut buffer = [0; 10]; |
29 | //! |
30 | //! // read up to 10 bytes |
31 | //! let n = f.read(&mut buffer).await?; |
32 | //! |
33 | //! println!("The bytes: {:?}" , &buffer[..n]); |
34 | //! # |
35 | //! # Ok(()) }) } |
36 | //! ``` |
37 | //! |
38 | //! [`Read`] and [`Write`] are so important, implementors of the two traits have a |
39 | //! nickname: readers and writers. So you'll sometimes see 'a reader' instead |
40 | //! of 'a type that implements the [`Read`] trait'. Much easier! |
41 | //! |
42 | //! ## Seek and BufRead |
43 | //! |
44 | //! Beyond that, there are two important traits that are provided: [`Seek`] |
45 | //! and [`BufRead`]. Both of these build on top of a reader to control |
46 | //! how the reading happens. [`Seek`] lets you control where the next byte is |
47 | //! coming from: |
48 | //! |
49 | //! ```no_run |
50 | //! use async_std::fs::File; |
51 | //! use async_std::io::SeekFrom; |
52 | //! use async_std::prelude::*; |
53 | //! |
54 | //! # fn main() -> std::io::Result<()> { async_std::task::block_on(async { |
55 | //! # |
56 | //! let mut f = File::open("foo.txt" ).await?; |
57 | //! let mut buffer = [0; 10]; |
58 | //! |
59 | //! // skip to the last 10 bytes of the file |
60 | //! f.seek(SeekFrom::End(-10)).await?; |
61 | //! |
62 | //! // read up to 10 bytes |
63 | //! let n = f.read(&mut buffer).await?; |
64 | //! |
65 | //! println!("The bytes: {:?}" , &buffer[..n]); |
66 | //! # |
67 | //! # Ok(()) }) } |
68 | //! ``` |
69 | //! |
70 | //! [`BufRead`] uses an internal buffer to provide a number of other ways to read, but |
71 | //! to show it off, we'll need to talk about buffers in general. Keep reading! |
72 | //! |
73 | //! ## BufReader and BufWriter |
74 | //! |
75 | //! Byte-based interfaces are unwieldy and can be inefficient, as we'd need to be |
76 | //! making near-constant calls to the operating system. To help with this, |
77 | //! `std::io` comes with two structs, [`BufReader`] and [`BufWriter`], which wrap |
78 | //! readers and writers. The wrapper uses a buffer, reducing the number of |
79 | //! calls and providing nicer methods for accessing exactly what you want. |
80 | //! |
81 | //! For example, [`BufReader`] works with the [`BufRead`] trait to add extra |
82 | //! methods to any reader: |
83 | //! |
84 | //! ```no_run |
85 | //! use async_std::fs::File; |
86 | //! use async_std::io::BufReader; |
87 | //! use async_std::prelude::*; |
88 | //! |
89 | //! # fn main() -> std::io::Result<()> { async_std::task::block_on(async { |
90 | //! # |
91 | //! let f = File::open("foo.txt" ).await?; |
92 | //! let mut reader = BufReader::new(f); |
93 | //! let mut buffer = String::new(); |
94 | //! |
95 | //! // read a line into buffer |
96 | //! reader.read_line(&mut buffer).await?; |
97 | //! |
98 | //! println!("{}" , buffer); |
99 | //! # |
100 | //! # Ok(()) }) } |
101 | //! ``` |
102 | //! |
103 | //! [`BufWriter`] doesn't add any new ways of writing; it just buffers every call |
104 | //! to [`write`][`Write::write`]: |
105 | //! |
106 | //! ```no_run |
107 | //! use async_std::fs::File; |
108 | //! use async_std::io::prelude::*; |
109 | //! use async_std::io::BufWriter; |
110 | //! |
111 | //! # fn main() -> std::io::Result<()> { async_std::task::block_on(async { |
112 | //! # |
113 | //! let f = File::create("foo.txt" ).await?; |
114 | //! { |
115 | //! let mut writer = BufWriter::new(f); |
116 | //! |
117 | //! // write a byte to the buffer |
118 | //! writer.write(&[42]).await?; |
119 | //! } // the buffer is flushed once writer goes out of scope |
120 | //! // |
121 | //! # |
122 | //! # Ok(()) }) } |
123 | //! ``` |
124 | //! |
125 | //! ## Standard input and output |
126 | //! |
127 | //! A very common source of input is standard input: |
128 | //! |
129 | //! ```no_run |
130 | //! use async_std::io; |
131 | //! |
132 | //! # fn main() -> std::io::Result<()> { async_std::task::block_on(async { |
133 | //! # |
134 | //! let mut input = String::new(); |
135 | //! |
136 | //! io::stdin().read_line(&mut input).await?; |
137 | //! |
138 | //! println!("You typed: {}" , input.trim()); |
139 | //! # |
140 | //! # Ok(()) }) } |
141 | //! ``` |
142 | //! |
143 | //! Note that you cannot use the [`?` operator] in functions that do not return |
144 | //! a [`Result<T, E>`][`Result`]. Instead, you can call [`.unwrap()`] |
145 | //! or `match` on the return value to catch any possible errors: |
146 | //! |
147 | //! ```no_run |
148 | //! use async_std::io; |
149 | //! |
150 | //! # fn main() -> std::io::Result<()> { async_std::task::block_on(async { |
151 | //! # |
152 | //! let mut input = String::new(); |
153 | //! |
154 | //! io::stdin().read_line(&mut input).await.unwrap(); |
155 | //! # |
156 | //! # Ok(()) }) } |
157 | //! ``` |
158 | //! |
159 | //! And a very common source of output is standard output: |
160 | //! |
161 | //! ```no_run |
162 | //! use async_std::io; |
163 | //! use async_std::io::prelude::*; |
164 | //! |
165 | //! # fn main() -> std::io::Result<()> { async_std::task::block_on(async { |
166 | //! # |
167 | //! io::stdout().write(&[42]).await?; |
168 | //! # |
169 | //! # Ok(()) }) } |
170 | //! ``` |
171 | //! |
172 | //! Of course, using [`io::stdout`] directly is less common than something like |
173 | //! [`println!`]. |
174 | //! |
175 | //! ## Iterator types |
176 | //! |
177 | //! A large number of the structures provided by `std::io` are for various |
178 | //! ways of iterating over I/O. For example, [`Lines`] is used to split over |
179 | //! lines: |
180 | //! |
181 | //! ```no_run |
182 | //! use async_std::fs::File; |
183 | //! use async_std::io::BufReader; |
184 | //! use async_std::prelude::*; |
185 | //! |
186 | //! # fn main() -> std::io::Result<()> { async_std::task::block_on(async { |
187 | //! # |
188 | //! let f = File::open("foo.txt" ).await?; |
189 | //! let reader = BufReader::new(f); |
190 | //! |
191 | //! let mut lines = reader.lines(); |
192 | //! while let Some(line) = lines.next().await { |
193 | //! println!("{}" , line?); |
194 | //! } |
195 | //! # |
196 | //! # Ok(()) }) } |
197 | //! ``` |
198 | //! |
199 | //! ## Functions |
200 | //! |
201 | //! There are a number of [functions][functions-list] that offer access to various |
202 | //! features. For example, we can use three of these functions to copy everything |
203 | //! from standard input to standard output: |
204 | //! |
205 | //! ```no_run |
206 | //! use async_std::io; |
207 | //! |
208 | //! # fn main() -> std::io::Result<()> { async_std::task::block_on(async { |
209 | //! # |
210 | //! io::copy(&mut io::stdin(), &mut io::stdout()).await?; |
211 | //! # |
212 | //! # Ok(()) }) } |
213 | //! ``` |
214 | //! |
215 | //! [functions-list]: #functions-1 |
216 | //! |
217 | //! ## io::Result |
218 | //! |
219 | //! Last, but certainly not least, is [`io::Result`]. This type is used |
220 | //! as the return type of many `std::io` functions that can cause an error, and |
221 | //! can be returned from your own functions as well. Many of the examples in this |
222 | //! module use the [`?` operator]: |
223 | //! |
224 | //! ``` |
225 | //! #![allow(dead_code)] |
226 | //! use async_std::io; |
227 | //! |
228 | //! async fn read_input() -> io::Result<()> { |
229 | //! let mut input = String::new(); |
230 | //! |
231 | //! io::stdin().read_line(&mut input).await?; |
232 | //! |
233 | //! println!("You typed: {}" , input.trim()); |
234 | //! |
235 | //! Ok(()) |
236 | //! } |
237 | //! ``` |
238 | //! |
239 | //! The return type of `read_input`, [`io::Result<()>`][`io::Result`], is a very |
240 | //! common type for functions which don't have a 'real' return value, but do want to |
241 | //! return errors if they happen. In this case, the only purpose of this function is |
242 | //! to read the line and print it, so we use `()`. |
243 | //! |
244 | //! ## Platform-specific behavior |
245 | //! |
246 | //! Many I/O functions throughout the standard library are documented to indicate |
247 | //! what various library or syscalls they are delegated to. This is done to help |
248 | //! applications both understand what's happening under the hood as well as investigate |
249 | //! any possibly unclear semantics. Note, however, that this is informative, not a binding |
250 | //! contract. The implementation of many of these functions are subject to change over |
251 | //! time and may call fewer or more syscalls/library functions. |
252 | //! |
253 | //! [`Read`]: trait.Read.html |
254 | //! [`Write`]: trait.Write.html |
255 | //! [`Seek`]: trait.Seek.html |
256 | //! [`BufRead`]: trait.BufRead.html |
257 | //! [`File`]: ../fs/struct.File.html |
258 | //! [`TcpStream`]: ../net/struct.TcpStream.html |
259 | //! [`Vec<T>`]: ../vec/struct.Vec.html |
260 | //! [`BufReader`]: struct.BufReader.html |
261 | //! [`BufWriter`]: struct.BufWriter.html |
262 | //! [`Write::write`]: trait.Write.html#tymethod.write |
263 | //! [`io::stdout`]: fn.stdout.html |
264 | //! [`println!`]: ../macro.println.html |
265 | //! [`Lines`]: struct.Lines.html |
266 | //! [`io::Result`]: type.Result.html |
267 | //! [`?` operator]: https://doc.rust-lang.org/stable/book/appendix-02-operators.html |
268 | //! [`Read::read`]: trait.Read.html#tymethod.read |
269 | //! [`Result`]: https://doc.rust-lang.org/std/result/enum.Result.html |
270 | //! [`.unwrap()`]: https://doc.rust-lang.org/std/result/enum.Result.html#method.unwrap |
271 | |
272 | const DEFAULT_BUF_SIZE: usize = 8 * 1024; |
273 | |
274 | cfg_std! { |
275 | #[doc (inline)] |
276 | pub use std::io::{Error, ErrorKind, IoSlice, IoSliceMut, Result, SeekFrom}; |
277 | |
278 | pub use buf_read::*; |
279 | pub use buf_reader::BufReader; |
280 | pub use buf_writer::{BufWriter, IntoInnerError}; |
281 | pub use copy::copy; |
282 | pub use cursor::Cursor; |
283 | pub use empty::{empty, Empty}; |
284 | pub use read::*; |
285 | pub use repeat::{repeat, Repeat}; |
286 | pub use seek::*; |
287 | pub use sink::{sink, Sink}; |
288 | pub use write::*; |
289 | |
290 | pub mod prelude; |
291 | |
292 | pub(crate) mod buf_read; |
293 | pub(crate) mod read; |
294 | pub(crate) mod seek; |
295 | pub(crate) mod write; |
296 | pub(crate) mod utils; |
297 | |
298 | mod buf_reader; |
299 | mod buf_writer; |
300 | mod copy; |
301 | mod cursor; |
302 | mod empty; |
303 | mod repeat; |
304 | mod sink; |
305 | } |
306 | |
307 | cfg_default! { |
308 | // For use in the print macros. |
309 | #[doc (hidden)] |
310 | #[cfg (not(target_os = "unknown" ))] |
311 | pub use stdio::{_eprint, _print}; |
312 | |
313 | #[cfg (not(target_os = "unknown" ))] |
314 | pub use stderr::{stderr, Stderr}; |
315 | #[cfg (not(target_os = "unknown" ))] |
316 | pub use stdin::{stdin, Stdin}; |
317 | #[cfg (not(target_os = "unknown" ))] |
318 | pub use stdout::{stdout, Stdout}; |
319 | pub use timeout::timeout; |
320 | |
321 | mod timeout; |
322 | #[cfg (not(target_os = "unknown" ))] |
323 | mod stderr; |
324 | #[cfg (not(target_os = "unknown" ))] |
325 | mod stdin; |
326 | #[cfg (not(target_os = "unknown" ))] |
327 | mod stdio; |
328 | #[cfg (not(target_os = "unknown" ))] |
329 | mod stdout; |
330 | } |
331 | |