rust/wasm from js
Some learnings related to using rust/wasm from js...
Call rust/wasm from js...
Some learnings related to using rust/wasm from js...
-
When you create Vec3 object, you can manipulate mostly like you expect
const vec3 = new Vec3(0, 1, 2); vec3.x = 42; // This works because we have a rust object
-
wasm_bindgen can not return references due to rust's borrowing... So setting properties on sub objects fail because they are copies instead of a reference.
const camera = new Camera(45, 1.7, 1, 1000); camera.position = new Vec3(3, 42, 3); // This works because we are replacing the whole object // Fails quietly!!!! camera.position.x = 42; // position is a copy, not a reference...
Can't fix it either, because we can't return a reference due to the borrow checking
#[cfg_attr(target_arch = "wasm32", wasm_bindgen(getter))] pub fn position(&self) -> &Vec3 { // error: cannot return a borrowed ref with #[wasm_bindgen] self.position }
vec3.rs
use serde::{Deserialize, Serialize};
use serde_wasm_bindgen::from_value;
#[cfg(target_arch = "wasm32")]
use wasm_bindgen::prelude::*; // Use serde_json for JSON serialization
#[cfg_attr(target_arch = "wasm32", wasm_bindgen)]
#[derive(Serialize, Deserialize, Clone, Copy)]
pub struct Vec3 {
#[serde(default)]
pub x: f32,
#[serde(default)]
pub y: f32,
#[serde(default)]
pub z: f32,
}
#[cfg_attr(target_arch = "wasm32", wasm_bindgen)]
impl Vec3 {
#[cfg_attr(target_arch = "wasm32", wasm_bindgen(constructor))]
pub fn new(x: f32, y: f32, z: f32) -> Vec3 {
Self { x, y, z }
}
#[cfg_attr(target_arch = "wasm32", wasm_bindgen(js_name = toString))]
pub fn to_string(&self) -> String {
format!("Vec3(x: {}, y: {}, z: {})", self.x, self.y, self.z)
}
#[cfg_attr(target_arch = "wasm32", wasm_bindgen(js_name = toJSON))]
pub fn to_json(&self) -> Result<JsValue, JsValue> {
Ok(serde_wasm_bindgen::to_value(&self)?)
}
// Static method to create a Vec3 instance from a JsValue
#[cfg_attr(target_arch = "wasm32", wasm_bindgen(js_name = fromJSON))]
pub fn from_json(value: JsValue) -> Result<Vec3, JsValue> {
from_value(value).map_err(|e| JsValue::from_str(&e.to_string()))
}
}
camera.rs
use crate::vec3::Vec3;
use serde::{Deserialize, Serialize};
#[cfg(target_arch = "wasm32")]
use wasm_bindgen::prelude::*; // Use serde_json for JSON serialization
#[cfg_attr(target_arch = "wasm32", wasm_bindgen)]
#[derive(Serialize, Deserialize)]
pub struct Camera {
fov: f32,
aspect: f32,
near: f32,
far: f32,
position: Vec3,
}
#[cfg_attr(target_arch = "wasm32", wasm_bindgen)]
impl Camera {
#[cfg_attr(target_arch = "wasm32", wasm_bindgen(constructor))]
pub fn new(fov: f32, aspect: f32, near: f32, far: f32) -> Self {
Camera {
fov,
aspect,
near,
far,
position: Vec3 {
x: 0.0,
y: 0.0,
z: 0.0,
},
}
}
// Setter for y
#[cfg_attr(target_arch = "wasm32", wasm_bindgen(setter))]
pub fn set_position(&mut self, value: Vec3) {
self.position = value;
}
#[cfg_attr(target_arch = "wasm32", wasm_bindgen(getter))]
pub fn position(&self) -> Vec3 {
self.position
}
#[cfg_attr(target_arch = "wasm32", wasm_bindgen(js_name = toString))]
pub fn to_string(&self) -> String {
format!(
"Camera(fov: {}, aspect: {}, near: {}, far: {})",
self.fov, self.aspect, self.near, self.far
)
}
#[cfg_attr(target_arch = "wasm32", wasm_bindgen(js_name = toJSON))]
pub fn to_json(&self) -> Result<JsValue, JsValue> {
Ok(serde_wasm_bindgen::to_value(&self)?)
}
}