wasm-bindgen icon indicating copy to clipboard operation
wasm-bindgen copied to clipboard

Allow returning fixed-size tuples and arrays

Open dbrgn opened this issue 6 years ago • 19 comments

It appears that returning (f32, f32, f32, f32) or [f32; 4] in a #[wasm_bindgen] function does not currently work. Would be great if fixed size arrays and tuples (maybe up to length 32) were supported.

dbrgn avatar Apr 12 '18 22:04 dbrgn

I think fixed-size-arrays are in theory easy enough (we'd probably pass them through allocated memory), tuples are a bit odder though. You're mostly looking for homogenous tuples, right? And both of these in JS would pop out as arrays?

alexcrichton avatar Apr 17 '18 20:04 alexcrichton

Yes. In my case I'd like to pass a list of 2D-coordinates to JS. Using a fixed size array would work fine too of course.

dbrgn avatar Apr 17 '18 20:04 dbrgn

Would love to see this as well, for both arrays and tuples. The output for either could be a JS array.

David-OConnor avatar Jul 10 '18 03:07 David-OConnor

This would be great.

In my use case, I wanted to return RGB value as 3 elements tuple or array of u8. However, they are not yet supported so I needed to create a struct like

#[wasm_bindgen]
pub struct Rgb { pub r: u8, pub g: u8, pub b: u8 }

But it is not so efficient since in JavaScript, accessing each field causes interaction between wasm and JS.

console.log(color.r, color.g, color.b);

For this use case, I could finally use 0xrrggbb format of u32 values for RGB values. But it's a solution only for this use case.


I also think mapping tuples to JS array is fine and reasonable. TypeScript supports tuples and actually it is transpiled into array.

https://www.typescriptlang.org/docs/handbook/basic-types.html

rhysd avatar Jan 25 '19 03:01 rhysd

As another use-case, I think tuples support could improve interfaces for js-sys iterators too.

In particular, .entries() on Map / Set / Array could produce an iterator over tuples of (JsValue, JsValue) right away instead of users having to repeat same boilerplate with JsArray + Reflect::get_u32(..., 0) + Reflect::get_u32(..., 1) to extract key and value on each iteration.

RReverser avatar Apr 13 '19 01:04 RReverser

Just an update - I imagine this might become easier these days (or, at least, soon) by leveraging multi-value Wasm feature.

RReverser avatar Apr 16 '20 01:04 RReverser

In case it's relevant to the discussion (e.g. RE wasm-bindgen backwards compatibility concerns, if there are any), and in case others are unaware, JS will probably get tuples in the next couple of years. The tc39 proposal repo has 1.4k stars (very high - up there with the decorators proposal) and the proposal is at stage 2 as of writing.

josephrocca avatar Apr 25 '21 20:04 josephrocca

@josephrocca, Tuples refer to Rust tuples, Wasm multi-value tuples return JavaScript arrays, and it would make the most sense to target the Wasm feature so that some cases won't need a wasm-bindgen shim at all.

ghost avatar Apr 25 '21 20:04 ghost

Are we waiting for the TC39 tuple proposal?

ForkKILLET avatar Mar 21 '22 04:03 ForkKILLET

@alexcrichton

I think fixed-size-arrays are in theory easy enough (we'd probably pass them through allocated memory)

is this still the case? I'm not too familiar with the internals of wasm_bindgen (yet), but I'd be interested in taking a stab at this!

stegaBOB avatar May 09 '23 22:05 stegaBOB

@stegaBOB I'm not entirely sure how easy or hard to implement this really is, but I'm happy to review a PR!

daxpedda avatar May 09 '23 23:05 daxpedda

@daxpedda I think we're pretty close to getting something that's working & ready for a review! As of now we're focused on getting fixed size arrays working only for compiling w/ multi-value. Would proceeding like that and throwing a runtime error on wasm-bindgen-cli if fixed size arrays exist and multi value is off be an acceptable change?

stegaBOB avatar May 25 '23 07:05 stegaBOB

Last time I checked multi-value doesn't currently work in Rust: https://github.com/rust-lang/rust/issues/73755.

I wouldn't mind merging something that doesn't work for now, but I also don't want to merge something I can't even test.

daxpedda avatar May 25 '23 10:05 daxpedda

@daxpedda I meant multi value using the multi-value-xform wasm-bindgen crate, not natively multi value. We ran into that rust issue as well unfortunately, but the transformer seems to work fine (although we also made a couple modifications to that transformer too)

stegaBOB avatar May 25 '23 16:05 stegaBOB

Would proceeding like that and throwing a runtime error on wasm-bindgen-cli if fixed size arrays exist and multi value is off be an acceptable change?

Sounds good then!

daxpedda avatar May 25 '23 21:05 daxpedda

Any examples on where this is implemented? Couldn't get it working from current documentation

lancenonce avatar May 29 '23 20:05 lancenonce

Any examples on where this is implemented? Couldn't get it working from current documentation

We're currently doing the wasm-bindgen work here: https://github.com/staratlasmeta/wasm-bindgen. It's not in a working state at the moment and there's still work we'll need to do, but its getting there.

stegaBOB avatar May 29 '23 21:05 stegaBOB

We currently have fixed size arrays for most numeric primitives working when using the WASM_BINDGEN_MULTI_VALUE=true option! Still a bit of work to be done (testing, clean up, making it work when multi value is disabled, etc), but I think we're close! I've opened a draft PR in the meantime if anyone wants to take a look at what we have so far: #3458.

stegaBOB avatar Jun 04 '23 06:06 stegaBOB

Thank you for the update! 🚀

lancenonce avatar Jun 05 '23 12:06 lancenonce