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::{Func, Ref, Val, ValType, F32, F64, V128};
13
14#[repr(C)]
18pub struct wasm_val_t {
19 pub kind: wasm_valkind_t,
21 pub of: wasm_val_union,
23}
24
25#[repr(C)]
27#[derive(Copy, Clone)]
28pub union wasm_val_union {
29 pub i32: i32,
31 pub i64: i64,
33 pub u32: u32,
35 pub u64: u64,
37 pub f32: f32,
39 pub f64: f64,
41 pub v128: u128,
43 pub ref_: *mut wasm_ref_t,
45}
46
47impl Drop for wasm_val_t {
48 fn drop(&mut self) {
49 if into_valtype(self.kind).is_ref() && !unsafe { self.of.ref_ }.is_null() {
50 drop(unsafe { Box::from_raw(self.of.ref_) });
51 }
52 }
53}
54
55impl Clone for wasm_val_t {
56 fn clone(&self) -> Self {
57 let mut ret = wasm_val_t {
58 kind: self.kind,
59 of: self.of,
60 };
61 unsafe {
62 if into_valtype(self.kind).is_ref() && !self.of.ref_.is_null() {
63 ret.of.ref_ = Box::into_raw(Box::new((*self.of.ref_).clone()));
64 }
65 }
66 ret
67 }
68}
69
70impl Default for wasm_val_t {
71 fn default() -> Self {
72 wasm_val_t {
73 kind: wasm_valkind_t::WASM_I32,
74 of: wasm_val_union { i32: 0 },
75 }
76 }
77}
78
79impl From<Val> for wasm_val_t {
80 fn from(val: Val) -> Self {
81 match val {
82 Val::I32(value) => Self {
83 kind: from_valtype(&ValType::I32),
84 of: wasm_val_union { i32: value },
85 },
86 Val::I64(value) => Self {
87 kind: from_valtype(&ValType::I64),
88 of: wasm_val_union { i64: value },
89 },
90 Val::F32(value) => Self {
91 kind: from_valtype(&ValType::F32),
92 of: wasm_val_union {
93 u32: value.to_bits(),
94 },
95 },
96 Val::F64(value) => Self {
97 kind: from_valtype(&ValType::F64),
98 of: wasm_val_union {
99 u64: value.to_bits(),
100 },
101 },
102 Val::V128(value) => Self {
103 kind: from_valtype(&ValType::V128),
104 of: wasm_val_union {
105 v128: value.as_u128(),
106 },
107 },
108 Val::FuncRef(funcref) => Self {
109 kind: from_valtype(&ValType::FuncRef),
110 of: wasm_val_union {
111 ref_: {
112 match funcref.is_null() {
113 true => ptr::null_mut(),
114 false => Box::into_raw(Box::new(wasm_ref_t {
115 inner: WasmRef::Func(funcref),
116 })),
117 }
118 },
119 },
120 },
121 Val::ExternRef(_) => {
122 core::panic!("`wasm_val_t`: creating a `wasm_val_t` from an `externref`")
123 }
124 }
125 }
126}
127
128impl wasm_val_t {
129 pub fn to_val(&self) -> Val {
135 match into_valtype(self.kind) {
136 ValType::I32 => Val::from(unsafe { self.of.i32 }),
137 ValType::I64 => Val::from(unsafe { self.of.i64 }),
138 ValType::F32 => Val::from(F32::from(unsafe { self.of.f32 })),
139 ValType::F64 => Val::from(F64::from(unsafe { self.of.f64 })),
140 ValType::V128 => Val::from(V128::from(unsafe { self.of.v128 })),
141 ValType::FuncRef => match unsafe { self.of.ref_ }.is_null() {
142 true => Val::FuncRef(<Ref<Func>>::Null),
143 false => ref_to_val(unsafe { &*self.of.ref_ }),
144 },
145 ValType::ExternRef => {
146 core::unreachable!("`wasm_val_t`: cannot contain non-function reference values")
147 }
148 }
149 }
150}
151
152#[cfg_attr(not(feature = "prefix-symbols"), no_mangle)]
158#[cfg_attr(feature = "prefix-symbols", wasmi_c_api_macros::prefix_symbol)]
159pub unsafe extern "C" fn wasm_val_copy(out: &mut MaybeUninit<wasm_val_t>, source: &wasm_val_t) {
160 utils::initialize(out, source.clone());
161}
162
163#[cfg_attr(not(feature = "prefix-symbols"), no_mangle)]
170#[cfg_attr(feature = "prefix-symbols", wasmi_c_api_macros::prefix_symbol)]
171pub unsafe extern "C" fn wasm_val_delete(val: *mut wasm_val_t) {
172 ptr::drop_in_place(val);
173}