diff options
| author | Palmer Cox <p@lmercox.com> | 2014-02-19 21:53:46 -0500 |
|---|---|---|
| committer | Palmer Cox <p@lmercox.com> | 2014-03-12 22:42:50 -0400 |
| commit | 9ba6bb5a71adeb861f8bf21c2b1f2fde3132480d (patch) | |
| tree | 8b334634887fcd0a6ba5a2ed926aec010386fc05 /src/libstd | |
| parent | 2eebeb81372e320510a1c1e2eef96eb5146a1e1f (diff) | |
| download | rust-9ba6bb5a71adeb861f8bf21c2b1f2fde3132480d.tar.gz rust-9ba6bb5a71adeb861f8bf21c2b1f2fde3132480d.zip | |
Update io iterators to produce IoResults
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
Diffstat (limited to 'src/libstd')
| -rw-r--r-- | src/libstd/io/buffered.rs | 10 | ||||
| -rw-r--r-- | src/libstd/io/extensions.rs | 29 | ||||
| -rw-r--r-- | src/libstd/io/mod.rs | 60 |
3 files changed, 53 insertions, 46 deletions
diff --git a/src/libstd/io/buffered.rs b/src/libstd/io/buffered.rs index fa122fa8c11..3ae44e4a1b5 100644 --- a/src/libstd/io/buffered.rs +++ b/src/libstd/io/buffered.rs @@ -537,9 +537,9 @@ mod test { 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 @@ mod test { 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); } diff --git a/src/libstd/io/extensions.rs b/src/libstd/io/extensions.rs index 0424b7783ce..f7cab755714 100644 --- a/src/libstd/io/extensions.rs +++ b/src/libstd/io/extensions.rs @@ -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 @@ use ptr::RawPtr; /// 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 @@ impl<'r, R: Reader> 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 @@ mod test { count: 0, }; let byte = reader.bytes().next(); - assert!(byte == Some(10)); + assert!(byte == Some(Ok(10))); } #[test] @@ -272,7 +277,7 @@ mod test { let mut reader = ErroringReader; let mut it = reader.bytes(); let byte = it.next(); - assert!(byte.is_none()); + assert!(byte.unwrap().is_err()); } #[test] diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs index 1c10c7b61c3..26dcd0c077c 100644 --- a/src/libstd/io/mod.rs +++ b/src/libstd/io/mod.rs @@ -31,7 +31,7 @@ Some examples of obvious things you might want to do use std::io; for line in io::stdin().lines() { - print!("{}", line); + print!("{}", line.unwrap()); } ``` @@ -57,26 +57,26 @@ Some examples of obvious things you might want to do * 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 @@ pub trait Reader { /// /// # 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 @@ impl<'r, T: Buffer> Iterator<~str> for Lines<'r, 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_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 @@ pub trait Buffer: Reader { /// /// # 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 @@ pub trait Buffer: Reader { /// /// # 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 } } |
