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
extern crate alloc;
extern crate core;
extern crate wee_alloc;
use alloc::vec::Vec;
use std::mem::MaybeUninit;
use std::slice;

#[repr(C)]
pub struct Ret2Val {
    one: u64,
    two: u64,
}

pub type EventFunc = fn(&String) -> (u64, String);

pub static mut ON_EVENT: Option<EventFunc> = None;

pub fn log(level: u32, message: &String) {
    unsafe {
        let (ptr, len) = string_to_ptr(message);
        _log(level, ptr, len);
    }
}

#[link(wasm_import_module = "env")]
extern "C" {
    #[link_name = "log"]
    fn _log(level: u32, ptr: u32, size: u32);
}

#[cfg_attr(all(target_arch = "wasm32"), export_name = "event")]
#[no_mangle]
unsafe extern "C" fn _event(ptr: u32, len: u32) -> Ret2Val {
    let name = &ptr_to_string(ptr, len);
    let (errno, result) = ON_EVENT.unwrap()(name);
    let (ptr, len) = string_to_ptr(&result);
    std::mem::forget(result);
    return Ret2Val {
        one: errno,
        two: ((ptr as u64) << 32) | len as u64,
    };
}

unsafe fn ptr_to_string(ptr: u32, len: u32) -> String {
    let slice = slice::from_raw_parts_mut(ptr as *mut u8, len as usize);
    let utf8 = std::str::from_utf8_unchecked_mut(slice);
    return String::from(utf8);
}

unsafe fn string_to_ptr(s: &String) -> (u32, u32) {
    return (s.as_ptr() as u32, s.len() as u32);
}

#[global_allocator]
static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT;

#[cfg_attr(all(target_arch = "wasm32"), export_name = "malloc")]
#[no_mangle]
extern "C" fn _malloc(size: u32) -> *mut u8 {
    malloc(size as usize)
}

#[cfg_attr(all(target_arch = "wasm32"), export_name = "ver")]
#[no_mangle]
extern "C" fn _ver() -> u8 {
    return 1;
}


fn malloc(size: usize) -> *mut u8 {
    let vec: Vec<MaybeUninit<u8>> = Vec::with_capacity(size);
    Box::into_raw(vec.into_boxed_slice()) as *mut u8
}

#[cfg_attr(all(target_arch = "wasm32"), export_name = "free")]
#[no_mangle]
unsafe extern "C" fn _free(ptr: u32, size: u32) {
    free(ptr as *mut u8, size as usize);
}

unsafe fn free(ptr: *mut u8, size: usize) {
    let _ = Vec::from_raw_parts(ptr, 0, size);
}