Add Read/Write::can_read/write_vectored

When working with an arbitrary reader or writer, code that uses vectored
operations may end up being slower than code that copies into a single
buffer when the underlying reader or writer doesn't actually support
vectored operations. These new methods allow you to ask the reader or
witer up front if vectored operations are efficiently supported.

Currently, you have to use some heuristics to guess by e.g. checking if
the read or write only accessed the first buffer. Hyper is one concrete
example of a library that has to do this dynamically:
0eaf304644/src/proto/h1/io.rs (L582-L594)
This commit is contained in:
Steven Fackler
2020-01-03 11:26:05 -08:00
parent 019ab732ce
commit 15262ec6be
43 changed files with 556 additions and 0 deletions

View File

@@ -20,6 +20,11 @@ impl<R: Read + ?Sized> Read for &mut R {
(**self).read_vectored(bufs)
}
#[inline]
fn can_read_vectored(&self) -> bool {
(**self).can_read_vectored()
}
#[inline]
unsafe fn initializer(&self) -> Initializer {
(**self).initializer()
@@ -52,6 +57,11 @@ impl<W: Write + ?Sized> Write for &mut W {
(**self).write_vectored(bufs)
}
#[inline]
fn can_write_vectored(&self) -> bool {
(**self).can_write_vectored()
}
#[inline]
fn flush(&mut self) -> io::Result<()> {
(**self).flush()
@@ -109,6 +119,11 @@ impl<R: Read + ?Sized> Read for Box<R> {
(**self).read_vectored(bufs)
}
#[inline]
fn can_read_vectored(&self) -> bool {
(**self).can_read_vectored()
}
#[inline]
unsafe fn initializer(&self) -> Initializer {
(**self).initializer()
@@ -141,6 +156,11 @@ impl<W: Write + ?Sized> Write for Box<W> {
(**self).write_vectored(bufs)
}
#[inline]
fn can_write_vectored(&self) -> bool {
(**self).can_write_vectored()
}
#[inline]
fn flush(&mut self) -> io::Result<()> {
(**self).flush()
@@ -240,6 +260,11 @@ impl Read for &[u8] {
Ok(nread)
}
#[inline]
fn can_read_vectored(&self) -> bool {
true
}
#[inline]
unsafe fn initializer(&self) -> Initializer {
Initializer::nop()
@@ -316,6 +341,11 @@ impl Write for &mut [u8] {
Ok(nwritten)
}
#[inline]
fn can_write_vectored(&self) -> bool {
true
}
#[inline]
fn write_all(&mut self, data: &[u8]) -> io::Result<()> {
if self.write(data)? == data.len() {
@@ -351,6 +381,11 @@ impl Write for Vec<u8> {
Ok(len)
}
#[inline]
fn can_write_vectored(&self) -> bool {
true
}
#[inline]
fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
self.extend_from_slice(buf);