about summary refs log tree commit diff
path: root/src/libstd/sys
diff options
context:
space:
mode:
authorDylan DPC <dylan.dpc@gmail.com>2020-04-27 22:14:55 +0200
committerGitHub <noreply@github.com>2020-04-27 22:14:55 +0200
commitc4d9f42f6d29b9c7bf8f6ca98be02621724cb9d2 (patch)
treefaf85c1d2ef5b674504ce069afa249e1f4e22b31 /src/libstd/sys
parent46ec74e60f238f694b46c976d6217e7cf8d4cf1a (diff)
parentc68f23ff6d670e579e0951352e20a1495b66fce0 (diff)
downloadrust-c4d9f42f6d29b9c7bf8f6ca98be02621724cb9d2.tar.gz
rust-c4d9f42f6d29b9c7bf8f6ca98be02621724cb9d2.zip
Rollup merge of #67841 - sfackler:can-vector, r=Amaneiu
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:
https://github.com/hyperium/hyper/blob/0eaf304644a396895a4ce1f0146e596640bb666a/src/proto/h1/io.rs#L582-L594
Diffstat (limited to 'src/libstd/sys')
-rw-r--r--src/libstd/sys/cloudabi/shims/fs.rs8
-rw-r--r--src/libstd/sys/cloudabi/shims/net.rs8
-rw-r--r--src/libstd/sys/cloudabi/shims/pipe.rs8
-rw-r--r--src/libstd/sys/hermit/fs.rs10
-rw-r--r--src/libstd/sys/hermit/net.rs10
-rw-r--r--src/libstd/sys/hermit/pipe.rs8
-rw-r--r--src/libstd/sys/hermit/stdio.rs15
-rw-r--r--src/libstd/sys/sgx/fd.rs10
-rw-r--r--src/libstd/sys/sgx/fs.rs8
-rw-r--r--src/libstd/sys/sgx/net.rs10
-rw-r--r--src/libstd/sys/sgx/pipe.rs8
-rw-r--r--src/libstd/sys/unix/ext/net.rs20
-rw-r--r--src/libstd/sys/unix/fd.rs10
-rw-r--r--src/libstd/sys/unix/fs.rs10
-rw-r--r--src/libstd/sys/unix/l4re.rs16
-rw-r--r--src/libstd/sys/unix/net.rs10
-rw-r--r--src/libstd/sys/unix/pipe.rs10
-rw-r--r--src/libstd/sys/unix/stdio.rs15
-rw-r--r--src/libstd/sys/vxworks/fd.rs10
-rw-r--r--src/libstd/sys/vxworks/fs.rs10
-rw-r--r--src/libstd/sys/vxworks/net.rs10
-rw-r--r--src/libstd/sys/vxworks/pipe.rs11
-rw-r--r--src/libstd/sys/wasi/fs.rs10
-rw-r--r--src/libstd/sys/wasi/net.rs8
-rw-r--r--src/libstd/sys/wasi/pipe.rs8
-rw-r--r--src/libstd/sys/wasi/stdio.rs15
-rw-r--r--src/libstd/sys/wasm/fs.rs8
-rw-r--r--src/libstd/sys/wasm/net.rs8
-rw-r--r--src/libstd/sys/wasm/pipe.rs8
-rw-r--r--src/libstd/sys/windows/fs.rs10
-rw-r--r--src/libstd/sys/windows/handle.rs10
-rw-r--r--src/libstd/sys/windows/net.rs10
-rw-r--r--src/libstd/sys/windows/pipe.rs10
33 files changed, 340 insertions, 0 deletions
diff --git a/src/libstd/sys/cloudabi/shims/fs.rs b/src/libstd/sys/cloudabi/shims/fs.rs
index e6160d1457d..ecb5b51cccd 100644
--- a/src/libstd/sys/cloudabi/shims/fs.rs
+++ b/src/libstd/sys/cloudabi/shims/fs.rs
@@ -202,6 +202,10 @@ impl File {
         match self.0 {}
     }
 
+    pub fn is_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 is_write_vectored(&self) -> bool {
+        match self.0 {}
+    }
+
     pub fn flush(&self) -> io::Result<()> {
         match self.0 {}
     }
