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, V128},
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 v128: u128,
47 pub ref_: *mut wasm_ref_t,
49}
50
51impl Drop for wasm_val_t {
52 fn drop(&mut self) {
53 if into_valtype(self.kind).is_ref() && !unsafe { self.of.ref_ }.is_null() {
54 drop(unsafe { Box::from_raw(self.of.ref_) });
55 }
56 }
57}
58
59impl Clone for wasm_val_t {
60 fn clone(&self) -> Self {
61 let mut ret = wasm_val_t {
62 kind: self.kind,
63 of: self.of,
64 };
65 unsafe {
66 if into_valtype(self.kind).is_ref() && !self.of.ref_.is_null() {
67 ret.of.ref_ = Box::into_raw(Box::new((*self.of.ref_).clone()));
68 }
69 }
70 ret
71 }
72}
73
74impl Default for wasm_val_t {
75 fn default() -> Self {
76 wasm_val_t {
77 kind: wasm_valkind_t::WASM_I32,
78 of: wasm_val_union { i32: 0 },
79 }
80 }
81}
82
83impl From<Val> for wasm_val_t {
84 fn from(val: Val) -> Self {
85 match val {
86 Val::I32(value) => Self {
87 kind: from_valtype(&ValType::I32),
88 of: wasm_val_union { i32: value },
89 },
90 Val::I64(value) => Self {
91 kind: from_valtype(&ValType::I64),
92 of: wasm_val_union { i64: value },
93 },
94 Val::F32(value) => Self {
95 kind: from_valtype(&ValType::F32),
96 of: wasm_val_union {
97 u32: value.to_bits(),
98 },
99 },
100 Val::F64(value) => Self {
101 kind: from_valtype(&ValType::F64),
102 of: wasm_val_union {
103 u64: value.to_bits(),
104 },
105 },
106 Val::V128(value) => Self {
107 kind: from_valtype(&ValType::V128),
108 of: wasm_val_union {
109 v128: value.as_u128(),
110 },
111 },
112 Val::FuncRef(funcref) => Self {
113 kind: from_valtype(&ValType::FuncRef),
114 of: wasm_val_union {
115 ref_: {
116 match funcref.is_null() {
117 true => ptr::null_mut(),
118 false => Box::into_raw(Box::new(wasm_ref_t {
119 inner: WasmRef::Func(funcref),
120 })),
121 }
122 },
123 },
124 },
125 Val::ExternRef(_) => {
126 core::panic!("`wasm_val_t`: creating a `wasm_val_t` from an `externref`")
127 }
128 }
129 }
130}
131
132impl wasm_val_t {
133 pub fn to_val(&self) -> Val {
139 match into_valtype(self.kind) {
140 ValType::I32 => Val::from(unsafe { self.of.i32 }),
141 ValType::I64 => Val::from(unsafe { self.of.i64 }),
142 ValType::F32 => Val::from(F32::from(unsafe { self.of.f32 })),
143 ValType::F64 => Val::from(F64::from(unsafe { self.of.f64 })),
144 ValType::V128 => Val::from(V128::from(unsafe { self.of.v128 })),
145 ValType::FuncRef => match unsafe { self.of.ref_ }.is_null() {
146 true => Val::FuncRef(FuncRef::null()),
147 false => ref_to_val(unsafe { &*self.of.ref_ }),
148 },
149 ValType::ExternRef => {
150 core::unreachable!("`wasm_val_t`: cannot contain non-function reference values")
151 }
152 }
153 }
154}
155
156#[cfg_attr(not(feature = "prefix-symbols"), no_mangle)]
162#[cfg_attr(feature = "prefix-symbols", wasmi_c_api_macros::prefix_symbol)]
163pub unsafe extern "C" fn wasm_val_copy(out: &mut MaybeUninit<wasm_val_t>, source: &wasm_val_t) {
164 utils::initialize(out, source.clone());
165}
166
167#[cfg_attr(not(feature = "prefix-symbols"), no_mangle)]
174#[cfg_attr(feature = "prefix-symbols", wasmi_c_api_macros::prefix_symbol)]
175pub unsafe extern "C" fn wasm_val_delete(val: *mut wasm_val_t) {
176 ptr::drop_in_place(val);
177}