diff options
| author | bors <bors@rust-lang.org> | 2014-12-06 20:12:13 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2014-12-06 20:12:13 +0000 |
| commit | de83d7dd191bf5564855057a29f9b5d9dcfcb201 (patch) | |
| tree | b90665fb9f4eeadbe858564f89b9b8c454a9bacf /src/libstd | |
| parent | 358db12a89d6edf4a61cb3c8d170449faea925cc (diff) | |
| parent | 72bc461ce3f34fca3aac87c83c0a7c606e9aecee (diff) | |
| download | rust-de83d7dd191bf5564855057a29f9b5d9dcfcb201.tar.gz rust-de83d7dd191bf5564855057a29f9b5d9dcfcb201.zip | |
auto merge of #19431 : erickt/rust/buf-writer-error, r=alexcrichton
Previously, `BufWriter::write` would just return an `std::io::OtherIoError` if someone attempted to write past the end of the wrapped buffer. This pull request changes the error to support partial writes and return a `std::io::ShortWrite`, or an `io::io::EndOfFile` if it's been fully exhausted. I've also optimized away a bounds check inside `BufWriter::write`, which should help shave off some nanoseconds in an inner loops.
Diffstat (limited to 'src/libstd')
| -rw-r--r-- | src/libstd/io/mem.rs | 44 |
1 files changed, 27 insertions, 17 deletions
diff --git a/src/libstd/io/mem.rs b/src/libstd/io/mem.rs index 8a329a5d27c..c5cd95f8501 100644 --- a/src/libstd/io/mem.rs +++ b/src/libstd/io/mem.rs @@ -278,20 +278,29 @@ impl<'a> BufWriter<'a> { impl<'a> Writer for BufWriter<'a> { #[inline] - fn write(&mut self, buf: &[u8]) -> IoResult<()> { - // return an error if the entire write does not fit in the buffer - let cap = if self.pos >= self.buf.len() { 0 } else { self.buf.len() - self.pos }; - if buf.len() > cap { - return Err(IoError { - kind: io::OtherIoError, - desc: "Trying to write past end of buffer", - detail: None - }) + fn write(&mut self, src: &[u8]) -> IoResult<()> { + let dst = self.buf[mut self.pos..]; + let dst_len = dst.len(); + + if dst_len == 0 { + return Err(io::standard_error(io::EndOfFile)); } - slice::bytes::copy_memory(self.buf[mut self.pos..], buf); - self.pos += buf.len(); - Ok(()) + let src_len = src.len(); + + if dst_len >= src_len { + slice::bytes::copy_memory(dst, src); + + self.pos += src_len; + + Ok(()) + } else { + slice::bytes::copy_memory(dst, src[..dst_len]); + + self.pos += dst_len; + + Err(io::standard_error(io::ShortWrite(dst_len))) + } } } @@ -302,7 +311,7 @@ impl<'a> Seek for BufWriter<'a> { #[inline] fn seek(&mut self, pos: i64, style: SeekStyle) -> IoResult<()> { let new = try!(combine(style, self.pos, self.buf.len(), pos)); - self.pos = new as uint; + self.pos = min(new as uint, self.buf.len()); Ok(()) } } @@ -419,7 +428,7 @@ mod test { #[test] fn test_buf_writer() { - let mut buf = [0 as u8, ..8]; + let mut buf = [0 as u8, ..9]; { let mut writer = BufWriter::new(&mut buf); assert_eq!(writer.tell(), Ok(0)); @@ -431,9 +440,10 @@ mod test { writer.write(&[]).unwrap(); assert_eq!(writer.tell(), Ok(8)); - assert!(writer.write(&[1]).is_err()); + assert_eq!(writer.write(&[8, 9]).unwrap_err().kind, io::ShortWrite(1)); + assert_eq!(writer.write(&[10]).unwrap_err().kind, io::EndOfFile); } - let b: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7]; + let b: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7, 8]; assert_eq!(buf.as_slice(), b); } @@ -474,7 +484,7 @@ mod test { match writer.write(&[0, 0]) { Ok(..) => panic!(), - Err(e) => assert_eq!(e.kind, io::OtherIoError), + Err(e) => assert_eq!(e.kind, io::ShortWrite(1)), } } |
