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

@ -659,6 +659,11 @@ impl Read for File {
self.inner.read_vectored(bufs)
}
#[inline]
fn can_read_vectored(&self) -> bool {
self.inner.can_read_vectored()
}
#[inline]
unsafe fn initializer(&self) -> Initializer {
Initializer::nop()
@ -674,6 +679,11 @@ impl Write for File {
self.inner.write_vectored(bufs)
}
#[inline]
fn can_write_vectored(&self) -> bool {
self.inner.can_write_vectored()
}
fn flush(&mut self) -> io::Result<()> {
self.inner.flush()
}
@ -694,6 +704,11 @@ impl Read for &File {
self.inner.read_vectored(bufs)
}
#[inline]
fn can_read_vectored(&self) -> bool {
self.inner.can_read_vectored()
}
#[inline]
unsafe fn initializer(&self) -> Initializer {
Initializer::nop()
@ -709,6 +724,11 @@ impl Write for &File {
self.inner.write_vectored(bufs)
}
#[inline]
fn can_write_vectored(&self) -> bool {
self.inner.can_write_vectored()
}
fn flush(&mut self) -> io::Result<()> {
self.inner.flush()
}

View File

@ -292,6 +292,10 @@ impl<R: Read> Read for BufReader<R> {
Ok(nread)
}
fn can_read_vectored(&self) -> bool {
self.inner.can_read_vectored()
}
// we can't skip unconditionally because of the large buffer case in read.
unsafe fn initializer(&self) -> Initializer {
self.inner.initializer()
@ -680,6 +684,10 @@ impl<W: Write> Write for BufWriter<W> {
}
}
fn can_write_vectored(&self) -> bool {
self.get_ref().can_write_vectored()
}
fn flush(&mut self) -> io::Result<()> {
self.flush_buf().and_then(|()| self.get_mut().flush())
}

View File

@ -266,6 +266,10 @@ where
Ok(nread)
}
fn can_read_vectored(&self) -> bool {
true
}
fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> {
let n = buf.len();
Read::read_exact(&mut self.fill_buf()?, buf)?;
@ -372,6 +376,11 @@ impl Write for Cursor<&mut [u8]> {
slice_write_vectored(&mut self.pos, self.inner, bufs)
}
#[inline]
fn can_write_vectored(&self) -> bool {
true
}
#[inline]
fn flush(&mut self) -> io::Result<()> {
Ok(())
@ -388,6 +397,11 @@ impl Write for Cursor<&mut Vec<u8>> {
vec_write_vectored(&mut self.pos, self.inner, bufs)
}
#[inline]
fn can_write_vectored(&self) -> bool {
true
}
#[inline]
fn flush(&mut self) -> io::Result<()> {
Ok(())
@ -404,6 +418,11 @@ impl Write for Cursor<Vec<u8>> {
vec_write_vectored(&mut self.pos, &mut self.inner, bufs)
}
#[inline]
fn can_write_vectored(&self) -> bool {
true
}
#[inline]
fn flush(&mut self) -> io::Result<()> {
Ok(())
@ -422,6 +441,11 @@ impl Write for Cursor<Box<[u8]>> {
slice_write_vectored(&mut self.pos, &mut self.inner, bufs)
}
#[inline]
fn can_write_vectored(&self) -> bool {
true
}
#[inline]
fn flush(&mut self) -> io::Result<()> {
Ok(())

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);

View File

@ -580,6 +580,19 @@ pub trait Read {
default_read_vectored(|b| self.read(b), bufs)
}
/// Determines if this `Read`er has an efficient `read_vectored`
/// implementation.
///
/// If a `Read`er does not override the default `read_vectored`
/// implementation, code using it may want to avoid the method all together
/// and coalesce writes into a single buffer for higher performance.
///
/// The default implementation returns `false`.
#[unstable(feature = "can_vector", issue = "none")]
fn can_read_vectored(&self) -> bool {
false
}
/// Determines if this `Read`er can work with buffers of uninitialized
/// memory.
///
@ -1304,6 +1317,19 @@ pub trait Write {
default_write_vectored(|b| self.write(b), bufs)
}
/// Determines if this `Write`er has an efficient `write_vectored`
/// implementation.
///
/// If a `Write`er does not override the default `write_vectored`
/// implementation, code using it may want to avoid the method all together
/// and coalesce writes into a single buffer for higher performance.
///
/// The default implementation returns `false`.
#[unstable(feature = "can_vector", issue = "none")]
fn can_write_vectored(&self) -> bool {
false
}
/// Flush this output stream, ensuring that all intermediately buffered
/// contents reach their destination.
///

View File

@ -87,6 +87,11 @@ impl Read for StdinRaw {
self.0.read_vectored(bufs)
}
#[inline]
fn can_read_vectored(&self) -> bool {
self.0.can_read_vectored()
}
#[inline]
unsafe fn initializer(&self) -> Initializer {
Initializer::nop()
@ -101,6 +106,11 @@ impl Write for StdoutRaw {
self.0.write_vectored(bufs)
}
#[inline]
fn can_write_vectored(&self) -> bool {
self.0.can_write_vectored()
}
fn flush(&mut self) -> io::Result<()> {
self.0.flush()
}
@ -114,6 +124,11 @@ impl Write for StderrRaw {
self.0.write_vectored(bufs)
}
#[inline]
fn can_write_vectored(&self) -> bool {
self.0.can_write_vectored()
}
fn flush(&mut self) -> io::Result<()> {
self.0.flush()
}
@ -140,6 +155,14 @@ impl<W: io::Write> io::Write for Maybe<W> {
}
}
#[inline]
fn can_write_vectored(&self) -> bool {
match self {
Maybe::Real(w) => w.can_write_vectored(),
Maybe::Fake => true,
}
}
fn flush(&mut self) -> io::Result<()> {
match *self {
Maybe::Real(ref mut w) => handle_ebadf(w.flush(), ()),
@ -162,6 +185,14 @@ impl<R: io::Read> io::Read for Maybe<R> {
Maybe::Fake => Ok(0),
}
}
#[inline]
fn can_read_vectored(&self) -> bool {
match self {
Maybe::Real(w) => w.can_read_vectored(),
Maybe::Fake => true,
}
}
}
fn handle_ebadf<T>(r: io::Result<T>, default: T) -> io::Result<T> {
@ -352,6 +383,10 @@ impl Read for Stdin {
self.lock().read_vectored(bufs)
}
#[inline]
fn can_read_vectored(&self) -> bool {
self.lock().can_read_vectored()
}
#[inline]
unsafe fn initializer(&self) -> Initializer {
Initializer::nop()
}
@ -376,6 +411,11 @@ impl Read for StdinLock<'_> {
self.inner.read_vectored(bufs)
}
#[inline]
fn can_read_vectored(&self) -> bool {
self.inner.can_read_vectored()
}
#[inline]
unsafe fn initializer(&self) -> Initializer {
Initializer::nop()
@ -543,6 +583,10 @@ impl Write for Stdout {
fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
self.lock().write_vectored(bufs)
}
#[inline]
fn can_write_vectored(&self) -> bool {
self.lock().can_write_vectored()
}
fn flush(&mut self) -> io::Result<()> {
self.lock().flush()
}
@ -561,6 +605,10 @@ impl Write for StdoutLock<'_> {
fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
self.inner.borrow_mut().write_vectored(bufs)
}
#[inline]
fn can_write_vectored(&self) -> bool {
self.inner.borrow_mut().can_write_vectored()
}
fn flush(&mut self) -> io::Result<()> {
self.inner.borrow_mut().flush()
}
@ -709,6 +757,10 @@ impl Write for Stderr {
fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
self.lock().write_vectored(bufs)
}
#[inline]
fn can_write_vectored(&self) -> bool {
self.lock().can_write_vectored()
}
fn flush(&mut self) -> io::Result<()> {
self.lock().flush()
}
@ -727,6 +779,10 @@ impl Write for StderrLock<'_> {
fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
self.inner.borrow_mut().write_vectored(bufs)
}
#[inline]
fn can_write_vectored(&self) -> bool {
self.inner.borrow_mut().can_write_vectored()
}
fn flush(&mut self) -> io::Result<()> {
self.inner.borrow_mut().flush()
}

View File

@ -179,6 +179,11 @@ impl Read for Repeat {
Ok(nwritten)
}
#[inline]
fn can_read_vectored(&self) -> bool {
true
}
#[inline]
unsafe fn initializer(&self) -> Initializer {
Initializer::nop()
@ -235,6 +240,11 @@ impl Write for Sink {
Ok(total_len)
}
#[inline]
fn can_write_vectored(&self) -> bool {
true
}
#[inline]
fn flush(&mut self) -> io::Result<()> {
Ok(())

View File

@ -243,6 +243,7 @@
#![feature(box_syntax)]
#![feature(c_variadic)]
#![feature(cfg_accessible)]
#![feature(can_vector)]
#![feature(cfg_target_has_atomic)]
#![feature(cfg_target_thread_local)]
#![feature(char_error_internals)]

View File

@ -576,6 +576,11 @@ impl Read for TcpStream {
self.0.read_vectored(bufs)
}
#[inline]
fn can_read_vectored(&self) -> bool {
self.0.can_read_vectored()
}
#[inline]
unsafe fn initializer(&self) -> Initializer {
Initializer::nop()
@ -591,6 +596,11 @@ impl Write for TcpStream {
self.0.write_vectored(bufs)
}
#[inline]
fn can_write_vectored(&self) -> bool {
self.0.can_write_vectored()
}
fn flush(&mut self) -> io::Result<()> {
Ok(())
}
@ -605,6 +615,11 @@ impl Read for &TcpStream {
self.0.read_vectored(bufs)
}
#[inline]
fn can_read_vectored(&self) -> bool {
self.0.can_read_vectored()
}
#[inline]
unsafe fn initializer(&self) -> Initializer {
Initializer::nop()
@ -620,6 +635,11 @@ impl Write for &TcpStream {
self.0.write_vectored(bufs)
}
#[inline]
fn can_write_vectored(&self) -> bool {
self.0.can_write_vectored()
}
fn flush(&mut self) -> io::Result<()> {
Ok(())
}

View File

@ -245,6 +245,10 @@ impl Write for ChildStdin {
self.inner.write_vectored(bufs)
}
fn can_write_vectored(&self) -> bool {
self.inner.can_write_vectored()
}
fn flush(&mut self) -> io::Result<()> {
Ok(())
}
@ -300,6 +304,11 @@ impl Read for ChildStdout {
self.inner.read_vectored(bufs)
}
#[inline]
fn can_read_vectored(&self) -> bool {
self.inner.can_read_vectored()
}
#[inline]
unsafe fn initializer(&self) -> Initializer {
Initializer::nop()
@ -356,6 +365,11 @@ impl Read for ChildStderr {
self.inner.read_vectored(bufs)
}
#[inline]
fn can_read_vectored(&self) -> bool {
self.inner.can_read_vectored()
}
#[inline]
unsafe fn initializer(&self) -> Initializer {
Initializer::nop()

View File

@ -202,6 +202,10 @@ impl File {
match self.0 {}
}
pub fn can_read_vectored(&self) -> bool {
match self.0 {}
}
pub fn write(&self, _buf: &[u8]) -> io::Result<usize> {
match self.0 {}
}
@ -210,6 +214,10 @@ impl File {
match self.0 {}
}
pub fn can_write_vectored(&self) -> bool {
match self.0 {}
}
pub fn flush(&self) -> io::Result<()> {
match self.0 {}
}

View File

@ -47,6 +47,10 @@ impl TcpStream {
match self.0 {}
}
pub fn can_read_vectored(&self) -> bool {
match self.0 {}
}
pub fn write(&self, _: &[u8]) -> io::Result<usize> {
match self.0 {}
}
@ -55,6 +59,10 @@ impl TcpStream {
match self.0 {}
}
pub fn can_write_vectored(&self) -> bool {
match self.0 {}
}
pub fn peer_addr(&self) -> io::Result<SocketAddr> {
match self.0 {}
}

View File

@ -12,6 +12,10 @@ impl AnonPipe {
match self.0 {}
}
pub fn can_read_vectored(&self) -> bool {
match self.0 {}
}
pub fn write(&self, _buf: &[u8]) -> io::Result<usize> {
match self.0 {}
}
@ -20,6 +24,10 @@ impl AnonPipe {
match self.0 {}
}
pub fn can_write_vectored(&self) -> bool {
match self.0 {}
}
pub fn diverge(&self) -> ! {
match self.0 {}
}

View File

@ -301,6 +301,11 @@ impl File {
crate::io::default_read_vectored(|buf| self.read(buf), bufs)
}
#[inline]
pub fn can_read_vectored(&self) -> bool {
false
}
pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
self.0.write(buf)
}
@ -309,6 +314,11 @@ impl File {
crate::io::default_write_vectored(|buf| self.write(buf), bufs)
}
#[inline]
pub fn can_write_vectored(&self) -> bool {
false
}
pub fn flush(&self) -> io::Result<()> {
Ok(())
}

View File

@ -99,6 +99,11 @@ impl TcpStream {
Ok(size)
}
#[inline]
pub fn can_read_vectored(&self) -> bool {
true
}
pub fn write(&self, buffer: &[u8]) -> io::Result<usize> {
self.write_vectored(&[IoSlice::new(buffer)])
}
@ -114,6 +119,11 @@ impl TcpStream {
Ok(size)
}
#[inline]
pub fn can_write_vectored(&self) -> bool {
true
}
pub fn peer_addr(&self) -> io::Result<SocketAddr> {
Err(io::Error::new(ErrorKind::Other, "peer_addr isn't supported"))
}

View File

@ -12,6 +12,10 @@ impl AnonPipe {
match self.0 {}
}
pub fn can_read_vectored(&self) -> bool {
match self.0 {}
}
pub fn write(&self, _buf: &[u8]) -> io::Result<usize> {
match self.0 {}
}
@ -20,6 +24,10 @@ impl AnonPipe {
match self.0 {}
}
pub fn can_write_vectored(&self) -> bool {
match self.0 {}
}
pub fn diverge(&self) -> ! {
match self.0 {}
}

View File

@ -20,6 +20,11 @@ impl Stdin {
// .read(data)
Ok(0)
}
#[inline]
pub fn can_read_vectored(&self) -> bool {
true
}
}
impl Stdout {
@ -51,6 +56,11 @@ impl Stdout {
}
}
#[inline]
pub fn can_write_vectored(&self) -> bool {
true
}
pub fn flush(&self) -> io::Result<()> {
Ok(())
}
@ -85,6 +95,11 @@ impl Stderr {
}
}
#[inline]
pub fn can_write_vectored(&self) -> bool {
true
}
pub fn flush(&self) -> io::Result<()> {
Ok(())
}

View File

@ -34,6 +34,11 @@ impl FileDesc {
usercalls::read(self.fd, bufs)
}
#[inline]
pub fn can_read_vectored(&self) -> bool {
true
}
pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
usercalls::write(self.fd, &[IoSlice::new(buf)])
}
@ -42,6 +47,11 @@ impl FileDesc {
usercalls::write(self.fd, bufs)
}
#[inline]
pub fn can_write_vectored(&self) -> bool {
true
}
pub fn flush(&self) -> io::Result<()> {
usercalls::flush(self.fd)
}

View File

@ -202,6 +202,10 @@ impl File {
match self.0 {}
}
pub fn can_read_vectored(&self) -> bool {
match self.0 {}
}
pub fn write(&self, _buf: &[u8]) -> io::Result<usize> {
match self.0 {}
}
@ -210,6 +214,10 @@ impl File {
match self.0 {}
}
pub fn can_write_vectored(&self) -> bool {
match self.0 {}
}
pub fn flush(&self) -> io::Result<()> {
match self.0 {}
}

View File

@ -149,6 +149,11 @@ impl TcpStream {
self.inner.inner.read_vectored(bufs)
}
#[inline]
pub fn can_read_vectored(&self) -> bool {
self.inner.inner.can_read_vectored()
}
pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
self.inner.inner.write(buf)
}
@ -157,6 +162,11 @@ impl TcpStream {
self.inner.inner.write_vectored(bufs)
}
#[inline]
pub fn can_write_vectored(&self) -> bool {
self.inner.inner.can_write_vectored()
}
pub fn peer_addr(&self) -> io::Result<SocketAddr> {
addr_to_sockaddr(&self.peer_addr)
}

View File

@ -12,6 +12,10 @@ impl AnonPipe {
match self.0 {}
}
pub fn can_read_vectored(&self) -> bool {
match self.0 {}
}
pub fn write(&self, _buf: &[u8]) -> io::Result<usize> {
match self.0 {}
}
@ -20,6 +24,10 @@ impl AnonPipe {
match self.0 {}
}
pub fn can_write_vectored(&self) -> bool {
match self.0 {}
}
pub fn diverge(&self) -> ! {
match self.0 {}
}

View File

@ -613,6 +613,11 @@ impl io::Read for UnixStream {
io::Read::read_vectored(&mut &*self, bufs)
}
#[inline]
fn can_read_vectored(&self) -> bool {
io::Read::can_read_vectored(&&*self)
}
#[inline]
unsafe fn initializer(&self) -> Initializer {
Initializer::nop()
@ -629,6 +634,11 @@ impl<'a> io::Read for &'a UnixStream {
self.0.read_vectored(bufs)
}
#[inline]
fn can_read_vectored(&self) -> bool {
self.0.can_read_vectored()
}
#[inline]
unsafe fn initializer(&self) -> Initializer {
Initializer::nop()
@ -645,6 +655,11 @@ impl io::Write for UnixStream {
io::Write::write_vectored(&mut &*self, bufs)
}
#[inline]
fn can_write_vectored(&self) -> bool {
io::Write::can_write_vectored(&&*self)
}
fn flush(&mut self) -> io::Result<()> {
io::Write::flush(&mut &*self)
}
@ -660,6 +675,11 @@ impl<'a> io::Write for &'a UnixStream {
self.0.write_vectored(bufs)
}
#[inline]
fn can_write_vectored(&self) -> bool {
self.0.can_write_vectored()
}
fn flush(&mut self) -> io::Result<()> {
Ok(())
}

View File

@ -64,6 +64,11 @@ impl FileDesc {
Ok(ret as usize)
}
#[inline]
pub fn can_read_vectored(&self) -> bool {
true
}
pub fn read_to_end(&self, buf: &mut Vec<u8>) -> io::Result<usize> {
let mut me = self;
(&mut me).read_to_end(buf)
@ -116,6 +121,11 @@ impl FileDesc {
Ok(ret as usize)
}
#[inline]
pub fn can_write_vectored(&self) -> bool {
true
}
pub fn write_at(&self, buf: &[u8], offset: u64) -> io::Result<usize> {
#[cfg(target_os = "android")]
use super::android::cvt_pwrite64;

View File

@ -828,6 +828,11 @@ impl File {
self.0.read_vectored(bufs)
}
#[inline]
pub fn can_read_vectored(&self) -> bool {
self.0.can_read_vectored()
}
pub fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<usize> {
self.0.read_at(buf, offset)
}
@ -840,6 +845,11 @@ impl File {
self.0.write_vectored(bufs)
}
#[inline]
pub fn can_write_vectored(&self) -> bool {
self.0.can_write_vectored()
}
pub fn write_at(&self, buf: &[u8], offset: u64) -> io::Result<usize> {
self.0.write_at(buf, offset)
}

View File

@ -55,6 +55,10 @@ pub mod net {
unimpl!();
}
pub fn can_read_vectored(&self) -> bool {
unimpl!();
}
pub fn peek(&self, _: &mut [u8]) -> io::Result<usize> {
unimpl!();
}
@ -75,6 +79,10 @@ pub mod net {
unimpl!();
}
pub fn can_write_vectored(&self) -> bool {
unimpl!();
}
pub fn set_timeout(&self, _: Option<Duration>, _: libc::c_int) -> io::Result<()> {
unimpl!();
}
@ -171,6 +179,10 @@ pub mod net {
unimpl!();
}
pub fn can_read_vectored(&self) -> bool {
unimpl!();
}
pub fn write(&self, _: &[u8]) -> io::Result<usize> {
unimpl!();
}
@ -179,6 +191,10 @@ pub mod net {
unimpl!();
}
pub fn can_write_vectored(&self) -> bool {
unimpl!();
}
pub fn peer_addr(&self) -> io::Result<SocketAddr> {
unimpl!();
}

View File

@ -226,6 +226,11 @@ impl Socket {
self.0.read_vectored(bufs)
}
#[inline]
pub fn can_read_vectored(&self) -> bool {
self.0.can_read_vectored()
}
fn recv_from_with_flags(
&self,
buf: &mut [u8],
@ -263,6 +268,11 @@ impl Socket {
self.0.write_vectored(bufs)
}
#[inline]
pub fn can_write_vectored(&self) -> bool {
self.0.can_write_vectored()
}
pub fn set_timeout(&self, dur: Option<Duration>, kind: libc::c_int) -> io::Result<()> {
let timeout = match dur {
Some(dur) => {

View File

@ -64,6 +64,11 @@ impl AnonPipe {
self.0.read_vectored(bufs)
}
#[inline]
pub fn can_read_vectored(&self) -> bool {
self.0.can_read_vectored()
}
pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
self.0.write(buf)
}
@ -72,6 +77,11 @@ impl AnonPipe {
self.0.write_vectored(bufs)
}
#[inline]
pub fn can_write_vectored(&self) -> bool {
self.0.can_write_vectored()
}
pub fn fd(&self) -> &FileDesc {
&self.0
}

View File

@ -20,6 +20,11 @@ impl io::Read for Stdin {
fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
ManuallyDrop::new(FileDesc::new(libc::STDIN_FILENO)).read_vectored(bufs)
}
#[inline]
fn can_read_vectored(&self) -> bool {
true
}
}
impl Stdout {
@ -37,6 +42,11 @@ impl io::Write for Stdout {
ManuallyDrop::new(FileDesc::new(libc::STDOUT_FILENO)).write_vectored(bufs)
}
#[inline]
fn can_write_vectored(&self) -> bool {
true
}
fn flush(&mut self) -> io::Result<()> {
Ok(())
}
@ -57,6 +67,11 @@ impl io::Write for Stderr {
ManuallyDrop::new(FileDesc::new(libc::STDERR_FILENO)).write_vectored(bufs)
}
#[inline]
fn can_write_vectored(&self) -> bool {
true
}
fn flush(&mut self) -> io::Result<()> {
Ok(())
}

View File

@ -54,6 +54,11 @@ impl FileDesc {
Ok(ret as usize)
}
#[inline]
fn can_read_vectored(&self) -> bool {
true
}
pub fn read_to_end(&self, buf: &mut Vec<u8>) -> io::Result<usize> {
let mut me = self;
(&mut me).read_to_end(buf)
@ -99,6 +104,11 @@ impl FileDesc {
Ok(ret as usize)
}
#[inline]
pub fn can_write_vectored(&self) -> bool {
true
}
pub fn write_at(&self, buf: &[u8], offset: u64) -> io::Result<usize> {
unsafe fn cvt_pwrite(
fd: c_int,

View File

@ -351,6 +351,11 @@ impl File {
self.0.read_vectored(bufs)
}
#[inline]
pub fn can_read_vectored(&self) -> bool {
self.0.can_read_vectored()
}
pub fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<usize> {
self.0.read_at(buf, offset)
}
@ -363,6 +368,11 @@ impl File {
self.0.write_vectored(bufs)
}
#[inline]
pub fn can_write_vectored(&self) -> bool {
self.0.can_write_vectored()
}
pub fn write_at(&self, buf: &[u8], offset: u64) -> io::Result<usize> {
self.0.write_at(buf, offset)
}

View File

@ -163,6 +163,11 @@ impl Socket {
self.0.read_vectored(bufs)
}
#[inline]
pub fn can_read_vectored(&self) -> bool {
self.0.can_read_vectored()
}
fn recv_from_with_flags(
&self,
buf: &mut [u8],
@ -200,6 +205,11 @@ impl Socket {
self.0.write_vectored(bufs)
}
#[inline]
pub fn can_write_vectored(&self) -> bool {
self.0.can_write_vectored()
}
pub fn set_timeout(&self, dur: Option<Duration>, kind: libc::c_int) -> io::Result<()> {
let timeout = match dur {
Some(dur) => {

View File

@ -24,10 +24,16 @@ impl AnonPipe {
pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
self.0.read(buf)
}
pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
self.0.read_vectored(bufs)
}
#[inline]
pub fn can_read_vectored(&self) -> bool {
self.0.can_read_vectored()
}
pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
self.0.write(buf)
}
@ -36,6 +42,11 @@ impl AnonPipe {
self.0.write_vectored(bufs)
}
#[inline]
pub fn can_write_vectored(&self) -> bool {
self.0.can_write_vectored()
}
pub fn fd(&self) -> &FileDesc {
&self.0
}

View File

@ -399,6 +399,11 @@ impl File {
self.fd.read(bufs)
}
#[inline]
pub fn can_read_vectored(&self) -> bool {
true
}
pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
self.write_vectored(&[IoSlice::new(buf)])
}
@ -407,6 +412,11 @@ impl File {
self.fd.write(bufs)
}
#[inline]
pub fn can_write_vectored(&self) -> bool {
true
}
pub fn flush(&self) -> io::Result<()> {
Ok(())
}

View File

@ -48,6 +48,10 @@ impl TcpStream {
unsupported()
}
pub fn can_read_vectored(&self) -> bool {
unsupported()
}
pub fn write(&self, _: &[u8]) -> io::Result<usize> {
unsupported()
}
@ -56,6 +60,10 @@ impl TcpStream {
unsupported()
}
pub fn can_write_vectored(&self) -> bool {
unsupported()
}
pub fn peer_addr(&self) -> io::Result<SocketAddr> {
unsupported()
}

View File

@ -12,6 +12,10 @@ impl AnonPipe {
match self.0 {}
}
pub fn can_read_vectored(&self) -> bool {
match self.0 {}
}
pub fn write(&self, _buf: &[u8]) -> io::Result<usize> {
match self.0 {}
}
@ -20,6 +24,10 @@ impl AnonPipe {
match self.0 {}
}
pub fn can_write_vectored(&self) -> bool {
match self.0 {}
}
pub fn diverge(&self) -> ! {
match self.0 {}
}

View File

@ -19,6 +19,11 @@ impl Stdin {
ManuallyDrop::new(unsafe { WasiFd::from_raw(self.as_raw_fd()) }).read(data)
}
#[inline]
pub fn can_read_vectored(&self) -> bool {
true
}
pub fn as_raw_fd(&self) -> u32 {
0
}
@ -37,6 +42,11 @@ impl Stdout {
ManuallyDrop::new(unsafe { WasiFd::from_raw(self.as_raw_fd()) }).write(data)
}
#[inline]
pub fn can_write_vectored(&self) -> bool {
true
}
pub fn flush(&self) -> io::Result<()> {
Ok(())
}
@ -59,6 +69,11 @@ impl Stderr {
ManuallyDrop::new(unsafe { WasiFd::from_raw(self.as_raw_fd()) }).write(data)
}
#[inline]
pub fn can_write_vectored(&self) -> bool {
true
}
pub fn flush(&self) -> io::Result<()> {
Ok(())
}

View File

@ -202,6 +202,10 @@ impl File {
match self.0 {}
}
pub fn can_read_vectored(&self) -> bool {
match self.0 {}
}
pub fn write(&self, _buf: &[u8]) -> io::Result<usize> {
match self.0 {}
}
@ -210,6 +214,10 @@ impl File {
match self.0 {}
}
pub fn can_write_vectored(&self) -> bool {
match self.0 {}
}
pub fn flush(&self) -> io::Result<()> {
match self.0 {}
}

View File

@ -44,6 +44,10 @@ impl TcpStream {
match self.0 {}
}
pub fn can_read_vectored(&self) -> bool {
match self.0 {}
}
pub fn write(&self, _: &[u8]) -> io::Result<usize> {
match self.0 {}
}
@ -52,6 +56,10 @@ impl TcpStream {
match self.0 {}
}
pub fn can_write_vectored(&self) -> bool {
match self.0 {}
}
pub fn peer_addr(&self) -> io::Result<SocketAddr> {
match self.0 {}
}

View File

@ -409,6 +409,11 @@ impl File {
self.handle.read_vectored(bufs)
}
#[inline]
pub fn can_read_vectored(&self) -> bool {
self.handle.can_read_vectored()
}
pub fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<usize> {
self.handle.read_at(buf, offset)
}
@ -421,6 +426,11 @@ impl File {
self.handle.write_vectored(bufs)
}
#[inline]
pub fn can_write_vectored(&self) -> bool {
self.handle.can_write_vectored()
}
pub fn write_at(&self, buf: &[u8], offset: u64) -> io::Result<usize> {
self.handle.write_at(buf, offset)
}

View File

@ -92,6 +92,11 @@ impl RawHandle {
crate::io::default_read_vectored(|buf| self.read(buf), bufs)
}
#[inline]
pub fn can_read_vectored(&self) -> bool {
false
}
pub fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<usize> {
let mut read = 0;
let len = cmp::min(buf.len(), <c::DWORD>::max_value() as usize) as c::DWORD;
@ -171,6 +176,11 @@ impl RawHandle {
crate::io::default_write_vectored(|buf| self.write(buf), bufs)
}
#[inline]
pub fn can_write_vectored(&self) -> bool {
false
}
pub fn write_at(&self, buf: &[u8], offset: u64) -> io::Result<usize> {
let mut written = 0;
let len = cmp::min(buf.len(), <c::DWORD>::max_value() as usize) as c::DWORD;

View File

@ -266,6 +266,11 @@ impl Socket {
}
}
#[inline]
pub fn can_read_vectored(&self) -> bool {
true
}
pub fn peek(&self, buf: &mut [u8]) -> io::Result<usize> {
self.recv_with_flags(buf, c::MSG_PEEK)
}
@ -324,6 +329,11 @@ impl Socket {
Ok(nwritten as usize)
}
#[inline]
pub fn can_write_vectored(&self) -> bool {
true
}
pub fn set_timeout(&self, dur: Option<Duration>, kind: c_int) -> io::Result<()> {
let timeout = match dur {
Some(dur) => {

View File

@ -182,6 +182,11 @@ impl AnonPipe {
self.inner.read_vectored(bufs)
}
#[inline]
pub fn can_read_vectored(&self) -> bool {
self.inner.can_read_vectored()
}
pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
self.inner.write(buf)
}
@ -189,6 +194,11 @@ impl AnonPipe {
pub fn write_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
self.inner.write_vectored(bufs)
}
#[inline]
pub fn can_write_vectored(&self) -> bool {
self.inner.can_write_vectored()
}
}
pub fn read2(p1: AnonPipe, v1: &mut Vec<u8>, p2: AnonPipe, v2: &mut Vec<u8>) -> io::Result<()> {

View File

@ -265,6 +265,11 @@ impl TcpStream {
self.inner.read_vectored(bufs)
}
#[inline]
pub fn can_read_vectored(&self) -> bool {
self.inner.can_read_vectored()
}
pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
let len = cmp::min(buf.len(), <wrlen_t>::max_value() as usize) as wrlen_t;
let ret = cvt(unsafe {
@ -277,6 +282,11 @@ impl TcpStream {
self.inner.write_vectored(bufs)
}
#[inline]
pub fn can_write_vectored(&self) -> bool {
self.inner.can_write_vectored()
}
pub fn peer_addr(&self) -> io::Result<SocketAddr> {
sockname(|buf, len| unsafe { c::getpeername(*self.inner.as_inner(), buf, len) })
}