wasmer_c_api/wasm_c_api/
value.rs1use super::types::{wasm_ref_t, wasm_valkind_enum};
2use std::convert::{TryFrom, TryInto};
3use wasmer_api::Value;
4
5#[allow(non_camel_case_types)]
15pub type wasm_valkind_t = u8;
16
17#[allow(non_camel_case_types)]
27#[derive(Clone, Copy)]
28pub union wasm_val_inner {
29 pub(crate) int32_t: i32,
30 pub(crate) int64_t: i64,
31 pub(crate) float32_t: f32,
32 pub(crate) float64_t: f64,
33 pub(crate) wref: *mut wasm_ref_t,
34}
35
36#[allow(non_camel_case_types)]
70#[repr(C)]
71pub struct wasm_val_t {
72 pub kind: wasm_valkind_t,
74
75 pub of: wasm_val_inner,
77}
78
79impl std::fmt::Debug for wasm_val_t {
80 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
81 let mut ds = f.debug_struct("wasm_val_t");
82 ds.field("kind", &self.kind);
83
84 match self.kind.try_into() {
85 Ok(wasm_valkind_enum::WASM_I32) => {
86 ds.field("i32", &unsafe { self.of.int32_t });
87 }
88 Ok(wasm_valkind_enum::WASM_I64) => {
89 ds.field("i64", &unsafe { self.of.int64_t });
90 }
91 Ok(wasm_valkind_enum::WASM_F32) => {
92 ds.field("f32", &unsafe { self.of.float32_t });
93 }
94 Ok(wasm_valkind_enum::WASM_F64) => {
95 ds.field("f64", &unsafe { self.of.float64_t });
96 }
97 Ok(wasm_valkind_enum::WASM_EXTERNREF) => {
98 ds.field("anyref", &unsafe { self.of.wref });
99 }
100 Ok(wasm_valkind_enum::WASM_FUNCREF) => {
101 ds.field("funcref", &unsafe { self.of.wref });
102 }
103 Ok(wasm_valkind_enum::WASM_EXNREF) => {
104 ds.field("exnref", &unsafe { self.of.wref });
105 }
106 Err(_) => {
107 ds.field("value", &"Invalid value type");
108 }
109 }
110 ds.finish()
111 }
112}
113
114wasm_declare_vec!(val);
115
116impl Clone for wasm_val_t {
117 fn clone(&self) -> Self {
118 wasm_val_t {
119 kind: self.kind,
120 of: self.of,
121 }
122 }
123}
124
125impl Default for wasm_val_t {
126 fn default() -> Self {
127 Self {
128 kind: wasm_valkind_enum::WASM_I64 as _,
129 of: wasm_val_inner { int64_t: 0 },
130 }
131 }
132}
133
134#[unsafe(no_mangle)]
135pub unsafe extern "C" fn wasm_val_copy(
136 out: &mut wasm_val_t,
138 val: &wasm_val_t,
139) {
140 out.kind = val.kind;
141 out.of = c_try!(val.kind.try_into().map(|kind| unsafe {
142 match kind {
143 wasm_valkind_enum::WASM_I32 => wasm_val_inner {
144 int32_t: val.of.int32_t,
145 },
146 wasm_valkind_enum::WASM_I64 => wasm_val_inner {
147 int64_t: val.of.int64_t,
148 },
149 wasm_valkind_enum::WASM_F32 => wasm_val_inner {
150 float32_t: val.of.float32_t,
151 },
152 wasm_valkind_enum::WASM_F64 => wasm_val_inner {
153 float64_t: val.of.float64_t,
154 },
155 wasm_valkind_enum::WASM_EXTERNREF => wasm_val_inner { wref: val.of.wref },
156 wasm_valkind_enum::WASM_FUNCREF => wasm_val_inner { wref: val.of.wref },
157 wasm_valkind_enum::WASM_EXNREF => wasm_val_inner { wref: val.of.wref },
158 }
159 }); otherwise ());
160}
161
162impl Drop for wasm_val_t {
163 fn drop(&mut self) {
164 let kind: Result<wasm_valkind_enum, _> = self.kind.try_into();
165 match kind {
166 Ok(wasm_valkind_enum::WASM_EXTERNREF) | Ok(wasm_valkind_enum::WASM_FUNCREF) => unsafe {
167 if !self.of.wref.is_null() {
168 drop(Box::from_raw(self.of.wref));
169 }
170 },
171 _ => {}
172 }
173 }
174}
175
176#[unsafe(no_mangle)]
177pub unsafe extern "C" fn wasm_val_delete(val: *mut wasm_val_t) {
178 if !val.is_null() {
179 unsafe {
180 std::ptr::drop_in_place(val);
181 }
182 }
183}
184
185impl TryFrom<wasm_valkind_t> for wasm_valkind_enum {
186 type Error = &'static str;
187
188 fn try_from(item: wasm_valkind_t) -> Result<Self, Self::Error> {
189 Ok(match item {
190 0 => wasm_valkind_enum::WASM_I32,
191 1 => wasm_valkind_enum::WASM_I64,
192 2 => wasm_valkind_enum::WASM_F32,
193 3 => wasm_valkind_enum::WASM_F64,
194 128 => wasm_valkind_enum::WASM_EXTERNREF,
195 129 => wasm_valkind_enum::WASM_FUNCREF,
196 130 => wasm_valkind_enum::WASM_EXNREF,
197 _ => return Err("valkind value out of bounds"),
198 })
199 }
200}
201
202impl TryFrom<wasm_val_t> for Value {
203 type Error = &'static str;
204
205 fn try_from(item: wasm_val_t) -> Result<Self, Self::Error> {
206 (&item).try_into()
207 }
208}
209
210impl TryFrom<&wasm_val_t> for Value {
211 type Error = &'static str;
212
213 fn try_from(item: &wasm_val_t) -> Result<Self, Self::Error> {
214 Ok(match item.kind.try_into()? {
215 wasm_valkind_enum::WASM_I32 => Value::I32(unsafe { item.of.int32_t }),
216 wasm_valkind_enum::WASM_I64 => Value::I64(unsafe { item.of.int64_t }),
217 wasm_valkind_enum::WASM_F32 => Value::F32(unsafe { item.of.float32_t }),
218 wasm_valkind_enum::WASM_F64 => Value::F64(unsafe { item.of.float64_t }),
219 wasm_valkind_enum::WASM_EXTERNREF => {
220 return Err("EXTERNREF not supported at this time");
221 }
222 wasm_valkind_enum::WASM_FUNCREF => return Err("FUNCREF not supported at this time"),
223 wasm_valkind_enum::WASM_EXNREF => return Err("EXNREF not supported at this time"),
224 })
225 }
226}
227
228impl TryFrom<Value> for wasm_val_t {
229 type Error = &'static str;
230
231 fn try_from(item: Value) -> Result<Self, Self::Error> {
232 wasm_val_t::try_from(&item)
233 }
234}
235
236impl TryFrom<&Value> for wasm_val_t {
237 type Error = &'static str;
238
239 fn try_from(item: &Value) -> Result<Self, Self::Error> {
240 Ok(match *item {
241 Value::I32(v) => wasm_val_t {
242 of: wasm_val_inner { int32_t: v },
243 kind: wasm_valkind_enum::WASM_I32 as _,
244 },
245 Value::I64(v) => wasm_val_t {
246 of: wasm_val_inner { int64_t: v },
247 kind: wasm_valkind_enum::WASM_I64 as _,
248 },
249 Value::F32(v) => wasm_val_t {
250 of: wasm_val_inner { float32_t: v },
251 kind: wasm_valkind_enum::WASM_F32 as _,
252 },
253 Value::F64(v) => wasm_val_t {
254 of: wasm_val_inner { float64_t: v },
255 kind: wasm_valkind_enum::WASM_F64 as _,
256 },
257 Value::V128(_) => return Err("128bit SIMD types not yet supported in Wasm C API"),
258 _ => todo!("Handle these values in TryFrom<Value> for wasm_val_t"),
259 })
260 }
261}