wasmtime_c_api/
extern.rs

1use crate::{
2    wasm_externkind_t, wasm_externtype_t, wasm_func_t, wasm_global_t, wasm_memory_t, wasm_table_t,
3    WasmStoreRef, WasmtimeStoreContext,
4};
5use std::mem::ManuallyDrop;
6use wasmtime::{Extern, Func, Global, Memory, SharedMemory, Table};
7
8#[derive(Clone)]
9pub struct wasm_extern_t {
10    pub(crate) store: WasmStoreRef,
11    pub(crate) which: Extern,
12}
13
14wasmtime_c_api_macros::declare_ref!(wasm_extern_t);
15
16#[unsafe(no_mangle)]
17pub 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)]
31pub 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)]
38pub 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)]
43pub 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)]
48pub 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)]
53pub 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)]
58pub 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)]
63pub 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)]
68pub 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)]
73pub 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)]
78pub struct wasmtime_extern_t {
79    pub kind: wasmtime_extern_kind_t,
80    pub of: wasmtime_extern_union,
81}
82
83pub type wasmtime_extern_kind_t = u8;
84pub const WASMTIME_EXTERN_FUNC: wasmtime_extern_kind_t = 0;
85pub const WASMTIME_EXTERN_GLOBAL: wasmtime_extern_kind_t = 1;
86pub const WASMTIME_EXTERN_TABLE: wasmtime_extern_kind_t = 2;
87pub const WASMTIME_EXTERN_MEMORY: wasmtime_extern_kind_t = 3;
88pub const WASMTIME_EXTERN_SHAREDMEMORY: wasmtime_extern_kind_t = 4;
89
90#[repr(C)]
91pub 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
99impl 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
109impl 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
122impl 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)]
153pub unsafe extern "C" fn wasmtime_extern_delete(e: &mut ManuallyDrop<wasmtime_extern_t>) {
154    ManuallyDrop::drop(e);
155}
156
157#[unsafe(no_mangle)]
158pub 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}