diff options
| author | bors <bors@rust-lang.org> | 2019-02-26 02:48:13 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2019-02-26 02:48:13 +0000 |
| commit | fb162e69449b423c5aed0d9c39f6c046fa300c30 (patch) | |
| tree | 5d4292df6a7db1b62137c4472f1e65317d3919e1 /src/libstd/net | |
| parent | 55c173c8ae8bda689fd609f391ee5e2e5b1b6d44 (diff) | |
| parent | 4785c748f2190440fb3f90b5319f121f2d31e0e4 (diff) | |
Auto merge of #58357 - sfackler:vectored-io, r=alexcrichton
Add vectored read and write support This functionality has lived for a while in the tokio ecosystem, where it can improve performance by minimizing copies. r? @alexcrichton
Diffstat (limited to 'src/libstd/net')
| -rw-r--r-- | src/libstd/net/tcp.rs | 69 |
1 files changed, 67 insertions, 2 deletions
diff --git a/src/libstd/net/tcp.rs b/src/libstd/net/tcp.rs index 51bd76ae436..3aa29f83b29 100644 --- a/src/libstd/net/tcp.rs +++ b/src/libstd/net/tcp.rs @@ -1,7 +1,7 @@ use io::prelude::*; use fmt; -use io::{self, Initializer}; +use io::{self, Initializer, IoVec, IoVecMut}; use net::{ToSocketAddrs, SocketAddr, Shutdown}; use sys_common::net as net_imp; use sys_common::{AsInner, FromInner, IntoInner}; @@ -569,6 +569,10 @@ impl TcpStream { impl Read for TcpStream { fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { self.0.read(buf) } + fn read_vectored(&mut self, bufs: &mut [IoVecMut<'_>]) -> io::Result<usize> { + self.0.read_vectored(bufs) + } + #[inline] unsafe fn initializer(&self) -> Initializer { Initializer::nop() @@ -577,12 +581,21 @@ impl Read for TcpStream { #[stable(feature = "rust1", since = "1.0.0")] impl Write for TcpStream { fn write(&mut self, buf: &[u8]) -> io::Result<usize> { self.0.write(buf) } + + fn write_vectored(&mut self, bufs: &[IoVec<'_>]) -> io::Result<usize> { + self.0.write_vectored(bufs) + } + fn flush(&mut self) -> io::Result<()> { Ok(()) } } #[stable(feature = "rust1", since = "1.0.0")] impl Read for &TcpStream { fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { self.0.read(buf) } + fn read_vectored(&mut self, bufs: &mut [IoVecMut<'_>]) -> io::Result<usize> { + self.0.read_vectored(bufs) + } + #[inline] unsafe fn initializer(&self) -> Initializer { Initializer::nop() @@ -591,6 +604,11 @@ impl Read for &TcpStream { #[stable(feature = "rust1", since = "1.0.0")] impl Write for &TcpStream { fn write(&mut self, buf: &[u8]) -> io::Result<usize> { self.0.write(buf) } + + fn write_vectored(&mut self, bufs: &[IoVec<'_>]) -> io::Result<usize> { + self.0.write_vectored(bufs) + } + fn flush(&mut self) -> io::Result<()> { Ok(()) } } @@ -911,7 +929,7 @@ impl fmt::Debug for TcpListener { #[cfg(all(test, not(any(target_os = "cloudabi", target_os = "emscripten"))))] mod tests { - use io::ErrorKind; + use io::{ErrorKind, IoVec, IoVecMut}; use io::prelude::*; use net::*; use net::test::{next_test_ip4, next_test_ip6}; @@ -1185,6 +1203,53 @@ mod tests { } #[test] + fn read_vectored() { + each_ip(&mut |addr| { + let srv = t!(TcpListener::bind(&addr)); + let mut s1 = t!(TcpStream::connect(&addr)); + let mut s2 = t!(srv.accept()).0; + + let len = s1.write(&[10, 11, 12]).unwrap(); + assert_eq!(len, 3); + + let mut a = []; + let mut b = [0]; + let mut c = [0; 3]; + let len = t!(s2.read_vectored( + &mut [IoVecMut::new(&mut a), IoVecMut::new(&mut b), IoVecMut::new(&mut c)], + )); + assert!(len > 0); + assert_eq!(b, [10]); + // some implementations don't support readv, so we may only fill the first buffer + assert!(len == 1 || c == [11, 12, 0]); + }) + } + + #[test] + fn write_vectored() { + each_ip(&mut |addr| { + let srv = t!(TcpListener::bind(&addr)); + let mut s1 = t!(TcpStream::connect(&addr)); + let mut s2 = t!(srv.accept()).0; + + let a = []; + let b = [10]; + let c = [11, 12]; + t!(s1.write_vectored(&[IoVec::new(&a), IoVec::new(&b), IoVec::new(&c)])); + + let mut buf = [0; 4]; + let len = t!(s2.read(&mut buf)); + // some implementations don't support writev, so we may only write the first buffer + if len == 1 { + assert_eq!(buf, [10, 0, 0, 0]); + } else { + assert_eq!(len, 3); + assert_eq!(buf, [10, 11, 12, 0]); + } + }) + } + + #[test] fn double_bind() { each_ip(&mut |addr| { let listener1 = t!(TcpListener::bind(&addr)); |
