auto merge of #12414 : DaGenix/rust/failing-iterator-wrappers, r=alexcrichton
Most IO related functions return an IoResult so that the caller can handle failure in whatever way is appropriate. However, the `lines`, `bytes`, and `chars` iterators all supress errors. This means that code that needs to handle errors can't use any of these iterators. All three of these iterators were updated to produce IoResults. Fixes #12368
This commit is contained in:
commit
6cbba7c54e
@ -19,7 +19,7 @@ pub fn load_errors(testfile: &Path) -> ~[ExpectedError] {
|
||||
let mut rdr = BufferedReader::new(File::open(testfile).unwrap());
|
||||
let mut line_num = 1u;
|
||||
for ln in rdr.lines() {
|
||||
error_patterns.push_all_move(parse_expected(line_num, ln));
|
||||
error_patterns.push_all_move(parse_expected(line_num, ln.unwrap()));
|
||||
line_num += 1u;
|
||||
}
|
||||
return error_patterns;
|
||||
|
@ -140,6 +140,7 @@ fn iter_header(testfile: &Path, it: |&str| -> bool) -> bool {
|
||||
// Assume that any directives will be found before the first
|
||||
// module or function. This doesn't seem to be an optimization
|
||||
// with a warm page cache. Maybe with a cold one.
|
||||
let ln = ln.unwrap();
|
||||
if ln.starts_with("fn") || ln.starts_with("mod") {
|
||||
return true;
|
||||
} else { if !(it(ln.trim())) { return false; } }
|
||||
|
@ -537,9 +537,9 @@ fn test_lines() {
|
||||
let in_buf = MemReader::new(bytes!("a\nb\nc").to_owned());
|
||||
let mut reader = BufferedReader::with_capacity(2, in_buf);
|
||||
let mut it = reader.lines();
|
||||
assert_eq!(it.next(), Some(~"a\n"));
|
||||
assert_eq!(it.next(), Some(~"b\n"));
|
||||
assert_eq!(it.next(), Some(~"c"));
|
||||
assert_eq!(it.next(), Some(Ok(~"a\n")));
|
||||
assert_eq!(it.next(), Some(Ok(~"b\n")));
|
||||
assert_eq!(it.next(), Some(Ok(~"c")));
|
||||
assert_eq!(it.next(), None);
|
||||
}
|
||||
|
||||
@ -569,8 +569,8 @@ fn test_chars() {
|
||||
let buf = [195u8, 159u8, 'a' as u8];
|
||||
let mut reader = BufferedReader::with_capacity(1, BufReader::new(buf));
|
||||
let mut it = reader.chars();
|
||||
assert_eq!(it.next(), Some('ß'));
|
||||
assert_eq!(it.next(), Some('a'));
|
||||
assert_eq!(it.next(), Some(Ok('ß')));
|
||||
assert_eq!(it.next(), Some(Ok('a')));
|
||||
assert_eq!(it.next(), None);
|
||||
}
|
||||
|
||||
|
@ -17,13 +17,15 @@
|
||||
|
||||
use container::Container;
|
||||
use iter::Iterator;
|
||||
use option::Option;
|
||||
use io::Reader;
|
||||
use option::{Option, Some, None};
|
||||
use result::{Ok, Err};
|
||||
use io;
|
||||
use io::{IoError, IoResult, Reader};
|
||||
use vec::{OwnedVector, ImmutableVector};
|
||||
use ptr::RawPtr;
|
||||
|
||||
/// An iterator that reads a single byte on each iteration,
|
||||
/// until `.read_byte()` returns `None`.
|
||||
/// until `.read_byte()` returns `EndOfFile`.
|
||||
///
|
||||
/// # Notes about the Iteration Protocol
|
||||
///
|
||||
@ -31,11 +33,10 @@
|
||||
/// an iteration, but continue to yield elements if iteration
|
||||
/// is attempted again.
|
||||
///
|
||||
/// # Failure
|
||||
/// # Error
|
||||
///
|
||||
/// Raises the same conditions as the `read` method, for
|
||||
/// each call to its `.next()` method.
|
||||
/// Yields `None` if the condition is handled.
|
||||
/// Any error other than `EndOfFile` that is produced by the underlying Reader
|
||||
/// is returned by the iterator and should be handled by the caller.
|
||||
pub struct Bytes<'r, T> {
|
||||
priv reader: &'r mut T,
|
||||
}
|
||||
@ -46,10 +47,14 @@ pub fn new(r: &'r mut R) -> Bytes<'r, R> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'r, R: Reader> Iterator<u8> for Bytes<'r, R> {
|
||||
impl<'r, R: Reader> Iterator<IoResult<u8>> for Bytes<'r, R> {
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<u8> {
|
||||
self.reader.read_byte().ok()
|
||||
fn next(&mut self) -> Option<IoResult<u8>> {
|
||||
match self.reader.read_byte() {
|
||||
Ok(x) => Some(Ok(x)),
|
||||
Err(IoError { kind: io::EndOfFile, .. }) => None,
|
||||
Err(e) => Some(Err(e))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -257,7 +262,7 @@ fn bytes_0_bytes() {
|
||||
count: 0,
|
||||
};
|
||||
let byte = reader.bytes().next();
|
||||
assert!(byte == Some(10));
|
||||
assert!(byte == Some(Ok(10)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -272,7 +277,7 @@ fn bytes_error() {
|
||||
let mut reader = ErroringReader;
|
||||
let mut it = reader.bytes();
|
||||
let byte = it.next();
|
||||
assert!(byte.is_none());
|
||||
assert!(byte.unwrap().is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -31,7 +31,7 @@
|
||||
use std::io;
|
||||
|
||||
for line in io::stdin().lines() {
|
||||
print!("{}", line);
|
||||
print!("{}", line.unwrap());
|
||||
}
|
||||
```
|
||||
|
||||
@ -57,26 +57,26 @@
|
||||
|
||||
* Iterate over the lines of a file
|
||||
|
||||
```rust
|
||||
```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);
|
||||
print!("{}", line.unwrap());
|
||||
}
|
||||
```
|
||||
|
||||
* Pull the lines of a file into a vector of strings
|
||||
|
||||
```rust
|
||||
```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: ~[~str] = file.lines().collect();
|
||||
let lines: ~[~str] = file.lines().map(|x| x.unwrap()).collect();
|
||||
```
|
||||
|
||||
* Make a simple TCP client connection and request
|
||||
@ -466,10 +466,8 @@ fn read_to_str(&mut self) -> IoResult<~str> {
|
||||
///
|
||||
/// # Error
|
||||
///
|
||||
/// The iterator protocol causes all specifics about errors encountered to
|
||||
/// be swallowed. All errors will be signified by returning `None` from the
|
||||
/// iterator. If this is undesirable, it is recommended to use the
|
||||
/// `read_byte` method.
|
||||
/// Any error other than `EndOfFile` that is produced by the underlying Reader
|
||||
/// is returned by the iterator and should be handled by the caller.
|
||||
fn bytes<'r>(&'r mut self) -> extensions::Bytes<'r, Self> {
|
||||
extensions::Bytes::new(self)
|
||||
}
|
||||
@ -986,7 +984,7 @@ pub trait Stream: Reader + Writer { }
|
||||
impl<T: Reader + Writer> Stream for T {}
|
||||
|
||||
/// An iterator that reads a line on each iteration,
|
||||
/// until `.read_line()` returns `None`.
|
||||
/// until `.read_line()` encounters `EndOfFile`.
|
||||
///
|
||||
/// # Notes about the Iteration Protocol
|
||||
///
|
||||
@ -996,21 +994,24 @@ impl<T: Reader + Writer> Stream for T {}
|
||||
///
|
||||
/// # Error
|
||||
///
|
||||
/// This iterator will swallow all I/O errors, transforming `Err` values to
|
||||
/// `None`. If errors need to be handled, it is recommended to use the
|
||||
/// `read_line` method directly.
|
||||
/// Any error other than `EndOfFile` that is produced by the underlying Reader
|
||||
/// is returned by the iterator and should be handled by the caller.
|
||||
pub struct Lines<'r, T> {
|
||||
priv buffer: &'r mut T,
|
||||
}
|
||||
|
||||
impl<'r, T: Buffer> Iterator<~str> for Lines<'r, T> {
|
||||
fn next(&mut self) -> Option<~str> {
|
||||
self.buffer.read_line().ok()
|
||||
impl<'r, T: Buffer> Iterator<IoResult<~str>> for Lines<'r, T> {
|
||||
fn next(&mut self) -> Option<IoResult<~str>> {
|
||||
match self.buffer.read_line() {
|
||||
Ok(x) => Some(Ok(x)),
|
||||
Err(IoError { kind: EndOfFile, ..}) => None,
|
||||
Err(y) => Some(Err(y))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// An iterator that reads a utf8-encoded character on each iteration,
|
||||
/// until `.read_char()` returns `None`.
|
||||
/// until `.read_char()` encounters `EndOfFile`.
|
||||
///
|
||||
/// # Notes about the Iteration Protocol
|
||||
///
|
||||
@ -1020,16 +1021,19 @@ fn next(&mut self) -> Option<~str> {
|
||||
///
|
||||
/// # Error
|
||||
///
|
||||
/// This iterator will swallow all I/O errors, transforming `Err` values to
|
||||
/// `None`. If errors need to be handled, it is recommended to use the
|
||||
/// `read_char` method directly.
|
||||
/// Any error other than `EndOfFile` that is produced by the underlying Reader
|
||||
/// is returned by the iterator and should be handled by the caller.
|
||||
pub struct Chars<'r, T> {
|
||||
priv buffer: &'r mut T
|
||||
}
|
||||
|
||||
impl<'r, T: Buffer> Iterator<char> for Chars<'r, T> {
|
||||
fn next(&mut self) -> Option<char> {
|
||||
self.buffer.read_char().ok()
|
||||
impl<'r, T: Buffer> Iterator<IoResult<char>> for Chars<'r, T> {
|
||||
fn next(&mut self) -> Option<IoResult<char>> {
|
||||
match self.buffer.read_char() {
|
||||
Ok(x) => Some(Ok(x)),
|
||||
Err(IoError { kind: EndOfFile, ..}) => None,
|
||||
Err(y) => Some(Err(y))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1095,9 +1099,8 @@ fn read_line(&mut self) -> IoResult<~str> {
|
||||
///
|
||||
/// # Error
|
||||
///
|
||||
/// This iterator will transform all error values to `None`, discarding the
|
||||
/// cause of the error. If this is undesirable, it is recommended to call
|
||||
/// `read_line` directly.
|
||||
/// Any error other than `EndOfFile` that is produced by the underlying Reader
|
||||
/// is returned by the iterator and should be handled by the caller.
|
||||
fn lines<'r>(&'r mut self) -> Lines<'r, Self> {
|
||||
Lines { buffer: self }
|
||||
}
|
||||
@ -1183,9 +1186,8 @@ fn read_char(&mut self) -> IoResult<char> {
|
||||
///
|
||||
/// # Error
|
||||
///
|
||||
/// This iterator will transform all error values to `None`, discarding the
|
||||
/// cause of the error. If this is undesirable, it is recommended to call
|
||||
/// `read_char` directly.
|
||||
/// Any error other than `EndOfFile` that is produced by the underlying Reader
|
||||
/// is returned by the iterator and should be handled by the caller.
|
||||
fn chars<'r>(&'r mut self) -> Chars<'r, Self> {
|
||||
Chars { buffer: self }
|
||||
}
|
||||
|
@ -182,7 +182,7 @@ fn main() {
|
||||
let mut proc_mode = false;
|
||||
|
||||
for line in rdr.lines() {
|
||||
let line = line.trim().to_owned();
|
||||
let line = line.unwrap().trim().to_owned();
|
||||
|
||||
if line.len() == 0u { continue; }
|
||||
|
||||
|
@ -72,7 +72,7 @@ pub fn read(mut reader: BufferedReader<StdReader>) -> Sudoku {
|
||||
|
||||
let mut g = vec::from_fn(10u, { |_i| ~[0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8] });
|
||||
for line in reader.lines() {
|
||||
let comps: ~[&str] = line.trim().split(',').collect();
|
||||
let comps: ~[&str] = line.unwrap().trim().split(',').collect();
|
||||
|
||||
if comps.len() == 3u {
|
||||
let row = from_str::<uint>(comps[0]).unwrap() as u8;
|
||||
|
Loading…
Reference in New Issue
Block a user