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:
parent
e1beee4992
commit
653c091262
1 changed files with 94 additions and 0 deletions
|
|
@ -27,6 +27,58 @@ pub trait FileExt {
|
|||
/// [`File::read`]: ../../../../std/fs/struct.File.html#method.read_vectored
|
||||
fn read_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.
|
||||
|
|
@ -45,6 +97,48 @@ pub trait FileExt {
|
|||
/// [`File::write`]: ../../../../std/fs/struct.File.html#method.write_vectored
|
||||
fn write_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.
|
||||
///
|
||||
/// This corresponds to the `fd_tell` syscall and is similar to
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue