1 use crate::prelude::*; 2 use std::borrow::Cow; 3 4 use super::{canonicalize_nan32, canonicalize_nan64, unwrap_val}; 5 use wasm_wave::wasm::{WasmFunc, WasmType, WasmTypeKind, WasmValue, WasmValueError}; 6 7 impl WasmType for crate::ValType { kind(&self) -> WasmTypeKind8 fn kind(&self) -> WasmTypeKind { 9 match self { 10 Self::I32 => WasmTypeKind::S32, 11 Self::I64 => WasmTypeKind::S64, 12 Self::F32 => WasmTypeKind::F32, 13 Self::F64 => WasmTypeKind::F64, 14 Self::V128 => WasmTypeKind::Tuple, 15 16 Self::Ref(_) => WasmTypeKind::Unsupported, 17 } 18 } 19 tuple_element_types(&self) -> Box<dyn Iterator<Item = Self> + '_>20 fn tuple_element_types(&self) -> Box<dyn Iterator<Item = Self> + '_> { 21 match *self { 22 Self::V128 => {} 23 _ => panic!("tuple_element_types called on non-tuple type"), 24 } 25 Box::new([Self::I64, Self::I64].into_iter()) 26 } 27 } 28 29 impl WasmValue for crate::Val { 30 type Type = crate::ValType; 31 kind(&self) -> WasmTypeKind32 fn kind(&self) -> WasmTypeKind { 33 match self { 34 Self::I32(_) => WasmTypeKind::S32, 35 Self::I64(_) => WasmTypeKind::S64, 36 Self::F32(_) => WasmTypeKind::F32, 37 Self::F64(_) => WasmTypeKind::F64, 38 Self::V128(_) => WasmTypeKind::Tuple, 39 Self::FuncRef(_) => WasmTypeKind::Unsupported, 40 Self::ExternRef(_) => WasmTypeKind::Unsupported, 41 Self::AnyRef(_) => WasmTypeKind::Unsupported, 42 Self::ExnRef(_) => WasmTypeKind::Unsupported, 43 Self::ContRef(_) => WasmTypeKind::Unsupported, 44 } 45 } 46 make_s32(val: i32) -> Self47 fn make_s32(val: i32) -> Self { 48 Self::I32(val) 49 } make_s64(val: i64) -> Self50 fn make_s64(val: i64) -> Self { 51 Self::I64(val) 52 } make_f32(val: f32) -> Self53 fn make_f32(val: f32) -> Self { 54 let val = canonicalize_nan32(val); 55 Self::F32(val.to_bits()) 56 } make_f64(val: f64) -> Self57 fn make_f64(val: f64) -> Self { 58 let val = canonicalize_nan64(val); 59 Self::F64(val.to_bits()) 60 } make_tuple( ty: &Self::Type, vals: impl IntoIterator<Item = Self>, ) -> Result<Self, WasmValueError>61 fn make_tuple( 62 ty: &Self::Type, 63 vals: impl IntoIterator<Item = Self>, 64 ) -> Result<Self, WasmValueError> { 65 match *ty { 66 Self::Type::V128 => {} 67 _ => { 68 return Err(WasmValueError::Other( 69 "tuples only used for v128 (v64x2)".to_string(), 70 )); 71 } 72 } 73 let mut iter = vals.into_iter(); 74 let Some(l_val) = iter.next() else { 75 return Err(WasmValueError::Other("expected 2 values".to_string())); 76 }; 77 let Some(h_val) = iter.next() else { 78 return Err(WasmValueError::Other("expected 2 values".to_string())); 79 }; 80 if iter.next().is_some() { 81 return Err(WasmValueError::Other("expected 2 values".to_string())); 82 } 83 84 let (Some(l), Some(h)) = (l_val.i64(), h_val.i64()) else { 85 return Err(WasmValueError::Other("expected 2 i64s (v64x2)".to_string())); 86 }; 87 Ok(Self::V128(((h as u128) << 64 | (l as u128)).into())) 88 } 89 unwrap_s32(&self) -> i3290 fn unwrap_s32(&self) -> i32 { 91 *unwrap_val!(self, Self::I32, "s32") 92 } 93 unwrap_s64(&self) -> i6494 fn unwrap_s64(&self) -> i64 { 95 *unwrap_val!(self, Self::I64, "s64") 96 } 97 unwrap_f32(&self) -> f3298 fn unwrap_f32(&self) -> f32 { 99 let val = f32::from_bits(*unwrap_val!(self, Self::F32, "f32")); 100 canonicalize_nan32(val) 101 } 102 unwrap_f64(&self) -> f64103 fn unwrap_f64(&self) -> f64 { 104 let val = f64::from_bits(*unwrap_val!(self, Self::F64, "f64")); 105 canonicalize_nan64(val) 106 } 107 #[expect(clippy::cast_possible_truncation, reason = "handled losslessly here")] unwrap_tuple(&self) -> Box<dyn Iterator<Item = Cow<'_, Self>> + '_>108 fn unwrap_tuple(&self) -> Box<dyn Iterator<Item = Cow<'_, Self>> + '_> { 109 let v = unwrap_val!(self, Self::V128, "tuple").as_u128(); 110 let low = v as i64; 111 let high = (v >> 64) as i64; 112 Box::new( 113 [Self::I64(low), Self::I64(high)] 114 .into_iter() 115 .map(Cow::Owned), 116 ) 117 } 118 } 119 120 impl WasmFunc for crate::FuncType { 121 type Type = crate::ValType; 122 params(&self) -> Box<dyn Iterator<Item = Self::Type> + '_>123 fn params(&self) -> Box<dyn Iterator<Item = Self::Type> + '_> { 124 Box::new(self.params()) 125 } 126 results(&self) -> Box<dyn Iterator<Item = Self::Type> + '_>127 fn results(&self) -> Box<dyn Iterator<Item = Self::Type> + '_> { 128 Box::new(self.results()) 129 } 130 } 131 132 #[cfg(test)] 133 mod tests { 134 #[test] core_vals_smoke_test()135 fn core_vals_smoke_test() { 136 use crate::Val; 137 for (val, want) in [ 138 (Val::I32(10), "10"), 139 (Val::I64(-10), "-10"), 140 (1.5f32.into(), "1.5"), 141 (f32::NAN.into(), "nan"), 142 (f32::INFINITY.into(), "inf"), 143 (f32::NEG_INFINITY.into(), "-inf"), 144 ((-1.5f64).into(), "-1.5"), 145 (f32::NAN.into(), "nan"), 146 (f32::INFINITY.into(), "inf"), 147 (f32::NEG_INFINITY.into(), "-inf"), 148 ( 149 Val::V128(0x1234567890abcdef1122334455667788.into()), 150 "(1234605616436508552, 1311768467294899695)", 151 ), 152 ] { 153 let got = wasm_wave::to_string(&val) 154 .unwrap_or_else(|err| panic!("failed to serialize {val:?}: {err}")); 155 assert_eq!(got, want, "for {val:?}"); 156 } 157 } 158 } 159