@@ -28,19 +28,23 @@ impl AsyncInputStream {
28
28
}
29
29
/// Like [`AsyncRead::read`], but doesn't require a `&mut self`.
30
30
pub async fn read ( & self , buf : & mut [ u8 ] ) -> Result < usize > {
31
- self . ready ( ) . await ;
32
- // Ideally, the ABI would be able to read directly into buf. However, with the default
33
- // generated bindings, it returns a newly allocated vec, which we need to copy into buf.
34
- let read = match self . stream . read ( buf. len ( ) as u64 ) {
35
- // We don't need to special-case 0 here: a value of 0 bytes from
36
- // WASI's `read` doesn't mean end-of-stream as it does in Rust,
37
- // however since we called `self.ready()`, we'll always get at
38
- // least one byte.
39
- Ok ( r) => r,
40
- // 0 bytes from Rust's `read` means end-of-stream.
41
- Err ( StreamError :: Closed ) => return Ok ( 0 ) ,
42
- Err ( StreamError :: LastOperationFailed ( err) ) => {
43
- return Err ( std:: io:: Error :: other ( err. to_debug_string ( ) ) )
31
+ let read = loop {
32
+ self . ready ( ) . await ;
33
+ // Ideally, the ABI would be able to read directly into buf.
34
+ // However, with the default generated bindings, it returns a
35
+ // newly allocated vec, which we need to copy into buf.
36
+ match self . stream . read ( buf. len ( ) as u64 ) {
37
+ // A read of 0 bytes from WASI's `read` doesn't mean
38
+ // end-of-stream as it does in Rust. However, `self.ready()`
39
+ // cannot guarantee that at least one byte is ready for
40
+ // reading, so in this case we try again.
41
+ Ok ( r) if r. is_empty ( ) => continue ,
42
+ Ok ( r) => break r,
43
+ // 0 bytes from Rust's `read` means end-of-stream.
44
+ Err ( StreamError :: Closed ) => return Ok ( 0 ) ,
45
+ Err ( StreamError :: LastOperationFailed ( err) ) => {
46
+ return Err ( std:: io:: Error :: other ( err. to_debug_string ( ) ) )
47
+ }
44
48
}
45
49
} ;
46
50
let len = read. len ( ) ;
0 commit comments