]> git.lizzy.rs Git - rust.git/commitdiff
Update io iterators to produce IoResults
authorPalmer Cox <p@lmercox.com>
Thu, 20 Feb 2014 02:53:46 +0000 (21:53 -0500)
committerPalmer Cox <p@lmercox.com>
Thu, 13 Mar 2014 02:42:50 +0000 (22:42 -0400)
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

src/compiletest/errors.rs
src/compiletest/header.rs
src/libstd/io/buffered.rs
src/libstd/io/extensions.rs
src/libstd/io/mod.rs
src/test/bench/shootout-k-nucleotide-pipes.rs
src/test/bench/sudoku.rs

index 3a6b1666c1e796ae2f63c6f67a1032837b2ffd2c..4fee64e630481e679dd9fdb6bc102f91a8850bb9 100644 (file)
@@ -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;
index 7f8be5ff090e6186611eb986bb75f5985ae0b0e3..81b76f6b09a835d6ea98eff16e42effdb66999ac 100644 (file)
@@ -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; } }
index fa122fa8c116005d54994afd5f21cb1e28d46d75..3ae44e4a1b5ce8872195fef24f9000717803258f 100644 (file)
@@ -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);
     }
 
index 0424b7783cec943db6c884971c230ef2c3ff9758..f7cab755714f20785e09fec7aa6a775e7ebab6ba 100644 (file)
 
 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
 ///
 /// 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]
index 1c10c7b61c364fb3c6f0591f6cf697a37609b7b0..26dcd0c077ce7d05fa920a333ff4411d515d7c43 100644 (file)
@@ -31,7 +31,7 @@
     use std::io;
 
     for line in io::stdin().lines() {
-        print!("{}", line);
+        print!("{}", line.unwrap());
     }
     ```
 
 
 * 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 }
     }
index 7188e119a8d6320be8e87d9e4b06d5eaaaafa099..d8bd0e6250f512cc3dbf73f8fddded946b20240f 100644 (file)
@@ -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; }
 
index b77180e8e4ccf2da681a2421cefd5cb6c6883229..d2ce61ee7556e166058c765344033109e814cef1 100644 (file)
@@ -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;