Skip to content

Commit 5a97090

Browse files
committed
more efficent File::read_buf impl for windows and unix
1 parent 146b396 commit 5a97090

File tree

10 files changed

+93
-12
lines changed

10 files changed

+93
-12
lines changed

library/std/src/fs.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ mod tests;
1313

1414
use crate::ffi::OsString;
1515
use crate::fmt;
16-
use crate::io::{self, IoSlice, IoSliceMut, Read, Seek, SeekFrom, Write};
16+
use crate::io::{self, IoSlice, IoSliceMut, Read, ReadBuf, Seek, SeekFrom, Write};
1717
use crate::path::{Path, PathBuf};
1818
use crate::sys::fs as fs_imp;
1919
use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner};
@@ -624,6 +624,10 @@ impl Read for File {
624624
self.inner.read_vectored(bufs)
625625
}
626626

627+
fn read_buf(&mut self, buf: &mut ReadBuf<'_>) -> io::Result<()> {
628+
self.inner.read_buf(buf)
629+
}
630+
627631
#[inline]
628632
fn is_read_vectored(&self) -> bool {
629633
self.inner.is_read_vectored()

library/std/src/io/mod.rs

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -448,6 +448,15 @@ pub(crate) fn default_read_exact<R: Read + ?Sized>(this: &mut R, mut buf: &mut [
448448
}
449449
}
450450

451+
pub(crate) fn default_read_buf<F>(read: F, buf: &mut ReadBuf<'_>) -> Result<()>
452+
where
453+
F: FnOnce(&mut [u8]) -> Result<usize>,
454+
{
455+
let n = read(buf.initialize_unfilled())?;
456+
buf.add_filled(n);
457+
Ok(())
458+
}
459+
451460
/// The `Read` trait allows for reading bytes from a source.
452461
///
453462
/// Implementors of the `Read` trait are called 'readers'.
@@ -787,9 +796,7 @@ pub trait Read {
787796
/// The default implementation delegates to `read`.
788797
#[unstable(feature = "read_buf", issue = "78485")]
789798
fn read_buf(&mut self, buf: &mut ReadBuf<'_>) -> Result<()> {
790-
let n = self.read(buf.initialize_unfilled())?;
791-
buf.add_filled(n);
792-
Ok(())
799+
default_read_buf(|b| self.read(b), buf)
793800
}
794801

795802
/// Read the exact number of bytes required to fill `buf`.

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#![unstable(reason = "not public", issue = "none", feature = "fd")]
22

3-
use crate::io::{self, Read};
3+
use crate::io::{self, Read, ReadBuf};
44
use crate::mem;
55
use crate::sys::cvt;
66
use crate::sys::hermit::abi;

library/std/src/sys/hermit/fs.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use crate::ffi::{CStr, CString, OsString};
22
use crate::fmt;
33
use crate::hash::{Hash, Hasher};
44
use crate::io::{self, Error, ErrorKind};
5-
use crate::io::{IoSlice, IoSliceMut, SeekFrom};
5+
use crate::io::{IoSlice, IoSliceMut, ReadBuf, SeekFrom};
66
use crate::os::unix::ffi::OsStrExt;
77
use crate::path::{Path, PathBuf};
88
use crate::sys::cvt;
@@ -312,6 +312,10 @@ impl File {
312312
false
313313
}
314314

315+
pub fn read_buf(&self, buf: &mut ReadBuf<'_>) -> io::Result<()> {
316+
crate::io::default_read_buf(|buf| self.read(buf), buf)
317+
}
318+
315319
pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
316320
self.0.write(buf)
317321
}

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

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
mod tests;
55

66
use crate::cmp;
7-
use crate::io::{self, IoSlice, IoSliceMut, Read};
7+
use crate::io::{self, IoSlice, IoSliceMut, Read, ReadBuf};
88
use crate::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd};
99
use crate::sys::cvt;
1010
use crate::sys_common::{AsInner, FromInner, IntoInner};
@@ -127,6 +127,23 @@ impl FileDesc {
127127
}
128128
}
129129