diff --git a/src/libstd/sys/cloudabi/shims/net.rs b/src/libstd/sys/cloudabi/shims/net.rs
index 67c436fa795..375aaab405d 100644
--- a/src/libstd/sys/cloudabi/shims/net.rs
+++ b/src/libstd/sys/cloudabi/shims/net.rs
@@ -47,6 +47,10 @@ impl TcpStream {
         match self.0 {}
     }
 
+    pub fn is_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 is_write_vectored(&self) -> bool {
+        match self.0 {}
+    }
+
     pub fn peer_addr(&self) -> io::Result<SocketAddr> {
         match self.0 {}
     }
diff --git a/src/libstd/sys/cloudabi/shims/pipe.rs b/src/libstd/sys/cloudabi/shims/pipe.rs
index fb14dc59101..10d0925823e 100644
--- a/src/libstd/sys/cloudabi/shims/pipe.rs
+++ b/src/libstd/sys/cloudabi/shims/pipe.rs
@@ -12,6 +12,10 @@ impl AnonPipe {
         match self.0 {}
     }
 
+    pub fn is_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 is_write_vectored(&self) -> bool {
+        match self.0 {}
+    }
+
     pub fn diverge(&self) -> ! {
         match self.0 {}
     }
diff --git a/src/libstd/sys/hermit/fs.rs b/src/libstd/sys/hermit/fs.rs
index 287a0390667..82ccab1462b 100644
--- a/src/libstd/sys/hermit/fs.rs
+++ b/src/libstd/sys/hermit/fs.rs
@@ -301,6 +301,11 @@ impl File {
         crate::io::default_read_vectored(|buf| self.read(buf), bufs)
     }
 
+    #[inline]
+    pub fn is_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 is_write_vectored(&self) -> bool {
+        false
+    }
+
     pub fn flush(&self) -> io::Result<()> {
         Ok(())
     }
diff --git a/src/libstd/sys/hermit/net.rs b/src/libstd/sys/hermit/net.rs
index 377c3132c5a..5b5379c8b05 100644
--- a/src/libstd/sys/hermit/net.rs
+++ b/src/libstd/sys/hermit/net.rs
@@ -99,6 +99,11 @@ impl TcpStream {
         Ok(size)
     }
 
+    #[inline]
+    pub fn is_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 is_write_vectored(&self) -> bool {
+        true
+    }
+
     pub fn peer_addr(&self) -> io::Result<SocketAddr> {
         Err(io::Error::new(ErrorKind::Other, "peer_addr isn't supported"))
     }
diff --git a/src/libstd/sys/hermit/pipe.rs b/src/libstd/sys/hermit/pipe.rs
index fb14dc59101..10d0925823e 100644
--- a/src/libstd/sys/hermit/pipe.rs
+++ b/src/libstd/sys/hermit/pipe.rs
@@ -12,6 +12,10 @@ impl AnonPipe {
         match self.0 {}
     }
 
+    pub fn is_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 is_write_vectored(&self) -> bool {
+        match self.0 {}
+    }
+
     pub fn diverge(&self) -> ! {
         match self.0 {}
     }
diff --git a/src/libstd/sys/hermit/stdio.rs b/src/libstd/sys/hermit/stdio.rs
index 2eb011ccb39..208265de465 100644
--- a/src/libstd/sys/hermit/stdio.rs
+++ b/src/libstd/sys/hermit/stdio.rs
@@ -20,6 +20,11 @@ impl Stdin {
         //    .read(data)
         Ok(0)
     }
+
+    #[inline]
+    pub fn is_read_vectored(&self) -> bool {
+        true
+    }
 }
 
 impl Stdout {
@@ -51,6 +56,11 @@ impl Stdout {
         }
     }
 
+    #[inline]
+    pub fn is_write_vectored(&self) -> bool {
+        true
+    }
+
     pub fn flush(&self) -> io::Result<()> {
         Ok(())
     }
@@ -85,6 +95,11 @@ impl Stderr {
         }
     }
 
+    #[inline]
+    pub fn is_write_vectored(&self) -> bool {
+        true
+    }
+
     pub fn flush(&self) -> io::Result<()> {
         Ok(())
     }
