Skip to content

Commit afa66af

Browse files
committed
feat(io): implement Read and Write for streams
Signed-off-by: Roman Volosatovs <[email protected]>
1 parent 260c609 commit afa66af

File tree

6 files changed

+88
-10
lines changed

6 files changed

+88
-10
lines changed

examples/cli-command.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
1+
use std::io::Write as _;
2+
13
wasi::cli::command::export!(Example);
24

35
struct Example;
46

57
impl wasi::exports::cli::run::Guest for Example {
68
fn run() -> Result<(), ()> {
7-
let stdout = wasi::cli::stdout::get_stdout();
8-
stdout.blocking_write_and_flush(b"Hello, WASI!").unwrap();
9+
let mut stdout = wasi::cli::stdout::get_stdout();
10+
stdout.write_all(b"Hello, WASI!").unwrap();
11+
stdout.flush().unwrap();
912
Ok(())
1013
}
1114
}

examples/hello-world.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1+
use std::io::Write as _;
2+
13
fn main() {
2-
let stdout = wasi::cli::stdout::get_stdout();
3-
stdout.blocking_write_and_flush(b"Hello, world!\n").unwrap();
4+
let mut stdout = wasi::cli::stdout::get_stdout();
5+
stdout.write_all(b"Hello, world!\n").unwrap();
6+
stdout.flush().unwrap();
47
}

examples/http-proxy.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use std::io::Write as _;
2+
13
use wasi::http::types::{
24
Fields, IncomingRequest, OutgoingBody, OutgoingResponse, ResponseOutparam,
35
};
@@ -13,8 +15,9 @@ impl wasi::exports::http::incoming_handler::Guest for Example {
1315

1416
ResponseOutparam::set(response_out, Ok(resp));
1517

16-
let out = body.write().unwrap();
17-
out.blocking_write_and_flush(b"Hello, WASI!").unwrap();
18+
let mut out = body.write().unwrap();
19+
out.write_all(b"Hello, WASI!").unwrap();
20+
out.flush().unwrap();
1821
drop(out);
1922

2023
OutgoingBody::finish(body, None).unwrap();
Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1+
#[cfg(feature = "std")]
2+
mod std;
3+
14
impl core::fmt::Display for crate::io::error::Error {
25
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
36
f.write_str(&self.to_debug_string())
47
}
58
}
6-
7-
#[cfg(feature = "std")]
8-
impl std::error::Error for crate::io::error::Error {}

src/ext/std.rs

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
use std::error::Error;
2+
use std::io;
3+
use std::num::NonZeroU64;
4+
5+
use crate::io::streams::StreamError;
6+
7+
impl Error for crate::io::error::Error {}
8+
9+
impl io::Read for crate::io::streams::InputStream {
10+
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
11+
let n = buf
12+
.len()
13+
.try_into()
14+
.map_err(|e| io::Error::new(io::ErrorKind::Other, e))?;
15+
match self.blocking_read(n) {
16+
Ok(chunk) => {
17+
let n = chunk.len();
18+
if n > buf.len() {
19+
return Err(io::Error::new(
20+
io::ErrorKind::Other,
21+
"more bytes read than requested",
22+
));
23+
}
24+
buf[..n].copy_from_slice(&chunk);
25+
Ok(n)
26+
}
27+
Err(StreamError::Closed) => Ok(0),
28+
Err(StreamError::LastOperationFailed(e)) => {
29+
Err(io::Error::new(io::ErrorKind::Other, e.to_debug_string()))
30+
}
31+
}
32+
}
33+
}
34+
35+
impl io::Write for crate::io::streams::OutputStream {
36+
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
37+
let n = loop {
38+
match self.check_write().map(NonZeroU64::new) {
39+
Ok(Some(n)) => {
40+
break n;
41+
}
42+
Ok(None) => {
43+
self.subscribe().block();
44+
}
45+
Err(StreamError::Closed) => return Ok(0),
46+
Err(StreamError::LastOperationFailed(e)) => {
47+
return Err(io::Error::new(io::ErrorKind::Other, e.to_debug_string()))
48+
}
49+
};
50+
};
51+
let n = n
52+
.get()
53+
.try_into()
54+
.map_err(|e| io::Error::new(io::ErrorKind::Other, e))?;
55+
let n = buf.len().min(n);
56+
crate::io::streams::OutputStream::write(self, &buf[..n]).map_err(|e| match e {
57+
StreamError::Closed => io::ErrorKind::UnexpectedEof.into(),
58+
StreamError::LastOperationFailed(e) => {
59+
io::Error::new(io::ErrorKind::Other, e.to_debug_string())
60+
}
61+
})?;
62+
Ok(n)
63+
}
64+
65+
fn flush(&mut self) -> io::Result<()> {
66+
self.blocking_flush()
67+
.map_err(|e| io::Error::new(io::ErrorKind::Other, e))
68+
}
69+
}

src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,7 @@
179179
#[cfg(feature = "std")]
180180
extern crate std;
181181

182-
mod errors;
182+
mod ext;
183183

184184
// These modules are all auto-generated by `./ci/regenerate.sh`
185185
mod bindings;

0 commit comments

Comments
 (0)