The theory behind returning a &str and Bool from Rust to WASM?

Hello,

I don't want to use wasm-bindgen because I don't want to get lost in a world of bundlers, (there is zero documentation on the web that explains wasm-bindgen without the use of webpack) and tbh, writing a barebones webassembly app is pretty fun, and a great learning experience.

So I have my arbitrarily complex Rust code working perfectly, but all I can return are i32s, (perhaps simply because I don't dare to try to send anything else!) I would like to return a bool, and also for debugging, I would like to console.log strings that I receive from Rust.

Could anyone enlighten me to the theory behind returning a string, and a bool? I'm guessing strings have to be sent as an array of numbers, possibly representing bytes, which then gets converted via javascript into a string. But I'm kind of guessing at this point, so don't really know where to begin.

Thank you kindly

This answer on StackOverflow details why you can only return numbers from WASM currently (although I'm not sure how up to date it is).

TL;DR: WebAssembly has no concept of a string, just numbers and linear memory. To return a string, you need to effectively return a pointer to the bytes in memory that make up that string, then decode it on the JS side. This is the sort of stuff that wasm-bindgen handles for you, if you opt to use it.

wasm-bindgen does have docs for using it without a bundler/Webpack, for what it's worth.

1 Like

For bool you can use what C does… return a i32 that is 0 (false) or not 0 (true).

Strings are a bit more complicated:
One approach is to return a *mut String and expose access methods to get the data pointer and length.

extern fn string_ptr(s: *mut String) -> *const u8 {
    unsafe {
      (*s).as_ptr()
    }
}

Once you have a pointer and length, you get a slice of the wasm memory in JS and decode the utf8 inside.

That still requires using wasm-pack though

That's my current setup, but I'm also using 0 to indicate success, on every other function, so a little bit contradictory. What about -0? That is recognized as different from +0, right?

One approach is to return a *mut String and expose access methods to get the data pointer and length.

Interesting. I'll have a think and a ponder about your solution tomorrow. I think I've seen some code somewhere that can call console.log from within Rust. Perhaps that's a good idea.

That's not true - for instance, glow's example uses wasm-bindgen on its own, without a bundler or wasm-pack. In my experience wasm-pack is mainly useful if you want to bundle a library for use on NPM/in the wider JS ecosystem, it's not something that's required for all wasm-bindgen projects.