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]
This commit is contained in:
commit
ec1d34eb27
@ -48,10 +48,12 @@ fn read(&mut self, buf: &mut [u8]) -> io::IoResult<uint> {
|
||||
}
|
||||
|
||||
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 @@ fn fill_buf<'a>(&'a mut self) -> io::IoResult<&'a [u8]> {
|
||||
}
|
||||
|
||||
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 @@ fn fill_buf<'a>(&'a mut self) -> io::IoResult<&'a [u8]> {
|
||||
static DATA: [u8, ..64] = [0, ..64];
|
||||
Ok(DATA.as_slice())
|
||||
}
|
||||
|
||||
fn consume(&mut self, _amt: uint) {}
|
||||
}
|
||||
|
||||
@ -117,7 +122,10 @@ fn fill_buf<'a>(&'a mut self) -> io::IoResult<&'a [u8]> {
|
||||
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 @@ pub fn new(writers: Vec<Box<Writer>>) -> 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 @@ fn read(&mut self, buf: &mut [u8]) -> io::IoResult<uint> {
|
||||
*slot = elt;
|
||||
len += 1;
|
||||
}
|
||||
if len == 0 {
|
||||
if len == 0 && buf.len() != 0 {
|
||||
Err(io::standard_error(io::EndOfFile))
|
||||
} else {
|
||||
Ok(len)
|
||||
@ -297,6 +302,14 @@ fn test_limit_reader_limit() {
|
||||
assert_eq!(0, r.limit());
|
||||
}
|
||||
|
||||
#[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;
|
||||
@ -415,4 +428,11 @@ fn test_iter_reader() {
|
||||
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user