diff options
| author | Stuart Cook <Zalathar@users.noreply.github.com> | 2025-09-04 10:01:51 +1000 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-09-04 10:01:51 +1000 |
| commit | f073f64eb687280fa626541a7649e9e805d21e63 (patch) | |
| tree | f3e35e6340679c84a98798517b5e163d8d71c5d0 /library/std/src/os | |
| parent | a1208bf765ba783ee4ebdc4c29ab0a0c215806ef (diff) | |
| parent | c914c471b9d83f9e6c74b0e6c2c8044efd3a57dd (diff) | |
| download | rust-f073f64eb687280fa626541a7649e9e805d21e63.tar.gz rust-f073f64eb687280fa626541a7649e9e805d21e63.zip | |
Rollup merge of #140459 - niklasf:feature/read-buf-at, r=tgross35
Add `read_buf` equivalents for positioned reads Adds the following items under the ~~`read_buf` (rust-lang/rust#78485)~~ `read_buf_at` (rust-lang/rust#140771) feature: - `std::os::unix::fs::FileExt::read_buf_at` - `std::os::unix::fs::FileExt::read_buf_exact_at` - `std::os::windows::fs::FileExt::seek_read_buf` try-job: `x86_64-msvc*` try-job: `test-various*` try-job: `dist-various*`
Diffstat (limited to 'library/std/src/os')
| -rw-r--r-- | library/std/src/os/unix/fs.rs | 89 | ||||
| -rw-r--r-- | library/std/src/os/windows/fs.rs | 43 |
2 files changed, 132 insertions, 0 deletions
diff --git a/library/std/src/os/unix/fs.rs b/library/std/src/os/unix/fs.rs index b776df3dde1..1d1a138b302 100644 --- a/library/std/src/os/unix/fs.rs +++ b/library/std/src/os/unix/fs.rs @@ -11,6 +11,7 @@ use super::platform::fs::MetadataExt as _; // Used for `File::read` on intra-doc links use crate::ffi::OsStr; use crate::fs::{self, OpenOptions, Permissions}; +use crate::io::BorrowedCursor; use crate::os::unix::io::{AsFd, AsRawFd}; use crate::path::Path; use crate::sealed::Sealed; @@ -130,6 +131,91 @@ pub trait FileExt { if !buf.is_empty() { Err(io::Error::READ_EXACT_EOF) } else { Ok(()) } } + /// Reads some bytes starting from a given offset into the buffer. + /// + /// This equivalent to the [`read_at`](FileExt::read_at) method, except that it is passed a + /// [`BorrowedCursor`] rather than `&mut [u8]` to allow use with uninitialized buffers. The new + /// data will be appended to any existing contents of `buf`. + /// + /// # Examples + /// + /// ```no_run + /// #![feature(core_io_borrowed_buf)] + /// #![feature(read_buf_at)] + /// + /// use std::io; + /// use std::io::BorrowedBuf; + /// use std::fs::File; + /// use std::mem::MaybeUninit; + /// use std::os::unix::prelude::*; + /// + /// fn main() -> io::Result<()> { + /// let mut file = File::open("pi.txt")?; + /// + /// // Read some bytes starting from offset 2 + /// let mut buf: [MaybeUninit<u8>; 10] = [MaybeUninit::uninit(); 10]; + /// let mut buf = BorrowedBuf::from(buf.as_mut_slice()); + /// file.read_buf_at(buf.unfilled(), 2)?; + /// + /// assert!(buf.filled().starts_with(b"1")); + /// + /// Ok(()) + /// } + /// ``` + #[unstable(feature = "read_buf_at", issue = "140771")] + fn read_buf_at(&self, buf: BorrowedCursor<'_>, offset: u64) -> io::Result<()> { + io::default_read_buf(|b| self.read_at(b, offset), buf) + } + + /// Reads the exact number of bytes required to fill the buffer from a given offset. + /// + /// This is equivalent to the [`read_exact_at`](FileExt::read_exact_at) method, except that it + /// is passed a [`BorrowedCursor`] rather than `&mut [u8]` to allow use with uninitialized + /// buffers. The new data will be appended to any existing contents of `buf`. + /// + /// # Examples + /// + /// ```no_run + /// #![feature(core_io_borrowed_buf)] + /// #![feature(read_buf_at)] + /// + /// use std::io; + /// use std::io::BorrowedBuf; + /// use std::fs::File; + /// use std::mem::MaybeUninit; + /// use std::os::unix::prelude::*; + /// + /// fn main() -> io::Result<()> { + /// let mut file = File::open("pi.txt")?; + /// + /// // Read exactly 10 bytes starting from offset 2 + /// let mut buf: [MaybeUninit<u8>; 10] = [MaybeUninit::uninit(); 10]; + /// let mut buf = BorrowedBuf::from(buf.as_mut_slice()); + /// file.read_buf_exact_at(buf.unfilled(), 2)?; + /// + /// assert_eq!(buf.filled(), b"1415926535"); + /// + /// Ok(()) + /// } + /// ``` + #[unstable(feature = "read_buf_at", issue = "140771")] + fn read_buf_exact_at(&self, mut buf: BorrowedCursor<'_>, mut offset: u64) -> io::Result<()> { + while buf.capacity() > 0 { + let prev_written = buf.written(); + match self.read_buf_at(buf.reborrow(), offset) { + Ok(()) => {} + Err(e) if e.is_interrupted() => {} + Err(e) => return Err(e), + } + let n = buf.written() - prev_written; + offset += n as u64; + if n == 0 { + return Err(io::Error::READ_EXACT_EOF); + } + } + Ok(()) + } + /// Writes a number of bytes starting from a given offset. /// /// Returns the number of bytes written. @@ -264,6 +350,9 @@ impl FileExt for fs::File { fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<usize> { self.as_inner().read_at(buf, offset) } + fn read_buf_at(&self, buf: BorrowedCursor<'_>, offset: u64) -> io::Result<()> { + self.as_inner().read_buf_at(buf, offset) + } fn read_vectored_at(&self, bufs: &mut [io::IoSliceMut<'_>], offset: u64) -> io::Result<usize> { self.as_inner().read_vectored_at(bufs, offset) } diff --git a/library/std/src/os/windows/fs.rs b/library/std/src/os/windows/fs.rs index ddb8dbd8fee..b445f368aeb 100644 --- a/library/std/src/os/windows/fs.rs +++ b/library/std/src/os/windows/fs.rs @@ -5,6 +5,7 @@ #![stable(feature = "rust1", since = "1.0.0")] use crate::fs::{self, Metadata, OpenOptions}; +use crate::io::BorrowedCursor; use crate::path::Path; use crate::sealed::Sealed; use crate::sys_common::{AsInner, AsInnerMut, IntoInner}; @@ -49,6 +50,44 @@ pub trait FileExt { #[stable(feature = "file_offset", since = "1.15.0")] fn seek_read(&self, buf: &mut [u8], offset: u64) -> io::Result<usize>; + /// Seeks to a given position and reads some bytes into the buffer. + /// + /// This is equivalent to the [`seek_read`](FileExt::seek_read) method, except that it is passed + /// a [`BorrowedCursor`] rather than `&mut [u8]` to allow use with uninitialized buffers. The + /// new data will be appended to any existing contents of `buf`. + /// + /// Reading beyond the end of the file will always succeed without reading any bytes. + /// + /// # Examples + /// + /// ```no_run + /// #![feature(core_io_borrowed_buf)] + /// #![feature(read_buf_at)] + /// + /// use std::io; + /// use std::io::BorrowedBuf; + /// use std::fs::File; + /// use std::mem::MaybeUninit; + /// use std::os::windows::prelude::*; + /// + /// fn main() -> io::Result<()> { + /// let mut file = File::open("pi.txt")?; + /// + /// // Read some bytes starting from offset 2 + /// let mut buf: [MaybeUninit<u8>; 10] = [MaybeUninit::uninit(); 10]; + /// let mut buf = BorrowedBuf::from(buf.as_mut_slice()); + /// file.seek_read_buf(buf.unfilled(), 2)?; + /// + /// assert!(buf.filled().starts_with(b"1")); + /// + /// Ok(()) + /// } + /// ``` + #[unstable(feature = "read_buf_at", issue = "140771")] + fn seek_read_buf(&self, buf: BorrowedCursor<'_>, offset: u64) -> io::Result<()> { + io::default_read_buf(|b| self.seek_read(b, offset), buf) + } + /// Seeks to a given position and writes a number of bytes. /// /// Returns the number of bytes written. @@ -89,6 +128,10 @@ impl FileExt for fs::File { self.as_inner().read_at(buf, offset) } + fn seek_read_buf(&self, buf: BorrowedCursor<'_>, offset: u64) -> io::Result<()> { + self.as_inner().read_buf_at(buf, offset) + } + fn seek_write(&self, buf: &[u8], offset: u64) -> io::Result<usize> { self.as_inner().write_at(buf, offset) } |
