Skip to content

Commit ec1d34e

Browse files
committed
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]
2 parents d30001d + 89a0060 commit ec1d34e

File tree

1 file changed

+38
-18
lines changed

1 file changed

+38
-18
lines changed

src/libstd/io/util.rs

+38-18
Original file line numberDiff line numberDiff line change
@@ -48,10 +48,12 @@ impl<R: Reader> Reader for LimitReader<R> {
4848
}
4949

5050
let len = cmp::min(self.limit, buf.len());
51-
self.inner.read(buf.mut_slice_to(len)).map(|len| {
52-
self.limit -= len;
53-
len
54-
})
51+
let res = self.inner.read(buf.mut_slice_to(len));
52+
match res {
53+
Ok(len) => self.limit -= len,
54+
_ => {}
55+
}
56+
res
5557
}
5658
}
5759

@@ -67,6 +69,8 @@ impl<R: Buffer> Buffer for LimitReader<R> {
6769
}
6870

6971
fn consume(&mut self, amt: uint) {
72+
// Don't let callers reset the limit by passing an overlarge value
73+
let amt = cmp::min(amt, self.limit);
7074
self.limit -= amt;
7175
self.inner.consume(amt);
7276
}
@@ -97,6 +101,7 @@ impl Buffer for ZeroReader {
97101
static DATA: [u8, ..64] = [0, ..64];
98102
Ok(DATA.as_slice())
99103
}
104+
100105
fn consume(&mut self, _amt: uint) {}
101106
}
102107

@@ -117,7 +122,10 @@ impl Buffer for NullReader {
117122
fn consume(&mut self, _amt: uint) {}
118123
}
119124

120-
/// A `Writer` which multiplexes writes to a set of `Writers`.
125+
/// A `Writer` which multiplexes writes to a set of `Writer`s.
126+
///
127+
/// The `Writer`s are delegated to in order. If any `Writer` returns an error,
128+
/// that error is returned immediately and remaining `Writer`s are not called.
121129
pub struct MultiWriter {
122130
writers: Vec<Box<Writer>>
123131
}
@@ -132,24 +140,22 @@ impl MultiWriter {
132140
impl Writer for MultiWriter {
133141
#[inline]
134142
fn write(&mut self, buf: &[u8]) -> io::IoResult<()> {
135-
let mut ret = Ok(());
136143
for writer in self.writers.mut_iter() {
137-
ret = ret.and(writer.write(buf));
144+
try!(writer.write(buf));
138145
}
139-
return ret;
146+
Ok(())
140147
}
141148

142149
#[inline]
143150
fn flush(&mut self) -> io::IoResult<()> {
144-
let mut ret = Ok(());
145151
for writer in self.writers.mut_iter() {
146-
ret = ret.and(writer.flush());
152+
try!(writer.flush());
147153
}
148-
return ret;
154+
Ok(())
149155
}
150156
}
151157

152-
/// A `Reader` which chains input from multiple `Readers`, reading each to
158+
/// A `Reader` which chains input from multiple `Reader`s, reading each to
153159
/// completion before moving onto the next.
154160
pub struct ChainedReader<I, R> {
155161
readers: I,
@@ -229,17 +235,16 @@ pub fn copy<R: Reader, W: Writer>(r: &mut R, w: &mut W) -> io::IoResult<()> {
229235
}
230236
}
231237

232-
/// A `Reader` which converts an `Iterator<u8>` into a `Reader`.
238+
/// An adaptor converting an `Iterator<u8>` to a `Reader`.
233239
pub struct IterReader<T> {
234240
iter: T,
235241
}
236242

237243
impl<T: Iterator<u8>> IterReader<T> {
238-
/// Create a new `IterReader` which will read from the specified `Iterator`.
244+
/// Creates a new `IterReader` which will read from the specified
245+
/// `Iterator`.
239246
pub fn new(iter: T) -> IterReader<T> {
240-
IterReader {
241-
iter: iter,
242-
}
247+
IterReader { iter: iter }
243248
}
244249
}
245250

@@ -251,7 +256,7 @@ impl<T: Iterator<u8>> Reader for IterReader<T> {
251256
*slot = elt;
252257
len += 1;
253258
}
254-
if len == 0 {
259+
if len == 0 && buf.len() != 0 {
255260
Err(io::standard_error(io::EndOfFile))
256261
} else {
257262
Ok(len)
@@ -297,6 +302,14 @@ mod test {
297302
assert_eq!(0, r.limit());
298303
}
299304

305+
#[test]
306+
fn test_limit_reader_overlong_consume() {
307+
let mut r = MemReader::new(vec![0, 1, 2, 3, 4, 5]);
308+
let mut r = LimitReader::new(r.by_ref(), 1);
309+
r.consume(2);
310+
assert_eq!(vec![], r.read_to_end().unwrap());
311+
}
312+
300313
#[test]
301314
fn test_null_writer() {
302315
let mut s = NullWriter;
@@ -415,4 +428,11 @@ mod test {
415428

416429
assert_eq!(r.read(buf).unwrap_err().kind, io::EndOfFile);
417430
}
431+
432+
#[test]
433+
fn iter_reader_zero_length() {
434+
let mut r = IterReader::new(range(0u8, 8));
435+
let mut buf = [];
436+
assert_eq!(Ok(0), r.read(buf));
437+
}
418438
}

0 commit comments

Comments
 (0)