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
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
#![allow(clippy::missing_safety_doc)]
use std::os::raw::c_char;
use crate::*;
#[no_mangle]
pub unsafe extern "C" fn extism_plugin_register(
wasm: *const u8,
wasm_size: Size,
with_wasi: bool,
) -> PluginIndex {
let data = std::slice::from_raw_parts(wasm, wasm_size as usize);
let plugin = match Plugin::new(data, with_wasi) {
Ok(x) => x,
Err(e) => {
eprintln!("Error creating Plugin: {:?}", e);
return -1;
}
};
if let Ok(mut plugins) = PLUGINS.lock() {
plugins.push(plugin);
return (plugins.len() - 1) as PluginIndex;
}
-1
}
#[no_mangle]
pub unsafe extern "C" fn extism_plugin_config(
plugin: PluginIndex,
json: *const u8,
json_size: Size,
) -> bool {
let mut plugin = PluginRef::new(plugin);
let data = std::slice::from_raw_parts(json, json_size as usize);
let json: std::collections::BTreeMap<String, String> = match serde_json::from_slice(data) {
Ok(x) => x,
Err(e) => {
plugin.as_mut().set_error(e);
return false;
}
};
let plugin = plugin.as_mut();
let wasi = &mut plugin.memory.store.data_mut().wasi;
let config = &mut plugin.manifest.as_mut().config;
for (k, v) in json.into_iter() {
let _ = wasi.push_env(&k, &v);
config.insert(k, v);
}
true
}
#[no_mangle]
pub unsafe extern "C" fn extism_function_exists(
plugin: PluginIndex,
func_name: *const c_char,
) -> bool {
let mut plugin = PluginRef::new(plugin);
let name = std::ffi::CStr::from_ptr(func_name);
let name = name.to_str().expect("Invalid function name");
plugin.as_mut().get_func(name).is_some()
}
#[no_mangle]
pub unsafe extern "C" fn extism_call(
plugin: PluginIndex,
func_name: *const c_char,
data: *const u8,
data_len: Size,
) -> i32 {
let mut plugin = PluginRef::new(plugin).init();
let plugin = plugin.as_mut();
let name = std::ffi::CStr::from_ptr(func_name);
let name = name.to_str().expect("Invalid function name");
let func = plugin
.get_func(name)
.unwrap_or_else(|| panic!("Function not found {name}"));
let data = std::slice::from_raw_parts(data, data_len as usize);
let handle = match plugin.memory.alloc_bytes(data) {
Ok(x) => x,
Err(e) => return plugin.error(e.context("Unable to allocate bytes"), -1),
};
#[cfg(feature = "debug")]
plugin.dump_memory();
plugin.set_input(handle);
let mut results = vec![Val::I32(0)];
match func.call(&mut plugin.memory.store, &[], results.as_mut_slice()) {
Ok(r) => r,
Err(e) => {
#[cfg(feature = "debug")]
plugin.dump_memory();
return plugin.error(e.context("Invalid write"), -1);
}
};
#[cfg(feature = "debug")]
plugin.dump_memory();
results[0].unwrap_i32()
}
#[no_mangle]
pub unsafe extern "C" fn extism_error(plugin: PluginIndex) -> *const c_char {
let plugin = PluginRef::new(plugin);
match &plugin.as_ref().last_error {
Some(e) => e.as_ptr() as *const _,
None => std::ptr::null(),
}
}
#[no_mangle]
pub unsafe extern "C" fn extism_output_length(plugin: PluginIndex) -> Size {
let plugin = PluginRef::new(plugin);
plugin.as_ref().memory.store.data().output_length as Size
}
#[no_mangle]
pub unsafe extern "C" fn extism_output_get(plugin: PluginIndex, buf: *mut u8, len: Size) {
let plugin = PluginRef::new(plugin);
let data = plugin.as_ref().memory.store.data();
let slice = std::slice::from_raw_parts_mut(buf, len as usize);
plugin
.as_ref()
.memory
.read(
MemoryBlock::new(data.output_offset, data.output_length),
slice,
)
.expect("Out of bounds read in extism_output_get");
}