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