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
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
pub extern crate prost;
pub extern crate wascap_codec;
use crate::guestmem::Stack;
use crate::kv::HostKeyValueStore;
use crate::kv::KeyValueStore;
use prost::Message;
use wascap_codec as codec;
pub type Result<T> = std::result::Result<T, errors::Error>;
pub const SOURCE_GUEST: &'static str = "guest";
#[link(wasm_import_module = "wascap")]
extern "C" {
fn __throw(a: *const u8, b: usize) -> !;
fn __console_log(ptr: *const u8, len: usize);
fn __host_call(ptr: *const u8, len: usize, retptr: *const u8) -> i32;
}
pub(crate) fn do_host_call(cmd: &codec::core::Command) -> Result<codec::core::Event> {
let mut cmdbytes = Vec::new();
cmd.encode(&mut cmdbytes)?;
let result_slice = unsafe {
let mut __stack = { guestmem::GlobalStack::new() };
let buf: Vec<u8> = Vec::new();
let retptr = buf.as_ptr();
let result_len = { __host_call(cmdbytes.as_ptr(), cmdbytes.len() as _, retptr) };
std::slice::from_raw_parts(retptr as _, result_len as _)
};
let event = codec::core::Event::decode(result_slice)?;
Ok(event)
}
#[macro_export]
macro_rules! call_handler {
($user_handler:ident) => {
#[no_mangle]
pub extern "C" fn __guest_call(param_ptr: i32, len: i32) -> i32 {
use std::slice;
use $crate::guestmem;
use $crate::guestmem::Stack;
use $crate::prost::Message;
let req = {
let mut __stack = unsafe { guestmem::GlobalStack::new() };
let slice = unsafe { slice::from_raw_parts(param_ptr as _, len as _) };
let cmd = $crate::wascap_codec::core::Command::decode(&slice).unwrap();
let ctx = $crate::CapabilitiesContext::new();
ctx.log("Invoking handler...");
let event: $crate::wascap_codec::core::Event = match $user_handler(&ctx, &cmd) {
Ok(evt) => evt,
Err(e) => {
ctx.log(&format!("Handler failed: {}", e));
$crate::wascap_codec::core::Event {
success: false,
error: Some($crate::wascap_codec::core::Error {
code: 500,
description: format!("{}", e),
}),
payload: None,
}
}
};
let mut buf = Vec::with_capacity(event.encoded_len());
let _res = event.encode(&mut buf).unwrap();
__stack.push(buf.as_ptr() as u32);
buf.len() as _
};
req
}
};
}
#[cold]
#[inline(never)]
pub(crate) fn throw_str(s: &str) -> ! {
unsafe {
__throw(s.as_ptr(), s.len());
}
}
#[cold]
#[inline(never)]
pub(crate) fn console_log(s: &str) {
unsafe {
__console_log(s.as_ptr(), s.len());
}
}
pub struct CapabilitiesContext {
kv: HostKeyValueStore,
}
impl CapabilitiesContext {
pub fn new() -> CapabilitiesContext {
CapabilitiesContext {
kv: HostKeyValueStore::new(),
}
}
pub fn kv(&self) -> &impl KeyValueStore {
&self.kv
}
pub fn log(&self, msg: &str) {
console_log(msg);
}
}
mod errors;
pub mod guestmem;
pub mod http;
mod kv;
pub mod prelude;