Skip to content

Commit 45cf1b9

Browse files
committed
wasm lib and wire-up
1 parent 233bf60 commit 45cf1b9

11 files changed

+195
-5
lines changed

2023/package-lock.json

+6
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

2023/package.json

+4-1
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,13 @@
1515
"react-router-dom": "^6.20.1",
1616
"react-scripts": "5.0.1",
1717
"typescript": "^4.9.5",
18-
"web-vitals": "^2.1.4"
18+
"web-vitals": "^2.1.4",
19+
"aoc2023": "file:./wasm"
1920
},
2021
"scripts": {
2122
"start": "react-scripts start",
23+
"build:wasm:dev": "cd rust-aoc2023 && rm -Rf ../wasm && wasm-pack build --out-dir ../wasm --dev --target web",
24+
"build:wasm:release": "cd rust-aoc2023 && rm -Rf ../wasm && wasm-pack build --out-dir ../wasm --target web",
2225
"build": "react-scripts build",
2326
"test": "react-scripts test",
2427
"eject": "react-scripts eject"

2023/rust-aoc2023/.gitignore

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
/target
2+
**/*.rs.bk
3+
Cargo.lock
4+
bin/
5+
pkg/
6+
wasm-pack.log

2023/rust-aoc2023/.travis.yml

+69
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
language: rust
2+
sudo: false
3+
4+
cache: cargo
5+
6+
matrix:
7+
include:
8+
9+
# Builds with wasm-pack.
10+
- rust: beta
11+
env: RUST_BACKTRACE=1
12+
addons:
13+
firefox: latest
14+
chrome: stable
15+
before_script:
16+
- (test -x $HOME/.cargo/bin/cargo-install-update || cargo install cargo-update)
17+
- (test -x $HOME/.cargo/bin/cargo-generate || cargo install --vers "^0.2" cargo-generate)
18+
- cargo install-update -a
19+
- curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh -s -- -f
20+
script:
21+
- cargo generate --git . --name testing
22+
# Having a broken Cargo.toml (in that it has curlies in fields) anywhere
23+
# in any of our parent dirs is problematic.
24+
- mv Cargo.toml Cargo.toml.tmpl
25+
- cd testing
26+
- wasm-pack build
27+
- wasm-pack test --chrome --firefox --headless
28+
29+
# Builds on nightly.
30+
- rust: nightly
31+
env: RUST_BACKTRACE=1
32+
before_script:
33+
- (test -x $HOME/.cargo/bin/cargo-install-update || cargo install cargo-update)
34+
- (test -x $HOME/.cargo/bin/cargo-generate || cargo install --vers "^0.2" cargo-generate)
35+
- cargo install-update -a
36+
- rustup target add wasm32-unknown-unknown
37+
script:
38+
- cargo generate --git . --name testing
39+
- mv Cargo.toml Cargo.toml.tmpl
40+
- cd testing
41+
- cargo check
42+
- cargo check --target wasm32-unknown-unknown
43+
- cargo check --no-default-features
44+
- cargo check --target wasm32-unknown-unknown --no-default-features
45+
- cargo check --no-default-features --features console_error_panic_hook
46+
- cargo check --target wasm32-unknown-unknown --no-default-features --features console_error_panic_hook
47+
- cargo check --no-default-features --features "console_error_panic_hook wee_alloc"
48+
- cargo check --target wasm32-unknown-unknown --no-default-features --features "console_error_panic_hook wee_alloc"
49+
50+
# Builds on beta.
51+
- rust: beta
52+
env: RUST_BACKTRACE=1
53+
before_script:
54+
- (test -x $HOME/.cargo/bin/cargo-install-update || cargo install cargo-update)
55+
- (test -x $HOME/.cargo/bin/cargo-generate || cargo install --vers "^0.2" cargo-generate)
56+
- cargo install-update -a
57+
- rustup target add wasm32-unknown-unknown
58+
script:
59+
- cargo generate --git . --name testing
60+
- mv Cargo.toml Cargo.toml.tmpl
61+
- cd testing
62+
- cargo check
63+
- cargo check --target wasm32-unknown-unknown
64+
- cargo check --no-default-features
65+
- cargo check --target wasm32-unknown-unknown --no-default-features
66+
- cargo check --no-default-features --features console_error_panic_hook
67+
- cargo check --target wasm32-unknown-unknown --no-default-features --features console_error_panic_hook
68+
# Note: no enabling the `wee_alloc` feature here because it requires
69+
# nightly for now.

2023/rust-aoc2023/Cargo.toml

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
[package]
2+
name = "rust-aoc2023"
3+
version = "0.1.0"
4+
authors = ["Ashley Stanton-Nurse <[email protected]>"]
5+
edition = "2018"
6+
7+
[lib]
8+
crate-type = ["cdylib", "rlib"]
9+
10+
[features]
11+
default = ["console_error_panic_hook"]
12+
13+
[dependencies]
14+
wasm-bindgen = "0.2.84"
15+
16+
# The `console_error_panic_hook` crate provides better debugging of panics by
17+
# logging them with `console.error`. This is great for development, but requires
18+
# all the `std::fmt` and `std::panicking` infrastructure, so isn't great for
19+
# code size when deploying.
20+
console_error_panic_hook = { version = "0.1.7", optional = true }
21+
22+
[dev-dependencies]
23+
wasm-bindgen-test = "0.3.34"
24+
25+
[profile.release]
26+
# Tell `rustc` to optimize for small code size.
27+
opt-level = "s"

2023/rust-aoc2023/src/lib.rs

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
mod utils;
2+
3+
use wasm_bindgen::prelude::*;
4+
5+
#[wasm_bindgen]
6+
extern "C" {
7+
fn alert(s: &str);
8+
}
9+
10+
#[wasm_bindgen]
11+
pub fn greet() {
12+
alert("Hello, rust-aoc2023!");
13+
}

2023/rust-aoc2023/src/utils.rs

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
pub fn set_panic_hook() {
2+
// When the `console_error_panic_hook` feature is enabled, we can call the
3+
// `set_panic_hook` function at least once during initialization, and then
4+
// we will get better error messages if our code ever panics.
5+
//
6+
// For more details see
7+
// https://github.com/rustwasm/console_error_panic_hook#readme
8+
#[cfg(feature = "console_error_panic_hook")]
9+
console_error_panic_hook::set_once();
10+
}

2023/src/App.tsx

+1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { RouteObject, RouterProvider, createBrowserRouter } from 'react-router-d
22
import './App.css';
33
import Home from './Home';
44
import Day from './Day';
5+
import init from "aoc2023";
56

67
const dayRoutes: RouteObject[] = Array.from({ length: 25 }, (_, i) => ({
78
path: `days/${i + 1}`,

2023/src/Day.tsx

+21-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { ChangeEvent, useCallback, useRef, DragEvent, useState } from "react"
22
import { Link } from "react-router-dom"
3+
import { useWasm } from "./Wasm";
34

45
export interface DayProps {
56
day: number
@@ -63,6 +64,7 @@ function StandardDayPart({part}: {part: number}) {
6364
const [ result, setResult ] = useState<string | null>(null);
6465
const [ file, setFile ] = useState<File | null>(null);
6566
const [ input, setInput ] = useState<string | null>(null);
67+
const wasm = useWasm();
6668

6769
const handleFileSelect = useCallback((file: File) => {
6870
setFile(file);
@@ -73,6 +75,10 @@ function StandardDayPart({part}: {part: number}) {
7375
}, [setInput]);
7476

7577
const handleSolve = useCallback(async () => {
78+
if(!wasm) {
79+
return;
80+
}
81+
7682
// Get an array buffer with either the file or input text, preferring the input text
7783
const inputBuffer = input
7884
? new TextEncoder().encode(input)
@@ -81,9 +87,21 @@ function StandardDayPart({part}: {part: number}) {
8187
return;
8288
}
8389

84-
alert(`TODO: Send ${inputBuffer?.byteLength} byte input to Rust and get result back`);
90+
wasm.greet();
8591
}, [file, input]);
8692

93+
const disabledReason = useCallback(() => {
94+
if(!wasm) {
95+
return "(loading WASM...)";
96+
}
97+
98+
if(!file && !input) {
99+
return "(no input provided)";
100+
}
101+
102+
return "";
103+
}, [wasm, file, input]);
104+
87105
return <div className="text-center flex flex-col gap-2">
88106
<h3 className="font-semibold text-lg">Part {part}</h3>
89107
<p>Upload or enter your input (entered input has priority)</p>
@@ -94,12 +112,12 @@ function StandardDayPart({part}: {part: number}) {
94112
className="border-2 rounded-lg p-4 w-full h-96"
95113
onChange={handleTextInput} />
96114
</div>
97-
{file || input
115+
{wasm && (file || input)
98116
? <button onClick={handleSolve} className="bg-green-100 hover:ring-blue-500 hover:ring-2 active:bg-white rounded p-2 m-2 text-center">
99117
Solve
100118
</button>
101119
: <button disabled={true} className="bg-gray-100 rounded p-2 m-2">
102-
Solve
120+
Solve {disabledReason()}
103121
</button>}
104122
{result && <>
105123
<h3 className="font-semibold text-lg">Result</h3>

2023/src/Wasm.tsx

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import init, { type InitOutput } from "aoc2023";
2+
import { PropsWithChildren, createContext, useContext, useEffect, useState } from "react";
3+
4+
export interface WasmContextState {
5+
wasm: InitOutput | null;
6+
}
7+
8+
export const WasmContext = createContext<WasmContextState | null>(null);
9+
10+
export function useWasm() {
11+
const state = useContext(WasmContext);
12+
return state?.wasm;
13+
}
14+
15+
export default function WasmProvider({ children }: PropsWithChildren) {
16+
const [ wasm, setWasm ] = useState<InitOutput | null>(null);
17+
18+
useEffect(() => {
19+
(async function initWasm() {
20+
console.log("Loading WASM Module...");
21+
const module = await init();
22+
console.log("WASM Module loaded!");
23+
setWasm(module);
24+
})();
25+
}, [wasm, setWasm]);
26+
27+
const state = {
28+
wasm,
29+
};
30+
31+
return <WasmContext.Provider value={state}>
32+
{children}
33+
</WasmContext.Provider>
34+
}

2023/src/index.tsx

+4-1
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,16 @@ import ReactDOM from 'react-dom/client';
33
import './index.css';
44
import App from './App';
55
import reportWebVitals from './reportWebVitals';
6+
import WasmProvider from './Wasm';
67

78
const root = ReactDOM.createRoot(
89
document.getElementById('root') as HTMLElement
910
);
1011
root.render(
1112
<React.StrictMode>
12-
<App />
13+
<WasmProvider>
14+
<App />
15+
</WasmProvider>
1316
</React.StrictMode>
1417
);
1518

0 commit comments

Comments
 (0)