auto merge of #11271 : adridu59/rust/patch-io, r=huonw
This commit is contained in:
commit
14c24accbc
2 changed files with 84 additions and 54 deletions
|
@ -43,12 +43,13 @@ $ ./example numbers.txt
|
||||||
|
|
||||||
An example program that does this task reads like this:
|
An example program that does this task reads like this:
|
||||||
|
|
||||||
~~~~{.xfail-test}
|
~~~~
|
||||||
# #[allow(unused_imports)];
|
# #[allow(unused_imports)];
|
||||||
|
# extern mod extra;
|
||||||
use std::io::buffered::BufferedReader;
|
use std::io::buffered::BufferedReader;
|
||||||
use std::io::fs::File;
|
use std::io::File;
|
||||||
# mod BufferedReader {
|
# mod BufferedReader {
|
||||||
# use std::io::fs::File;
|
# use std::io::File;
|
||||||
# use std::io::mem::MemReader;
|
# use std::io::mem::MemReader;
|
||||||
# use std::io::buffered::BufferedReader;
|
# use std::io::buffered::BufferedReader;
|
||||||
# static s : &'static [u8] = bytes!("1 2\n\
|
# static s : &'static [u8] = bytes!("1 2\n\
|
||||||
|
@ -71,10 +72,9 @@ fn main() {
|
||||||
fn read_int_pairs() -> ~[(int,int)] {
|
fn read_int_pairs() -> ~[(int,int)] {
|
||||||
let mut pairs = ~[];
|
let mut pairs = ~[];
|
||||||
|
|
||||||
let args = std::os::args();
|
|
||||||
|
|
||||||
// Path takes a generic by-value, rather than by reference
|
// Path takes a generic by-value, rather than by reference
|
||||||
let path = Path::new(args.get_opt(1).expect("No input file parameter!").as_slice());
|
# let _g = std::io::ignore_io_error();
|
||||||
|
let path = Path::new(&"foo.txt");
|
||||||
let mut reader = BufferedReader::new(File::open(&path));
|
let mut reader = BufferedReader::new(File::open(&path));
|
||||||
|
|
||||||
// 1. Iterate over the lines of our file.
|
// 1. Iterate over the lines of our file.
|
||||||
|
@ -242,13 +242,14 @@ If the example is rewritten to use failure, these error cases can be trapped.
|
||||||
In this rewriting, failures are trapped by placing the I/O logic in a sub-task,
|
In this rewriting, failures are trapped by placing the I/O logic in a sub-task,
|
||||||
and trapping its exit status using `task::try`:
|
and trapping its exit status using `task::try`:
|
||||||
|
|
||||||
~~~~{.xfail-test}
|
~~~~
|
||||||
# #[allow(unused_imports)];
|
# #[allow(unused_imports)];
|
||||||
|
# extern mod extra;
|
||||||
use std::io::buffered::BufferedReader;
|
use std::io::buffered::BufferedReader;
|
||||||
use std::io::fs::File;
|
use std::io::File;
|
||||||
use std::task;
|
use std::task;
|
||||||
# mod BufferedReader {
|
# mod BufferedReader {
|
||||||
# use std::io::fs::File;
|
# use std::io::File;
|
||||||
# use std::io::mem::MemReader;
|
# use std::io::mem::MemReader;
|
||||||
# use std::io::buffered::BufferedReader;
|
# use std::io::buffered::BufferedReader;
|
||||||
# static s : &'static [u8] = bytes!("1 2\n\
|
# static s : &'static [u8] = bytes!("1 2\n\
|
||||||
|
@ -280,8 +281,8 @@ fn main() {
|
||||||
|
|
||||||
fn read_int_pairs() -> ~[(int,int)] {
|
fn read_int_pairs() -> ~[(int,int)] {
|
||||||
let mut pairs = ~[];
|
let mut pairs = ~[];
|
||||||
let args = std::os::args();
|
# let _g = std::io::ignore_io_error();
|
||||||
let path = Path::new(args.get_opt(1).expect("No input file parameter!").as_slice());
|
let path = Path::new(&"foo.txt");
|
||||||
|
|
||||||
let mut reader = BufferedReader::new(File::open(&path));
|
let mut reader = BufferedReader::new(File::open(&path));
|
||||||
for line in reader.lines() {
|
for line in reader.lines() {
|
||||||
|
@ -346,12 +347,13 @@ If no handler is found, `Condition::raise` will fail the task with an appropriat
|
||||||
Rewriting the example to use a condition in place of ignoring malformed lines makes it slightly longer,
|
Rewriting the example to use a condition in place of ignoring malformed lines makes it slightly longer,
|
||||||
but similarly clear as the version that used `fail!` in the logic where the error occurs:
|
but similarly clear as the version that used `fail!` in the logic where the error occurs:
|
||||||
|
|
||||||
~~~~{.xfail-test}
|
~~~~
|
||||||
# #[allow(unused_imports)];
|
# #[allow(unused_imports)];
|
||||||
|
# extern mod extra;
|
||||||
use std::io::buffered::BufferedReader;
|
use std::io::buffered::BufferedReader;
|
||||||
use std::io::fs::File;
|
use std::io::File;
|
||||||
# mod BufferedReader {
|
# mod BufferedReader {
|
||||||
# use std::io::fs::File;
|
# use std::io::File;
|
||||||
# use std::io::mem::MemReader;
|
# use std::io::mem::MemReader;
|
||||||
# use std::io::buffered::BufferedReader;
|
# use std::io::buffered::BufferedReader;
|
||||||
# static s : &'static [u8] = bytes!("1 2\n\
|
# static s : &'static [u8] = bytes!("1 2\n\
|
||||||
|
@ -378,8 +380,8 @@ fn main() {
|
||||||
|
|
||||||
fn read_int_pairs() -> ~[(int,int)] {
|
fn read_int_pairs() -> ~[(int,int)] {
|
||||||
let mut pairs = ~[];
|
let mut pairs = ~[];
|
||||||
let args = std::os::args();
|
# let _g = std::io::ignore_io_error();
|
||||||
let path = Path::new(args.get_opt(1).expect("No input file parameter!").as_slice());
|
let path = Path::new(&"foo.txt");
|
||||||
|
|
||||||
let mut reader = BufferedReader::new(File::open(&path));
|
let mut reader = BufferedReader::new(File::open(&path));
|
||||||
for line in reader.lines() {
|
for line in reader.lines() {
|
||||||
|
@ -415,12 +417,13 @@ To trap a condition, use `Condition::trap` in some caller of the site that calls
|
||||||
For example, this version of the program traps the `malformed_line` condition
|
For example, this version of the program traps the `malformed_line` condition
|
||||||
and replaces bad input lines with the pair `(-1,-1)`:
|
and replaces bad input lines with the pair `(-1,-1)`:
|
||||||
|
|
||||||
~~~~{.xfail-test}
|
~~~~
|
||||||
# #[allow(unused_imports)];
|
# #[allow(unused_imports)];
|
||||||
|
# extern mod extra;
|
||||||
use std::io::buffered::BufferedReader;
|
use std::io::buffered::BufferedReader;
|
||||||
use std::io::fs::File;
|
use std::io::File;
|
||||||
# mod BufferedReader {
|
# mod BufferedReader {
|
||||||
# use std::io::fs::File;
|
# use std::io::File;
|
||||||
# use std::io::mem::MemReader;
|
# use std::io::mem::MemReader;
|
||||||
# use std::io::buffered::BufferedReader;
|
# use std::io::buffered::BufferedReader;
|
||||||
# static s : &'static [u8] = bytes!("1 2\n\
|
# static s : &'static [u8] = bytes!("1 2\n\
|
||||||
|
@ -452,8 +455,8 @@ fn main() {
|
||||||
|
|
||||||
fn read_int_pairs() -> ~[(int,int)] {
|
fn read_int_pairs() -> ~[(int,int)] {
|
||||||
let mut pairs = ~[];
|
let mut pairs = ~[];
|
||||||
let args = std::os::args();
|
# let _g = std::io::ignore_io_error();
|
||||||
let path = Path::new(args.get_opt(1).expect("No input file parameter!").as_slice());
|
let path = Path::new(&"foo.txt");
|
||||||
|
|
||||||
let mut reader = BufferedReader::new(File::open(&path));
|
let mut reader = BufferedReader::new(File::open(&path));
|
||||||
for line in reader.lines() {
|
for line in reader.lines() {
|
||||||
|
@ -490,12 +493,13 @@ In the example program, the first form of the `malformed_line` API implicitly as
|
||||||
This assumption may not be correct; some callers may wish to skip malformed lines, for example.
|
This assumption may not be correct; some callers may wish to skip malformed lines, for example.
|
||||||
Changing the condition's return type from `(int,int)` to `Option<(int,int)>` will suffice to support this type of recovery:
|
Changing the condition's return type from `(int,int)` to `Option<(int,int)>` will suffice to support this type of recovery:
|
||||||
|
|
||||||
~~~~{.xfail-test}
|
~~~~
|
||||||
# #[allow(unused_imports)];
|
# #[allow(unused_imports)];
|
||||||
|
# extern mod extra;
|
||||||
use std::io::buffered::BufferedReader;
|
use std::io::buffered::BufferedReader;
|
||||||
use std::io::fs::File;
|
use std::io::File;
|
||||||
# mod BufferedReader {
|
# mod BufferedReader {
|
||||||
# use std::io::fs::File;
|
# use std::io::File;
|
||||||
# use std::io::mem::MemReader;
|
# use std::io::mem::MemReader;
|
||||||
# use std::io::buffered::BufferedReader;
|
# use std::io::buffered::BufferedReader;
|
||||||
# static s : &'static [u8] = bytes!("1 2\n\
|
# static s : &'static [u8] = bytes!("1 2\n\
|
||||||
|
@ -528,8 +532,8 @@ fn main() {
|
||||||
|
|
||||||
fn read_int_pairs() -> ~[(int,int)] {
|
fn read_int_pairs() -> ~[(int,int)] {
|
||||||
let mut pairs = ~[];
|
let mut pairs = ~[];
|
||||||
let args = std::os::args();
|
# let _g = std::io::ignore_io_error();
|
||||||
let path = Path::new(args.get_opt(1).expect("No input file parameter!").as_slice());
|
let path = Path::new(&"foo.txt");
|
||||||
|
|
||||||
let mut reader = BufferedReader::new(File::open(&path));
|
let mut reader = BufferedReader::new(File::open(&path));
|
||||||
for line in reader.lines() {
|
for line in reader.lines() {
|
||||||
|
@ -575,12 +579,13 @@ until all relevant combinations encountered in practice are encoded.
|
||||||
In the example, suppose a third possible recovery form arose: reusing the previous value read.
|
In the example, suppose a third possible recovery form arose: reusing the previous value read.
|
||||||
This can be encoded in the handler API by introducing a helper type: `enum MalformedLineFix`.
|
This can be encoded in the handler API by introducing a helper type: `enum MalformedLineFix`.
|
||||||
|
|
||||||
~~~~{.xfail-test}
|
~~~~
|
||||||
# #[allow(unused_imports)];
|
# #[allow(unused_imports)];
|
||||||
|
# extern mod extra;
|
||||||
use std::io::buffered::BufferedReader;
|
use std::io::buffered::BufferedReader;
|
||||||
use std::io::fs::File;
|
use std::io::File;
|
||||||
# mod BufferedReader {
|
# mod BufferedReader {
|
||||||
# use std::io::fs::File;
|
# use std::io::File;
|
||||||
# use std::io::mem::MemReader;
|
# use std::io::mem::MemReader;
|
||||||
# use std::io::buffered::BufferedReader;
|
# use std::io::buffered::BufferedReader;
|
||||||
# static s : &'static [u8] = bytes!("1 2\n\
|
# static s : &'static [u8] = bytes!("1 2\n\
|
||||||
|
@ -622,8 +627,8 @@ fn main() {
|
||||||
|
|
||||||
fn read_int_pairs() -> ~[(int,int)] {
|
fn read_int_pairs() -> ~[(int,int)] {
|
||||||
let mut pairs = ~[];
|
let mut pairs = ~[];
|
||||||
let args = std::os::args();
|
# let _g = std::io::ignore_io_error();
|
||||||
let path = Path::new(args.get_opt(1).expect("No input file parameter!").as_slice());
|
let path = Path::new(&"foo.txt");
|
||||||
|
|
||||||
let mut reader = BufferedReader::new(File::open(&path));
|
let mut reader = BufferedReader::new(File::open(&path));
|
||||||
for line in reader.lines() {
|
for line in reader.lines() {
|
||||||
|
@ -699,12 +704,13 @@ task <unnamed> failed at 'called `Option::unwrap()` on a `None` value', .../libs
|
||||||
To make the program robust — or at least flexible — in the face of this potential failure,
|
To make the program robust — or at least flexible — in the face of this potential failure,
|
||||||
a second condition and a helper function will suffice:
|
a second condition and a helper function will suffice:
|
||||||
|
|
||||||
~~~~{.xfail-test}
|
~~~~
|
||||||
# #[allow(unused_imports)];
|
# #[allow(unused_imports)];
|
||||||
|
# extern mod extra;
|
||||||
use std::io::buffered::BufferedReader;
|
use std::io::buffered::BufferedReader;
|
||||||
use std::io::fs::File;
|
use std::io::File;
|
||||||
# mod BufferedReader {
|
# mod BufferedReader {
|
||||||
# use std::io::fs::File;
|
# use std::io::File;
|
||||||
# use std::io::mem::MemReader;
|
# use std::io::mem::MemReader;
|
||||||
# use std::io::buffered::BufferedReader;
|
# use std::io::buffered::BufferedReader;
|
||||||
# static s : &'static [u8] = bytes!("1 2\n\
|
# static s : &'static [u8] = bytes!("1 2\n\
|
||||||
|
@ -760,8 +766,8 @@ fn parse_int(x: &str) -> int {
|
||||||
|
|
||||||
fn read_int_pairs() -> ~[(int,int)] {
|
fn read_int_pairs() -> ~[(int,int)] {
|
||||||
let mut pairs = ~[];
|
let mut pairs = ~[];
|
||||||
let args = std::os::args();
|
# let _g = std::io::ignore_io_error();
|
||||||
let path = Path::new(args.get_opt(1).expect("No input file parameter!").as_slice());
|
let path = Path::new(&"foo.txt");
|
||||||
|
|
||||||
let mut reader = BufferedReader::new(File::open(&path));
|
let mut reader = BufferedReader::new(File::open(&path));
|
||||||
for line in reader.lines() {
|
for line in reader.lines() {
|
||||||
|
|
|
@ -186,23 +186,29 @@ while still providing feedback about errors. The basic strategy:
|
||||||
so that nullable values do not have to be 'unwrapped' before use.
|
so that nullable values do not have to be 'unwrapped' before use.
|
||||||
|
|
||||||
These features combine in the API to allow for expressions like
|
These features combine in the API to allow for expressions like
|
||||||
`File::new("diary.txt").write_line("met a girl")` without having to
|
`File::create(&Path::new("diary.txt")).write(bytes!("Met a girl.\n"))`
|
||||||
worry about whether "diary.txt" exists or whether the write
|
without having to worry about whether "diary.txt" exists or whether
|
||||||
succeeds. As written, if either `new` or `write_line` encounters
|
the write succeeds. As written, if either `new` or `write_line`
|
||||||
an error the task will fail.
|
encounters an error the task will fail.
|
||||||
|
|
||||||
If you wanted to handle the error though you might write
|
If you wanted to handle the error though you might write:
|
||||||
|
|
||||||
let mut error = None;
|
```rust
|
||||||
do io_error::cond(|e: IoError| {
|
use std::io::File;
|
||||||
error = Some(e);
|
use std::io::{IoError, io_error};
|
||||||
}).in {
|
|
||||||
File::new("diary.txt").write_line("met a girl");
|
|
||||||
}
|
|
||||||
|
|
||||||
if error.is_some() {
|
let mut error = None;
|
||||||
println("failed to write my diary");
|
io_error::cond.trap(|e: IoError| {
|
||||||
}
|
error = Some(e);
|
||||||
|
}).inside(|| {
|
||||||
|
File::create(&Path::new("diary.txt")).write(bytes!("Met a girl.\n"));
|
||||||
|
});
|
||||||
|
|
||||||
|
if error.is_some() {
|
||||||
|
println("failed to write my diary");
|
||||||
|
}
|
||||||
|
# ::std::io::fs::unlink(&Path::new("diary.txt"));
|
||||||
|
```
|
||||||
|
|
||||||
XXX: Need better condition handling syntax
|
XXX: Need better condition handling syntax
|
||||||
|
|
||||||
|
@ -500,10 +506,16 @@ pub trait Reader {
|
||||||
///
|
///
|
||||||
/// # Example
|
/// # Example
|
||||||
///
|
///
|
||||||
/// let mut reader = BufferedReader::new(File::open(&Path::new("foo.txt")));
|
/// ```rust
|
||||||
/// for line in reader.lines() {
|
/// use std::io;
|
||||||
/// println(line);
|
/// # let _g = ::std::io::ignore_io_error();
|
||||||
/// }
|
/// let mut reader = io::stdin();
|
||||||
|
///
|
||||||
|
/// let mut bytes = [0, .. 10];
|
||||||
|
/// reader.read(bytes);
|
||||||
|
///
|
||||||
|
/// if reader.eof() { println("stdin() had at most 10 bytes of data."); }
|
||||||
|
/// ```
|
||||||
///
|
///
|
||||||
/// # Failure
|
/// # Failure
|
||||||
///
|
///
|
||||||
|
@ -1098,6 +1110,18 @@ pub trait Buffer: Reader {
|
||||||
/// encoded unicode codepoints. If a newline is encountered, then the
|
/// encoded unicode codepoints. If a newline is encountered, then the
|
||||||
/// newline is contained in the returned string.
|
/// newline is contained in the returned string.
|
||||||
///
|
///
|
||||||
|
/// # Example
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// use std::io::buffered::BufferedReader;
|
||||||
|
/// use std::io;
|
||||||
|
/// # let _g = ::std::io::ignore_io_error();
|
||||||
|
///
|
||||||
|
/// let mut reader = BufferedReader::new(io::stdin());
|
||||||
|
///
|
||||||
|
/// let input = reader.read_line().unwrap_or(~"nothing");
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
/// # Failure
|
/// # Failure
|
||||||
///
|
///
|
||||||
/// This function will raise on the `io_error` condition (except for
|
/// This function will raise on the `io_error` condition (except for
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue