{
"path": "/posts/rust-for-javascript-engineers-all-a-board",
"site": "at://did:plc:pans3xjam4khj7y54dx7gtfg/site.standard.publication/3mdqevmg6w32c",
"tags": [
"rust",
"game dev",
"WASM"
],
"$type": "site.standard.document",
"title": "Rust for JavaScript Engineers - All a Board",
"description": "Calling JS from Rust, building the Connect-4 board as a Vec, and rendering it as HTML across the WASM boundary.",
"publishedAt": "2025-08-23T23:50:09.000Z",
"textContent": "<a href=\"/connectors\" target=\"_blank\" rel=\"noopener noreferrer\">Connect Four</a> | <a href=\"https://github.com/tauseefk/connectors\" target=\"_blank\" rel=\"noopener noreferrer\">Repository</a>\n\nIn the last post we looked at setting up the codebase to build Rust crates, and then importing them into a JavaScript project.\n\nBy the end of the post we'd gone over a simple enum based design for each position of the Connect 4 board. In this post, I'm going to expand on how we can take that simple data structure, build out the entire grid, and then render it using HTML elements.\n\nBut first, a bit of house-keeping.\nWe'd looked at calling Rust functions from JavaScript, but not the other way around. So let's dive into that.\n\nCalling Home\n\nLet's expose a JavaScript function (Math.random), on the global object as that's how it is made available to WASM. Everything else remains the same.\n\nRight now if we try to call: mathRandom directly in Rust, the compiler won't let us build.\n\nLet's repurpose our say_hello function with this:\n\nOn re-building connecto.rs, it throws the following error.\n\nThe problem here is that even though the function is attached to the window object, Rust has no way of knowing it exists.\nNow let's write the equivalent of a \"trust me bro\" to placate the Rust compiler.\n\n1.\n\nThe extern block is used as an FFI (Foreign Function Interface) to allow Rust code to call foreign code. This generally means that the safety guarantees of the Rust compiler can't save you anymore, and you better be really sure about what this function does.\n\n2.\n\nThe second thing worth highlighting is the js_name = mathRandom. This is a way to translate names between JavaScript and Rust, so we can maintain appropriate style-guides on either end of the FFI.\n\n3.\n\nIn our Rust code the function will be available as math_random and as the javascript function Math.random returns a floating point value between 0-1 the return type of f32 will suffice. Let's put it to use.\n\nOnce re-compiled the app should log:\n\nRandom number: 0.7674366\n\nThe actual random number would vary.\n\nAs calling JavaScript's standard library function is a common thing people do, the js_sys crate conveniently provides us handles to all of them.\nLet's swap our hand-rolled version of Math.random and just use the one provided by the crate.\n\nThat works as expected: Random number: 0.583796439883168\n\nPrinting the grid\n\nFor rendering the grid it would be ideal to only print 1 character per enum variant so all the positions align. Let's update the Display trait implementation.\n\nIf you rememeber from the last time, the Display trait is implemented so when we try to print each of the TileType variants the actual string will be displayed.\n\nLet's try printing the enum variant.\n\nThis now prints: Tile 1 belongs to: R\n\nAnd with that we're ready to print the entire connect 4 board. As printing an empty board is not fun, let's generate a randomized board using the js_sys::Math::random() function.\n\nGame Board\n\nThis should be fairly similar to a JavaScript function that tries to populate an array with enum values.\nThe as keyword is used to cast one type of number into another, and we want to go from a floating point number to a whole number.\nIn this case as we're never going to have more than 3 variants, there's no need to store anything larger than an unsigned 8-bit int (max value: 255).\n\nLet's print this sucker.\n\nThis should print a nice randomly populated grid of R | B | _.\n\nConnect-4 boards cannot assume arbitrary random states due to the constraint of each tile dropping to the lowest available position. However we'll come back to that after we look at sending this data over to the JavaScript side.\n\nReturning the grid\n\nLet's expose our TileType enum to the JavaScript side by adding a #[wasm_bindgen] macro at it's top.\n\nSo far we've only exposed a function and an enum to the JavaScript side, however another data type struct is more suitable for returning custom data structures.\nLet's start by creating a new struct that can be later reused to implement the gameplay.\n\nNothing new here, the wasm_bindgen macro will create the JavaScript glue code for this struct. usize just means unsigned int corresponding to the size of memory addresses for your particular machine. For most modern machines this translates to u64.\n\nNow let's expose a constructor:\n\nThe glue code for struct results in a JavaScript class. All JavaScript classes (other than pure static ones) need to be instantiated. new constructor ends up becoming a static method on the corresponding Board class in the JavaScript package.\nWe can instantiate it like this: const board = Board.new(6, 7).\n\nLet's add another method that can return the randomized board we generated earlier:\n\n1.\n\nThe best way to return array like data from Rust to JavaScript is TypedArrays, and in this case it ends up being a Uint8Array. As each board position can only take one of three enum variants, 8-bits are more than sufficient.\n\n2.\n\nSlices are one of three array like data types available in Rust. The details are outside the scope of this tutorial and the Rust book provides a much better explanation than I'd be able to here.\n\nNow let's get rid of our say_hello function as we won't been needing that anymore, and print the data received on the JavaScript side.\n\nThis is the entirely of the script now:\n\nThis should print an entire 7x6 grid of randomized Tiles.\n\nRendering Board as HTML\n\nThis part should be familiar. As we have all the data on the JavaScript side, we can use it to render the Board as HTML instead of logging it to the console.\n\nWe won't go into the CSS changes, but feel free to get creative here.\nThe full project at this stage is here.\n\nWe're getting close to gameplay now. In the next post we'll look into adding player turns to the Board struct, and some methods that allow players to make moves.",
"canonicalUrl": "https://afloat.boats/posts/rust-for-javascript-engineers-all-a-board"
}