Get a Look on Key Rust Crates for WebAssembly

Reading Time: 4 minutes
This image has an empty alt attribute; its file name is blogwal.jpg

WebAssembly is the future of Web Development. It is a low-level assembly-like language with a compact binary format that runs with near-native performance and provides languages such as C/C++ and Rust with a compilation target so that they can run on the web.

Hello, folks! your wait is over, we have come up with a new blog WebAssembly with Rust. In this blog, we will take a look at some key Crates/Libraries which we can use in the development of WebAssembly applications with Rust. Hope you will enjoy the blog.

We have separated the Rust crates into various types according to its features:

  • Dynamic Allocation.
  • Parsing and generating .wasm binaries.
  • Interpreting and compiling webAssembly.
  • Interacting with JavaScript with DOM.
  • Error reporting and logging.

We will discuss these types one by one.

Dynamic Allocation

wee_alloc:

wee_alloc is focused on targeting WebAssembly, producing a small .wasm code size, and having a simple, correct implementation. It is geared towards code that makes a handful of initial dynamically sized allocations, and then performs its heavy lifting without any further allocations.

This scenario requires some allocator to exist, but we are more than happy to trade allocation performance for small code size. In contrast, wee_alloc would be a poor choice for a scenario where allocation is a performance bottleneck.

Features of we_alloc:

  • size_classes: On by default. Use size classes for smaller allocations to provide amortized O(1) allocation for them. Increases uncompressed .wasm code size by about 450 bytes (up to a total of ~1.2K).
  • extra_assertions: Enable various extra, expensive integrity assertions and defensive mechanisms, such as poisoning freed memory. This incurs a large runtime overhead. It is useful when debugging a use-after-free or wee_alloc itself.
  • static_array_backend: Force the use of an OS-independent backing implementation with a global maximum size fixed at compile time. Suitable for deploying to non-WASM/Unix/Windows #![no_std] environments, such as on embedded devices with esoteric or effectively absent operating systems.

Parsing and generating .wasm binaries

party-wasm:

Party-wasm is Low-level WebAssembly format library for serializing, deserializing, and building .wasm binaries. Good support for well-known custom sections, such as the “names” section and “reloc.WHATEVER” sections.

wasmparser:

wasmparser is a parser library reports events as they happened and only stores parsing information for a brief period of time, making it very fast and memory-efficient. The event-driven model, however, has some drawbacks. If you need random access to the entire WebAssembly data-structure, this is not the right library for you. This library can help you to achieve it.

Interpreting and compiling WebAssembly

wasmi:

wasmi is a WebAssembly interpreter which was conceived as a component of parity-ethereum and substrate. These projects are related to blockchain and require a high degree of correctness, even if that might be over conservative. This specifically means that we are not trying to be involved in any implementation of any of work-in-progress Wasm proposals. We are also trying to be as close as possible to the spec, which means we are trying to avoid features that is not directly supported by the spec. This means that it is flexible on the one hand and on the other hand there shouldn’t be a problem migrating to another spec compliant execution engine.

wasmtime:

The Wasmtime crate is an embedding API of the Wasmtime WebAssembly runtime. This is intended to be used in Rust projects and provides a high-level API of working with WebAssembly modules.

Features of wasmtime:

  • Lightweight. Wasmtime is a standalone runtime for WebAssembly that scales with your needs. It fits on tiny chips as well as makes use of huge servers.
  • Fast. Wasmtime can help to generate the high-quality machine code at runtime.
  • Configurable. Whether you need to precompile your wasm ahead of time, generate code blazingly fast with Lightbeam, or interpret it at runtime, Wasmtime has you covered for all your wasm-executing needs.
  • WASI. Wasmtime supports a rich set of APIs for interacting with the host environment through the WASI standard.

Interacting with Javascript and DOM

wasm-bindgen:

This crate contains the runtime support necessary for wasm-bindgen the attribute and tool. Crates pull in the #[wasm_bindgen] attribute through this crate and this crate also provides JS bindings through the JsValue interface.

Features of wasm-bindgen:

  • Lightweight. Only pay for what you use wasm_bindgen only generates bindings and glue for the JavaScript imports you actually use and Rust functionality that you export. For example, importing and using the document.querySelector method doesn’t cause Node.prototype.appendChild or window.alert to be included in the bindings as well.
  • ECMAScript modules. Just import WebAssembly modules the same way you would import JavaScript modules. Future compatible with WebAssembly modules and ECMAScript modules integration.
  • Designed with the “Web IDL bindings” proposal in mind. Eventually, there won’t be any JavaScript shims between Rust-generated wasm functions and native DOM methods. 

wasm-bindgen-futures:

wasm-bindgen-futures crate provides a bridge for working with JavaScript Promise types as a Rust Future, and similarly contains utilities to turn a rust Future into a JavaScript Promise. This can be useful when working with asynchronous or otherwise blocking work in Rust (wasm), and provides the ability to interoperate with JavaScript events and JavaScript I/O primitives.

web-sys:

web-sys crate by default contains very little when compiled as almost all of its exposed APIs are gated by Cargo features. The exhaustive list of features can be found in crates/web-sys/Cargo.toml, but the thumb rule for web-sys is that each type has its own cargo feature (named after the type). Using an API requires enabling the features for all types used in the API, and APIs should mention in the documentation what features they require.

Error reporting and loging

console_error_panic_hook:

console_error_panic_hook helps us to debug the errors of the WebAssembly application by providing a panic hook that forwards panic messages to console.error. When an error is reported with console.error, browser dev tools and node.js will typically capture a stack trace and display it with the logged error message.

console_log:

console_log help us to formatting of log messages (timestamps, file and line info, etc.) this crate can be used with the fern logger via the console_log::log function.

Example:

This image has an empty alt attribute; its file name is screenshot-from-2020-04-10-20-40-03.png

Note: I hope our blogs help you to enhance your learning. I’ll post more blogs on WebAssembly with Rust. Stay Tuned.
Happy learning!!!

References:

This image has an empty alt attribute; its file name is footer-2.jpg

Written by 

Pankaj Chaudhary is a Software Consultant at Knoldus LLP. Who has good knowledge of Rust, Python, Java, and C. Now he is working as Rust developer and also work on machine learning and data analysis because he loves to play with data and extract some useful information from it. His hobbies are bike riding and explore new places.