Skip to content

Commit 51d7220

Browse files
authored
Rollup merge of rust-lang#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.
2 parents 87b8681 + f226e6b commit 51d7220

File tree

1 file changed

+94
-0
lines changed
  • src/libstd/sys/wasi/ext

1 file changed

+94
-0
lines changed

src/libstd/sys/wasi/ext/fs.rs

+94
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,58 @@ pub trait FileExt {
2727
/// [`File::read`]: ../../../../std/fs/struct.File.html#method.read_vectored
2828
fn read_at(&self, bufs: &mut [IoSliceMut<'_>], offset: u64) -> io::Result<usize>;
2929

30+
/// Reads the exact number of byte required to fill `buf` from the given offset.
31+
///
32+
/// The offset is relative to the start of the file and thus independent
33+
/// from the current cursor.
34+
///
35+
/// The current file cursor is not affected by this function.
36+
///
37+
/// Similar to [`Read::read_exact`] but uses [`read_at`] instead of `read`.
38+
///
39+
/// [`Read::read_exact`]: ../../../../std/io/trait.Read.html#method.read_exact
40+
/// [`read_at`]: #tymethod.read_at
41+
///
42+
/// # Errors
43+
///
44+
/// If this function encounters an error of the kind
45+
/// [`ErrorKind::Interrupted`] then the error is ignored and the operation
46+
/// will continue.
47+
///
48+
/// If this function encounters an "end of file" before completely filling
49+
/// the buffer, it returns an error of the kind [`ErrorKind::UnexpectedEof`].
50+
/// The contents of `buf` are unspecified in this case.
51+
///
52+
/// If any other read error is encountered then this function immediately
53+
/// returns. The contents of `buf` are unspecified in this case.
54+
///
55+
/// If this function returns an error, it is unspecified how many bytes it
56+
/// has read, but it will never read more than would be necessary to
57+
/// completely fill the buffer.
58+
///
59+
/// [`ErrorKind::Interrupted`]: ../../../../std/io/enum.ErrorKind.html#variant.Interrupted
60+
/// [`ErrorKind::UnexpectedEof`]: ../../../../std/io/enum.ErrorKind.html#variant.UnexpectedEof
61+
#[stable(feature = "rw_exact_all_at", since = "1.33.0")]
62+
fn read_exact_at(&self, mut buf: &mut [u8], mut offset: u64) -> io::Result<()> {
63+
while !buf.is_empty() {
64+
match self.read_at(buf, offset) {
65+
Ok(0) => break,
66+
Ok(n) => {
67+
let tmp = buf;
68+
buf = &mut tmp[n..];
69+
offset += n as u64;
70+
}
71+
Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {}
72+
Err(e) => return Err(e),
73+
}
74+
}
75+
if !buf.is_empty() {
76+
Err(io::Error::new(io::ErrorKind::UnexpectedEof, "failed to fill whole buffer"))
77+
} else {
78+
Ok(())
79+
}
80+
}
81+
3082
/// Writes a number of bytes starting from a given offset.
3183
///
3284
/// Returns the number of bytes written.
@@ -45,6 +97,48 @@ pub trait FileExt {
4597
/// [`File::write`]: ../../../../std/fs/struct.File.html#method.write_vectored
4698
fn write_at(&self, bufs: &[IoSlice<'_>], offset: u64) -> io::Result<usize>;
4799

100+
/// Attempts to write an entire buffer starting from a given offset.
101+
///
102+
/// The offset is relative to the start of the file and thus independent
103+
/// from the current cursor.
104+
///
105+
/// The current file cursor is not affected by this function.
106+
///
107+
/// This method will continuously call [`write_at`] until there is no more data
108+
/// to be written or an error of non-[`ErrorKind::Interrupted`] kind is
109+
/// returned. This method will not return until the entire buffer has been
110+
/// successfully written or such an error occurs. The first error that is
111+
/// not of [`ErrorKind::Interrupted`] kind generated from this method will be
112+
/// returned.
113+
///
114+
/// # Errors
115+
///
116+
/// This function will return the first error of
117+
/// non-[`ErrorKind::Interrupted`] kind that [`write_at`] returns.
118+
///
119+
/// [`ErrorKind::Interrupted`]: ../../../../std/io/enum.ErrorKind.html#variant.Interrupted
120+
/// [`write_at`]: #tymethod.write_at
121+
#[stable(feature = "rw_exact_all_at", since = "1.33.0")]
122+
fn write_all_at(&self, mut buf: &[u8], mut offset: u64) -> io::Result<()> {
123+
while !buf.is_empty() {
124+
match self.write_at(buf, offset) {
125+
Ok(0) => {
126+
return Err(io::Error::new(
127+
io::ErrorKind::WriteZero,
128+
"failed to write whole buffer",
129+
));
130+
}
131+
Ok(n) => {
132+
buf = &buf[n..];
133+
offset += n as u64
134+
}
135+
Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {}
136+
Err(e) => return Err(e),
137+
}
138+
}
139+
Ok(())
140+
}
141+
48142
/// Returns the current position within the file.
49143
///
50144
/// This corresponds to the `fd_tell` syscall and is similar to

0 commit comments

Comments
 (0)