diff options
| author | Manish Goregaokar <manishsmail@gmail.com> | 2015-02-23 14:54:34 +0530 |
|---|---|---|
| committer | Alex Crichton <alex@alexcrichton.com> | 2015-02-23 11:43:56 -0800 |
| commit | 65b1a985229663435851997e44155482eda2f6f4 (patch) | |
| tree | f39f9c4bf0f13113fdcf19757252d9c9be460876 /src/libstd/io | |
| parent | db04229d23119e76f52408b61d960e1bcc52af7a (diff) | |
| parent | b46e3eec7aec546d8c4e212cc4e27ec870071e74 (diff) | |
| download | rust-65b1a985229663435851997e44155482eda2f6f4.tar.gz rust-65b1a985229663435851997e44155482eda2f6f4.zip | |
Rollup merge of #22640 - sfackler:fix-take, r=alexcrichton
We can't call into the inner reader for a 0-byte read because that may end up blocking or returning an error. r? @alexcrichton
Diffstat (limited to 'src/libstd/io')
| -rw-r--r-- | src/libstd/io/mod.rs | 35 |
1 files changed, 35 insertions, 0 deletions
diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs index 5b319f4c687..3b4e15953c4 100644 --- a/src/libstd/io/mod.rs +++ b/src/libstd/io/mod.rs @@ -669,6 +669,11 @@ impl<T> Take<T> { impl<T: Read> Read for Take<T> { fn read(&mut self, buf: &mut [u8]) -> Result<usize> { + // Don't call into inner reader at all at EOF because it may still block + if self.limit == 0 { + return Ok(0); + } + let max = cmp::min(buf.len() as u64, self.limit) as usize; let n = try!(self.inner.read(&mut buf[..max])); self.limit -= n as u64; @@ -676,6 +681,21 @@ impl<T: Read> Read for Take<T> { } } +impl<T: BufRead> BufRead for Take<T> { + fn fill_buf(&mut self) -> Result<&[u8]> { + let buf = try!(self.inner.fill_buf()); + let cap = cmp::min(buf.len() as u64, self.limit) as usize; + Ok(&buf[..cap]) + } + + fn consume(&mut self, amt: usize) { + // Don't let callers reset the limit by passing an overlarge value + let amt = cmp::min(amt as u64, self.limit) as usize; + self.limit -= amt as u64; + self.inner.consume(amt); + } +} + /// An adaptor which will emit all read data to a specified writer as well. /// /// For more information see `ReadExt::tee` @@ -846,6 +866,7 @@ impl<B: BufRead> Iterator for Lines<B> { mod tests { use prelude::v1::*; use io::prelude::*; + use io; use super::Cursor; #[test] @@ -943,4 +964,18 @@ mod tests { let mut v = String::new(); assert!(c.read_to_string(&mut v).is_err()); } + + #[test] + fn take_eof() { + struct R; + + impl Read for R { + fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { + Err(io::Error::new(io::ErrorKind::Other, "", None)) + } + } + + let mut buf = [0; 1]; + assert_eq!(Ok(0), R.take(0).read(&mut buf)); + } } |
