about summary refs log tree commit diff
path: root/src/libstd
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2014-12-06 20:12:13 +0000
committerbors <bors@rust-lang.org>2014-12-06 20:12:13 +0000
commitde83d7dd191bf5564855057a29f9b5d9dcfcb201 (patch)
treeb90665fb9f4eeadbe858564f89b9b8c454a9bacf /src/libstd
parent358db12a89d6edf4a61cb3c8d170449faea925cc (diff)
parent72bc461ce3f34fca3aac87c83c0a7c606e9aecee (diff)
downloadrust-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.rs44
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)),
         }
     }