use crate::r#ref::{ref_to_val, WasmRefInner}; use crate::{from_valtype, into_valtype, wasm_ref_t, wasm_valkind_t, WASM_I32}; use std::mem::MaybeUninit; use std::ptr; use wasmtime::{Val, ValType}; #[repr(C)] pub struct wasm_val_t { pub kind: wasm_valkind_t, pub of: wasm_val_union, } #[repr(C)] #[derive(Copy, Clone)] pub union wasm_val_union { pub i32: i32, pub i64: i64, pub u32: u32, pub u64: u64, pub f32: f32, pub f64: f64, pub ref_: *mut wasm_ref_t, } impl Drop for wasm_val_t { fn drop(&mut self) { match into_valtype(self.kind) { ValType::FuncRef | ValType::ExternRef => unsafe { if !self.of.ref_.is_null() { drop(Box::from_raw(self.of.ref_)); } }, _ => {} } } } impl Clone for wasm_val_t { fn clone(&self) -> Self { let mut ret = wasm_val_t { kind: self.kind, of: self.of, }; unsafe { match into_valtype(self.kind) { ValType::ExternRef | ValType::FuncRef if !self.of.ref_.is_null() => { ret.of.ref_ = Box::into_raw(Box::new((*self.of.ref_).clone())); } _ => {} } } return ret; } } impl Default for wasm_val_t { fn default() -> Self { wasm_val_t { kind: WASM_I32, of: wasm_val_union { i32: 0 }, } } } impl wasm_val_t { pub fn from_val(val: Val) -> wasm_val_t { match val { Val::I32(i) => wasm_val_t { kind: from_valtype(&ValType::I32), of: wasm_val_union { i32: i }, }, Val::I64(i) => wasm_val_t { kind: from_valtype(&ValType::I64), of: wasm_val_union { i64: i }, }, Val::F32(f) => wasm_val_t { kind: from_valtype(&ValType::F32), of: wasm_val_union { u32: f }, }, Val::F64(f) => wasm_val_t { kind: from_valtype(&ValType::F64), of: wasm_val_union { u64: f }, }, Val::ExternRef(None) => wasm_val_t { kind: from_valtype(&ValType::ExternRef), of: wasm_val_union { ref_: ptr::null_mut(), }, }, Val::ExternRef(Some(r)) => wasm_val_t { kind: from_valtype(&ValType::ExternRef), of: wasm_val_union { ref_: Box::into_raw(Box::new(wasm_ref_t { r: WasmRefInner::ExternRef(r), })), }, }, Val::FuncRef(None) => wasm_val_t { kind: from_valtype(&ValType::FuncRef), of: wasm_val_union { ref_: ptr::null_mut(), }, }, Val::FuncRef(Some(f)) => wasm_val_t { kind: from_valtype(&ValType::FuncRef), of: wasm_val_union { ref_: Box::into_raw(Box::new(wasm_ref_t { r: WasmRefInner::FuncRef(f), })), }, }, _ => unimplemented!("wasm_val_t::from_val {:?}", val), } } pub fn val(&self) -> Val { match into_valtype(self.kind) { ValType::I32 => Val::from(unsafe { self.of.i32 }), ValType::I64 => Val::from(unsafe { self.of.i64 }), ValType::F32 => Val::from(unsafe { self.of.f32 }), ValType::F64 => Val::from(unsafe { self.of.f64 }), ValType::ExternRef => unsafe { if self.of.ref_.is_null() { Val::ExternRef(None) } else { ref_to_val(&*self.of.ref_) } }, ValType::FuncRef => unsafe { if self.of.ref_.is_null() { Val::FuncRef(None) } else { ref_to_val(&*self.of.ref_) } }, _ => unimplemented!("wasm_val_t::val {:?}", self.kind), } } } #[no_mangle] pub unsafe extern "C" fn wasm_val_copy(out: &mut MaybeUninit, source: &wasm_val_t) { crate::initialize(out, source.clone()); } #[no_mangle] pub unsafe extern "C" fn wasm_val_delete(val: *mut wasm_val_t) { ptr::drop_in_place(val); }