Skip to content

Commit e3b265d

Browse files
Return ptrdiff_t
1 parent 2c3b56c commit e3b265d

2 files changed

Lines changed: 42 additions & 18 deletions

File tree

crates/c-api/include/wasi.h

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -149,13 +149,14 @@ WASI_API_EXTERN void wasi_config_inherit_stdout(wasi_config_t *config);
149149
* \brief Configures standard output to be directed to \p callback
150150
*
151151
* \param callback The callback that will get called for each write with the
152-
* buffer
152+
* buffer. A positive return value indicates the amount of bytes written.
153+
* Negative return values indicate that an error has occured.
153154
* \param data An optional user provided data that will be passed to \p callback
154155
* \param finalizer An optional callback to be called to destroy \p data
155156
*/
156157
WASI_API_EXTERN void wasi_config_set_stdout_custom(
157158
wasi_config_t *config,
158-
void (*callback)(void *, const unsigned char *, size_t), void *data,
159+
ptrdiff_t (*callback)(void *, const unsigned char *, size_t), void *data,
159160
void (*finalizer)(void *));
160161

161162
/**
@@ -180,13 +181,14 @@ WASI_API_EXTERN void wasi_config_inherit_stderr(wasi_config_t *config);
180181
* \brief Configures standard error output to be directed to \p callback
181182
*
182183
* \param callback The callback that will get called for each write with the
183-
* buffer
184+
* buffer. A positive return value indicates the amount of bytes written.
185+
* Negative return values indicate that an error has occured.
184186
* \param data An optional user provided data that will be passed to \p callback
185187
* \param finalizer An optional callback to be called to destroy \p data
186188
*/
187189
WASI_API_EXTERN void wasi_config_set_stderr_custom(
188190
wasi_config_t *config,
189-
void (*callback)(void *, const unsigned char *, size_t), void *data,
191+
ptrdiff_t (*callback)(void *, const unsigned char *, size_t), void *data,
190192
void (*finalizer)(void *));
191193

192194
/**

crates/c-api/src/wasi.rs

Lines changed: 36 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -156,12 +156,12 @@ pub extern "C" fn wasi_config_inherit_stdout(config: &mut wasi_config_t) {
156156

157157
struct CustomOutputStreamInner {
158158
foreign_data: crate::ForeignData,
159-
callback: extern "C" fn(*mut c_void, *const u8, usize),
159+
callback: extern "C" fn(*mut c_void, *const u8, usize) -> isize,
160160
}
161161

162162
impl CustomOutputStreamInner {
163-
pub fn write(&self, buf: &[u8]) {
164-
(self.callback)(self.foreign_data.data, buf.as_ptr(), buf.len());
163+
pub fn write(&self, buf: &[u8]) -> isize {
164+
(self.callback)(self.foreign_data.data, buf.as_ptr(), buf.len())
165165
}
166166
}
167167

@@ -172,7 +172,7 @@ pub struct CustomOutputStream {
172172
impl CustomOutputStream {
173173
pub fn new(
174174
foreign_data: crate::ForeignData,
175-
callback: extern "C" fn(*mut c_void, *const u8, usize),
175+
callback: extern "C" fn(*mut c_void, *const u8, usize) -> isize,
176176
) -> Self {
177177
Self {
178178
inner: std::sync::Arc::new(CustomOutputStreamInner {
@@ -199,16 +199,28 @@ impl wasmtime_wasi::p2::Pollable for CustomOutputStream {
199199
#[async_trait::async_trait]
200200
impl wasmtime_wasi::p2::OutputStream for CustomOutputStream {
201201
fn write(&mut self, bytes: Bytes) -> Result<(), StreamError> {
202-
self.inner.write(&bytes);
203-
// Always ready for writing
202+
let wrote = self.inner.write(&bytes);
203+
204+
if wrote < 0 {
205+
return Err(StreamError::Trap(anyhow::anyhow!(
206+
"Custom write function failed with error code '{}'",
207+
wrote.abs()
208+
)));
209+
}
210+
211+
if wrote as usize != bytes.len() {
212+
return Err(StreamError::Trap(anyhow::anyhow!(
213+
"Partial writes in wasip2 implementation are not allowed"
214+
)));
215+
}
216+
204217
Ok(())
205218
}
206219
fn flush(&mut self) -> Result<(), StreamError> {
207-
// This stream is always flushed
208220
Ok(())
209221
}
210222
fn check_write(&mut self) -> Result<usize, StreamError> {
211-
Ok(8192)
223+
Ok(usize::MAX)
212224
}
213225
}
214226

@@ -218,8 +230,18 @@ impl AsyncWrite for CustomOutputStream {
218230
_cx: &mut Context<'_>,
219231
buf: &[u8],
220232
) -> Poll<io::Result<usize>> {
221-
self.inner.write(buf);
222-
Poll::Ready(Ok(buf.len()))
233+
let wrote = self.inner.write(buf);
234+
Poll::Ready(if wrote >= 0 {
235+
Ok(wrote as _)
236+
} else {
237+
Err(io::Error::new(
238+
io::ErrorKind::Other,
239+
format!(
240+
"Custom write function failed with error code '{}'",
241+
wrote.abs()
242+
),
243+
))
244+
})
223245
}
224246
fn poll_flush(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<io::Result<()>> {
225247
Poll::Ready(Ok(()))
@@ -244,13 +266,13 @@ impl wasmtime_wasi::cli::StdoutStream for CustomOutputStream {
244266
#[unsafe(no_mangle)]
245267
pub extern "C" fn wasi_config_set_stdout_custom(
246268
config: &mut wasi_config_t,
247-
callback: Option<extern "C" fn(*mut c_void, *const u8, usize)>,
269+
callback: extern "C" fn(*mut c_void, *const u8, usize) -> isize,
248270
data: *mut c_void,
249271
finalizer: Option<extern "C" fn(*mut c_void)>,
250272
) {
251273
config.builder.stdout(CustomOutputStream::new(
252274
crate::ForeignData { data, finalizer },
253-
callback.expect("Callback must be provided"),
275+
callback,
254276
));
255277
}
256278

@@ -279,13 +301,13 @@ pub extern "C" fn wasi_config_inherit_stderr(config: &mut wasi_config_t) {
279301
#[unsafe(no_mangle)]
280302
pub extern "C" fn wasi_config_set_stderr_custom(
281303
config: &mut wasi_config_t,
282-
callback: Option<extern "C" fn(*mut c_void, *const u8, usize)>,
304+
callback: extern "C" fn(*mut c_void, *const u8, usize) -> isize,
283305
data: *mut c_void,
284306
finalizer: Option<extern "C" fn(*mut c_void)>,
285307
) {
286308
config.builder.stderr(CustomOutputStream::new(
287309
crate::ForeignData { data, finalizer },
288-
callback.expect("Callback must be provided"),
310+
callback,
289311
));
290312
}
291313

0 commit comments

Comments
 (0)