5

I'm working on a project that's meant to be compiled to webassembly. So I guess I have to mark the library as no_std. But as it currently relies on Vec, String and HashSet quite a lot this seems to be impossible as I get errors for those features.

How can I remove/replace those features without loosing the functionality in a no_std environment like webassembly. I guess I could go for &str instead of String, but what about the others?

If I remove #![cfg_attr(not(test), no_std)] and compile the project it seems to work as a webassembly binary. Why is that, if I get errors when adding the line?

mottosson
  • 3,283
  • 4
  • 35
  • 73
  • 6
    Compiling to webassembly doesn't require `no_std` – kmdreko Dec 27 '20 at 19:48
  • 2
    Oh! I thought wasm was a no_std environment. I've seen no_std mentioned in every other post about wasm so that's why I thought so. https://rustwasm.github.io/docs/book/reference/which-crates-work-with-wasm.html says: `A good rule of thumb is that if a crate supports embedded and #![no_std] usage, it probably also supports WebAssembly.` for example. – mottosson Dec 27 '20 at 20:53
  • 2
    The `wasm32-unknown-unknown` target does have the `std` crate available, but not all parts are implemented. (You can see this [here](https://github.com/rust-lang/rust/blob/76188b6830897a875a1289809c12b5c5d69bb7ef/library/std/src/sys/wasm/mod.rs#L19-L48) in the Rust source code.) So if you try to use `std::fs` or `std::net` in WebAssembly, for example, your code can panic or return an error. But for things like `Vec` and `HashMap` there should be no problems. – Frxstrem Dec 27 '20 at 21:00
  • 1
    Great! That explains it then! :) Thanks! Are there any reasons to try to keep it no_std in wasm? – mottosson Dec 27 '20 at 21:36
  • It can help keep binary sizes small. – gxtaillon Mar 06 '22 at 19:12

2 Answers2

12

As has been mentioned in the comments, you don't need to restrict yourself to no_std in WASM, since much of the standard library is available, including both of these collections.

However, if you're building in a real no_std environment, you can use Vec provided you use the alloc crate, which allows you to allocate memory. String is likewise available. In most situations, you will have some memory allocation available, so alloc is an option.

You can't use HashMap or HashSet in a no_std environment because to avoid hash collision attacks, they need to have access to a secure source of random data. Even no_std environments may deal with untrusted data, so preserving this security invariant is important. There, you can use the BTreeMap and BTreeSet instead (also from alloc), which provide similar functionality with slightly different performance characteristics and slightly different requirements on the data in question. Because these collections are deterministic, they can be implemented without more than a memory allocator.

bk2204
  • 64,793
  • 6
  • 84
  • 100
4

Use the hashbrown crate. It’s a standalone export of the Rust standard library’s HashMap, but as mentioned before it does depend on the existence of a global allocator to function.

realkstrawn93
  • 722
  • 1
  • 6
  • 13