Skip to content

Commit 6f6a2b6

Browse files
authored
Rollup merge of rust-lang#108326 - tmiasko:read-buf, r=thomcc
Implement read_buf for a few more types Implement read_buf for TcpStream, Stdin, StdinLock, ChildStdout, ChildStderr (and internally for AnonPipe, Handle, Socket), so that it skips buffer initialization. The other provided methods like read_to_string and read_to_end are implemented in terms of read_buf and so benefit from the optimization as well. This commit also implements read_vectored and is_read_vectored where applicable.
2 parents 0622508 + 8ffb6af commit 6f6a2b6

File tree

15 files changed

+205
-25
lines changed

15 files changed

+205
-25
lines changed

library/std/src/fs/tests.rs

+19-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@ use crate::io::prelude::*;
22

33
use crate::env;
44
use crate::fs::{self, File, OpenOptions};
5-
use crate::io::{ErrorKind, SeekFrom};
5+
use crate::io::{BorrowedBuf, ErrorKind, SeekFrom};
6+
use crate::mem::MaybeUninit;
67
use crate::path::Path;
78
use crate::str;
89
use crate::sync::Arc;
@@ -401,6 +402,23 @@ fn file_test_io_seek_read_write() {
401402
check!(fs::remove_file(&filename));
402403
}
403404

405+
#[test]
406+
fn file_test_read_buf() {
407+
let tmpdir = tmpdir();
408+
let filename = &tmpdir.join("test");
409+
check!(fs::write(filename, &[1, 2, 3, 4]));
410+
411+
let mut buf: [MaybeUninit<u8>; 128] = MaybeUninit::uninit_array();
412+
let mut buf = BorrowedBuf::from(buf.as_mut_slice());
413+
let mut file = check!(File::open(filename));
414+
check!(file.read_buf(buf.unfilled()));
415+
assert_eq!(buf.filled(), &[1, 2, 3, 4]);
416+
// File::read_buf should omit buffer initialization.
417+
assert_eq!(buf.init_len(), 4);
418+
419+
check!(fs::remove_file(filename));
420+
}
421+
404422
#[test]
405423
fn file_test_stat_is_correct_on_is_file() {
406424
let tmpdir = tmpdir();

library/std/src/io/stdio.rs

+12-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use crate::io::prelude::*;
88
use crate::cell::{Cell, RefCell};
99
use crate::fmt;
1010
use crate::fs::File;
11-
use crate::io::{self, BufReader, IoSlice, IoSliceMut, LineWriter, Lines};
11+
use crate::io::{self, BorrowedCursor, BufReader, IoSlice, IoSliceMut, LineWriter, Lines};
1212
use crate::sync::atomic::{AtomicBool, Ordering};
1313
use crate::sync::{Arc, Mutex, MutexGuard, OnceLock, ReentrantMutex, ReentrantMutexGuard};
1414
use crate::sys::stdio;
@@ -97,6 +97,10 @@ impl Read for StdinRaw {
9797
handle_ebadf(self.0.read(buf), 0)
9898
}
9999

100+
fn read_buf(&mut self, buf: BorrowedCursor<'_>) -> io::Result<()> {
101+
handle_ebadf(self.0.read_buf(buf), ())
102+
}
103+
100104
fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
101105
handle_ebadf(self.0.read_vectored(bufs), 0)
102106
}
@@ -418,6 +422,9 @@ impl Read for Stdin {
418422
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
419423
self.lock().read(buf)
420424
}
425+
fn read_buf(&mut self, buf: BorrowedCursor<'_>) -> io::Result<()> {
426+
self.lock().read_buf(buf)
427+
}
421428
fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
422429
self.lock().read_vectored(bufs)
423430
}
@@ -450,6 +457,10 @@ impl Read for StdinLock<'_> {
450457
self.inner.read(buf)
451458
}
452459

460+
fn read_buf(&mut self, buf: BorrowedCursor<'_>) -> io::Result<()> {
461+
self.inner.read_buf(buf)
462+
}
463+
453464
fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
454465
self.inner.read_vectored(bufs)
455466
}

library/std/src/net/tcp.rs

+9-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ mod tests;
66
use crate::io::prelude::*;
77

88
use crate::fmt;
9-
use crate::io::{self, IoSlice, IoSliceMut};
9+
use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut};
1010
use crate::iter::FusedIterator;
1111
use crate::net::{Shutdown, SocketAddr, ToSocketAddrs};
1212
use crate::sys_common::net as net_imp;
@@ -619,6 +619,10 @@ impl Read for TcpStream {
619619
self.0.read(buf)
620620
}
621621

622+
fn read_buf(&mut self, buf: BorrowedCursor<'_>) -> io::Result<()> {
623+
self.0.read_buf(buf)
624+
}
625+
622626
fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
623627
self.0.read_vectored(bufs)
624628
}
@@ -653,6 +657,10 @@ impl Read for &TcpStream {
653657
self.0.read(buf)
654658
}
655659

