| //! Traits, helpers, and type definitions for core I/O functionality. | |
| //! | |
| //! The `std::io` module contains a number of common things you'll need | |
| //! when doing input and output. The most core part of this module is | |
| //! the [`Read`] and [`Write`] traits, which provide the | |
| //! most general interface for reading and writing input and output. | |
| //! | |
| //! ## Read and Write | |
| //! | |
| //! Because they are traits, [`Read`] and [`Write`] are implemented by a number | |
| //! of other types, and you can implement them for your types too. As such, | |
| //! you'll see a few different types of I/O throughout the documentation in | |
| //! this module: [`File`]s, [`TcpStream`]s, and sometimes even [`Vec<T>`]s. For | |
| //! example, [`Read`] adds a [`read`][`Read::read`] method, which we can use on | |
| //! [`File`]s: | |
| //! | |
| //! ```no_run | |
| //! use std::io; | |
| //! use std::io::prelude::*; | |
| //! use std::fs::File; | |
| //! | |
| //! fn main() -> io::Result<()> { | |
| //! let mut f = File::open("foo.txt")?; | |
| //! let mut buffer = [0; 10]; | |
| //! | |
| //! // read up to 10 bytes | |
| //! let n = f.read(&mut buffer)?; | |
| //! | |
| //! println!("The bytes: {:?}", &buffer[..n]); | |
| //! Ok(()) | |
| //! } | |
| //! ``` | |
| //! | |
| //! [`Read`] and [`Write`] are so important, implementors of the two traits have a | |
| //! nickname: readers and writers. So you'll sometimes see 'a reader' instead | |
| //! of 'a type that implements the [`Read`] trait'. Much easier! | |
| //! | |
| //! ## Seek and BufRead | |
| //! | |
| //! Beyond that, there are two important traits that are provided: [`Seek`] | |
| //! and [`BufRead`]. Both of these build on top of a reader to control | |
| //! how the reading happens. [`Seek`] lets you control where the next byte is | |
| //! coming from: | |
| //! | |
| //! ```no_run | |
| //! use std::io; | |
| //! use std::io::prelude::*; | |
| //! use std::io::SeekFrom; | |
| //! use std::fs::File; | |
| //! | |
| //! fn main() -> io::Result<()> { | |
| //! let mut f = File::open("foo.txt")?; | |
| //! let mut buffer = [0; 10]; | |
| //! | |
| //! // skip to the last 10 bytes of the file | |
| //! f.seek(SeekFrom::End(-10))?; | |
| //! | |
| //! // read up to 10 bytes | |
| //! let n = f.read(&mut buffer)?; | |
| //! | |
| //! println!("The bytes: {:?}", &buffer[..n]); | |
| //! Ok(()) | |
| //! } | |
| //! ``` | |
| //! | |
| //! [`BufRead`] uses an internal buffer to provide a number of other ways to read, but | |
| //! to show it off, we'll need to talk about buffers in general. Keep reading! | |
| //! | |
| //! ## BufReader and BufWriter | |
| //! | |
| //! 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 two structs, [`BufReader`] and [`BufWriter`], which wrap | |
| //! readers and writers. The wrapper uses a buffer, reducing the number of | |
| //! calls and providing nicer methods for accessing exactly what you want. | |
| //! | |
| //! For example, [`BufReader`] works with the [`BufRead`] trait to add extra | |
| //! methods to any reader: | |
| //! | |
| //! ```no_run | |
| //! use std::io; | |
| //! use std::io::prelude::*; | |
| //! use std::io::BufReader; | |
| //! use std::fs::File; | |
| //! | |
| //! fn main() -> io::Result<()> { | |
| //! let f = File::open("foo.txt")?; | |
| //! let mut reader = BufReader::new(f); | |
| //! let mut buffer = String::new(); | |
| //! | |
| //! // read a line into buffer | |
| //! reader.read_line(&mut buffer)?; | |
| //! | |
| //! println!("{buffer}"); | |
| //! Ok(()) | |
| //! } | |
| //! ``` | |
| //! | |
| //! [`BufWriter`] doesn't add any new ways of writing; it just buffers every call | |
| //! to [`write`][`Write::write`]: | |
| //! | |
| //! ```no_run | |
| //! use std::io; | |
| //! use std::io::prelude::*; | |
| //! use std::io::BufWriter; | |
| //! use std::fs::File; | |
| //! | |
| //! fn main() -> io::Result<()> { | |
| //! let f = File::create("foo.txt")?; | |
| //! { | |
| //! let mut writer = BufWriter::new(f); | |
| //! | |
| //! // write a byte to the buffer | |
| //! writer.write(&[42])?; | |
| //! | |
| //! } // the buffer is flushed once writer goes out of scope | |
| //! | |
| //! Ok(()) | |
| //! } | |
| //! ``` | |
| //! | |
| //! ## Standard input and output | |
| //! | |
| //! A very common source of input is standard input: | |
| //! | |
| //! ```no_run | |
| //! use std::io; | |
| //! | |
| //! fn main() -> io::Result<()> { | |
| //! let mut input = String::new(); | |
| //! | |
| //! io::stdin().read_line(&mut input)?; | |
| //! | |
| //! println!("You typed: {}", input.trim()); | |
| //! Ok(()) | |
| //! } | |
| //! ``` | |
| //! | |
| //! Note that you cannot use the [`?` operator] in functions that do not return | |
| //! a [`Result<T, E>`][`Result`]. Instead, you can call [`.unwrap()`] | |
| //! or `match` on the return value to catch any possible errors: | |
| //! | |
| //! ```no_run | |
| //! use std::io; | |
| //! | |
| //! let mut input = String::new(); | |
| //! | |
| //! io::stdin().read_line(&mut input).unwrap(); | |
| //! ``` | |
| //! | |
| //! And a very common source of output is standard output: | |
| //! | |
| //! ```no_run | |
| //! use std::io; | |
| //! use std::io::prelude::*; | |
| //! | |
| //! fn main() -> io::Result<()> { | |
| //! io::stdout().write(&[42])?; | |
| //! Ok(()) | |
| //! } | |
| //! ``` | |
| //! | |
| //! Of course, using [`io::stdout`] directly is less common than something like | |
| //! [`println!`]. | |
| //! | |
| //! ## Iterator types | |
| //! | |
| //! A large number of the structures provided by `std::io` are for various | |
| //! ways of iterating over I/O. For example, [`Lines`] is used to split over | |
| //! lines: | |
| //! | |
| //! ```no_run | |
| //! use std::io; | |
| //! use std::io::prelude::*; | |
| //! use std::io::BufReader; | |
| //! use std::fs::File; | |
| //! | |
| //! fn main() -> io::Result<()> { | |
| //! let f = File::open("foo.txt")?; | |
| //! let reader = BufReader::new(f); | |
| //! | |
| //! for line in reader.lines() { | |
| //! println!("{}", line?); | |
| //! } | |
| //! Ok(()) | |
| //! } | |
| //! ``` | |
| //! | |
| //! ## Functions | |
| //! | |
| //! There are a number of [functions][functions-list] that offer access to various | |
| //! features. For example, we can use three of these functions to copy everything | |
| //! from standard input to standard output: | |
| //! | |
| //! ```no_run | |
| //! use std::io; | |
| //! | |
| //! fn main() -> io::Result<()> { | |
| //! io::copy(&mut io::stdin(), &mut io::stdout())?; | |
| //! Ok(()) | |
| //! } | |
| //! ``` | |
| //! | |
| //! [functions-list]: #functions-1 | |
| //! | |
| //! ## io::Result | |
| //! | |
| //! Last, but certainly not least, is [`io::Result`]. This type is used | |
| //! as the return type of many `std::io` functions that can cause an error, and | |
| //! can be returned from your own functions as well. Many of the examples in this | |
| //! module use the [`?` operator]: | |
| //! | |
| //! ``` | |
| //! use std::io; | |
| //! | |
| //! fn read_input() -> io::Result<()> { | |
| //! let mut input = String::new(); | |
| //! | |
| //! io::stdin().read_line(&mut input)?; | |
| //! | |
| //! println!("You typed: {}", input.trim()); | |
| //! | |
| //! Ok(()) | |
| //! } | |
| //! ``` | |
| //! | |
| //! The return type of `read_input()`, [`io::Result<()>`][`io::Result`], is a very | |
| //! common type for functions which don't have a 'real' return value, but do want to | |
| //! return errors if they happen. In this case, the only purpose of this function is | |
| //! to read the line and print it, so we use `()`. | |
| //! | |
| //! ## Platform-specific behavior | |
| //! | |
| //! Many I/O functions throughout the standard library are documented to indicate | |
| //! what various library or syscalls they are delegated to. This is done to help | |
| //! applications both understand what's happening under the hood as well as investigate | |
| //! any possibly unclear semantics. Note, however, that this is informative, not a binding | |
| //! contract. The implementation of many of these functions are subject to change over | |
| //! time and may call fewer or more syscalls/library functions. | |
| //! | |
| //! ## I/O Safety | |
| //! | |
| //! Rust follows an I/O safety discipline that is comparable to its memory safety discipline. This | |
| //! means that file descriptors can be *exclusively owned*. (Here, "file descriptor" is meant to | |
| //! subsume similar concepts that exist across a wide range of operating systems even if they might | |
| //! use a different name, such as "handle".) An exclusively owned file descriptor is one that no | |
| //! other code is allowed to access in any way, but the owner is allowed to access and even close | |
| //! it any time. A type that owns its file descriptor should usually close it in its `drop` | |
| //! function. Types like [`File`] own their file descriptor. Similarly, file descriptors | |
| //! can be *borrowed*, granting the temporary right to perform operations on this file descriptor. | |
| //! This indicates that the file descriptor will not be closed for the lifetime of the borrow, but | |
| //! it does *not* imply any right to close this file descriptor, since it will likely be owned by | |
| //! someone else. | |
| //! | |
| //! The platform-specific parts of the Rust standard library expose types that reflect these | |
| //! concepts, see [`os::unix`] and [`os::windows`]. | |
| //! | |
| //! To uphold I/O safety, it is crucial that no code acts on file descriptors it does not own or | |
| //! borrow, and no code closes file descriptors it does not own. In other words, a safe function | |
| //! that takes a regular integer, treats it as a file descriptor, and acts on it, is *unsound*. | |
| //! | |
| //! Not upholding I/O safety and acting on a file descriptor without proof of ownership can lead to | |
| //! misbehavior and even Undefined Behavior in code that relies on ownership of its file | |
| //! descriptors: a closed file descriptor could be re-allocated, so the original owner of that file | |
| //! descriptor is now working on the wrong file. Some code might even rely on fully encapsulating | |
| //! its file descriptors with no operations being performed by any other part of the program. | |
| //! | |
| //! Note that exclusive ownership of a file descriptor does *not* imply exclusive ownership of the | |
| //! underlying kernel object that the file descriptor references (also called "open file description" on | |
| //! some operating systems). File descriptors basically work like [`Arc`]: when you receive an owned | |
| //! file descriptor, you cannot know whether there are any other file descriptors that reference the | |
| //! same kernel object. However, when you create a new kernel object, you know that you are holding | |
| //! the only reference to it. Just be careful not to lend it to anyone, since they can obtain a | |
| //! clone and then you can no longer know what the reference count is! In that sense, [`OwnedFd`] is | |
| //! like `Arc` and [`BorrowedFd<'a>`] is like `&'a Arc` (and similar for the Windows types). In | |
| //! particular, given a `BorrowedFd<'a>`, you are not allowed to close the file descriptor -- just | |
| //! like how, given a `&'a Arc`, you are not allowed to decrement the reference count and | |
| //! potentially free the underlying object. There is no equivalent to `Box` for file descriptors in | |
| //! the standard library (that would be a type that guarantees that the reference count is `1`), | |
| //! however, it would be possible for a crate to define a type with those semantics. | |
| //! | |
| //! [`File`]: crate::fs::File | |
| //! [`TcpStream`]: crate::net::TcpStream | |
| //! [`io::stdout`]: stdout | |
| //! [`io::Result`]: self::Result | |
| //! [`?` operator]: ../../book/appendix-02-operators.html | |
| //! [`Result`]: crate::result::Result | |
| //! [`.unwrap()`]: crate::result::Result::unwrap | |
| //! [`os::unix`]: ../os/unix/io/index.html | |
| //! [`os::windows`]: ../os/windows/io/index.html | |
| //! [`OwnedFd`]: ../os/fd/struct.OwnedFd.html | |
| //! [`BorrowedFd<'a>`]: ../os/fd/struct.BorrowedFd.html | |
| //! [`Arc`]: crate::sync::Arc | |
| #![stable(feature = "rust1", since = "1.0.0")] | |
| #[cfg(test)] | |
| mod tests; | |
| use alloc_crate::io::OsFunctions; | |
| #[unstable(feature = "raw_os_error_ty", issue = "107792")] | |
| pub use alloc_crate::io::RawOsError; | |
| #[doc(hidden)] | |
| #[unstable(feature = "io_const_error_internals", issue = "none")] | |
| pub use alloc_crate::io::SimpleMessage; | |
| #[stable(feature = "bufwriter_into_parts", since = "1.56.0")] | |
| pub use alloc_crate::io::WriterPanicked; | |
| #[unstable(feature = "io_const_error", issue = "133448")] | |
| pub use alloc_crate::io::const_error; | |
| #[stable(feature = "io_read_to_string", since = "1.65.0")] | |
| pub use alloc_crate::io::read_to_string; | |
| #[unstable(feature = "read_buf", issue = "78485")] | |
| pub use alloc_crate::io::{BorrowedBuf, BorrowedCursor}; | |
| #[stable(feature = "rust1", since = "1.0.0")] | |
| pub use alloc_crate::io::{ | |
| BufRead, BufReader, BufWriter, Bytes, Chain, Cursor, Empty, Error, ErrorKind, IntoInnerError, | |
| LineWriter, Lines, Read, Repeat, Result, Seek, SeekFrom, Sink, Split, Take, Write, empty, | |
| repeat, sink, | |
| }; | |
| #[allow(unused_imports, reason = "only used by certain platforms")] | |
| pub(crate) use alloc_crate::io::{ | |
| DEFAULT_BUF_SIZE, default_read_buf, default_read_vectored, default_write_vectored, | |
| }; | |
| pub(crate) use alloc_crate::io::{ | |
| IoHandle, SpecReadByte, default_read_to_end, default_read_to_string, stream_len_default, | |
| }; | |
| #[stable(feature = "iovec", since = "1.36.0")] | |
| pub use alloc_crate::io::{IoSlice, IoSliceMut}; | |
| #[stable(feature = "anonymous_pipe", since = "1.87.0")] | |
| pub use self::pipe::{PipeReader, PipeWriter, pipe}; | |
| #[stable(feature = "is_terminal", since = "1.70.0")] | |
| pub use self::stdio::IsTerminal; | |
| pub(crate) use self::stdio::attempt_print_to_stderr; | |
| #[unstable(feature = "print_internals", issue = "none")] | |
| #[doc(hidden)] | |
| pub use self::stdio::{_eprint, _print}; | |
| #[unstable(feature = "internal_output_capture", issue = "none")] | |
| #[doc(no_inline, hidden)] | |
| pub use self::stdio::{set_output_capture, try_set_output_capture}; | |
| #[stable(feature = "rust1", since = "1.0.0")] | |
| pub use self::{ | |
| copy::copy, | |
| stdio::{Stderr, StderrLock, Stdin, StdinLock, Stdout, StdoutLock, stderr, stdin, stdout}, | |
| }; | |
| mod buffered; | |
| pub(crate) mod copy; | |
| mod cursor; | |
| mod error; | |
| mod impls; | |
| mod pipe; | |
| pub mod prelude; | |
| mod stdio; | |
| mod util; | |
| pub(crate) use stdio::cleanup; |