use crate::{
ExternRef,
F32,
F64,
Func,
Nullable,
Ref,
V128,
ValType,
core::{RawRef, RawVal},
store::AsStoreId,
};
#[derive(Clone, Debug)]
pub enum Val {
I32(i32),
I64(i64),
F32(F32),
F64(F64),
V128(V128),
FuncRef(Nullable<Func>),
ExternRef(Nullable<ExternRef>),
}
impl Val {
pub(crate) fn from_raw_parts(val: RawVal, ty: ValType, store: impl AsStoreId) -> Self {
match ty {
ValType::I32 => Self::I32(val.into()),
ValType::I64 => Self::I64(val.into()),
ValType::F32 => Self::F32(val.into()),
ValType::F64 => Self::F64(val.into()),
#[cfg(feature = "simd")]
ValType::V128 => Self::V128(val.into()),
#[cfg(not(feature = "simd"))]
ValType::V128 => {
panic!("Val::from_raw_parts does not work for `v128` values without `simd`")
}
ValType::FuncRef => Self::FuncRef(<Nullable<Func>>::from_raw_parts(val.into(), store)),
ValType::ExternRef => {
Self::ExternRef(<Nullable<ExternRef>>::from_raw_parts(val.into(), store))
}
}
}
pub(crate) fn unwrap_raw_val(&self, store: impl AsStoreId) -> Option<RawVal> {
let value = match *self {
Self::I32(value) => value.into(),
Self::I64(value) => value.into(),
Self::F32(value) => value.into(),
Self::F64(value) => value.into(),
#[cfg(feature = "simd")]
Self::V128(value) => value.into(),
#[cfg(not(feature = "simd"))]
Self::V128(_) => {
unimplemented!("must enable `simd` crate feature to use `V128` values")
}
Self::FuncRef(value) => <Nullable<Func>>::unwrap_raw(&value, store)?.into(),
Self::ExternRef(value) => <Nullable<ExternRef>>::unwrap_raw(&value, store)?.into(),
};
Some(value)
}
pub(crate) fn unwrap_raw_ref(&self, store: impl AsStoreId) -> Option<RawRef> {
let value = match *self {
Self::FuncRef(value) => <Nullable<Func>>::unwrap_raw(&value, store)?,
Self::ExternRef(value) => <Nullable<ExternRef>>::unwrap_raw(&value, store)?,
_ => return None,
};
Some(value)
}
pub(crate) fn as_raw_or_none(&self) -> Option<RawVal> {
let raw = match *self {
Self::I32(value) => value.into(),
Self::I64(value) => value.into(),
Self::F32(value) => value.into(),
Self::F64(value) => value.into(),
#[cfg(feature = "simd")]
Self::V128(value) => value.into(),
Self::FuncRef(Nullable::Null) => RawRef::null().into(),
Self::ExternRef(Nullable::Null) => RawRef::null().into(),
_ => return None,
};
Some(raw)
}
#[inline]
#[deprecated(note = "use `Val::default_for_ty` instead")]
pub fn default(ty: ValType) -> Self {
Self::default_for_ty(ty)
}
#[inline]
pub fn default_for_ty(ty: ValType) -> Self {
match ty {
ValType::I32 => Self::I32(0),
ValType::I64 => Self::I64(0),
ValType::F32 => Self::F32(0f32.into()),
ValType::F64 => Self::F64(0f64.into()),
ValType::V128 => Self::V128(V128::from(0_u128)),
ValType::FuncRef => Self::from(<Nullable<Func>>::Null),
ValType::ExternRef => Self::from(<Nullable<ExternRef>>::Null),
}
}
#[inline]
pub fn ty(&self) -> ValType {
match *self {
Self::I32(_) => ValType::I32,
Self::I64(_) => ValType::I64,
Self::F32(_) => ValType::F32,
Self::F64(_) => ValType::F64,
Self::V128(_) => ValType::V128,
Self::FuncRef(_) => ValType::FuncRef,
Self::ExternRef(_) => ValType::ExternRef,
}
}
pub fn i32(&self) -> Option<i32> {
match self {
Self::I32(value) => Some(*value),
_ => None,
}
}
pub fn i64(&self) -> Option<i64> {
match self {
Self::I64(value) => Some(*value),
_ => None,
}
}
pub fn f32(&self) -> Option<F32> {
match self {
Self::F32(value) => Some(*value),
_ => None,
}
}
pub fn f64(&self) -> Option<F64> {
match self {
Self::F64(value) => Some(*value),
_ => None,
}
}
pub fn funcref(&self) -> Option<Nullable<&Func>> {
match self {
Self::FuncRef(value) => Some(value.as_ref()),
_ => None,
}
}
pub fn externref(&self) -> Option<Nullable<&ExternRef>> {
match self {
Self::ExternRef(value) => Some(value.as_ref()),
_ => None,
}
}
}
impl From<i32> for Val {
#[inline]
fn from(val: i32) -> Self {
Self::I32(val)
}
}
impl From<i64> for Val {
#[inline]
fn from(val: i64) -> Self {
Self::I64(val)
}
}
impl From<f32> for Val {
#[inline]
fn from(val: f32) -> Self {
Self::F32(F32::from_float(val))
}
}
impl From<f64> for Val {
#[inline]
fn from(val: f64) -> Self {
Self::F64(F64::from_float(val))
}
}
impl From<F32> for Val {
#[inline]
fn from(val: F32) -> Self {
Self::F32(val)
}
}
impl From<F64> for Val {
#[inline]
fn from(val: F64) -> Self {
Self::F64(val)
}
}
impl From<Ref> for Val {
fn from(value: Ref) -> Self {
match value {
Ref::Func(nullable) => Self::FuncRef(nullable),
Ref::Extern(nullable) => Self::ExternRef(nullable),
}
}
}
impl From<Func> for Val {
#[inline]
fn from(func: Func) -> Self {
Self::FuncRef(Nullable::Val(func))
}
}
impl From<ExternRef> for Val {
#[inline]
fn from(externref: ExternRef) -> Self {
Self::ExternRef(Nullable::Val(externref))
}
}
impl From<Nullable<Func>> for Val {
#[inline]
fn from(funcref: Nullable<Func>) -> Self {
Self::FuncRef(funcref)
}
}
impl From<Nullable<ExternRef>> for Val {
#[inline]
fn from(externref: Nullable<ExternRef>) -> Self {
Self::ExternRef(externref)
}
}
impl From<V128> for Val {
#[inline]
fn from(value: V128) -> Self {
Self::V128(value)
}
}