mirror of
https://github.com/rust-lang/rust.git
synced 2025-04-14 13:06:49 +00:00
Rollup merge of #74076 - sunfishcode:wasi-fileext-newmethods, r=alexcrichton
Add `read_exact_at` and `write_all_at` to WASI's `FileExt` This adds `read_exact_at` and `write_all_at` to WASI's `FileExt`, similar to the Unix versions of the same names.
This commit is contained in:
commit
427ef98bc3
@ -12,6 +12,24 @@ use crate::sys_common::{AsInner, AsInnerMut, FromInner};
|
||||
///
|
||||
/// [`File`]: ../../../../std/fs/struct.File.html
|
||||
pub trait FileExt {
|
||||
/// Reads a number of bytes starting from a given offset.
|
||||
///
|
||||
/// Returns the number of bytes read.
|
||||
///
|
||||
/// The offset is relative to the start of the file and thus independent
|
||||
/// from the current cursor.
|
||||
///
|
||||
/// The current file cursor is not affected by this function.
|
||||
///
|
||||
/// Note that similar to [`File::read`], it is not an error to return with a
|
||||
/// short read.
|
||||
///
|
||||
/// [`File::read`]: ../../../../std/fs/struct.File.html#method.read
|
||||
fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<usize> {
|
||||
let bufs = &mut [IoSliceMut::new(buf)];
|
||||
self.read_vectored_at(bufs, offset)
|
||||
}
|
||||
|
||||
/// Reads a number of bytes starting from a given offset.
|
||||
///
|
||||
/// Returns the number of bytes read.
|
||||
@ -25,7 +43,80 @@ pub trait FileExt {
|
||||
/// return with a short read.
|
||||
///
|
||||
/// [`File::read`]: ../../../../std/fs/struct.File.html#method.read_vectored
|
||||
fn read_at(&self, bufs: &mut [IoSliceMut<'_>], offset: u64) -> io::Result<usize>;
|
||||
fn read_vectored_at(&self, bufs: &mut [IoSliceMut<'_>], offset: u64) -> io::Result<usize>;
|
||||
|
||||
/// Reads the exact number of byte required to fill `buf` from the given offset.
|
||||
///
|
||||
/// The offset is relative to the start of the file and thus independent
|
||||
/// from the current cursor.
|
||||
///
|
||||
/// The current file cursor is not affected by this function.
|
||||
///
|
||||
/// Similar to [`Read::read_exact`] but uses [`read_at`] instead of `read`.
|
||||
///
|
||||
/// [`Read::read_exact`]: ../../../../std/io/trait.Read.html#method.read_exact
|
||||
/// [`read_at`]: #tymethod.read_at
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// If this function encounters an error of the kind
|
||||
/// [`ErrorKind::Interrupted`] then the error is ignored and the operation
|
||||
/// will continue.
|
||||
///
|
||||
/// If this function encounters an "end of file" before completely filling
|
||||
/// the buffer, it returns an error of the kind [`ErrorKind::UnexpectedEof`].
|
||||
/// The contents of `buf` are unspecified in this case.
|
||||
///
|
||||
/// If any other read error is encountered then this function immediately
|
||||
/// returns. The contents of `buf` are unspecified in this case.
|
||||
///
|
||||
/// If this function returns an error, it is unspecified how many bytes it
|
||||
/// has read, but it will never read more than would be necessary to
|
||||
/// completely fill the buffer.
|
||||
///
|
||||
/// [`ErrorKind::Interrupted`]: ../../../../std/io/enum.ErrorKind.html#variant.Interrupted
|
||||
/// [`ErrorKind::UnexpectedEof`]: ../../../../std/io/enum.ErrorKind.html#variant.UnexpectedEof
|
||||
#[stable(feature = "rw_exact_all_at", since = "1.33.0")]
|
||||
fn read_exact_at(&self, mut buf: &mut [u8], mut offset: u64) -> io::Result<()> {
|
||||
while !buf.is_empty() {
|
||||
match self.read_at(buf, offset) {
|
||||
Ok(0) => break,
|
||||
Ok(n) => {
|
||||
let tmp = buf;
|
||||
buf = &mut tmp[n..];
|
||||
offset += n as u64;
|
||||
}
|
||||
Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {}
|
||||
Err(e) => return Err(e),
|
||||
}
|
||||
}
|
||||
if !buf.is_empty() {
|
||||
Err(io::Error::new(io::ErrorKind::UnexpectedEof, "failed to fill whole buffer"))
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Writes a number of bytes starting from a given offset.
|
||||
///
|
||||
/// Returns the number of bytes written.
|
||||
///
|
||||
/// The offset is relative to the start of the file and thus independent
|
||||
/// from the current cursor.
|
||||
///
|
||||
/// The current file cursor is not affected by this function.
|
||||
///
|
||||
/// When writing beyond the end of the file, the file is appropriately
|
||||
/// extended and the intermediate bytes are initialized with the value 0.
|
||||
///
|
||||
/// Note that similar to [`File::write`], it is not an error to return a
|
||||
/// short write.
|
||||
///
|
||||
/// [`File::write`]: ../../../../std/fs/struct.File.html#write.v
|
||||
fn write_at(&self, buf: &[u8], offset: u64) -> io::Result<usize> {
|
||||
let bufs = &[IoSlice::new(buf)];
|
||||
self.write_vectored_at(bufs, offset)
|
||||
}
|
||||
|
||||
/// Writes a number of bytes starting from a given offset.
|
||||
///
|
||||
@ -43,7 +134,49 @@ pub trait FileExt {
|
||||
/// short write.
|
||||
///
|
||||
/// [`File::write`]: ../../../../std/fs/struct.File.html#method.write_vectored
|
||||
fn write_at(&self, bufs: &[IoSlice<'_>], offset: u64) -> io::Result<usize>;
|
||||
fn write_vectored_at(&self, bufs: &[IoSlice<'_>], offset: u64) -> io::Result<usize>;
|
||||
|
||||
/// Attempts to write an entire buffer starting from a given offset.
|
||||
///
|
||||
/// The offset is relative to the start of the file and thus independent
|
||||
/// from the current cursor.
|
||||
///
|
||||
/// The current file cursor is not affected by this function.
|
||||
///
|
||||
/// This method will continuously call [`write_at`] until there is no more data
|
||||
/// to be written or an error of non-[`ErrorKind::Interrupted`] kind is
|
||||
/// returned. This method will not return until the entire buffer has been
|
||||
/// successfully written or such an error occurs. The first error that is
|
||||
/// not of [`ErrorKind::Interrupted`] kind generated from this method will be
|
||||
/// returned.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// This function will return the first error of
|
||||
/// non-[`ErrorKind::Interrupted`] kind that [`write_at`] returns.
|
||||
///
|
||||
/// [`ErrorKind::Interrupted`]: ../../../../std/io/enum.ErrorKind.html#variant.Interrupted
|
||||
/// [`write_at`]: #tymethod.write_at
|
||||
#[stable(feature = "rw_exact_all_at", since = "1.33.0")]
|
||||
fn write_all_at(&self, mut buf: &[u8], mut offset: u64) -> io::Result<()> {
|
||||
while !buf.is_empty() {
|
||||
match self.write_at(buf, offset) {
|
||||
Ok(0) => {
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::WriteZero,
|
||||
"failed to write whole buffer",
|
||||
));
|
||||
}
|
||||
Ok(n) => {
|
||||
buf = &buf[n..];
|
||||
offset += n as u64
|
||||
}
|
||||
Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {}
|
||||
Err(e) => return Err(e),
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Returns the current position within the file.
|
||||
///
|
||||
@ -105,11 +238,11 @@ pub trait FileExt {
|
||||
// FIXME: bind random_get maybe? - on crates.io for unix
|
||||
|
||||
impl FileExt for fs::File {
|
||||
fn read_at(&self, bufs: &mut [IoSliceMut<'_>], offset: u64) -> io::Result<usize> {
|
||||
fn read_vectored_at(&self, bufs: &mut [IoSliceMut<'_>], offset: u64) -> io::Result<usize> {
|
||||
self.as_inner().fd().pread(bufs, offset)
|
||||
}
|
||||
|
||||
fn write_at(&self, bufs: &[IoSlice<'_>], offset: u64) -> io::Result<usize> {
|
||||
fn write_vectored_at(&self, bufs: &[IoSlice<'_>], offset: u64) -> io::Result<usize> {
|
||||
self.as_inner().fd().pwrite(bufs, offset)
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user