diff options
| author | Manish Goregaokar <manishsmail@gmail.com> | 2020-07-10 23:26:34 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-07-10 23:26:34 -0700 |
| commit | 427ef98bc3ed87190f389bebc64cc76604c0213a (patch) | |
| tree | d90160d0a1c771b5709dc44ddf843e999d110be9 /src/libstd/sys | |
| parent | 2ae7d8cdba4ee8584bdcdcd22699d151a6b8959f (diff) | |
| parent | 58fc61b79cd15fdafad6e15991553f5c33422ade (diff) | |
| download | rust-427ef98bc3ed87190f389bebc64cc76604c0213a.tar.gz rust-427ef98bc3ed87190f389bebc64cc76604c0213a.zip | |
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.
Diffstat (limited to 'src/libstd/sys')
| -rw-r--r-- | src/libstd/sys/wasi/ext/fs.rs | 141 |
1 files changed, 137 insertions, 4 deletions
diff --git a/src/libstd/sys/wasi/ext/fs.rs b/src/libstd/sys/wasi/ext/fs.rs index 6696efa8871..f41c6626ccf 100644 --- a/src/libstd/sys/wasi/ext/fs.rs +++ b/src/libstd/sys/wasi/ext/fs.rs @@ -21,11 +21,102 @@ pub trait FileExt { /// /// 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. + /// + /// 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_vectored`], it is not an error to /// 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) } |
