1 use crate::{ 2 WasmStoreRef, WasmtimeStoreContext, wasm_externkind_t, wasm_externtype_t, wasm_func_t, 3 wasm_global_t, wasm_memory_t, wasm_table_t, 4 }; 5 use std::mem::ManuallyDrop; 6 use wasmtime::{Extern, Func, Global, Memory, SharedMemory, Table}; 7 8 #[derive(Clone)] 9 pub struct wasm_extern_t { 10 pub(crate) store: WasmStoreRef, 11 pub(crate) which: Extern, 12 } 13 14 wasmtime_c_api_macros::declare_ref!(wasm_extern_t); 15 16 #[unsafe(no_mangle)] 17 pub extern "C" fn wasm_extern_kind(e: &wasm_extern_t) -> wasm_externkind_t { 18 match e.which { 19 Extern::Func(_) => crate::WASM_EXTERN_FUNC, 20 Extern::Global(_) => crate::WASM_EXTERN_GLOBAL, 21 Extern::Table(_) => crate::WASM_EXTERN_TABLE, 22 Extern::Memory(_) => crate::WASM_EXTERN_MEMORY, 23 Extern::SharedMemory(_) => panic!( 24 "Shared Memory no implemented for wasm_* types. Please use wasmtime_* types instead" 25 ), 26 Extern::Tag(_) => todo!(), // FIXME: #10252 C embedder API for exceptions and control tags. 27 } 28 } 29 30 #[unsafe(no_mangle)] 31 pub unsafe extern "C" fn wasm_extern_type(e: &wasm_extern_t) -> Box<wasm_externtype_t> { 32 Box::new(wasm_externtype_t::from_extern_type( 33 e.which.ty(&e.store.context()), 34 )) 35 } 36 37 #[unsafe(no_mangle)] 38 pub extern "C" fn wasm_extern_as_func(e: &wasm_extern_t) -> Option<&wasm_func_t> { 39 wasm_func_t::try_from(e) 40 } 41 42 #[unsafe(no_mangle)] 43 pub extern "C" fn wasm_extern_as_func_const(e: &wasm_extern_t) -> Option<&wasm_func_t> { 44 wasm_extern_as_func(e) 45 } 46 47 #[unsafe(no_mangle)] 48 pub extern "C" fn wasm_extern_as_global(e: &wasm_extern_t) -> Option<&wasm_global_t> { 49 wasm_global_t::try_from(e) 50 } 51 52 #[unsafe(no_mangle)] 53 pub extern "C" fn wasm_extern_as_global_const(e: &wasm_extern_t) -> Option<&wasm_global_t> { 54 wasm_extern_as_global(e) 55 } 56 57 #[unsafe(no_mangle)] 58 pub extern "C" fn wasm_extern_as_table(e: &wasm_extern_t) -> Option<&wasm_table_t> { 59 wasm_table_t::try_from(e) 60 } 61 62 #[unsafe(no_mangle)] 63 pub extern "C" fn wasm_extern_as_table_const(e: &wasm_extern_t) -> Option<&wasm_table_t> { 64 wasm_extern_as_table(e) 65 } 66 67 #[unsafe(no_mangle)] 68 pub extern "C" fn wasm_extern_as_memory(e: &wasm_extern_t) -> Option<&wasm_memory_t> { 69 wasm_memory_t::try_from(e) 70 } 71 72 #[unsafe(no_mangle)] 73 pub extern "C" fn wasm_extern_as_memory_const(e: &wasm_extern_t) -> Option<&wasm_memory_t> { 74 wasm_extern_as_memory(e) 75 } 76 77 #[repr(C)] 78 pub struct wasmtime_extern_t { 79 pub kind: wasmtime_extern_kind_t, 80 pub of: wasmtime_extern_union, 81 } 82 83 pub type wasmtime_extern_kind_t = u8; 84 pub const WASMTIME_EXTERN_FUNC: wasmtime_extern_kind_t = 0; 85 pub const WASMTIME_EXTERN_GLOBAL: wasmtime_extern_kind_t = 1; 86 pub const WASMTIME_EXTERN_TABLE: wasmtime_extern_kind_t = 2; 87 pub const WASMTIME_EXTERN_MEMORY: wasmtime_extern_kind_t = 3; 88 pub const WASMTIME_EXTERN_SHAREDMEMORY: wasmtime_extern_kind_t = 4; 89 90 #[repr(C)] 91 pub union wasmtime_extern_union { 92 pub func: Func, 93 pub table: Table, 94 pub global: Global, 95 pub memory: Memory, 96 pub sharedmemory: ManuallyDrop<Box<SharedMemory>>, 97 } 98 99 impl Drop for wasmtime_extern_t { 100 fn drop(&mut self) { 101 if self.kind == WASMTIME_EXTERN_SHAREDMEMORY { 102 unsafe { 103 ManuallyDrop::drop(&mut self.of.sharedmemory); 104 } 105 } 106 } 107 } 108 109 impl wasmtime_extern_t { 110 pub unsafe fn to_extern(&self) -> Extern { 111 match self.kind { 112 WASMTIME_EXTERN_FUNC => Extern::Func(self.of.func), 113 WASMTIME_EXTERN_GLOBAL => Extern::Global(self.of.global), 114 WASMTIME_EXTERN_TABLE => Extern::Table(self.of.table), 115 WASMTIME_EXTERN_MEMORY => Extern::Memory(self.of.memory), 116 WASMTIME_EXTERN_SHAREDMEMORY => Extern::SharedMemory((**self.of.sharedmemory).clone()), 117 other => panic!("unknown wasmtime_extern_kind_t: {other}"), 118 } 119 } 120 } 121 122 impl From<Extern> for wasmtime_extern_t { 123 fn from(item: Extern) -> wasmtime_extern_t { 124 match item { 125 Extern::Func(func) => wasmtime_extern_t { 126 kind: WASMTIME_EXTERN_FUNC, 127 of: wasmtime_extern_union { func }, 128 }, 129 Extern::Global(global) => wasmtime_extern_t { 130 kind: WASMTIME_EXTERN_GLOBAL, 131 of: wasmtime_extern_union { global }, 132 }, 133 Extern::Table(table) => wasmtime_extern_t { 134 kind: WASMTIME_EXTERN_TABLE, 135 of: wasmtime_extern_union { table }, 136 }, 137 Extern::Memory(memory) => wasmtime_extern_t { 138 kind: WASMTIME_EXTERN_MEMORY, 139 of: wasmtime_extern_union { memory }, 140 }, 141 Extern::SharedMemory(sharedmemory) => wasmtime_extern_t { 142 kind: WASMTIME_EXTERN_SHAREDMEMORY, 143 of: wasmtime_extern_union { 144 sharedmemory: ManuallyDrop::new(Box::new(sharedmemory)), 145 }, 146 }, 147 Extern::Tag(_) => todo!(), // FIXME: #10252 C embedder API for exceptions and control tags. 148 } 149 } 150 } 151 152 #[unsafe(no_mangle)] 153 pub unsafe extern "C" fn wasmtime_extern_delete(e: &mut ManuallyDrop<wasmtime_extern_t>) { 154 ManuallyDrop::drop(e); 155 } 156 157 #[unsafe(no_mangle)] 158 pub unsafe extern "C" fn wasmtime_extern_type( 159 store: WasmtimeStoreContext<'_>, 160 e: &wasmtime_extern_t, 161 ) -> Box<wasm_externtype_t> { 162 Box::new(wasm_externtype_t::from_extern_type(e.to_extern().ty(store))) 163 } 164