130+
pub fn read_buf(&self, buf: &mut ReadBuf<'_>) -> io::Result<()> {
131+
let ret = cvt(unsafe {
132+
libc::read(
133+
self.as_raw_fd(),
134+
buf.unfilled_mut().as_mut_ptr() as *mut c_void,
135+
cmp::min(buf.remaining(), READ_LIMIT),
136+
)
137+
})?;
138+
139+
// Safety: `ret` bytes were written to the initialized portion of the buffer
140+
unsafe {
141+
buf.assume_init(ret as usize);
142+
}
143+
buf.add_filled(ret as usize);
144+
Ok(())
145+
}
146+
130147
pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
131148
let ret = cvt(unsafe {
132149
libc::write(

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

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use crate::os::unix::prelude::*;
22

33
use crate::ffi::{CStr, CString, OsStr, OsString};
44
use crate::fmt;
5-
use crate::io::{self, Error, IoSlice, IoSliceMut, SeekFrom};
5+
use crate::io::{self, Error, IoSlice, IoSliceMut, ReadBuf, SeekFrom};
66
use crate::mem;
77
use crate::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd};
88
use crate::path::{Path, PathBuf};
@@ -864,6 +864,10 @@ impl File {
864864
self.0.read_at(buf, offset)
865865
}
866866

867+
pub fn read_buf(&self, buf: &mut ReadBuf<'_>) -> io::Result<()> {
868+
self.0.read_buf(buf)
869+
}
870+
867871
pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
868872
self.0.write(buf)
869873
}

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

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use crate::ffi::OsString;
22
use crate::fmt;
33
use crate::hash::{Hash, Hasher};
4-
use crate::io::{self, IoSlice, IoSliceMut, SeekFrom};
4+
use crate::io::{self, IoSlice, IoSliceMut, ReadBuf, SeekFrom};
55
use crate::path::{Path, PathBuf};
66
use crate::sys::time::SystemTime;
77
use crate::sys::unsupported;
@@ -206,6 +206,10 @@ impl File {
206206
self.0
207207
}
208208

209+
pub fn read_buf(&self, buf: &mut ReadBuf<'_>) -> io::Result<()> {
210+
self.0
211+
}
212+
209213
pub fn write(&self, _buf: &[u8]) -> io::Result<usize> {
210214
self.0
211215
}

library/std/src/sys/wasi/fs.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
use super::fd::WasiFd;
44
use crate::ffi::{CStr, CString, OsStr, OsString};
55
use crate::fmt;
6-
use crate::io::{self, IoSlice, IoSliceMut, SeekFrom};
6+
use crate::io::{self, IoSlice, IoSliceMut, ReadBuf, SeekFrom};
77
use crate::iter;
88
use crate::mem::{self, ManuallyDrop};
99
use crate::os::raw::c_int;
@@ -411,6 +411,10 @@ impl File {
411411
true
412412
}
413413

414+
pub fn read_buf(&self, buf: &mut ReadBuf<'_>) -> io::Result<()> {
415+
crate::io::default_read_buf(|buf| self.read(buf), buf)
416+
}
417+
414418
pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
415419
self.write_vectored(&[IoSlice::new(buf)])
416420
}

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

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use crate::os::windows::prelude::*;
22

33
use crate::ffi::OsString;
44
use crate::fmt;
5-
use crate::io::{self, Error, IoSlice, IoSliceMut, SeekFrom};
5+
use crate::io::{self, Error, IoSlice, IoSliceMut, ReadBuf, SeekFrom};
66
use crate::mem;
77
use crate::os::windows::io::{AsHandle, BorrowedHandle};
88
use crate::path::{Path, PathBuf};
@@ -420,6 +420,10 @@ impl File {
420420
self.handle.read_at(buf, offset)
421421
}
422422

423+
pub fn read_buf(&self, buf: &mut ReadBuf<'_>) -> io::Result<()> {
424+
self.handle.read_buf(buf)
425+
}
426+
423427
pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
424428
self.handle.write(buf)
425429
}

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

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#![unstable(issue = "none", feature = "windows_handle")]
22

33
use crate::cmp;
4-
use crate::io::{self, ErrorKind, IoSlice, IoSliceMut, Read};
4+
use crate::io::{self, ErrorKind, IoSlice, IoSliceMut, Read, ReadBuf};
55
use crate::mem;
66
use crate::os::windows::io::{
77
AsHandle, AsRawHandle, BorrowedHandle, FromRawHandle, IntoRawHandle, OwnedHandle, RawHandle,
@@ -130,6 +130,39 @@ impl Handle {
130130
}
131131
}
132132

133+
pub fn read_buf(&self, buf: &mut ReadBuf<'_>) -> io::Result<()> {
134+
let mut read = 0;
135+
let len = cmp::min(buf.remaining(), <c::DWORD>::MAX as usize) as c::DWORD;
136+
let res = cvt(unsafe {
137+
c::ReadFile(
138+
self.as_raw_handle(),
139+
buf.unfilled_mut().as_mut_ptr() as c::LPVOID,
140+
len,
141+
&mut read,
142+
ptr::null_mut(),
143+
)
144+
});
145+
146+
match res {
147+
Ok(_) => {
148+
// Safety: `read` bytes were written to the initialized portion of the buffer
149+
unsafe {
150+
buf.assume_init(read as usize);
151+
}
152+
buf.add_filled(read as usize);
153+
Ok(())
154+
}
155+
156+
// The special treatment of BrokenPipe is to deal with Windows
157+
// pipe semantics, which yields this error when *reading* from
158+
// a pipe after the other end has closed; we interpret that as
159+
// EOF on the pipe.
160+
Err(ref e) if e.kind() == ErrorKind::BrokenPipe => Ok(()),
161+
162+
Err(e) => Err(e),
163+
}
164+
}
165+
133166
pub unsafe fn read_overlapped(
134167
&self,
135168
buf: &mut [u8],

0 commit comments

Comments
 (0)