Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 2ccb45f

Browse files
committed
Add read_buf equivalents for positioned reads
Adds the following items under the `read_buf` (#78485) feature: - `std::os::unix::FileExt::read_buf_at` - `std::os::unix::FileExt::read_buf_exact_at` - `std::os::windows::FileExt::seek_read_buf`
1 parent 4c83e55 commit 2ccb45f

File tree

6 files changed

+117
-14
lines changed

6 files changed

+117
-14
lines changed

‎library/std/src/os/unix/fs.rs

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ use super::platform::fs::MetadataExt as _;
1111
// Used for `File::read` on intra-doc links
1212
use crate::ffi::OsStr;
1313
use crate::fs::{self, OpenOptions, Permissions};
14+
use crate::io::BorrowedCursor;
1415
use crate::os::unix::io::{AsFd, AsRawFd};
1516
use crate::path::Path;
1617
use crate::sealed::Sealed;
@@ -130,6 +131,42 @@ pub trait FileExt {
130131
if !buf.is_empty() { Err(io::Error::READ_EXACT_EOF) } else { Ok(()) }
131132
}
132133

134+
/// Reads some bytes starting from a given offset into the buffer.
135+
///
136+
/// This equivalent to the [`read_at`](FileExt::read_at) method,
137+
/// except that it is passed a [`BorrowedCursor`] rather than `&mut [u8]` to allow
138+
/// use with uninitialized buffers. The new data will be appended to any
139+
/// existing contents of `buf`.
140+
#[unstable(feature = "read_buf", issue = "78485")]
141+
fn read_buf_at(&self, buf: BorrowedCursor<'_>, offset: u64) -> io::Result<()> {
142+
io::default_read_buf(|b| self.read_at(b, offset), buf)
143+
}
144+
145+
/// Reads the exact number of bytes required to fill the buffer from a given
146+
/// offset.
147+
///
148+
/// This is equivalent to the [`read_exact_at`](FileExt::read_exact_at) method,
149+
/// except that it is passed a [`BorrowedCursor`] rather than `&mut [u8]` to allow
150+
/// use with uninitialized buffers. The new data will be appended to any
151+
/// existing contents of `buf`.
152+
#[unstable(feature = "read_buf", issue = "78485")]
153+
fn read_buf_exact_at(&self, mut buf: BorrowedCursor<'_>, mut offset: u64) -> io::Result<()> {
154+
while buf.capacity() > 0 {
155+
let prev_written = buf.written();
156+
match self.read_buf_at(buf.reborrow(), offset) {
157+
Ok(()) => {}
158+
Err(e) if e.is_interrupted() => {}
159+
Err(e) => return Err(e),
160+
}
161+
let n = buf.written() - prev_written;
162+
offset += n as u64;
163+
if n == 0 {
164+
return Err(io::Error::READ_EXACT_EOF);
165+
}
166+
}
167+
Ok(())
168+
}
169+
133170
/// Writes a number of bytes starting from a given offset.
134171
///
135172
/// Returns the number of bytes written.
@@ -264,6 +301,9 @@ impl FileExt for fs::File {
264301
fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<usize> {
265302
self.as_inner().read_at(buf, offset)
266303
}
304+
fn read_buf_at(&self, buf: BorrowedCursor<'_>, offset: u64) -> io::Result<()> {
305+
self.as_inner().read_buf_at(buf, offset)
306+
}
267307
fn read_vectored_at(&self, bufs: &mut [io::IoSliceMut<'_>], offset: u64) -> io::Result<usize> {
268308
self.as_inner().read_vectored_at(bufs, offset)
269309
}

‎library/std/src/os/windows/fs.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#![stable(feature = "rust1", since = "1.0.0")]
66

77
use crate::fs::{self, Metadata, OpenOptions};
8+
use crate::io::BorrowedCursor;
89
use crate::path::Path;
910
use crate::sealed::Sealed;
1011
use crate::sys_common::{AsInner, AsInnerMut, IntoInner};
@@ -49,6 +50,20 @@ pub trait FileExt {
4950
#[stable(feature = "file_offset", since = "1.15.0")]
5051
fn seek_read(&self, buf: &mut [u8], offset: u64) -> io::Result<usize>;
5152

53+
/// Seeks to a given position and reads some bytes into the buffer.
54+
///
55+
/// This is equivalent to the [`seek_read`](FileExt::seek_read) method, except
56+
/// that it is passed a [`BorrowedCursor`] rather than `&mut [u8]` to allow use
57+
/// with uninitialized buffers. The new data will be appended to any existing
58+
/// contents of `buf`.
59+
///
60+
/// Reading beyond the end of the file will always succeed without reading
61+
/// any bytes.
62+
#[unstable(feature = "read_buf", issue = "78485")]
63+
fn seek_read_buf(&self, buf: BorrowedCursor<'_>, offset: u64) -> io::Result<()> {
64+
io::default_read_buf(|b| self.seek_read(b, offset), buf)
65+
}
66+
5267
/// Seeks to a given position and writes a number of bytes.
5368
///
5469
/// Returns the number of bytes written.
@@ -89,6 +104,10 @@ impl FileExt for fs::File {
89104
self.as_inner().read_at(buf, offset)
90105
}
91106

107+
fn seek_read_buf(&self, buf: BorrowedCursor<'_>, offset: u64) -> io::Result<()> {
108+
self.as_inner().read_buf_at(buf, offset)
109+
}
110+
92111
fn seek_write(&self, buf: &[u8], offset: u64) -> io::Result<usize> {
93112
self.as_inner().write_at(buf, offset)
94113
}

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

Lines changed: 32 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,19 @@ const fn max_iov() -> usize {
8787
16 // The minimum value required by POSIX.
8888
}
8989

90+
#[cfg(not(any(
91+
all(target_os = "linux", not(target_env = "musl")),
92+
target_os = "android",
93+
target_os = "hurd"
94+
)))]
95+
use libc::pread as pread64;
96+
#[cfg(any(
97+
all(target_os = "linux", not(target_env = "musl")),
98+
target_os = "android",
99+
target_os = "hurd"
100+
))]
101+
use libc::pread64;
102+
90103
impl FileDesc {
91104
#[inline]
92105
pub fn try_clone(&self) -> io::Result<Self> {
@@ -146,21 +159,8 @@ impl FileDesc {
146159
(&mut me).read_to_end(buf)
147160
}
148161

149-
#[cfg_attr(target_os = "vxworks", allow(unused_unsafe))]
150162
pub fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<usize> {
151-
#[cfg(not(any(
152-
all(target_os = "linux", not(target_env = "musl")),
153-
target_os = "android",
154-
target_os = "hurd"
155-
)))]
156-
use libc::pread as pread64;
157-
#[cfg(any(
158-
all(target_os = "linux", not(target_env = "musl")),
159-
target_os = "android",
160-
target_os = "hurd"
161-
))]
162-
use libc::pread64;
163-
163+
#[cfg_attr(target_os = "vxworks", allow(unused_unsafe))]
164164
unsafe {
165165
cvt(pread64(
166166
self.as_raw_fd(),
@@ -188,6 +188,24 @@ impl FileDesc {
188188
Ok(())
189189
}
190190

191+
pub fn read_buf_at(&self, mut cursor: BorrowedCursor<'_>, offset: u64) -> io::Result<()> {
192+
#[cfg_attr(target_os = "vxworks", allow(unused_unsafe))]
193+
let ret = cvt(unsafe {
194+
pread64(
195+
self.as_raw_fd(),
196+
cursor.as_mut().as_mut_ptr() as *mut libc::c_void,
197+
cmp::min(cursor.capacity(), READ_LIMIT),
198+
offset as off64_t,
199+
)
200+
})?;
201+
202+
// Safety: `ret` bytes were written to the initialized portion of the buffer
203+
unsafe {
204+
cursor.advance_unchecked(ret as usize);
205+
}
206+
Ok(())
207+
}
208+
191209
#[cfg(any(
192210
target_os = "aix",
193211
target_os = "dragonfly", // DragonFly 1.5

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1411,6 +1411,10 @@ impl File {
14111411
self.0.read_buf(cursor)
14121412
}
14131413

1414+
pub fn read_buf_at(&self, cursor: BorrowedCursor<'_>, offset: u64) -> io::Result<()> {
1415+
self.0.read_buf_at(cursor, offset)
1416+
}
1417+
14141418
pub fn read_vectored_at(&self, bufs: &mut [IoSliceMut<'_>], offset: u64) -> io::Result<usize> {
14151419
self.0.read_vectored_at(bufs, offset)
14161420
}

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -586,6 +586,10 @@ impl File {
586586
self.handle.read_buf(cursor)
587587
}
588588

589+
pub fn read_buf_at(&self, cursor: BorrowedCursor<'_>, offset: u64) -> io::Result<()> {
590+
self.handle.read_buf_at(cursor, offset)
591+
}
592+
589593
pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
590594
self.handle.write(buf)
591595
}

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

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,24 @@ impl Handle {
136136
}
137137
}
138138

139+
pub fn read_buf_at(&self, mut cursor: BorrowedCursor<'_>, offset: u64) -> io::Result<()> {
140+
let res = unsafe {
141+
self.synchronous_read(cursor.as_mut().as_mut_ptr(), cursor.capacity(), Some(offset))
142+
};
143+
144+
match res {
145+
Ok(read) => {
146+
// Safety: `read` bytes were written to the initialized portion of the buffer
147+
unsafe {
148+
cursor.advance_unchecked(read);
149+
}
150+
Ok(())
151+
}
152+
Err(ref e) if e.raw_os_error() == Some(c::ERROR_HANDLE_EOF as i32) => Ok(()),
153+
Err(e) => Err(e),
154+
}
155+
}
156+
139157
pub fn read_to_end(&self, buf: &mut Vec<u8>) -> io::Result<usize> {
140158
let mut me = self;
141159

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /