I have been trying to build a thin bindgen
-based wrapper between React
and Egui
(a GUI library written in Rust). I wish to let Rust manage all the complex, static objects and let the JS layer insert and remove data primarily via basic functions and JSON data.
There are a few issues with this, starting with type mismatches and misuse of ?Sized
. I am new to Rust and I get the impression that I am being far too ambitious.
That said, I’d appreciate if one experienced Rust developer could at least tell me whether what I’m trying to do makes any sense and whether I am on the right track.
Here’s a link to an online Rust playground: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=49c4dc4232092f6512d6f0997f89d347
Link to the project: https://github.com/andreamancuso/react-wasm/pull/12
Any help at this stage would be much appreciated.
use std::collections::HashMap;
use std::sync::Mutex;
use once_cell::sync::Lazy;
use wasm_bindgen::prelude::*;
use serde_json::{Value};
static REACT_EGUI: Lazy<Mutex<Box<ReactEgui<dyn Render + Send>>>> = Lazy::new(|| {
Mutex::new(Box::new(ReactEgui::new()))
});
#[wasm_bindgen]
extern "C" {
#[wasm_bindgen(js_namespace = console)]
fn log(a: &str);
}
#[wasm_bindgen]
pub unsafe fn add_widget(raw_widget_def: String) {
let mut m = REACT_EGUI.lock().unwrap_throw();
m.add_widget(raw_widget_def);
}
// ----------------
pub trait Render {
fn render(&self);
}
pub struct ReactEgui<T: Render + Send + ?Sized> {
pub widgets: HashMap<&'static u64, Box<T>>,
}
impl<T: ?Sized> ReactEgui<T>
where T: Render + Send {
pub fn new() -> ReactEgui<T> {
ReactEgui{
widgets: HashMap::new()
}
}
pub fn add_widget(&mut self, raw_widget_def: String) {
log("an");
let widget_def: Value = serde_json::from_str(&*raw_widget_def).unwrap();
if widget_def.is_object() && widget_def["type"].is_string() {
log("bn");
let maybe_widget_type = widget_def["type"].as_str();
let maybe_widget_id = widget_def["id"].as_u64();
if maybe_widget_id.is_some() && maybe_widget_type.is_some() {
log("cn");
let widget_id = &maybe_widget_id.unwrap();
if maybe_widget_type == Option::from("Button") {
log("dn");
let label = widget_def["label"].as_str();
if label.is_some() {
log("en");
self.widgets.insert(widget_id, Box::new(Button::new(*widget_id, label.unwrap())));
log("fn");
}
}
}
}
}
pub fn render(&self) {
}
}
pub struct Button {
pub id: u64,
pub label: String,
}
impl Button {
pub fn new(id: u64, label: &str) -> Button {
Button{
id,
label: label.parse().unwrap()
}
}
}
impl Render for Button {
fn render(&self) {
}
}
pub struct InputText {
pub id: u64,
pub value: String,
}
impl InputText {
fn new(id: u64, value: &str) -> InputText {
InputText{
id,
value: value.parse().unwrap()
}
}
fn set_value(mut self, value: &str) -> () {
self.value = value.parse().unwrap();
}
}
impl Render for InputText {
fn render(&self) {
}
}