1use crate::{
2 from_valtype,
3 into_valtype,
4 r#ref::ref_to_val,
5 utils,
6 wasm_ref_t,
7 wasm_valkind_t,
8 WasmRef,
9};
10use alloc::boxed::Box;
11use core::{mem::MaybeUninit, ptr};
12use wasmi::{
13 core::{ValType, F32, F64},
14 FuncRef,
15 Val,
16};
17
18#[repr(C)]
22pub struct wasm_val_t {
23 pub kind: wasm_valkind_t,
25 pub of: wasm_val_union,
27}
28
29#[repr(C)]
31#[derive(Copy, Clone)]
32pub union wasm_val_union {
33 pub i32: i32,
35 pub i64: i64,
37 pub u32: u32,
39 pub u64: u64,
41 pub f32: f32,
43 pub f64: f64,
45 pub ref_: *mut wasm_ref_t,
47}
48
49impl Drop for wasm_val_t {
50 fn drop(&mut self) {
51 if into_valtype(self.kind).is_ref() && !unsafe { self.of.ref_ }.is_null() {
52 drop(unsafe { Box::from_raw(self.of.ref_) });
53 }
54 }
55}
56
57impl Clone for wasm_val_t {
58 fn clone(&self) -> Self {
59 let mut ret = wasm_val_t {
60 kind: self.kind,
61 of: self.of,
62 };
63 unsafe {
64 if into_valtype(self.kind).is_ref() && !self.of.ref_.is_null() {
65 ret.of.ref_ = Box::into_raw(Box::new((*self.of.ref_).clone()));
66 }
67 }
68 ret
69 }
70}
71
72impl Default for wasm_val_t {
73 fn default() -> Self {
74 wasm_val_t {
75 kind: wasm_valkind_t::WASM_I32,
76 of: wasm_val_union { i32: 0 },
77 }
78 }
79}
80
81impl From<Val> for wasm_val_t {
82 fn from(val: Val) -> Self {
83 match val {
84 Val::I32(value) => Self {
85 kind: from_valtype(&ValType::I32),
86 of: wasm_val_union { i32: value },
87 },
88 Val::I64(value) => Self {
89 kind: from_valtype(&ValType::I64),
90 of: wasm_val_union { i64: value },
91 },
92 Val::F32(value) => Self {
93 kind: from_valtype(&ValType::F32),
94 of: wasm_val_union { u32: value.into() },
95 },
96 Val::F64(value) => Self {
97 kind: from_valtype(&ValType::F64),
98 of: wasm_val_union { u64: value.into() },
99 },
100 Val::FuncRef(funcref) => Self {
101 kind: from_valtype(&ValType::FuncRef),
102 of: wasm_val_union {
103 ref_: {
104 match funcref.is_null() {
105 true => ptr::null_mut(),
106 false => Box::into_raw(Box::new(wasm_ref_t {
107 inner: WasmRef::Func(funcref),
108 })),
109 }
110 },
111 },
112 },
113 Val::ExternRef(_) => {
114 core::panic!("`wasm_val_t`: creating a `wasm_val_t` from an `externref`")
115 }
116 }
117 }
118}
119
120impl wasm_val_t {
121 pub fn to_val(&self) -> Val {
127 match into_valtype(self.kind) {
128 ValType::I32 => Val::from(unsafe { self.of.i32 }),
129 ValType::I64 => Val::from(unsafe { self.of.i64 }),
130 ValType::F32 => Val::from(F32::from(unsafe { self.of.f32 })),
131 ValType::F64 => Val::from(F64::from(unsafe { self.of.f64 })),
132 ValType::FuncRef => match unsafe { self.of.ref_ }.is_null() {
133 true => Val::FuncRef(FuncRef::null()),
134 false => ref_to_val(unsafe { &*self.of.ref_ }),
135 },
136 ValType::ExternRef => {
137 core::unreachable!("`wasm_val_t`: cannot contain non-function reference values")
138 }
139 }
140 }
141}
142
143#[cfg_attr(not(feature = "prefix-symbols"), no_mangle)]
149#[cfg_attr(feature = "prefix-symbols", wasmi_c_api_macros::prefix_symbol)]
150pub unsafe extern "C" fn wasm_val_copy(out: &mut MaybeUninit<wasm_val_t>, source: &wasm_val_t) {
151 utils::initialize(out, source.clone());
152}
153
154#[cfg_attr(not(feature = "prefix-symbols"), no_mangle)]
161#[cfg_attr(feature = "prefix-symbols", wasmi_c_api_macros::prefix_symbol)]
162pub unsafe extern "C" fn wasm_val_delete(val: *mut wasm_val_t) {
163 ptr::drop_in_place(val);
164}