660+
fn read_buf(&mut self, buf: BorrowedCursor<'_>) -> io::Result<()> {
661+
self.0.read_buf(buf)
662+
}
663+
656664
fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
657665
self.0.read_vectored(bufs)
658666
}

library/std/src/net/tcp/tests.rs

+23-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use crate::fmt;
22
use crate::io::prelude::*;
3-
use crate::io::{ErrorKind, IoSlice, IoSliceMut};
3+
use crate::io::{BorrowedBuf, ErrorKind, IoSlice, IoSliceMut};
4+
use crate::mem::MaybeUninit;
45
use crate::net::test::{next_test_ip4, next_test_ip6};
56
use crate::net::*;
67
use crate::sync::mpsc::channel;
@@ -279,6 +280,27 @@ fn partial_read() {
279280
})
280281
}
281282

283+
#[test]
284+
fn read_buf() {
285+
each_ip(&mut |addr| {
286+
let srv = t!(TcpListener::bind(&addr));
287+
let t = thread::spawn(move || {
288+
let mut s = t!(TcpStream::connect(&addr));
289+
s.write_all(&[1, 2, 3, 4]).unwrap();
290+
});
291+
292+
let mut s = t!(srv.accept()).0;
293+
let mut buf: [MaybeUninit<u8>; 128] = MaybeUninit::uninit_array();
294+
let mut buf = BorrowedBuf::from(buf.as_mut_slice());
295+
t!(s.read_buf(buf.unfilled()));
296+
assert_eq!(buf.filled(), &[1, 2, 3, 4]);
297+
// TcpStream::read_buf should omit buffer initialization.
298+
assert_eq!(buf.init_len(), 4);
299+
300+
t.join().ok().expect("thread panicked");
301+
})
302+
}
303+
282304
#[test]
283305
fn read_vectored() {
284306
each_ip(&mut |addr| {

library/std/src/process.rs

+9-1
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ use crate::convert::Infallible;
110110
use crate::ffi::OsStr;
111111
use crate::fmt;
112112
use crate::fs;
113-
use crate::io::{self, IoSlice, IoSliceMut};
113+
use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut};
114114
use crate::num::NonZeroI32;
115115
use crate::path::Path;
116116
use crate::str;
@@ -354,6 +354,10 @@ impl Read for ChildStdout {
354354
self.inner.read(buf)
355355
}
356356

357+
fn read_buf(&mut self, buf: BorrowedCursor<'_>) -> io::Result<()> {
358+
self.inner.read_buf(buf)
359+
}
360+
357361
fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
358362
self.inner.read_vectored(bufs)
359363
}
@@ -419,6 +423,10 @@ impl Read for ChildStderr {
419423
self.inner.read(buf)
420424
}
421425

426+
fn read_buf(&mut self, buf: BorrowedCursor<'_>) -> io::Result<()> {
427+
self.inner.read_buf(buf)
428+
}
429+
422430
fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
423431
self.inner.read_vectored(bufs)
424432
}

library/std/src/process/tests.rs

+30-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
use crate::io::prelude::*;
22

33
use super::{Command, Output, Stdio};
4-
use crate::io::ErrorKind;
4+
use crate::io::{BorrowedBuf, ErrorKind};
5+
use crate::mem::MaybeUninit;
56
use crate::str;
67

