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.
This commit is contained in:
commit
de83d7dd19
@ -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)),
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user