xref: /wasmtime-44.0.1/crates/c-api/src/extern.rs (revision dbaaa92f)
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