about summary refs log tree commit diff
path: root/src/libstd/sys
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2020-07-11 06:28:04 +0000
committerbors <bors@rust-lang.org>2020-07-11 06:28:04 +0000
commit346aec9b02f3c74f3fce97fd6bda24709d220e49 (patch)
tree8ddad2b3c566486f44ea01f6305e1beeb11140f7 /src/libstd/sys
parentdaecab3a784f28082df90cebb204998051f3557d (diff)
parent79fc3861dfd1190b257ef7f4208533c3945254b7 (diff)
downloadrust-346aec9b02f3c74f3fce97fd6bda24709d220e49.tar.gz
rust-346aec9b02f3c74f3fce97fd6bda24709d220e49.zip
Auto merge of #74235 - Manishearth:rollup-bgs3q14, r=Manishearth
Rollup of 19 pull requests

Successful merges:

 - #71322 (Accept tuple.0.0 as tuple indexing (take 2))
 - #72303 (Add core::future::{poll_fn, PollFn})
 - #73862 (Stabilize casts and coercions to `&[T]` in const fn)
 - #73887 (stabilize const mem::forget)
 - #73989 (adjust ub-enum test to be endianess-independent)
 - #74045 (Explain effects of debugging options from config.toml)
 - #74076 (Add `read_exact_at` and `write_all_at` to WASI's `FileExt`)
 - #74099 (Add VecDeque::range* methods)
 - #74100 (Use str::strip* in bootstrap)
 - #74103 (Only add CFGuard on `windows-msvc` targets)
 - #74109 (Only allow `repr(i128/u128)` on enum)
 - #74122 (Start-up clean-up)
 - #74125 (Correctly mark the ending span of a match arm)
 - #74127 (Avoid "whitelist")
 - #74129 (:arrow_up: rust-analyzer)
 - #74135 (Update books)
 - #74145 (Update rust-installer to latest version)
 - #74161 (Fix  disabled dockerfiles)
 - #74162 (take self by value in ToPredicate)

Failed merges:

r? @ghost
Diffstat (limited to 'src/libstd/sys')
-rw-r--r--src/libstd/sys/wasi/ext/fs.rs141
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)
     }