How to make ReadableStreamByobReader.read_with_u8_array() work? #3579
-
SummaryI have a On this reader, I want to read to a user-provided array, so I use But I always get the following error:
Here is a sample for illustration: fn sample(readable: web_sys::ReadableStream, buf: &mut [u8]) {
let reader = readable.
get_reader_with_options(
web_sys::ReadableStreamGetReaderOptions::new()
.mode(web_sys::ReadableStreamReaderMode::Byob),
)
.dyn_into::<web_sys::ReadableStreamByobReader>()
.expect("Invalid readable stream");
let promise = reader.read_with_u8_array(buf);
let obj = JsFuture::from(promise).await;
console::log_1(&JsValue::from_str(&format!("{obj:?}")));
} In the console, I get:
(btw, the console log seems truncated, I don't know why) |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 10 replies
-
This is apparently a limitation by the spec.
Which already has a note there saying:
This is actually not correct anymore, see the new spec:
Was fixed in 2018: WebAssembly/spec#889. I guess browsers didn't catch up yet, tried it in Firefox and Chrome. |
Beta Was this translation helpful? Give feedback.
-
If I call Here is a modified sample: fn sample(readable: web_sys::ReadableStream, buf: &mut [u8]) -> Result<Option<usize>, JsValue> {
let reader = readable.
get_reader_with_options(
web_sys::ReadableStreamGetReaderOptions::new()
.mode(web_sys::ReadableStreamReaderMode::Byob),
)
.dyn_into::<web_sys::ReadableStreamByobReader>()
.expect("Invalid readable stream");
let typed_array = js_sys::Uint8Array::new(&JsValue::from(buf.len()));
let promise = reader.read_with_array_buffer_view(&typed_array);
let obj = JsFuture::from(promise).await?;
// now it works, and I can retrieve the value
let done = js_sys::Reflect::get(&obj, &JsValue::from("done"))?
.as_bool()
.unwrap_or(false);
if done {
Ok(None)
} else {
let array = js_sys::Reflect::get(&obj, &JsValue::from("value"))?
.dyn_into::<js_sys::Uint8Array>()
.expect("Unexpected read value");
let len = array.byte_length() as usize;
array.copy_to(&mut buf[..len]);
Ok(Some(len))
}
} |
Beta Was this translation helpful? Give feedback.
Yes.
There's actually a pretty good reason for this.
ReadableStreamBYOBReader
doesn't quite work like you'd expect: you can't just pass it aUint8Array
, wait for the promise to resolve, and then read the results out of the original buffer like you can in something like Rust'sstd::io::Read::read
.This is because it actually takes control over the
Uint8Array
while it's being read into. You can't access it anymore until the promise gives it back to you, and the original reference to it stays invalid forever. You can only access it through the new referenc…