diff --git a/lib/c-api/src/wasm_c_api/wasi/mod.rs b/lib/c-api/src/wasm_c_api/wasi/mod.rs index 410fe0e80..d000d61c7 100644 --- a/lib/c-api/src/wasm_c_api/wasi/mod.rs +++ b/lib/c-api/src/wasm_c_api/wasi/mod.rs @@ -60,9 +60,47 @@ pub struct wasi_pipe_t { struct WasiPipeDataWithDestructor { data: Vec, + // Buffer of already-read data that is being read into, + // then the result is returned + temp_buffer: Vec, destructor: WasiConsoleIoEnvDestructor, } +impl WasiPipeDataWithDestructor { + fn read_buffer(&mut self, read_cb: WasiConsoleIoReadCallback, max_read: Option) -> io::Result> { + + const BLOCK_SIZE: usize = 1024; + + let mut final_buf = Vec::new(); + + match max_read { + None => { + // read from pipe until EOF encountered + }, + Some(max) => { + // read from pipe until either EOF or maximum number of bytes + for i in + } + } + + /* + let result = unsafe { + let ptr = buf.as_mut_ptr() as *mut c_char; + (self_read)(data.data.as_mut_ptr() as *const c_void, ptr, buf.len()) + }; + if result >= 0 { + Ok(result as usize) + } else { + Err(io::Error::new( + io::ErrorKind::Other, + format!("could not read from wasi_pipe_t: {result}"), + )) + } + */ + + } +} + impl Drop for WasiPipeDataWithDestructor { fn drop(&mut self) { let error = unsafe { (self.destructor)(self.data.as_mut_ptr() as *const c_void) }; @@ -73,6 +111,15 @@ impl Drop for WasiPipeDataWithDestructor { } impl wasi_pipe_t { + + /// Read bytes from this pipe into the internal buffer, + /// returning how many bytes were read + fn read_from_pipe_store_in_buffer(&self) -> io::Result { + let mut data = self.get_data_mut("read_from_pipe")?; + data.read_into_buffer(); + Ok(data.temp_buffer.len()) + } + fn get_data_mut( &self, op_id: &'static str, @@ -105,17 +152,8 @@ impl io::Read for wasi_pipe_t { fn read(&mut self, buf: &mut [u8]) -> io::Result { let self_read = self.read; let mut data = self.get_data_mut("read")?; - let result = unsafe { - let ptr = buf.as_mut_ptr() as *mut c_char; - (self_read)(data.data.as_mut_ptr() as *const c_void, ptr, buf.len()) - }; - if result >= 0 { - Ok(result as usize) - } else { - Err(io::Error::new( - io::ErrorKind::Other, - format!("could not read from wasi_pipe_t: {result}"), - )) + if data.temp_buffer.len() >= buf.len() { + // fill up buf by draining temp_buffer first, then read more bytes } } } @@ -212,7 +250,7 @@ impl VirtualFile for wasi_pipe_t { + self.bytes_available_write()?.unwrap_or(0usize)) } fn bytes_available_read(&self) -> Result, FsError> { - Ok(None) + let read = self.read_from_pipe_store_in_buffer(); } fn bytes_available_write(&self) -> Result, FsError> { Ok(None) @@ -237,6 +275,7 @@ pub unsafe extern "C" fn wasi_pipe_new_internal( seek, data: Some(Box::new(Arc::new(Mutex::new(WasiPipeDataWithDestructor { data: data_vec, + temp_buffer: Vec::new(), destructor, })))), })) @@ -461,15 +500,17 @@ pub unsafe extern "C" fn wasi_pipe_delete_str(buf: *mut c_char) { let _ = CString::from_raw(buf); } -#[no_mangle] -pub unsafe extern "C" fn wasi_pipe_read_str(ptr: *const wasi_pipe_t, buf: *mut *mut c_char) -> i64 { - use std::ffi::CString; +unsafe fn wasi_pipe_read_bytes_internal( + ptr: *const wasi_pipe_t, + buf: &mut Vec +) -> i64 { + use std::io::Read; const BLOCK_SIZE: usize = 1024; - let mut target = Vec::new(); let ptr = &mut *(ptr as *mut wasi_pipe_t); + let mut target = Vec::new(); loop { let mut v = vec![0; BLOCK_SIZE]; @@ -487,6 +528,20 @@ pub unsafe extern "C" fn wasi_pipe_read_str(ptr: *const wasi_pipe_t, buf: *mut * } } + *buf = target; + 0 +} + +#[no_mangle] +pub unsafe extern "C" fn wasi_pipe_read_str(ptr: *const wasi_pipe_t, buf: *mut *mut c_char) -> i64 { + use std::ffi::CString; + + let mut target = Vec::new(); + let read_result = wasi_pipe_read_bytes_internal(ptr, &mut target); + if read_result < 0 { + return read_result; + } + target.push(0); let len = target.len(); let c_string = match CString::from_vec_with_nul(target.clone()) {