Using JSON Data in a Rust WebAssembly/wasm Module
Beginner Deck
I'm working on a toolmtg to make Magic: The Gathering Commander decks. It works okay if you send in 100 cards. It falls over if you give it 1,000 to sort through. A bummer, as that's the entire point.
I used performance.now()pn to measure times for adjusting individual cards. They average at 1ms per when there's 100. Updates jump to 30-100ms each when there's a thousand. Net result: things lock up. Then, they time out.
The page doesn't do that much, it's mainly updating data-* attributes that CSS uses to position and highlight things. The CSS was fine with a thousand cards in an earlier iteration. I know it can handle it. That points to the calculations for making changes as the problem.
The calculations are done in JavaScript. I could dig in and optimize them. Or, I could use this as an opportunity to learn a little about how wasm works. There's a chance that if use the same approach, but in rust, it'll have the speed I need. Me being me, I'm going with that.
First thing to figure out was how to get wasm to work at all. Took a little poking, but I got it goinginit. Next up: figuring out how to ingest and use the data.
Show Me The Data
The source data comes from Archidektdekt. It's a big ol' json from their APIapi. The goal is to ingest it, refine it, export the updates, then push them back to Archidekt. So, I'm looking at basic CRUDcrud. I created the following rust prototype to figure out the pipeline.
./Cargo.toml
[package]
name = "wasm_json_data_parser"
version = "0.1.0"
edition = "2024"
[lib]
crate-type = ["cdylib"]
[dependencies]
once_cell = "1.21.3"
serde = { version = "1.0.228", features = ["derive"] }
serde_json = "1.0.149"
wasm-bindgen = "0.2.108"
web-sys = { version = "0.3.85", features = ["console"] }./src/lib.rs
use Lazy;
use ;
use Mutex;
use *;
use console;
static GLOBAL_KNOWLEDGE: =
new;
;
./index.html
click me
Running this wasm-packwp command generates the pkg
directory and files used in the index.html
file.
Simple(ish) But Effective
Here's what it looks like on a page:
Bits and Bobs
A few notes on how things fit together:
-
The
wasm_json_data_parser.jsfile pulls in a secondwasm_json_data_parser_bg.wasmfile. They are 9KB and 108KB, respectively. While that's a sizeable payload for such basic functionality, it's not unreasonable. Especially if it gets the thing I'm working on to actually work. -
This is my first run at both wasm and keeping persistent data around inside it. It feels like there's an extra step in the middle where the JavaScript hits
Oraclewhich then calls out to theKnowledgeinstance for the actual functionality. I took a few runs are removing that layer. Haven't hit on anything that works yet. -
It also feels like there's an extra layer holding
DatainsideKnowledge. I couldn't figure out how to load the JSON directly intoKnowledge. It's created before the JSON comes with: -
It feels like there should be a way to reduce the duplication of the lines unlocking
GLOBAL_KNOWLEDGE. I tried moving the repeated lines to a single funciton and calling it. Didn't figure that out yet. -
Calling everything as functions on the class feels weird. That is, doing this:
Instead of something like:
I tried to set that up. All I got was errors.
But, whatever, calling on the class works just fine.
Onward
Overall, I very happy with the code. Sure, it would be great to figure how to slim things down. But, I'll take working code any way I can get it. Especially when it's my first crack at it.
Next step is to use this structure to implement the features for me Deck Refiner. I'll write up the results of that when I'm done.
-a
References
This is the main thing in the mix for doing the wasm.
The bog standard way to work with data structures.
Footnotes
The idea is to throw a bunch of possible cards into an oversized deck then whittle it down to 100 for a commander deck.
The preferred way to check how long things are taking to do their thing on a web page.
A quick run getting a WebAssembly module up and running in Rust.
Very cool tool for searching for cards and assembling decks. My thing is based off it. Just with another way to look at cards to refine decks.
Archidekt let's you pull data from their API. For example, here the JSON for one of my earlier decks:
Create, Read, Update, and Delete. The most fundamental of tooling interactions.
I'm still getting my head wrapped around wasm, but the general idea is to use something like wasm-pack to compile your rust into a javascript file and a wasm file. You call the JS from your page which then does incantations to pull in the wasm.
You'll need to install wasm-pack to run the command.