1
Fork 0

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

View file

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

View file

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

View file

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

View file

@ -580,6 +580,19 @@ pub trait Read {
default_read_vectored(|b| self.read(b), bufs) 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 /// Determines if this `Read`er can work with buffers of uninitialized
/// memory. /// memory.
/// ///
@ -1304,6 +1317,19 @@ pub trait Write {
default_write_vectored(|b| self.write(b), bufs) 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 /// Flush this output stream, ensuring that all intermediately buffered
/// contents reach their destination. /// contents reach their destination.
/// ///

View file

@ -87,6 +87,11 @@ impl Read for StdinRaw {
self.0.read_vectored(bufs) self.0.read_vectored(bufs)
} }
#[inline]
fn can_read_vectored(&self) -> bool {
self.0.can_read_vectored()
}
#[inline] #[inline]
unsafe fn initializer(&self) -> Initializer { unsafe fn initializer(&self) -> Initializer {
Initializer::nop() Initializer::nop()
@ -101,6 +106,11 @@ impl Write for StdoutRaw {
self.0.write_vectored(bufs) self.0.write_vectored(bufs)
} }
#[inline]
fn can_write_vectored(&self) -> bool {
self.0.can_write_vectored()
}
fn flush(&mut self) -> io::Result<()> { fn flush(&mut self) -> io::Result<()> {
self.0.flush() self.0.flush()
} }
@ -114,6 +124,11 @@ impl Write for StderrRaw {
self.0.write_vectored(bufs) self.0.write_vectored(bufs)
} }
#[inline]
fn can_write_vectored(&self) -> bool {
self.0.can_write_vectored()
}
fn flush(&mut self) -> io::Result<()> { fn flush(&mut self) -> io::Result<()> {
self.0.flush() 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<()> { fn flush(&mut self) -> io::Result<()> {
match *self { match *self {
Maybe::Real(ref mut w) => handle_ebadf(w.flush(), ()), 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), 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> { 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) self.lock().read_vectored(bufs)
} }
#[inline] #[inline]
fn can_read_vectored(&self) -> bool {
self.lock().can_read_vectored()
}
#[inline]
unsafe fn initializer(&self) -> Initializer { unsafe fn initializer(&self) -> Initializer {
Initializer::nop() Initializer::nop()
} }
@ -376,6 +411,11 @@ impl Read for StdinLock<'_> {
self.inner.read_vectored(bufs) self.inner.read_vectored(bufs)
} }
#[inline]
fn can_read_vectored(&self) -> bool {
self.inner.can_read_vectored()
}
#[inline] #[inline]
unsafe fn initializer(&self) -> Initializer { unsafe fn initializer(&self) -> Initializer {
Initializer::nop() Initializer::nop()
@ -543,6 +583,10 @@ impl Write for Stdout {
fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> { fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
self.lock().write_vectored(bufs) self.lock().write_vectored(bufs)
} }
#[inline]
fn can_write_vectored(&self) -> bool {
self.lock().can_write_vectored()
}
fn flush(&mut self) -> io::Result<()> { fn flush(&mut self) -> io::Result<()> {
self.lock().flush() self.lock().flush()
} }
@ -561,6 +605,10 @@ impl Write for StdoutLock<'_> {
fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> { fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
self.inner.borrow_mut().write_vectored(bufs) 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<()> { fn flush(&mut self) -> io::Result<()> {
self.inner.borrow_mut().flush() self.inner.borrow_mut().flush()
} }
@ -709,6 +757,10 @@ impl Write for Stderr {
fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> { fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
self.lock().write_vectored(bufs) self.lock().write_vectored(bufs)
} }
#[inline]
fn can_write_vectored(&self) -> bool {
self.lock().can_write_vectored()
}
fn flush(&mut self) -> io::Result<()> { fn flush(&mut self) -> io::Result<()> {
self.lock().flush() self.lock().flush()
} }
@ -727,6 +779,10 @@ impl Write for StderrLock<'_> {
fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> { fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
self.inner.borrow_mut().write_vectored(bufs) 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<()> { fn flush(&mut self) -> io::Result<()> {
self.inner.borrow_mut().flush() self.inner.borrow_mut().flush()
} }

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -149,6 +149,11 @@ impl TcpStream {
self.inner.inner.read_vectored(bufs) 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> { pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
self.inner.inner.write(buf) self.inner.inner.write(buf)
} }
@ -157,6 +162,11 @@ impl TcpStream {
self.inner.inner.write_vectored(bufs) 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> { pub fn peer_addr(&self) -> io::Result<SocketAddr> {
addr_to_sockaddr(&self.peer_addr) addr_to_sockaddr(&self.peer_addr)
} }

View file

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

View file

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

View file

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

View file

@ -828,6 +828,11 @@ impl File {
self.0.read_vectored(bufs) 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> { pub fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<usize> {
self.0.read_at(buf, offset) self.0.read_at(buf, offset)
} }
@ -840,6 +845,11 @@ impl File {
self.0.write_vectored(bufs) 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> { pub fn write_at(&self, buf: &[u8], offset: u64) -> io::Result<usize> {
self.0.write_at(buf, offset) self.0.write_at(buf, offset)
} }

View file

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

View file

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

View file

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

View file

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

View file

@ -54,6 +54,11 @@ impl FileDesc {
Ok(ret as usize) 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> { pub fn read_to_end(&self, buf: &mut Vec<u8>) -> io::Result<usize> {
let mut me = self; let mut me = self;
(&mut me).read_to_end(buf) (&mut me).read_to_end(buf)
@ -99,6 +104,11 @@ impl FileDesc {
Ok(ret as usize) 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> { pub fn write_at(&self, buf: &[u8], offset: u64) -> io::Result<usize> {
unsafe fn cvt_pwrite( unsafe fn cvt_pwrite(
fd: c_int, fd: c_int,

View file

@ -351,6 +351,11 @@ impl File {
self.0.read_vectored(bufs) 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> { pub fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<usize> {
self.0.read_at(buf, offset) self.0.read_at(buf, offset)
} }
@ -363,6 +368,11 @@ impl File {
self.0.write_vectored(bufs) 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> { pub fn write_at(&self, buf: &[u8], offset: u64) -> io::Result<usize> {
self.0.write_at(buf, offset) self.0.write_at(buf, offset)
} }

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -19,6 +19,11 @@ impl Stdin {
ManuallyDrop::new(unsafe { WasiFd::from_raw(self.as_raw_fd()) }).read(data) 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 { pub fn as_raw_fd(&self) -> u32 {
0 0
} }
@ -37,6 +42,11 @@ impl Stdout {
ManuallyDrop::new(unsafe { WasiFd::from_raw(self.as_raw_fd()) }).write(data) 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<()> { pub fn flush(&self) -> io::Result<()> {
Ok(()) Ok(())
} }
@ -59,6 +69,11 @@ impl Stderr {
ManuallyDrop::new(unsafe { WasiFd::from_raw(self.as_raw_fd()) }).write(data) 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<()> { pub fn flush(&self) -> io::Result<()> {
Ok(()) Ok(())
} }

View file

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

View file

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

View file

@ -409,6 +409,11 @@ impl File {
self.handle.read_vectored(bufs) 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> { pub fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<usize> {
self.handle.read_at(buf, offset) self.handle.read_at(buf, offset)
} }
@ -421,6 +426,11 @@ impl File {
self.handle.write_vectored(bufs) 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> { pub fn write_at(&self, buf: &[u8], offset: u64) -> io::Result<usize> {
self.handle.write_at(buf, offset) self.handle.write_at(buf, offset)
} }

View file

@ -92,6 +92,11 @@ impl RawHandle {
crate::io::default_read_vectored(|buf| self.read(buf), bufs) 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> { pub fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<usize> {
let mut read = 0; let mut read = 0;
let len = cmp::min(buf.len(), <c::DWORD>::max_value() as usize) as c::DWORD; 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) 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> { pub fn write_at(&self, buf: &[u8], offset: u64) -> io::Result<usize> {
let mut written = 0; let mut written = 0;
let len = cmp::min(buf.len(), <c::DWORD>::max_value() as usize) as c::DWORD; 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> { pub fn peek(&self, buf: &mut [u8]) -> io::Result<usize> {
self.recv_with_flags(buf, c::MSG_PEEK) self.recv_with_flags(buf, c::MSG_PEEK)
} }
@ -324,6 +329,11 @@ impl Socket {
Ok(nwritten as usize) 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<()> { pub fn set_timeout(&self, dur: Option<Duration>, kind: c_int) -> io::Result<()> {
let timeout = match dur { let timeout = match dur {
Some(dur) => { Some(dur) => {

View file

@ -182,6 +182,11 @@ impl AnonPipe {
self.inner.read_vectored(bufs) 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> { pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
self.inner.write(buf) self.inner.write(buf)
} }
@ -189,6 +194,11 @@ impl AnonPipe {
pub fn write_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result<usize> { pub fn write_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
self.inner.write_vectored(bufs) 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<()> { 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) 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> { 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 len = cmp::min(buf.len(), <wrlen_t>::max_value() as usize) as wrlen_t;
let ret = cvt(unsafe { let ret = cvt(unsafe {
@ -277,6 +282,11 @@ impl TcpStream {
self.inner.write_vectored(bufs) 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> { pub fn peer_addr(&self) -> io::Result<SocketAddr> {
sockname(|buf, len| unsafe { c::getpeername(*self.inner.as_inner(), buf, len) }) sockname(|buf, len| unsafe { c::getpeername(*self.inner.as_inner(), buf, len) })
} }