about summary refs log tree commit diff
path: root/src/libstd
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2014-08-16 05:36:14 +0000
committerbors <bors@rust-lang.org>2014-08-16 05:36:14 +0000
commitec1d34eb276f8eedf026143d18c9416dc5836d50 (patch)
tree16304df2558af1c5a5608873a24a9b0fb381487a /src/libstd
parentd30001d04d2006645468d3c194c9e3ae6ddc4b52 (diff)
parent89a0060997479de770be0a63731423e2a305beda (diff)
downloadrust-ec1d34eb276f8eedf026143d18c9416dc5836d50.tar.gz
rust-ec1d34eb276f8eedf026143d18c9416dc5836d50.zip
auto merge of #16513 : sfackler/rust/io-util-cleanup, r=alexcrichton
* Fix `LimitReader`'s `Buffer::consume` impl to avoid limit underflow
* Make `MultiWriter` fail fast instead of always running through each
    `Writer`. This may or may not be what we want, but it at least
    doesn't throw any errors encountered in later `Writer`s into oblivion.
* Prevent `IterReader`'s `Reader::read` impl from returning EOF if given
    an empty buffer.

[breaking-change]
Diffstat (limited to 'src/libstd')
-rw-r--r--src/libstd/io/util.rs56
1 files changed, 38 insertions, 18 deletions
diff --git a/src/libstd/io/util.rs b/src/libstd/io/util.rs
index e928323030c..c3cd2faf773 100644
--- a/src/libstd/io/util.rs
+++ b/src/libstd/io/util.rs
@@ -48,10 +48,12 @@ impl<R: Reader> Reader for LimitReader<R> {
         }
 
         let len = cmp::min(self.limit, buf.len());
-        self.inner.read(buf.mut_slice_to(len)).map(|len| {
-            self.limit -= len;
-            len
-        })
+        let res = self.inner.read(buf.mut_slice_to(len));
+        match res {
+            Ok(len) => self.limit -= len,
+            _ => {}
+        }
+        res
     }
 }
 
@@ -67,6 +69,8 @@ impl<R: Buffer> Buffer for LimitReader<R> {
     }
 
     fn consume(&mut self, amt: uint) {
+        // Don't let callers reset the limit by passing an overlarge value
+        let amt = cmp::min(amt, self.limit);
         self.limit -= amt;
         self.inner.consume(amt);
     }
@@ -97,6 +101,7 @@ impl Buffer for ZeroReader {
         static DATA: [u8, ..64] = [0, ..64];
         Ok(DATA.as_slice())
     }
+
     fn consume(&mut self, _amt: uint) {}
 }
 
@@ -117,7 +122,10 @@ impl Buffer for NullReader {
     fn consume(&mut self, _amt: uint) {}
 }
 
-/// A `Writer` which multiplexes writes to a set of `Writers`.
+/// A `Writer` which multiplexes writes to a set of `Writer`s.
+///
+/// The `Writer`s are delegated to in order. If any `Writer` returns an error,
+/// that error is returned immediately and remaining `Writer`s are not called.
 pub struct MultiWriter {
     writers: Vec<Box<Writer>>
 }
@@ -132,24 +140,22 @@ impl MultiWriter {
 impl Writer for MultiWriter {
     #[inline]
     fn write(&mut self, buf: &[u8]) -> io::IoResult<()> {
-        let mut ret = Ok(());
         for writer in self.writers.mut_iter() {
-            ret = ret.and(writer.write(buf));
+            try!(writer.write(buf));
         }
-        return ret;
+        Ok(())
     }
 
     #[inline]
     fn flush(&mut self) -> io::IoResult<()> {
-        let mut ret = Ok(());
         for writer in self.writers.mut_iter() {
-            ret = ret.and(writer.flush());
+            try!(writer.flush());
         }
-        return ret;
+        Ok(())
     }
 }
 
-/// A `Reader` which chains input from multiple `Readers`, reading each to
+/// A `Reader` which chains input from multiple `Reader`s, reading each to
 /// completion before moving onto the next.
 pub struct ChainedReader<I, R> {
     readers: I,
@@ -229,17 +235,16 @@ pub fn copy<R: Reader, W: Writer>(r: &mut R, w: &mut W) -> io::IoResult<()> {
     }
 }
 
-/// A `Reader` which converts an `Iterator<u8>` into a `Reader`.
+/// An adaptor converting an `Iterator<u8>` to a `Reader`.
 pub struct IterReader<T> {
     iter: T,
 }
 
 impl<T: Iterator<u8>> IterReader<T> {
-    /// Create a new `IterReader` which will read from the specified `Iterator`.
+    /// Creates a new `IterReader` which will read from the specified
+    /// `Iterator`.
     pub fn new(iter: T) -> IterReader<T> {
-        IterReader {
-            iter: iter,
-        }
+        IterReader { iter: iter }
     }
 }
 
@@ -251,7 +256,7 @@ impl<T: Iterator<u8>> Reader for IterReader<T> {
             *slot = elt;
             len += 1;
         }
-        if len == 0 {
+        if len == 0 && buf.len() != 0 {
             Err(io::standard_error(io::EndOfFile))
         } else {
             Ok(len)
@@ -298,6 +303,14 @@ mod test {
     }
 
     #[test]
+    fn test_limit_reader_overlong_consume() {
+        let mut r = MemReader::new(vec![0, 1, 2, 3, 4, 5]);
+        let mut r = LimitReader::new(r.by_ref(), 1);
+        r.consume(2);
+        assert_eq!(vec![], r.read_to_end().unwrap());
+    }
+
+    #[test]
     fn test_null_writer() {
         let mut s = NullWriter;
         let buf = vec![0, 0, 0];
@@ -415,4 +428,11 @@ mod test {
 
         assert_eq!(r.read(buf).unwrap_err().kind, io::EndOfFile);
     }
+
+    #[test]
+    fn iter_reader_zero_length() {
+        let mut r = IterReader::new(range(0u8, 8));
+        let mut buf = [];
+        assert_eq!(Ok(0), r.read(buf));
+    }
 }