Why Rust and WebAssembly
A four-function calculator does not need Rust. This one uses it because the interesting part of a calculator is not the arithmetic, it is the handful of inputs for which there is no correct answer. Writing the engine in Rust and compiling it to WebAssembly makes those cases the compiler's problem rather than the reviewer's, and it keeps every calculation on the user's own machine. This page explains both halves of that choice.
Errors are values, not special numbers
In JavaScript, dividing by zero gives Infinity and taking the square root of a negative number gives NaN. Both are ordinary numbers as far as the language is concerned, so they flow through every later operation without complaint and surface as a wrong answer several steps downstream. In Rust, division and square root return a Result type, and the compiler will not let the calling code use the value without first dealing with the possibility of failure. The three failure cases become the three documented errors on the errors page rather than three silent numeric surprises.
The same argument covers integer overflow. Factorial is computed with checked multiplication, which returns an error rather than wrapping around to a small positive number. That is the difference between the calculator telling you 21! is out of range and the calculator confidently showing you a number that is off by 18 quintillion.
No server, no round trip
WebAssembly is what lets compiled Rust run inside a browser tab. The module is fetched once when the page loads and every key press after that is a local function call. There is no calculation endpoint, nothing to rate limit, nothing to go down, and no record of what anyone typed. It also means the calculator keeps working on a flaky connection once the page is loaded.
Keeping the module small
A calculator that needs a large download before it can add two numbers is a bad trade. The release profile in this crate sets opt-level = "z", which optimises for size rather than speed, and enables link-time optimisation, which strips code paths nothing reaches. The build is produced by wasm-pack build --target web, which emits both the WebAssembly binary and the JavaScript glue the page imports as an ES module.
Optimising for size rather than speed costs nothing here. The heaviest thing the calculator computes is a loop of at most 20 multiplications, which is far below the point where the difference between size-optimised and speed-optimised code is measurable by a human.
What the toolchain actually produces, and how the browser fetches and instantiates it, is covered on the build output page. The shape of the boundary itself — why every value is a float and what a fallible call costs — is on the f64 boundary page.
Tested on the Rust side
The crate carries 86 unit tests, and they all pass. They cover the arithmetic, the memory register, the history record, and the edge cases that motivated the choice of Rust in the first place: division by zero, square root of a negative number, factorial overflow at 21 and beyond, floating point imprecision when adding 0.1 and 0.2, and values as extreme as 10 to the power of 150. Because the engine is a plain Rust library as well as a WebAssembly module, those tests run natively without a browser or a headless driver. A further 11 tests run against the compiled WebAssembly itself, covering the exported wrappers, the history serialisation, and the real conversion of a Rust error into a JavaScript exception. The testing page explains why both suites are needed.
Questions and answers
Why write a calculator in Rust instead of JavaScript?
For compiler-enforced error handling. Division and square root return a Result type and factorial uses checked multiplication, so division by zero, negative square roots, and integer overflow become explicit errors instead of Infinity, NaN, or a wrapped number.
Does using WebAssembly make the calculator faster?
Speed is not the reason it is used here. The heaviest computation is a loop of at most 20 multiplications. WebAssembly is used because it lets compiled Rust run in the browser with no server round trip.
How large is the WebAssembly module?
The release profile is built with opt-level z and link-time optimisation, which optimises for size rather than speed and strips unreachable code paths, keeping the module small enough to fetch on first load.