1 use alloc::format;
2
3 #[no_mangle]
diplomat_init()4 unsafe extern "C" fn diplomat_init() {
5 #[cfg(debug_assertions)]
6 std::panic::set_hook(Box::new(panic_handler));
7 #[cfg(feature = "log")]
8 log::set_logger(&ConsoleLogger)
9 .map(|()| log::set_max_level(log::LevelFilter::Debug))
10 .unwrap();
11 }
12
panic_handler(info: &std::panic::PanicInfo)13 fn panic_handler(info: &std::panic::PanicInfo) {
14 let msg = match info.payload().downcast_ref::<&'static str>() {
15 Some(&s) => s,
16 None => match info.payload().downcast_ref::<String>() {
17 Some(s) => s.as_str(),
18 None => "Box<Any>",
19 },
20 };
21
22 let msg = match info.location() {
23 Some(l) => format!(
24 "wasm panicked at {}:{}:{}:\n{msg}",
25 l.file(),
26 l.line(),
27 l.column(),
28 ),
29 None => format!("wasm panicked at <unknown location>:\n{msg}"),
30 };
31
32 extern "C" {
33 fn diplomat_throw_error_js(ptr: *const u8, len: usize);
34 }
35
36 unsafe { diplomat_throw_error_js(msg.as_ptr(), msg.len()) }
37 }
38
39 #[cfg(feature = "log")]
40 struct ConsoleLogger;
41
42 #[cfg(feature = "log")]
43 impl log::Log for ConsoleLogger {
44 #[inline]
enabled(&self, metadata: &log::Metadata) -> bool45 fn enabled(&self, metadata: &log::Metadata) -> bool {
46 metadata.level() <= log::max_level()
47 }
48
log(&self, record: &log::Record)49 fn log(&self, record: &log::Record) {
50 if !self.enabled(record.metadata()) {
51 return;
52 }
53
54 let out = match record.level() {
55 log::Level::Error => {
56 extern "C" {
57 fn diplomat_console_error_js(ptr: *const u8, len: usize);
58 }
59 diplomat_console_error_js
60 }
61 log::Level::Warn => {
62 extern "C" {
63 fn diplomat_console_warn_js(ptr: *const u8, len: usize);
64 }
65 diplomat_console_warn_js
66 }
67 log::Level::Info => {
68 extern "C" {
69 fn diplomat_console_info_js(ptr: *const u8, len: usize);
70 }
71 diplomat_console_info_js
72 }
73 log::Level::Debug => {
74 extern "C" {
75 fn diplomat_console_log_js(ptr: *const u8, len: usize);
76 }
77 diplomat_console_log_js
78 }
79 log::Level::Trace => {
80 extern "C" {
81 fn diplomat_console_debug_js(ptr: *const u8, len: usize);
82 }
83 diplomat_console_debug_js
84 }
85 };
86
87 let msg = alloc::format!("{}", record.args());
88
89 unsafe { out(msg.as_ptr(), msg.len()) };
90 }
91
flush(&self)92 fn flush(&self) {}
93 }
94