diff --git a/src/libstd/sys/sgx/fd.rs b/src/libstd/sys/sgx/fd.rs
index 7da2424a642..90158030c7f 100644
--- a/src/libstd/sys/sgx/fd.rs
+++ b/src/libstd/sys/sgx/fd.rs
@@ -34,6 +34,11 @@ impl FileDesc {
         usercalls::read(self.fd, bufs)
     }
 
+    #[inline]
+    pub fn is_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 is_write_vectored(&self) -> bool {
+        true
+    }
+
     pub fn flush(&self) -> io::Result<()> {
         usercalls::flush(self.fd)
     }
diff --git a/src/libstd/sys/sgx/fs.rs b/src/libstd/sys/sgx/fs.rs
index e6160d1457d..ecb5b51cccd 100644
--- a/src/libstd/sys/sgx/fs.rs
+++ b/src/libstd/sys/sgx/fs.rs
@@ -202,6 +202,10 @@ impl File {
         match self.0 {}
     }
 
+    pub fn is_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 is_write_vectored(&self) -> bool {
+        match self.0 {}
+    }
+
     pub fn flush(&self) -> io::Result<()> {
         match self.0 {}
     }
diff --git a/src/libstd/sys/sgx/net.rs b/src/libstd/sys/sgx/net.rs
index bd0652ab464..666a157b09c 100644
--- a/src/libstd/sys/sgx/net.rs
+++ b/src/libstd/sys/sgx/net.rs
@@ -149,6 +149,11 @@ impl TcpStream {
         self.inner.inner.read_vectored(bufs)
     }
 
