Auto merge of #46830 - Diggsey:cursor-vec-mut, r=alexcrichton

Implement `Write` for `Cursor<&mut Vec<T>>`

Fixes #30132

r? @dtolnay (I'm just going through `feature-accepted` issues I swear 😛)
This commit is contained in:
bors 2018-01-10 06:33:31 +00:00
commit 27ede55414

View File

@ -252,14 +252,54 @@ impl<T> BufRead for Cursor<T> where T: AsRef<[u8]> {
fn consume(&mut self, amt: usize) { self.pos += amt as u64; }
}
// Non-resizing write implementation
fn slice_write(pos_mut: &mut u64, slice: &mut [u8], buf: &[u8]) -> io::Result<usize> {
let pos = cmp::min(*pos_mut, slice.len() as u64);
let amt = (&mut slice[(pos as usize)..]).write(buf)?;
*pos_mut += amt as u64;
Ok(amt)
}
// Resizing write implementation
fn vec_write(pos_mut: &mut u64, vec: &mut Vec<u8>, buf: &[u8]) -> io::Result<usize> {
let pos: usize = (*pos_mut).try_into().map_err(|_| {
Error::new(ErrorKind::InvalidInput,
"cursor position exceeds maximum possible vector length")
})?;
// Make sure the internal buffer is as least as big as where we
// currently are
let len = vec.len();
if len < pos {
// use `resize` so that the zero filling is as efficient as possible
vec.resize(pos, 0);
}
// Figure out what bytes will be used to overwrite what's currently
// there (left), and what will be appended on the end (right)
{
let space = vec.len() - pos;
let (left, right) = buf.split_at(cmp::min(space, buf.len()));
vec[pos..pos + left.len()].copy_from_slice(left);
vec.extend_from_slice(right);
}
// Bump us forward
*pos_mut = (pos + buf.len()) as u64;
Ok(buf.len())
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a> Write for Cursor<&'a mut [u8]> {
#[inline]
fn write(&mut self, data: &[u8]) -> io::Result<usize> {
let pos = cmp::min(self.pos, self.inner.len() as u64);
let amt = (&mut self.inner[(pos as usize)..]).write(data)?;
self.pos += amt as u64;
Ok(amt)
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
slice_write(&mut self.pos, self.inner, buf)
}
fn flush(&mut self) -> io::Result<()> { Ok(()) }
}
#[unstable(feature = "cursor_mut_vec", issue = "30132")]
impl<'a> Write for Cursor<&'a mut Vec<u8>> {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
vec_write(&mut self.pos, self.inner, buf)
}
fn flush(&mut self) -> io::Result<()> { Ok(()) }
}
@ -267,29 +307,7 @@ impl<'a> Write for Cursor<&'a mut [u8]> {
#[stable(feature = "rust1", since = "1.0.0")]
impl Write for Cursor<Vec<u8>> {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
let pos: usize = self.position().try_into().map_err(|_| {
Error::new(ErrorKind::InvalidInput,
"cursor position exceeds maximum possible vector length")
})?;
// Make sure the internal buffer is as least as big as where we
// currently are
let len = self.inner.len();
if len < pos {
// use `resize` so that the zero filling is as efficient as possible
self.inner.resize(pos, 0);
}
// Figure out what bytes will be used to overwrite what's currently
// there (left), and what will be appended on the end (right)
{
let space = self.inner.len() - pos;
let (left, right) = buf.split_at(cmp::min(space, buf.len()));
self.inner[pos..pos + left.len()].copy_from_slice(left);
self.inner.extend_from_slice(right);
}
// Bump us forward
self.set_position((pos + buf.len()) as u64);
Ok(buf.len())
vec_write(&mut self.pos, &mut self.inner, buf)
}
fn flush(&mut self) -> io::Result<()> { Ok(()) }
}
@ -298,10 +316,7 @@ impl Write for Cursor<Vec<u8>> {
impl Write for Cursor<Box<[u8]>> {
#[inline]
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
let pos = cmp::min(self.pos, self.inner.len() as u64);
let amt = (&mut self.inner[(pos as usize)..]).write(buf)?;
self.pos += amt as u64;
Ok(amt)
slice_write(&mut self.pos, &mut self.inner, buf)
}
fn flush(&mut self) -> io::Result<()> { Ok(()) }
}
@ -331,6 +346,17 @@ mod tests {
assert_eq!(&writer.get_ref()[..], b);
}
#[test]
fn test_mem_mut_writer() {
let mut vec = Vec::new();
let mut writer = Cursor::new(&mut vec);
assert_eq!(writer.write(&[0]).unwrap(), 1);
assert_eq!(writer.write(&[1, 2, 3]).unwrap(), 3);
assert_eq!(writer.write(&[4, 5, 6, 7]).unwrap(), 4);
let b: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7];
assert_eq!(&writer.get_ref()[..], b);
}
#[test]
fn test_box_slice_writer() {
let mut writer = Cursor::new(vec![0u8; 9].into_boxed_slice());