Building Your First WebAssembly Module in Rust
This challenge will guide you through the process of creating a WebAssembly (Wasm) module using Rust. WebAssembly is a binary instruction format for a stack-based virtual machine, designed as a portable compilation target for high-level languages like C, C++, and Rust, enabling deployment on the web for client and server applications. Successfully completing this will demonstrate your ability to leverage Rust for high-performance, cross-platform code.
Problem Description
Your task is to create a simple Rust library that will be compiled into a WebAssembly module. This module should expose a single function, add, that takes two i32 integers as input and returns their sum as an i32.
Key Requirements:
- Rust Project Setup: Create a new Rust project that is configured to build for a WebAssembly target.
- Wasm Function Export: Define a Rust function named
addthat accepts twoi32arguments and returns ani32. - Exporting the Function: Ensure that the
addfunction is correctly exported from the Wasm module so it can be called by JavaScript or other Wasm runtimes. - Compilation: Compile your Rust code into a
.wasmfile.
Expected Behavior:
When the compiled Wasm module is loaded and the add function is invoked with two i32 values, it should return the correct arithmetic sum of those values.
Edge Cases to Consider:
- Integer overflow: While Rust's default behavior for
i32addition in debug mode is to panic on overflow, in release mode, it will wrap. For this challenge, assume standard integer arithmetic.
Examples
Example 1:
- Input to Wasm Function:
add(5, 10) - Expected Output from Wasm Function:
15 - Explanation: The
addfunction receives 5 and 10, and returns their sum, 15.
Example 2:
- Input to Wasm Function:
add(-3, 7) - Expected Output from Wasm Function:
4 - Explanation: The
addfunction receives -3 and 7, and returns their sum, 4.
Example 3:
- Input to Wasm Function:
add(i32::MAX, 1) - Expected Output from Wasm Function:
i32::MIN(due to wrapping in release mode) - Explanation: This demonstrates integer overflow behavior where the result wraps around. For this challenge, you do not need to implement specific overflow handling beyond Rust's default.
Constraints
- The Rust compiler version used should be recent (e.g., 1.60.0 or later).
- The only external dependency allowed is
wasm-bindgenfor easier integration if desired, but the core challenge can be met without it by using Rust's built-in Wasm support. - The final output should be a single
.wasmfile. - Performance is not a primary concern for this introductory challenge; correctness and compilation are key.
Notes
- You will need to set up your Rust environment to cross-compile for WebAssembly. This typically involves installing the appropriate target using
rustup:rustup target add wasm32-unknown-unknown. - When compiling, you'll use
cargo build --target wasm32-unknown-unknown. - To make your Rust function callable from JavaScript, you'll often use a tool like
wasm-bindgenwhich can generate JavaScript bindings. However, for this challenge, simply compiling towasm32-unknown-unknownand verifying the exported function is sufficient. The#[no_mangle]attribute might be useful to ensure the function name is preserved. - Consider how to "export" functions in Rust for Wasm. The
#[wasm_bindgen]attribute from thewasm-bindgencrate is the standard way to do this, but if you choosewasm32-unknown-unknown, you'll need to be mindful of how functions become available. Forwasm32-unknown-unknown, functions without#[wasm_bindgen]are generally not directly callable from external environments without a Wasm runtime that exposes them. For this challenge, if you don't usewasm-bindgen, you can aim for#[no_mangle]and understand that direct invocation might require a bit more setup in a host environment.