wasmer_c_api/wasm_c_api/externals/
mod.rs

1mod function;
2mod global;
3mod memory;
4mod table;
5
6use super::store::StoreRef;
7// use super::types::{wasm_externkind_enum, wasm_externkind_t};
8pub use function::*;
9pub use global::*;
10pub use memory::*;
11pub use table::*;
12use wasmer_api::{Extern, ExternType, Function, Global, Memory, Table};
13
14#[allow(non_camel_case_types)]
15#[derive(Clone)]
16pub struct wasm_extern_t {
17    pub(crate) inner: Extern,
18    pub(crate) store: StoreRef,
19}
20
21impl wasm_extern_t {
22    pub(crate) fn new(store: StoreRef, inner: Extern) -> Self {
23        Self { inner, store }
24    }
25
26    pub(crate) fn global(&self) -> Global {
27        match &self.inner {
28            Extern::Global(g) => g.clone(),
29            _ => unsafe { std::hint::unreachable_unchecked() },
30        }
31    }
32
33    pub(crate) fn function(&self) -> Function {
34        match &self.inner {
35            Extern::Function(f) => f.clone(),
36            _ => unsafe { std::hint::unreachable_unchecked() },
37        }
38    }
39
40    pub(crate) fn table(&self) -> Table {
41        match &self.inner {
42            Extern::Table(t) => t.clone(),
43            _ => unsafe { std::hint::unreachable_unchecked() },
44        }
45    }
46
47    pub(crate) fn memory(&self) -> Memory {
48        match &self.inner {
49            Extern::Memory(m) => m.clone(),
50            _ => unsafe { std::hint::unreachable_unchecked() },
51        }
52    }
53}
54
55// #[unsafe(no_mangle)]
56// pub extern "C" fn wasm_extern_kind(e: &wasm_extern_t) -> wasm_externkind_t {
57//     (match e.inner {
58//         Extern::Function(_) => wasm_externkind_enum::WASM_EXTERN_FUNC,
59//         Extern::Table(_) => wasm_externkind_enum::WASM_EXTERN_TABLE,
60//         Extern::Global(_) => wasm_externkind_enum::WASM_EXTERN_GLOBAL,
61//         Extern::Memory(_) => wasm_externkind_enum::WASM_EXTERN_MEMORY,
62//     }) as wasm_externkind_t
63// }
64
65impl wasm_extern_t {
66    pub(crate) unsafe fn ty(&self) -> ExternType {
67        let store_ref = unsafe { self.store.store() };
68        self.inner.ty(&store_ref)
69    }
70}
71
72impl From<wasm_extern_t> for Extern {
73    fn from(other: wasm_extern_t) -> Self {
74        other.inner
75    }
76}
77
78wasm_declare_boxed_vec!(extern);
79
80/// Copy a `wasm_extern_t`.
81#[unsafe(no_mangle)]
82pub unsafe extern "C" fn wasm_extern_copy(r#extern: &wasm_extern_t) -> Box<wasm_extern_t> {
83    Box::new(r#extern.clone())
84}
85
86/// Delete an extern.
87#[unsafe(no_mangle)]
88pub unsafe extern "C" fn wasm_extern_delete(_extern: Option<Box<wasm_extern_t>>) {}
89
90#[unsafe(no_mangle)]
91pub extern "C" fn wasm_func_as_extern(func: Option<&wasm_func_t>) -> Option<&wasm_extern_t> {
92    Some(&func?.extern_)
93}
94
95#[unsafe(no_mangle)]
96pub extern "C" fn wasm_global_as_extern(global: Option<&wasm_global_t>) -> Option<&wasm_extern_t> {
97    Some(&global?.extern_)
98}
99
100#[unsafe(no_mangle)]
101pub extern "C" fn wasm_memory_as_extern(memory: Option<&wasm_memory_t>) -> Option<&wasm_extern_t> {
102    Some(&memory?.extern_)
103}
104
105#[unsafe(no_mangle)]
106pub extern "C" fn wasm_table_as_extern(table: Option<&wasm_table_t>) -> Option<&wasm_extern_t> {
107    Some(&table?.extern_)
108}
109
110#[unsafe(no_mangle)]
111pub extern "C" fn wasm_extern_as_func(r#extern: Option<&wasm_extern_t>) -> Option<&wasm_func_t> {
112    wasm_func_t::try_from(r#extern?)
113}
114
115#[unsafe(no_mangle)]
116pub extern "C" fn wasm_extern_as_global(
117    r#extern: Option<&wasm_extern_t>,
118) -> Option<&wasm_global_t> {
119    wasm_global_t::try_from(r#extern?)
120}
121
122#[unsafe(no_mangle)]
123pub extern "C" fn wasm_extern_as_memory(
124    r#extern: Option<&wasm_extern_t>,
125) -> Option<&wasm_memory_t> {
126    wasm_memory_t::try_from(r#extern?)
127}
128
129#[unsafe(no_mangle)]
130pub extern "C" fn wasm_extern_as_table(r#extern: Option<&wasm_extern_t>) -> Option<&wasm_table_t> {
131    wasm_table_t::try_from(r#extern?)
132}
133
134#[cfg(test)]
135mod tests {
136    #[cfg(not(target_os = "windows"))]
137    use inline_c::assert_c;
138    #[cfg(target_os = "windows")]
139    use wasmer_inline_c::assert_c;
140
141    #[allow(
142        unexpected_cfgs,
143        reason = "tools like cargo-llvm-coverage pass --cfg coverage"
144    )]
145    #[cfg_attr(coverage_nightly, coverage(off))]
146    #[test]
147    fn test_extern_copy() {
148        (assert_c! {
149            #include "tests/wasmer.h"
150
151            int main() {
152                wasm_engine_t* engine = wasm_engine_new();
153                wasm_store_t* store = wasm_store_new(engine);
154
155                wasm_byte_vec_t wat;
156                wasmer_byte_vec_new_from_string(
157                    &wat,
158                    "(module\n"
159                    "  (func (export \"function\")))"
160                );
161                wasm_byte_vec_t wasm;
162                wat2wasm(&wat, &wasm);
163
164                wasm_module_t* module = wasm_module_new(store, &wasm);
165                assert(module);
166
167                wasm_extern_vec_t imports = WASM_EMPTY_VEC;
168                wasm_trap_t* trap = NULL;
169
170                wasm_instance_t* instance = wasm_instance_new(store, module, &imports, &trap);
171                assert(instance);
172
173                wasm_extern_vec_t exports;
174                wasm_instance_exports(instance, &exports);
175
176                assert(exports.size == 1);
177
178                wasm_extern_t* function = exports.data[0];
179                assert(wasm_extern_kind(function) == WASM_EXTERN_FUNC);
180
181                wasm_extern_t* function_copy = wasm_extern_copy(function);
182                assert(wasm_extern_kind(function_copy) == WASM_EXTERN_FUNC);
183
184                wasm_extern_delete(function_copy);
185                wasm_extern_vec_delete(&exports);
186                wasm_instance_delete(instance);
187                wasm_module_delete(module);
188                wasm_byte_vec_delete(&wasm);
189                wasm_byte_vec_delete(&wat);
190                wasm_store_delete(store);
191                wasm_engine_delete(engine);
192
193                return 0;
194            }
195        })
196        .success();
197    }
198}