generated from Tamschi/rust-template
-
-
Notifications
You must be signed in to change notification settings - Fork 0
/
lib.rs
102 lines (89 loc) · 2.63 KB
/
lib.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
#![doc(html_root_url = "https://docs.rs/an-asteracea-app/0.0.1")]
#![warn(clippy::pedantic)]
use asteracea::{bumpalo::Bump, lignin, rhizome::Node};
use lignin::{
auto_safety::{Align, AutoSafe as _},
ThreadBound,
};
use lignin_dom::load;
use log::{trace, LevelFilter};
use std::{cell::RefCell, mem::swap, pin::Pin, slice, sync::Mutex};
use wasm_bindgen::prelude::*;
mod app;
use app::App;
#[global_allocator]
static ALLOC: wee_alloc::WeeAlloc<'_> = wee_alloc::WeeAlloc::INIT;
#[wasm_bindgen]
#[allow(clippy::items_after_statements)]
pub fn main() {
console_error_panic_hook::set_once();
fern::Dispatch::new()
.format(|out, message, record| {
out.finish(format_args!(
"{:5} [{}] {}",
record.level(),
record.target(),
message,
))
})
.level(LevelFilter::Trace)
.chain(fern::Output::call(console_log::log))
.apply()
.expect_throw("Failed to set up logging.");
enum RootOwner {}
let root = Node::new_for::<RootOwner>();
struct LoadAllocator<'a>(&'a Bump);
impl<'a> load::Allocator<'a> for LoadAllocator<'a> {
fn allocate<T>(&self, instance: T) -> &'a T {
self.0.alloc(instance)
}
fn allocate_slice<T>(&self, iter: &mut dyn ExactSizeIterator<Item = T>) -> &'a [T] {
self.0.alloc_slice_fill_iter(iter)
}
}
let app: &'static RefCell<Option<Pin<Box<App>>>> = Box::leak(Box::new(RefCell::new(None)));
let render = {
let mut bump_a = Bump::new();
let mut bump_b = Bump::new();
let document = web_sys::window().unwrap_throw().document().unwrap_throw();
let app_root = document.create_element("DIV").unwrap_throw();
app_root.set_attribute("id", "app-root").unwrap_throw();
document
.body()
.unwrap_throw()
.append_with_node_1(&app_root)
.unwrap_throw();
let mut previous: lignin::Node<ThreadBound> = lignin::Node::Multi(&[]);
let mut differ = lignin_dom::diff::DomDiffer::new_for_element_child_nodes(app_root);
let render = Mutex::new(move || {
trace!("render");
unsafe {
let current = app
.borrow()
.as_ref()
.unwrap_throw()
.as_ref()
.render(&bump_b, App::render_args_builder().build())
.unwrap_throw()
.deanonymize();
differ.update_child_nodes(
slice::from_ref(previous.align_ref()),
slice::from_ref(current.align_ref()),
1000,
);
previous = std::mem::transmute::<lignin::Node<_>, lignin::Node<_>>(current);
bump_a.reset();
swap(&mut bump_a, &mut bump_b);
}
});
let render: &dyn Fn() = Box::leak(Box::new(move || (render.lock().unwrap_throw())()));
render
};
*app.borrow_mut() = Some(Box::pin(
App::new(
&root.into_arc(),
App::new_args_builder().render(render).build(),
)
.unwrap_throw(),
));
}