+    #[inline]
+    pub fn is_read_vectored(&self) -> bool {
+        self.inner.inner.is_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 is_write_vectored(&self) -> bool {
+        self.inner.inner.is_write_vectored()
+    }
+
     pub fn peer_addr(&self) -> io::Result<SocketAddr> {
         addr_to_sockaddr(&self.peer_addr)
     }
diff --git a/src/libstd/sys/sgx/pipe.rs b/src/libstd/sys/sgx/pipe.rs
index fb14dc59101..10d0925823e 100644
--- a/src/libstd/sys/sgx/pipe.rs
+++ b/src/libstd/sys/sgx/pipe.rs
@@ -12,6 +12,10 @@ impl AnonPipe {
         match self.0 {}
     }
 
+    pub fn is_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 is_write_vectored(&self) -> bool {
+        match self.0 {}
+    }
+
     pub fn diverge(&self) -> ! {
         match self.0 {}
     }
diff --git a/src/libstd/sys/unix/ext/net.rs b/src/libstd/sys/unix/ext/net.rs
index 4c3cb67c9ee..bfdc39ada75 100644
--- a/src/libstd/sys/unix/ext/net.rs
+++ b/src/libstd/sys/unix/ext/net.rs
@@ -614,6 +614,11 @@ impl io::Read for UnixStream {
     }
 
     #[inline]
+    fn is_read_vectored(&self) -> bool {
+        io::Read::is_read_vectored(&&*self)
+    }
+
+    #[inline]
     unsafe fn initializer(&self) -> Initializer {
         Initializer::nop()
     }
@@ -630,6 +635,11 @@ impl<'a> io::Read for &'a UnixStream {
     }
 
     #[inline]
+    fn is_read_vectored(&self) -> bool {
+        self.0.is_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 is_write_vectored(&self) -> bool {
+        io::Write::is_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 is_write_vectored(&self) -> bool {
+        self.0.is_write_vectored()
+    }
+
     fn flush(&mut self) -> io::Result<()> {
         Ok(())
     }
diff --git a/src/libstd/sys/unix/fd.rs b/src/libstd/sys/unix/fd.rs
index 1bba56e334a..1ef7ffacfcf 100644
--- a/src/libstd/sys/unix/fd.rs
+++ b/src/libstd/sys/unix/fd.rs
@@ -64,6 +64,11 @@ impl FileDesc {
         Ok(ret as usize)
     }
 
+    #[inline]
+    pub fn is_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 is_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;
diff --git a/src/libstd/sys/unix/fs.rs b/src/libstd/sys/unix/fs.rs
index a233aa47dff..2cfc63d9492 100644
--- a/src/libstd/sys/unix/fs.rs
+++ b/src/libstd/sys/unix/fs.rs
@@ -828,6 +828,11 @@ impl File {
         self.0.read_vectored(bufs)
     }
 
+    #[inline]
+    pub fn is_read_vectored(&self) -> bool {
+        self.0.is_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 is_write_vectored(&self) -> bool {
+        self.0.is_write_vectored()
+    }
+
     pub fn write_at(&self, buf: &[u8], offset: u64) -> io::Result<usize> {
         self.0.write_at(buf, offset)
     }
diff --git a/src/libstd/sys/unix/l4re.rs b/src/libstd/sys/unix/l4re.rs
index c6e4f5693ed..a2912387108 100644
--- a/src/libstd/sys/unix/l4re.rs
+++ b/src/libstd/sys/unix/l4re.rs
@@ -55,6 +55,10 @@ pub mod net {
             unimpl!();
         }
 
+        pub fn is_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 is_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 is_read_vectored(&self) -> bool {
+            unimpl!();
+        }
+
         pub fn write(&self, _: &[u8]) -> io::Result<usize> {
             unimpl!();
         }
@@ -179,6 +191,10 @@ pub mod net {
             unimpl!();
         }
 
+        pub fn is_write_vectored(&self) -> bool {
+            unimpl!();
+        }
+
         pub fn peer_addr(&self) -> io::Result<SocketAddr> {
             unimpl!();
         }
diff --git a/src/libstd/sys/unix/net.rs b/src/libstd/sys/unix/net.rs
index d18c22b0573..f062bc012f7 100644
--- a/src/libstd/sys/unix/net.rs
+++ b/src/libstd/sys/unix/net.rs
@@ -226,6 +226,11 @@ impl Socket {
         self.0.read_vectored(bufs)
     }
 
+    #[inline]
+    pub fn is_read_vectored(&self) -> bool {
+        self.0.is_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 is_write_vectored(&self) -> bool {
+        self.0.is_write_vectored()
+    }
+
     pub fn set_timeout(&self, dur: Option<Duration>, kind: libc::c_int) -> io::Result<()> {
         let timeout = match dur {
             Some(dur) => {
diff --git a/src/libstd/sys/unix/pipe.rs b/src/libstd/sys/unix/pipe.rs
index 2a861c87801..f2a2eabef91 100644
--- a/src/libstd/sys/unix/pipe.rs
+++ b/src/libstd/sys/unix/pipe.rs
@@ -64,6 +64,11 @@ impl AnonPipe {
         self.0.read_vectored(bufs)
     }
 
+    #[inline]
+    pub fn is_read_vectored(&self) -> bool {
+        self.0.is_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 is_write_vectored(&self) -> bool {
+        self.0.is_write_vectored()
+    }
+
     pub fn fd(&self) -> &FileDesc {
         &self.0
     }
diff --git a/src/libstd/sys/unix/stdio.rs b/src/libstd/sys/unix/stdio.rs
index b9c56963885..f8353214cbc 100644
--- a/src/libstd/sys/unix/stdio.rs
+++ b/src/libstd/sys/unix/stdio.rs
@@ -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 is_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 is_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 is_write_vectored(&self) -> bool {
+        true
+    }
+
     fn flush(&mut self) -> io::Result<()> {
         Ok(())
     }
diff --git a/src/libstd/sys/vxworks/fd.rs b/src/libstd/sys/vxworks/fd.rs
index 65c67dabc1a..23e9dc428ce 100644
--- a/src/libstd/sys/vxworks/fd.rs
+++ b/src/libstd/sys/vxworks/fd.rs
@@ -54,6 +54,11 @@ impl FileDesc {
         Ok(ret as usize)
     }
 
+    #[inline]
+    fn is_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 is_write_vectored(&self) -> bool {
+        true
+    }
+
     pub fn write_at(&self, buf: &[u8], offset: u64) -> io::Result<usize> {
         unsafe fn cvt_pwrite(
             fd: c_int,
diff --git a/src/libstd/sys/vxworks/fs.rs b/src/libstd/sys/vxworks/fs.rs
index 68f2c133170..557e65ca01b 100644
--- a/src/libstd/sys/vxworks/fs.rs
+++ b/src/libstd/sys/vxworks/fs.rs
@@ -351,6 +351,11 @@ impl File {
         self.0.read_vectored(bufs)
     }
 
+    #[inline]
+    pub fn is_read_vectored(&self) -> bool {
+        self.0.is_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 is_write_vectored(&self) -> bool {
+        self.0.is_write_vectored()
+    }
+
     pub fn write_at(&self, buf: &[u8], offset: u64) -> io::Result<usize> {
         self.0.write_at(buf, offset)
     }
diff --git a/src/libstd/sys/vxworks/net.rs b/src/libstd/sys/vxworks/net.rs
index 7d4e5624f7e..de0b15b43a2 100644
--- a/src/libstd/sys/vxworks/net.rs
+++ b/src/libstd/sys/vxworks/net.rs
@@ -163,6 +163,11 @@ impl Socket {
         self.0.read_vectored(bufs)
     }
 
+    #[inline]
+    pub fn is_read_vectored(&self) -> bool {
+        self.0.is_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 is_write_vectored(&self) -> bool {
+        self.0.is_write_vectored()
+    }
+
     pub fn set_timeout(&self, dur: Option<Duration>, kind: libc::c_int) -> io::Result<()> {
         let timeout = match dur {
             Some(dur) => {
diff --git a/src/libstd/sys/vxworks/pipe.rs b/src/libstd/sys/vxworks/pipe.rs
index 0990cb8e83c..a18376212af 100644
--- a/src/libstd/sys/vxworks/pipe.rs
+++ b/src/libstd/sys/vxworks/pipe.rs
@@ -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 is_read_vectored(&self) -> bool {
+        self.0.is_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 is_write_vectored(&self) -> bool {
+        self.0.is_write_vectored()
+    }
+
     pub fn fd(&self) -> &FileDesc {
         &self.0
     }
diff --git a/src/libstd/sys/wasi/fs.rs b/src/libstd/sys/wasi/fs.rs
index a11f61fdd69..793daea43c2 100644
--- a/src/libstd/sys/wasi/fs.rs
+++ b/src/libstd/sys/wasi/fs.rs
@@ -399,6 +399,11 @@ impl File {
         self.fd.read(bufs)
     }
 
+    #[inline]
+    pub fn is_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 is_write_vectored(&self) -> bool {
+        true
+    }
+
     pub fn flush(&self) -> io::Result<()> {
         Ok(())
     }
diff --git a/src/libstd/sys/wasi/net.rs b/src/libstd/sys/wasi/net.rs
index 8a69028ff1d..e186453588d 100644
--- a/src/libstd/sys/wasi/net.rs
+++ b/src/libstd/sys/wasi/net.rs
@@ -48,6 +48,10 @@ impl TcpStream {
         unsupported()
     }
 
+    pub fn is_read_vectored(&self) -> bool {
+        true
+    }
+
     pub fn write(&self, _: &[u8]) -> io::Result<usize> {
         unsupported()
     }
@@ -56,6 +60,10 @@ impl TcpStream {
         unsupported()
     }
 
+    pub fn is_write_vectored(&self) -> bool {
+        true
+    }
+
     pub fn peer_addr(&self) -> io::Result<SocketAddr> {
         unsupported()
     }
diff --git a/src/libstd/sys/wasi/pipe.rs b/src/libstd/sys/wasi/pipe.rs
index fb14dc59101..10d0925823e 100644
--- a/src/libstd/sys/wasi/pipe.rs
+++ b/src/libstd/sys/wasi/pipe.rs
@@ -12,6 +12,10 @@ impl AnonPipe {
         match self.0 {}
     }
 
+    pub fn is_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 is_write_vectored(&self) -> bool {
+        match self.0 {}
+    }
+
     pub fn diverge(&self) -> ! {
         match self.0 {}
     }
diff --git a/src/libstd/sys/wasi/stdio.rs b/src/libstd/sys/wasi/stdio.rs
index 1d53884f2d6..9f9e35566ec 100644
--- a/src/libstd/sys/wasi/stdio.rs
+++ b/src/libstd/sys/wasi/stdio.rs
@@ -19,6 +19,11 @@ impl Stdin {
         ManuallyDrop::new(unsafe { WasiFd::from_raw(self.as_raw_fd()) }).read(data)
     }
 
+    #[inline]
+    pub fn is_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 is_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 is_write_vectored(&self) -> bool {
+        true
+    }
+
     pub fn flush(&self) -> io::Result<()> {
         Ok(())
     }
diff --git a/src/libstd/sys/wasm/fs.rs b/src/libstd/sys/wasm/fs.rs
index e6160d1457d..ecb5b51cccd 100644
--- a/src/libstd/sys/wasm/fs.rs
+++ b/src/libstd/sys/wasm/fs.rs
@@ -202,6 +202,10 @@ impl File {
         match self.0 {}
     }
 
+    pub fn is_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 is_write_vectored(&self) -> bool {
+        match self.0 {}
+    }
+
     pub fn flush(&self) -> io::Result<()> {
         match self.0 {}
     }
diff --git a/src/libstd/sys/wasm/net.rs b/src/libstd/sys/wasm/net.rs
index b7c3108f172..5c9f1098f9b 100644
--- a/src/libstd/sys/wasm/net.rs
+++ b/src/libstd/sys/wasm/net.rs
@@ -44,6 +44,10 @@ impl TcpStream {
         match self.0 {}
     }
 
+    pub fn is_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 is_write_vectored(&self) -> bool {
+        match self.0 {}
+    }
+
     pub fn peer_addr(&self) -> io::Result<SocketAddr> {
         match self.0 {}
     }
diff --git a/src/libstd/sys/wasm/pipe.rs b/src/libstd/sys/wasm/pipe.rs
index fb14dc59101..10d0925823e 100644
--- a/src/libstd/sys/wasm/pipe.rs
+++ b/src/libstd/sys/wasm/pipe.rs
@@ -12,6 +12,10 @@ impl AnonPipe {
         match self.0 {}
     }
 
+    pub fn is_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 is_write_vectored(&self) -> bool {
+        match self.0 {}
+    }
+
     pub fn diverge(&self) -> ! {
         match self.0 {}
     }
diff --git a/src/libstd/sys/windows/fs.rs b/src/libstd/sys/windows/fs.rs
index 427f4b684e1..cdbfac267b9 100644
--- a/src/libstd/sys/windows/fs.rs
+++ b/src/libstd/sys/windows/fs.rs
@@ -409,6 +409,11 @@ impl File {
         self.handle.read_vectored(bufs)
     }
 
+    #[inline]
+    pub fn is_read_vectored(&self) -> bool {
+        self.handle.is_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 is_write_vectored(&self) -> bool {
+        self.handle.is_write_vectored()
+    }
+
     pub fn write_at(&self, buf: &[u8], offset: u64) -> io::Result<usize> {
         self.handle.write_at(buf, offset)
     }
diff --git a/src/libstd/sys/windows/handle.rs b/src/libstd/sys/windows/handle.rs
index d00381792e3..2131cfc2c94 100644
--- a/src/libstd/sys/windows/handle.rs
+++ b/src/libstd/sys/windows/handle.rs
@@ -92,6 +92,11 @@ impl RawHandle {
         crate::io::default_read_vectored(|buf| self.read(buf), bufs)
     }
 
+    #[inline]
+    pub fn is_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 is_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;
diff --git a/src/libstd/sys/windows/net.rs b/src/libstd/sys/windows/net.rs
index d8d4fdfce2f..a15ded92f08 100644
--- a/src/libstd/sys/windows/net.rs
+++ b/src/libstd/sys/windows/net.rs
@@ -266,6 +266,11 @@ impl Socket {
         }
     }
 
+    #[inline]
+    pub fn is_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 is_write_vectored(&self) -> bool {
+        true
+    }
+
     pub fn set_timeout(&self, dur: Option<Duration>, kind: c_int) -> io::Result<()> {
         let timeout = match dur {
             Some(dur) => {
diff --git a/src/libstd/sys/windows/pipe.rs b/src/libstd/sys/windows/pipe.rs
index 992e634dea5..104a8db4659 100644
--- a/src/libstd/sys/windows/pipe.rs
+++ b/src/libstd/sys/windows/pipe.rs
@@ -182,6 +182,11 @@ impl AnonPipe {
         self.inner.read_vectored(bufs)
     }
 
+    #[inline]
+    pub fn is_read_vectored(&self) -> bool {
+        self.inner.is_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 is_write_vectored(&self) -> bool {
+        self.inner.is_write_vectored()
+    }
 }
 
 pub fn read2(p1: AnonPipe, v1: &mut Vec<u8>, p2: AnonPipe, v2: &mut Vec<u8>) -> io::Result<()> {