diff --git a/crates/wac-types/src/core.rs b/crates/wac-types/src/core.rs index 87de30d..67fdbeb 100644 --- a/crates/wac-types/src/core.rs +++ b/crates/wac-types/src/core.rs @@ -111,15 +111,17 @@ impl fmt::Display for CoreExtern { } } -impl From for CoreExtern { - fn from(ty: wasmparser::TableType) -> Self { - Self::Table { - element_type: ty.element_type.into(), +impl TryFrom for CoreExtern { + type Error = anyhow::Error; + + fn try_from(ty: wasmparser::TableType) -> anyhow::Result { + Ok(Self::Table { + element_type: ty.element_type.try_into()?, initial: ty.initial, maximum: ty.maximum, table64: ty.table64, shared: ty.shared, - } + }) } } @@ -135,13 +137,15 @@ impl From for CoreExtern { } } -impl From for CoreExtern { - fn from(ty: wasmparser::GlobalType) -> Self { - Self::Global { - val_type: ty.content_type.into(), +impl TryFrom for CoreExtern { + type Error = anyhow::Error; + + fn try_from(ty: wasmparser::GlobalType) -> anyhow::Result { + Ok(Self::Global { + val_type: ty.content_type.try_into()?, mutable: ty.mutable, shared: ty.shared, - } + }) } } @@ -177,16 +181,18 @@ impl fmt::Display for CoreType { } } -impl From for CoreType { - fn from(ty: wasmparser::ValType) -> Self { - match ty { +impl TryFrom for CoreType { + type Error = anyhow::Error; + + fn try_from(ty: wasmparser::ValType) -> anyhow::Result { + Ok(match ty { wasmparser::ValType::I32 => Self::I32, wasmparser::ValType::I64 => Self::I64, wasmparser::ValType::F32 => Self::F32, wasmparser::ValType::F64 => Self::F64, wasmparser::ValType::V128 => Self::V128, - wasmparser::ValType::Ref(ty) => Self::Ref(ty.into()), - } + wasmparser::ValType::Ref(ty) => Self::Ref(ty.try_into()?), + }) } } @@ -253,12 +259,14 @@ impl fmt::Display for CoreRefType { } } -impl From for CoreRefType { - fn from(ty: wasmparser::RefType) -> Self { - Self { +impl TryFrom for CoreRefType { + type Error = anyhow::Error; + + fn try_from(ty: wasmparser::RefType) -> anyhow::Result { + Ok(Self { nullable: ty.is_nullable(), - heap_type: ty.heap_type().into(), - } + heap_type: ty.heap_type().try_into()?, + }) } } @@ -316,9 +324,11 @@ pub enum HeapType { NoCont, } -impl From for HeapType { - fn from(ty: wasmparser::HeapType) -> Self { - match ty { +impl TryFrom for HeapType { + type Error = anyhow::Error; + + fn try_from(ty: wasmparser::HeapType) -> anyhow::Result { + Ok(match ty { wasmparser::HeapType::Abstract { shared: false, ty } => match ty { wasmparser::AbstractHeapType::Any => Self::Any, wasmparser::AbstractHeapType::Func => Self::Func, @@ -336,15 +346,15 @@ impl From for HeapType { wasmparser::AbstractHeapType::NoCont => Self::NoCont, }, wasmparser::HeapType::Abstract { shared: true, ty } => { - panic!("shared heap types are not supported: {:?}", ty) + anyhow::bail!("shared heap types are not supported: {ty:?}") } wasmparser::HeapType::Concrete(index) => { Self::Concrete(index.as_module_index().unwrap()) } wasmparser::HeapType::Exact(_) => { - todo!("wasmparser::HeapType::Exact"); + anyhow::bail!("exact heap types are not yet supported") } - } + }) } } diff --git a/crates/wac-types/src/package.rs b/crates/wac-types/src/package.rs index af6a923..0ba9f76 100644 --- a/crates/wac-types/src/package.rs +++ b/crates/wac-types/src/package.rs @@ -462,14 +462,16 @@ impl<'a> TypeConverter<'a> { let imports = module_ty .imports .iter() - .map(|((module, name), ty)| ((module.clone(), name.clone()), self.entity_type(*ty))) - .collect(); + .map(|((module, name), ty)| { + Ok(((module.clone(), name.clone()), self.entity_type(*ty)?)) + }) + .collect::>()?; let exports = module_ty .exports .iter() - .map(|(name, ty)| (name.clone(), self.entity_type(*ty))) - .collect(); + .map(|(name, ty)| Ok((name.clone(), self.entity_type(*ty)?))) + .collect::>()?; let module_id = self.types.add_module_type(ModuleType { imports, exports }); self.cache @@ -803,25 +805,35 @@ impl<'a> TypeConverter<'a> { resource_id } - fn entity_type(&self, ty: wasmparser::types::EntityType) -> CoreExtern { - match ty { - wasmparser::types::EntityType::Func(ty) => CoreExtern::Func(self.func_type(ty)), - wasmparser::types::EntityType::Table(ty) => ty.into(), + fn entity_type(&self, ty: wasmparser::types::EntityType) -> Result { + Ok(match ty { + wasmparser::types::EntityType::Func(ty) => CoreExtern::Func(self.func_type(ty)?), + wasmparser::types::EntityType::Table(ty) => ty.try_into()?, wasmparser::types::EntityType::Memory(ty) => ty.into(), - wasmparser::types::EntityType::Global(ty) => ty.into(), - wasmparser::types::EntityType::Tag(ty) => CoreExtern::Tag(self.func_type(ty)), + wasmparser::types::EntityType::Global(ty) => ty.try_into()?, + wasmparser::types::EntityType::Tag(ty) => CoreExtern::Tag(self.func_type(ty)?), wasmparser::types::EntityType::FuncExact(_) => { todo!("wasmparser::types::EntityType::FuncExact") } - } + }) } - fn func_type(&self, ty: wasmparser::types::CoreTypeId) -> CoreFuncType { + fn func_type(&self, ty: wasmparser::types::CoreTypeId) -> Result { let func_ty = self.wasm_types[ty].unwrap_func(); - CoreFuncType { - params: func_ty.params().iter().copied().map(Into::into).collect(), - results: func_ty.results().iter().copied().map(Into::into).collect(), - } + Ok(CoreFuncType { + params: func_ty + .params() + .iter() + .copied() + .map(TryInto::try_into) + .collect::>()?, + results: func_ty + .results() + .iter() + .copied() + .map(TryInto::try_into) + .collect::>()?, + }) } fn find_owner(&self, mut id: wasm::ComponentAnyTypeId) -> Option<&(Owner, String)> { diff --git a/crates/wac-types/tests/heap_type_conversion.rs b/crates/wac-types/tests/heap_type_conversion.rs new file mode 100644 index 0000000..0414f90 --- /dev/null +++ b/crates/wac-types/tests/heap_type_conversion.rs @@ -0,0 +1,48 @@ +use wac_types::HeapType; + +#[test] +fn shared_heap_type_returns_error() { + let shared_heap = wasmparser::HeapType::Abstract { + shared: true, + ty: wasmparser::AbstractHeapType::Func, + }; + + let result: Result = shared_heap.try_into(); + assert!( + result.is_err(), + "shared heap types should return an error, not panic" + ); + let err = result.unwrap_err().to_string(); + assert!( + err.contains("shared heap types are not supported"), + "error should mention shared heap types: {err}" + ); +} + +#[test] +fn exact_heap_type_returns_error() { + let exact_heap = wasmparser::HeapType::Exact(wasmparser::UnpackedIndex::Module(0)); + + let result: Result = exact_heap.try_into(); + assert!( + result.is_err(), + "exact heap types should return an error, not panic" + ); + let err = result.unwrap_err().to_string(); + assert!( + err.contains("not yet supported"), + "error should mention unsupported: {err}" + ); +} + +#[test] +fn non_shared_heap_type_succeeds() { + let heap = wasmparser::HeapType::Abstract { + shared: false, + ty: wasmparser::AbstractHeapType::Func, + }; + + let result: Result = heap.try_into(); + assert!(result.is_ok(), "non-shared heap types should convert fine"); + assert_eq!(result.unwrap(), HeapType::Func); +}