1use crate::{from_valtype, into_valtype, utils, wasm_ref_t, wasm_valkind_t};
2use alloc::boxed::Box;
3use core::{mem::MaybeUninit, ptr};
4use wasmi::{F32, F64, Func, Nullable, Ref, Val, ValType};
5
6#[repr(C)]
10pub struct wasm_val_t {
11 pub kind: wasm_valkind_t,
13 pub of: wasm_val_union,
15}
16
17#[repr(C)]
19#[derive(Copy, Clone)]
20pub union wasm_val_union {
21 pub i32: i32,
23 pub i64: i64,
25 pub u32: u32,
27 pub u64: u64,
29 pub f32: f32,
31 pub f64: f64,
33 pub ref_: *mut wasm_ref_t,
35}
36
37impl Drop for wasm_val_t {
38 fn drop(&mut self) {
39 if into_valtype(self.kind).is_ref() && !unsafe { self.of.ref_ }.is_null() {
40 drop(unsafe { Box::from_raw(self.of.ref_) });
41 }
42 }
43}
44
45impl Clone for wasm_val_t {
46 fn clone(&self) -> Self {
47 let mut ret = wasm_val_t {
48 kind: self.kind,
49 of: self.of,
50 };
51 unsafe {
52 if into_valtype(self.kind).is_ref() && !self.of.ref_.is_null() {
53 ret.of.ref_ = Box::into_raw(Box::new((*self.of.ref_).clone()));
54 }
55 }
56 ret
57 }
58}
59
60impl Default for wasm_val_t {
61 fn default() -> Self {
62 wasm_val_t {
63 kind: wasm_valkind_t::WASM_I32,
64 of: wasm_val_union { i32: 0 },
65 }
66 }
67}
68
69impl From<Val> for wasm_val_t {
70 fn from(val: Val) -> Self {
71 match val {
72 Val::I32(value) => Self {
73 kind: from_valtype(&ValType::I32),
74 of: wasm_val_union { i32: value },
75 },
76 Val::I64(value) => Self {
77 kind: from_valtype(&ValType::I64),
78 of: wasm_val_union { i64: value },
79 },
80 Val::F32(value) => Self {
81 kind: from_valtype(&ValType::F32),
82 of: wasm_val_union {
83 u32: value.to_bits(),
84 },
85 },
86 Val::F64(value) => Self {
87 kind: from_valtype(&ValType::F64),
88 of: wasm_val_union {
89 u64: value.to_bits(),
90 },
91 },
92 Val::V128(value) => core::panic!(
93 "`wasm_val_t`: creating a `wasm_val_t` from an `v128` value is not supported but found: {value:?}"
94 ),
95 Val::FuncRef(funcref) => Self {
96 kind: from_valtype(&ValType::FuncRef),
97 of: wasm_val_union {
98 ref_: {
99 match funcref.is_null() {
100 true => ptr::null_mut(),
101 false => Box::into_raw(Box::new(wasm_ref_t {
102 inner: Ref::Func(funcref),
103 })),
104 }
105 },
106 },
107 },
108 Val::ExternRef(_) => {
109 core::panic!("`wasm_val_t`: creating a `wasm_val_t` from an `externref`")
110 }
111 }
112 }
113}
114
115impl wasm_val_t {
116 pub fn to_val(&self) -> Val {
122 match self.kind {
123 wasm_valkind_t::WASM_I32 => Val::from(unsafe { self.of.i32 }),
124 wasm_valkind_t::WASM_I64 => Val::from(unsafe { self.of.i64 }),
125 wasm_valkind_t::WASM_F32 => Val::from(F32::from(unsafe { self.of.f32 })),
126 wasm_valkind_t::WASM_F64 => Val::from(F64::from(unsafe { self.of.f64 })),
127 wasm_valkind_t::WASM_FUNCREF => match unsafe { self.of.ref_ }.is_null() {
128 true => Val::FuncRef(<Nullable<Func>>::Null),
129 false => Val::from((unsafe { &*self.of.ref_ }).inner),
130 },
131 wasm_valkind_t::WASM_EXTERNREF => {
132 core::unreachable!("`wasm_val_t`: cannot contain non-function reference values")
133 }
134 }
135 }
136}
137
138#[cfg_attr(not(feature = "prefix-symbols"), unsafe(no_mangle))]
144#[cfg_attr(feature = "prefix-symbols", wasmi_c_api_macros::prefix_symbol)]
145pub unsafe extern "C" fn wasm_val_copy(out: &mut MaybeUninit<wasm_val_t>, source: &wasm_val_t) {
146 utils::initialize(out, source.clone());
147}
148
149#[cfg_attr(not(feature = "prefix-symbols"), unsafe(no_mangle))]
156#[cfg_attr(feature = "prefix-symbols", wasmi_c_api_macros::prefix_symbol)]
157pub unsafe extern "C" fn wasm_val_delete(val: *mut wasm_val_t) {
158 unsafe {
159 ptr::drop_in_place(val);
160 }
161}