rollup merge of #19329: steveklabnik/doc_style_cleanup2
This commit is contained in:
@@ -16,207 +16,205 @@
|
||||
// error handling
|
||||
|
||||
|
||||
/*! I/O, including files, networking, timers, and processes
|
||||
|
||||
`std::io` provides Rust's basic I/O types,
|
||||
for reading and writing to files, TCP, UDP,
|
||||
and other types of sockets and pipes,
|
||||
manipulating the file system, spawning processes.
|
||||
|
||||
# Examples
|
||||
|
||||
Some examples of obvious things you might want to do
|
||||
|
||||
* Read lines from stdin
|
||||
|
||||
```rust
|
||||
use std::io;
|
||||
|
||||
for line in io::stdin().lines() {
|
||||
print!("{}", line.unwrap());
|
||||
}
|
||||
```
|
||||
|
||||
* Read a complete file
|
||||
|
||||
```rust
|
||||
use std::io::File;
|
||||
|
||||
let contents = File::open(&Path::new("message.txt")).read_to_end();
|
||||
```
|
||||
|
||||
* Write a line to a file
|
||||
|
||||
```rust
|
||||
# #![allow(unused_must_use)]
|
||||
use std::io::File;
|
||||
|
||||
let mut file = File::create(&Path::new("message.txt"));
|
||||
file.write(b"hello, file!\n");
|
||||
# drop(file);
|
||||
# ::std::io::fs::unlink(&Path::new("message.txt"));
|
||||
```
|
||||
|
||||
* Iterate over the lines of a file
|
||||
|
||||
```rust,no_run
|
||||
use std::io::BufferedReader;
|
||||
use std::io::File;
|
||||
|
||||
let path = Path::new("message.txt");
|
||||
let mut file = BufferedReader::new(File::open(&path));
|
||||
for line in file.lines() {
|
||||
print!("{}", line.unwrap());
|
||||
}
|
||||
```
|
||||
|
||||
* Pull the lines of a file into a vector of strings
|
||||
|
||||
```rust,no_run
|
||||
use std::io::BufferedReader;
|
||||
use std::io::File;
|
||||
|
||||
let path = Path::new("message.txt");
|
||||
let mut file = BufferedReader::new(File::open(&path));
|
||||
let lines: Vec<String> = file.lines().map(|x| x.unwrap()).collect();
|
||||
```
|
||||
|
||||
* Make a simple TCP client connection and request
|
||||
|
||||
```rust
|
||||
# #![allow(unused_must_use)]
|
||||
use std::io::TcpStream;
|
||||
|
||||
# // connection doesn't fail if a server is running on 8080
|
||||
# // locally, we still want to be type checking this code, so lets
|
||||
# // just stop it running (#11576)
|
||||
# if false {
|
||||
let mut socket = TcpStream::connect("127.0.0.1:8080").unwrap();
|
||||
socket.write(b"GET / HTTP/1.0\n\n");
|
||||
let response = socket.read_to_end();
|
||||
# }
|
||||
```
|
||||
|
||||
* Make a simple TCP server
|
||||
|
||||
```rust
|
||||
# fn main() { }
|
||||
# fn foo() {
|
||||
# #![allow(dead_code)]
|
||||
use std::io::{TcpListener, TcpStream};
|
||||
use std::io::{Acceptor, Listener};
|
||||
|
||||
let listener = TcpListener::bind("127.0.0.1:80");
|
||||
|
||||
// bind the listener to the specified address
|
||||
let mut acceptor = listener.listen();
|
||||
|
||||
fn handle_client(mut stream: TcpStream) {
|
||||
// ...
|
||||
# &mut stream; // silence unused mutability/variable warning
|
||||
}
|
||||
// accept connections and process them, spawning a new tasks for each one
|
||||
for stream in acceptor.incoming() {
|
||||
match stream {
|
||||
Err(e) => { /* connection failed */ }
|
||||
Ok(stream) => spawn(proc() {
|
||||
// connection succeeded
|
||||
handle_client(stream)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// close the socket server
|
||||
drop(acceptor);
|
||||
# }
|
||||
```
|
||||
|
||||
|
||||
# Error Handling
|
||||
|
||||
I/O is an area where nearly every operation can result in unexpected
|
||||
errors. Errors should be painfully visible when they happen, and handling them
|
||||
should be easy to work with. It should be convenient to handle specific I/O
|
||||
errors, and it should also be convenient to not deal with I/O errors.
|
||||
|
||||
Rust's I/O employs a combination of techniques to reduce boilerplate
|
||||
while still providing feedback about errors. The basic strategy:
|
||||
|
||||
* All I/O operations return `IoResult<T>` which is equivalent to
|
||||
`Result<T, IoError>`. The `Result` type is defined in the `std::result`
|
||||
module.
|
||||
* If the `Result` type goes unused, then the compiler will by default emit a
|
||||
warning about the unused result. This is because `Result` has the
|
||||
`#[must_use]` attribute.
|
||||
* Common traits are implemented for `IoResult`, e.g.
|
||||
`impl<R: Reader> Reader for IoResult<R>`, so that error values do not have
|
||||
to be 'unwrapped' before use.
|
||||
|
||||
These features combine in the API to allow for expressions like
|
||||
`File::create(&Path::new("diary.txt")).write(b"Met a girl.\n")`
|
||||
without having to worry about whether "diary.txt" exists or whether
|
||||
the write succeeds. As written, if either `new` or `write_line`
|
||||
encounters an error then the result of the entire expression will
|
||||
be an error.
|
||||
|
||||
If you wanted to handle the error though you might write:
|
||||
|
||||
```rust
|
||||
# #![allow(unused_must_use)]
|
||||
use std::io::File;
|
||||
|
||||
match File::create(&Path::new("diary.txt")).write(b"Met a girl.\n") {
|
||||
Ok(()) => (), // succeeded
|
||||
Err(e) => println!("failed to write to my diary: {}", e),
|
||||
}
|
||||
|
||||
# ::std::io::fs::unlink(&Path::new("diary.txt"));
|
||||
```
|
||||
|
||||
So what actually happens if `create` encounters an error?
|
||||
It's important to know that what `new` returns is not a `File`
|
||||
but an `IoResult<File>`. If the file does not open, then `new` will simply
|
||||
return `Err(..)`. Because there is an implementation of `Writer` (the trait
|
||||
required ultimately required for types to implement `write_line`) there is no
|
||||
need to inspect or unwrap the `IoResult<File>` and we simply call `write_line`
|
||||
on it. If `new` returned an `Err(..)` then the followup call to `write_line`
|
||||
will also return an error.
|
||||
|
||||
## `try!`
|
||||
|
||||
Explicit pattern matching on `IoResult`s can get quite verbose, especially
|
||||
when performing many I/O operations. Some examples (like those above) are
|
||||
alleviated with extra methods implemented on `IoResult`, but others have more
|
||||
complex interdependencies among each I/O operation.
|
||||
|
||||
The `try!` macro from `std::macros` is provided as a method of early-return
|
||||
inside `Result`-returning functions. It expands to an early-return on `Err`
|
||||
and otherwise unwraps the contained `Ok` value.
|
||||
|
||||
If you wanted to read several `u32`s from a file and return their product:
|
||||
|
||||
```rust
|
||||
use std::io::{File, IoResult};
|
||||
|
||||
fn file_product(p: &Path) -> IoResult<u32> {
|
||||
let mut f = File::open(p);
|
||||
let x1 = try!(f.read_le_u32());
|
||||
let x2 = try!(f.read_le_u32());
|
||||
|
||||
Ok(x1 * x2)
|
||||
}
|
||||
|
||||
match file_product(&Path::new("numbers.bin")) {
|
||||
Ok(x) => println!("{}", x),
|
||||
Err(e) => println!("Failed to read numbers!")
|
||||
}
|
||||
```
|
||||
|
||||
With `try!` in `file_product`, each `read_le_u32` need not be directly
|
||||
concerned with error handling; instead its caller is responsible for
|
||||
responding to errors that may occur while attempting to read the numbers.
|
||||
|
||||
*/
|
||||
//! I/O, including files, networking, timers, and processes
|
||||
//!
|
||||
//! `std::io` provides Rust's basic I/O types,
|
||||
//! for reading and writing to files, TCP, UDP,
|
||||
//! and other types of sockets and pipes,
|
||||
//! manipulating the file system, spawning processes.
|
||||
//!
|
||||
//! # Examples
|
||||
//!
|
||||
//! Some examples of obvious things you might want to do
|
||||
//!
|
||||
//! * Read lines from stdin
|
||||
//!
|
||||
//! ```rust
|
||||
//! use std::io;
|
||||
//!
|
||||
//! for line in io::stdin().lines() {
|
||||
//! print!("{}", line.unwrap());
|
||||
//! }
|
||||
//! ```
|
||||
//!
|
||||
//! * Read a complete file
|
||||
//!
|
||||
//! ```rust
|
||||
//! use std::io::File;
|
||||
//!
|
||||
//! let contents = File::open(&Path::new("message.txt")).read_to_end();
|
||||
//! ```
|
||||
//!
|
||||
//! * Write a line to a file
|
||||
//!
|
||||
//! ```rust
|
||||
//! # #![allow(unused_must_use)]
|
||||
//! use std::io::File;
|
||||
//!
|
||||
//! let mut file = File::create(&Path::new("message.txt"));
|
||||
//! file.write(b"hello, file!\n");
|
||||
//! # drop(file);
|
||||
//! # ::std::io::fs::unlink(&Path::new("message.txt"));
|
||||
//! ```
|
||||
//!
|
||||
//! * Iterate over the lines of a file
|
||||
//!
|
||||
//! ```rust,no_run
|
||||
//! use std::io::BufferedReader;
|
||||
//! use std::io::File;
|
||||
//!
|
||||
//! let path = Path::new("message.txt");
|
||||
//! let mut file = BufferedReader::new(File::open(&path));
|
||||
//! for line in file.lines() {
|
||||
//! print!("{}", line.unwrap());
|
||||
//! }
|
||||
//! ```
|
||||
//!
|
||||
//! * Pull the lines of a file into a vector of strings
|
||||
//!
|
||||
//! ```rust,no_run
|
||||
//! use std::io::BufferedReader;
|
||||
//! use std::io::File;
|
||||
//!
|
||||
//! let path = Path::new("message.txt");
|
||||
//! let mut file = BufferedReader::new(File::open(&path));
|
||||
//! let lines: Vec<String> = file.lines().map(|x| x.unwrap()).collect();
|
||||
//! ```
|
||||
//!
|
||||
//! * Make a simple TCP client connection and request
|
||||
//!
|
||||
//! ```rust
|
||||
//! # #![allow(unused_must_use)]
|
||||
//! use std::io::TcpStream;
|
||||
//!
|
||||
//! # // connection doesn't fail if a server is running on 8080
|
||||
//! # // locally, we still want to be type checking this code, so lets
|
||||
//! # // just stop it running (#11576)
|
||||
//! # if false {
|
||||
//! let mut socket = TcpStream::connect("127.0.0.1:8080").unwrap();
|
||||
//! socket.write(b"GET / HTTP/1.0\n\n");
|
||||
//! let response = socket.read_to_end();
|
||||
//! # }
|
||||
//! ```
|
||||
//!
|
||||
//! * Make a simple TCP server
|
||||
//!
|
||||
//! ```rust
|
||||
//! # fn main() { }
|
||||
//! # fn foo() {
|
||||
//! # #![allow(dead_code)]
|
||||
//! use std::io::{TcpListener, TcpStream};
|
||||
//! use std::io::{Acceptor, Listener};
|
||||
//!
|
||||
//! let listener = TcpListener::bind("127.0.0.1:80");
|
||||
//!
|
||||
//! // bind the listener to the specified address
|
||||
//! let mut acceptor = listener.listen();
|
||||
//!
|
||||
//! fn handle_client(mut stream: TcpStream) {
|
||||
//! // ...
|
||||
//! # &mut stream; // silence unused mutability/variable warning
|
||||
//! }
|
||||
//! // accept connections and process them, spawning a new tasks for each one
|
||||
//! for stream in acceptor.incoming() {
|
||||
//! match stream {
|
||||
//! Err(e) => { /* connection failed */ }
|
||||
//! Ok(stream) => spawn(proc() {
|
||||
//! // connection succeeded
|
||||
//! handle_client(stream)
|
||||
//! })
|
||||
//! }
|
||||
//! }
|
||||
//!
|
||||
//! // close the socket server
|
||||
//! drop(acceptor);
|
||||
//! # }
|
||||
//! ```
|
||||
//!
|
||||
//!
|
||||
//! # Error Handling
|
||||
//!
|
||||
//! I/O is an area where nearly every operation can result in unexpected
|
||||
//! errors. Errors should be painfully visible when they happen, and handling them
|
||||
//! should be easy to work with. It should be convenient to handle specific I/O
|
||||
//! errors, and it should also be convenient to not deal with I/O errors.
|
||||
//!
|
||||
//! Rust's I/O employs a combination of techniques to reduce boilerplate
|
||||
//! while still providing feedback about errors. The basic strategy:
|
||||
//!
|
||||
//! * All I/O operations return `IoResult<T>` which is equivalent to
|
||||
//! `Result<T, IoError>`. The `Result` type is defined in the `std::result`
|
||||
//! module.
|
||||
//! * If the `Result` type goes unused, then the compiler will by default emit a
|
||||
//! warning about the unused result. This is because `Result` has the
|
||||
//! `#[must_use]` attribute.
|
||||
//! * Common traits are implemented for `IoResult`, e.g.
|
||||
//! `impl<R: Reader> Reader for IoResult<R>`, so that error values do not have
|
||||
//! to be 'unwrapped' before use.
|
||||
//!
|
||||
//! These features combine in the API to allow for expressions like
|
||||
//! `File::create(&Path::new("diary.txt")).write(b"Met a girl.\n")`
|
||||
//! without having to worry about whether "diary.txt" exists or whether
|
||||
//! the write succeeds. As written, if either `new` or `write_line`
|
||||
//! encounters an error then the result of the entire expression will
|
||||
//! be an error.
|
||||
//!
|
||||
//! If you wanted to handle the error though you might write:
|
||||
//!
|
||||
//! ```rust
|
||||
//! # #![allow(unused_must_use)]
|
||||
//! use std::io::File;
|
||||
//!
|
||||
//! match File::create(&Path::new("diary.txt")).write(b"Met a girl.\n") {
|
||||
//! Ok(()) => (), // succeeded
|
||||
//! Err(e) => println!("failed to write to my diary: {}", e),
|
||||
//! }
|
||||
//!
|
||||
//! # ::std::io::fs::unlink(&Path::new("diary.txt"));
|
||||
//! ```
|
||||
//!
|
||||
//! So what actually happens if `create` encounters an error?
|
||||
//! It's important to know that what `new` returns is not a `File`
|
||||
//! but an `IoResult<File>`. If the file does not open, then `new` will simply
|
||||
//! return `Err(..)`. Because there is an implementation of `Writer` (the trait
|
||||
//! required ultimately required for types to implement `write_line`) there is no
|
||||
//! need to inspect or unwrap the `IoResult<File>` and we simply call `write_line`
|
||||
//! on it. If `new` returned an `Err(..)` then the followup call to `write_line`
|
||||
//! will also return an error.
|
||||
//!
|
||||
//! ## `try!`
|
||||
//!
|
||||
//! Explicit pattern matching on `IoResult`s can get quite verbose, especially
|
||||
//! when performing many I/O operations. Some examples (like those above) are
|
||||
//! alleviated with extra methods implemented on `IoResult`, but others have more
|
||||
//! complex interdependencies among each I/O operation.
|
||||
//!
|
||||
//! The `try!` macro from `std::macros` is provided as a method of early-return
|
||||
//! inside `Result`-returning functions. It expands to an early-return on `Err`
|
||||
//! and otherwise unwraps the contained `Ok` value.
|
||||
//!
|
||||
//! If you wanted to read several `u32`s from a file and return their product:
|
||||
//!
|
||||
//! ```rust
|
||||
//! use std::io::{File, IoResult};
|
||||
//!
|
||||
//! fn file_product(p: &Path) -> IoResult<u32> {
|
||||
//! let mut f = File::open(p);
|
||||
//! let x1 = try!(f.read_le_u32());
|
||||
//! let x2 = try!(f.read_le_u32());
|
||||
//!
|
||||
//! Ok(x1 * x2)
|
||||
//! }
|
||||
//!
|
||||
//! match file_product(&Path::new("numbers.bin")) {
|
||||
//! Ok(x) => println!("{}", x),
|
||||
//! Err(e) => println!("Failed to read numbers!")
|
||||
//! }
|
||||
//! ```
|
||||
//!
|
||||
//! With `try!` in `file_product`, each `read_le_u32` need not be directly
|
||||
//! concerned with error handling; instead its caller is responsible for
|
||||
//! responding to errors that may occur while attempting to read the numbers.
|
||||
|
||||
#![experimental]
|
||||
#![deny(unused_must_use)]
|
||||
|
||||
Reference in New Issue
Block a user