78
fn known_command() -> Command {
@@ -119,6 +120,34 @@ fn stdin_works() {
119120
assert_eq!(out, "foobar\n");
120121
}
121122

123+
#[test]
124+
#[cfg_attr(any(target_os = "vxworks"), ignore)]
125+
fn child_stdout_read_buf() {
126+
let mut cmd = shell_cmd();
127+
if cfg!(target_os = "windows") {
128+
cmd.arg("/C").arg("echo abc");
129+
} else {
130+
cmd.arg("-c").arg("echo abc");
131+
};
132+
cmd.stdin(Stdio::null());
133+
cmd.stdout(Stdio::piped());
134+
let child = cmd.spawn().unwrap();
135+
136+
let mut stdout = child.stdout.unwrap();
137+
let mut buf: [MaybeUninit<u8>; 128] = MaybeUninit::uninit_array();
138+
let mut buf = BorrowedBuf::from(buf.as_mut_slice());
139+
stdout.read_buf(buf.unfilled()).unwrap();
140+
141+
// ChildStdout::read_buf should omit buffer initialization.
142+
if cfg!(target_os = "windows") {
143+
assert_eq!(buf.filled(), b"abc\r\n");
144+
assert_eq!(buf.init_len(), 5);
145+
} else {
146+
assert_eq!(buf.filled(), b"abc\n");
147+
assert_eq!(buf.init_len(), 4);
148+
};
149+
}
150+
122151
#[test]
123152
#[cfg_attr(any(target_os = "vxworks"), ignore)]
124153
fn test_process_status() {

library/std/src/sys/unix/fd.rs

+9
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,15 @@ impl<'a> Read for &'a FileDesc {
283283
fn read_buf(&mut self, cursor: BorrowedCursor<'_>) -> io::Result<()> {
284284
(**self).read_buf(cursor)
285285
}
286+
287+
fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
288+
(**self).read_vectored(bufs)
289+
}
290+
291+
#[inline]
292+
fn is_read_vectored(&self) -> bool {
293+
(**self).is_read_vectored()
294+
}
286295
}
287296

288297
impl AsInner<OwnedFd> for FileDesc {

library/std/src/sys/unix/net.rs

+22-6
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use crate::cmp;
22
use crate::ffi::CStr;
3-
use crate::io::{self, IoSlice, IoSliceMut};
3+
use crate::io::{self, BorrowedBuf, BorrowedCursor, IoSlice, IoSliceMut};
44
use crate::mem;
55
use crate::net::{Shutdown, SocketAddr};
66
use crate::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, RawFd};
@@ -240,19 +240,35 @@ impl Socket {
240240
self.0.duplicate().map(Socket)
241241
}
242242

243-
fn recv_with_flags(&self, buf: &mut [u8], flags: c_int) -> io::Result<usize> {
243+
fn recv_with_flags(&self, mut buf: BorrowedCursor<'_>, flags: c_int) -> io::Result<()> {
244244
let ret = cvt(unsafe {
245-
libc::recv(self.as_raw_fd(), buf.as_mut_ptr() as *mut c_void, buf.len(), flags)
245+
libc::recv(
246+
self.as_raw_fd(),
247+
buf.as_mut().as_mut_ptr() as *mut c_void,
248+
buf.capacity(),
249+
flags,
250+
)
246251
})?;
247-
Ok(ret as usize)
252+
unsafe {
253+
buf.advance(ret as usize);
254+
}
255+
Ok(())
248256
}
249257

250258
pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
251-
self.recv_with_flags(buf, 0)
259+
let mut buf = BorrowedBuf::from(buf);
260+
self.recv_with_flags(buf.unfilled(), 0)?;
261+
Ok(buf.len())
252262
}
253263

254264
pub fn peek(&self, buf: &mut [u8]) -> io::Result<usize> {
255-
self.recv_with_flags(buf, MSG_PEEK)
265+
let mut buf = BorrowedBuf::from(buf);
266+
self.recv_with_flags(buf.unfilled(), MSG_PEEK)?;
267+
Ok(buf.len())
268+
}
269+
270+
pub fn read_buf(&self, buf: BorrowedCursor<'_>) -> io::Result<()> {
271+
self.recv_with_flags(buf, 0)
256272
}
257273

258274
pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {

library/std/src/sys/unix/pipe.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::io::{self, IoSlice, IoSliceMut};
1+
use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut};
22
use crate::mem;
33
use crate::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, RawFd};
44
use crate::sys::fd::FileDesc;
@@ -49,6 +49,10 @@ impl AnonPipe {
4949
self.0.read(buf)
5050
}
5151

52+
pub fn read_buf(&self, buf: BorrowedCursor<'_>) -> io::Result<()> {
53+
self.0.read_buf(buf)
54+
}
55+
5256
pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
5357
self.0.read_vectored(bufs)
5458
}

library/std/src/sys/unix/stdio.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::io::{self, IoSlice, IoSliceMut};
1+
use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut};
22
use crate::mem::ManuallyDrop;
33
use crate::os::unix::io::FromRawFd;
44
use crate::sys::fd::FileDesc;
@@ -18,6 +18,10 @@ impl io::Read for Stdin {
1818
unsafe { ManuallyDrop::new(FileDesc::from_raw_fd(libc::STDIN_FILENO)).read(buf) }
1919
}
2020

21+
fn read_buf(&mut self, buf: BorrowedCursor<'_>) -> io::Result<()> {
22+
unsafe { ManuallyDrop::new(FileDesc::from_raw_fd(libc::STDIN_FILENO)).read_buf(buf) }
23+
}
24+
2125
fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
2226
unsafe { ManuallyDrop::new(FileDesc::from_raw_fd(libc::STDIN_FILENO)).read_vectored(bufs) }
2327
}

library/std/src/sys/unsupported/pipe.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::io::{self, IoSlice, IoSliceMut};
1+
use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut};
22

33
pub struct AnonPipe(!);
44

@@ -7,6 +7,10 @@ impl AnonPipe {
77
self.0
88
}
99

10+
pub fn read_buf(&self, _buf: BorrowedCursor<'_>) -> io::Result<()> {
11+
self.0
12+
}
13+
1014
pub fn read_vectored(&self, _bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
1115
self.0
1216
}

library/std/src/sys/windows/handle.rs

+9
Original file line numberDiff line numberDiff line change
@@ -327,7 +327,16 @@ impl<'a> Read for &'a Handle {
327327
(**self).read(buf)
328328
}
329329

330+
fn read_buf(&mut self, buf: BorrowedCursor<'_>) -> io::Result<()> {
331+
(**self).read_buf(buf)
332+
}
333+
330334
fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
331335
(**self).read_vectored(bufs)
332336
}
337+
338+
#[inline]
339+
fn is_read_vectored(&self) -> bool {
340+
(**self).is_read_vectored()
341+
}
333342
}

0 commit comments

Comments
 (0)