summaryrefslogtreecommitdiffstats
path: root/third_party/rust/diplomat-runtime/src/wasm_glue.rs
blob: 98a46139a3e923af6e3dd4f21e4fa578db9fd491 (plain)
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
use alloc::format;
use core::panic::PanicInfo;

#[no_mangle]
unsafe extern "C" fn diplomat_init() {
    #[cfg(debug_assertions)]
    std::panic::set_hook(Box::new(panic_handler));
    #[cfg(feature = "log")]
    log::set_logger(&ConsoleLogger)
        .map(|()| log::set_max_level(log::LevelFilter::Debug))
        .unwrap();
}

fn panic_handler(info: &PanicInfo) {
    let msg = match info.payload().downcast_ref::<&'static str>() {
        Some(&s) => s,
        None => match info.payload().downcast_ref::<String>() {
            Some(s) => s.as_str(),
            None => "Box<Any>",
        },
    };

    let msg = match info.location() {
        Some(l) => format!(
            "wasm panicked at {}:{}:{}:\n{msg}",
            l.file(),
            l.line(),
            l.column(),
        ),
        None => format!("wasm panicked at <unknown location>:\n{msg}"),
    };

    extern "C" {
        fn diplomat_throw_error_js(ptr: *const u8, len: usize);
    }

    unsafe { diplomat_throw_error_js(msg.as_ptr(), msg.len()) }
}

#[cfg(feature = "log")]
struct ConsoleLogger;

#[cfg(feature = "log")]
impl log::Log for ConsoleLogger {
    #[inline]
    fn enabled(&self, metadata: &log::Metadata) -> bool {
        metadata.level() <= log::max_level()
    }

    fn log(&self, record: &log::Record) {
        if !self.enabled(record.metadata()) {
            return;
        }

        let out = match record.level() {
            log::Level::Error => {
                extern "C" {
                    fn diplomat_console_error_js(ptr: *const u8, len: usize);
                }
                diplomat_console_error_js
            }
            log::Level::Warn => {
                extern "C" {
                    fn diplomat_console_warn_js(ptr: *const u8, len: usize);
                }
                diplomat_console_warn_js
            }
            log::Level::Info => {
                extern "C" {
                    fn diplomat_console_info_js(ptr: *const u8, len: usize);
                }
                diplomat_console_info_js
            }
            log::Level::Debug => {
                extern "C" {
                    fn diplomat_console_log_js(ptr: *const u8, len: usize);
                }
                diplomat_console_log_js
            }
            log::Level::Trace => {
                extern "C" {
                    fn diplomat_console_debug_js(ptr: *const u8, len: usize);
                }
                diplomat_console_debug_js
            }
        };

        let msg = alloc::format!("{}", record.args());

        unsafe { out(msg.as_ptr(), msg.len()) };
    }

    fn flush(&self) {}
}