Add vectored read and write support

This functionality has lived for a while in the tokio ecosystem, where
it can improve performance by minimizing copies.
This commit is contained in:
Steven Fackler
2019-02-08 20:42:34 +01:00
parent 4772dc8087
commit 31bcec648a
29 changed files with 1033 additions and 92 deletions

View File

@@ -1,5 +1,6 @@
use cmp;
use io::{self, SeekFrom, Read, Initializer, Write, Seek, BufRead, Error, ErrorKind};
use io::{self, SeekFrom, Read, Initializer, Write, Seek, BufRead, Error, ErrorKind, IoVecMut,
IoVec};
use fmt;
use mem;
@@ -13,6 +14,11 @@ impl<'a, R: Read + ?Sized> Read for &'a mut R {
(**self).read(buf)
}
#[inline]
fn read_vectored(&mut self, bufs: &mut [IoVecMut<'_>]) -> io::Result<usize> {
(**self).read_vectored(bufs)
}
#[inline]
unsafe fn initializer(&self) -> Initializer {
(**self).initializer()
@@ -38,6 +44,11 @@ impl<'a, W: Write + ?Sized> Write for &'a mut W {
#[inline]
fn write(&mut self, buf: &[u8]) -> io::Result<usize> { (**self).write(buf) }
#[inline]
fn write_vectored(&mut self, bufs: &[IoVec<'_>]) -> io::Result<usize> {
(**self).write_vectored(bufs)
}
#[inline]
fn flush(&mut self) -> io::Result<()> { (**self).flush() }
@@ -82,6 +93,11 @@ impl<R: Read + ?Sized> Read for Box<R> {
(**self).read(buf)
}
#[inline]
fn read_vectored(&mut self, bufs: &mut [IoVecMut<'_>]) -> io::Result<usize> {
(**self).read_vectored(bufs)
}
#[inline]
unsafe fn initializer(&self) -> Initializer {
(**self).initializer()
@@ -107,6 +123,11 @@ impl<W: Write + ?Sized> Write for Box<W> {
#[inline]
fn write(&mut self, buf: &[u8]) -> io::Result<usize> { (**self).write(buf) }
#[inline]
fn write_vectored(&mut self, bufs: &[IoVec<'_>]) -> io::Result<usize> {
(**self).write_vectored(bufs)
}
#[inline]
fn flush(&mut self) -> io::Result<()> { (**self).flush() }
@@ -171,6 +192,19 @@ impl<'a> Read for &'a [u8] {
Ok(amt)
}
#[inline]
fn read_vectored(&mut self, bufs: &mut [IoVecMut<'_>]) -> io::Result<usize> {
let mut nread = 0;
for buf in bufs {
nread += self.read(buf.as_mut_slice())?;
if self.is_empty() {
break;
}
}
Ok(nread)
}
#[inline]
unsafe fn initializer(&self) -> Initializer {
Initializer::nop()
@@ -231,6 +265,19 @@ impl<'a> Write for &'a mut [u8] {
Ok(amt)
}
#[inline]
fn write_vectored(&mut self, bufs: &[IoVec<'_>]) -> io::Result<usize> {
let mut nwritten = 0;
for buf in bufs {
nwritten += self.write(buf.as_slice())?;
if self.is_empty() {
break;
}
}
Ok(nwritten)
}
#[inline]
fn write_all(&mut self, data: &[u8]) -> io::Result<()> {
if self.write(data)? == data.len() {
@@ -254,6 +301,16 @@ impl Write for Vec<u8> {
Ok(buf.len())
}
#[inline]
fn write_vectored(&mut self, bufs: &[IoVec<'_>]) -> io::Result<usize> {
let len = bufs.iter().map(|b| b.as_slice().len()).sum();
self.reserve(len);
for buf in bufs {
self.extend_from_slice(buf.as_slice());
}
Ok(len)
}
#[inline]
fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
self.extend_from_slice(buf);