From fd342411e24a8ae159555beb747ae9a27cf75ddf Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 23 Jun 2025 04:24:21 +0000 Subject: [PATCH 1/5] Bump wasmparser from 0.224.1 to 0.235.0 Bumps [wasmparser](https://github.com/bytecodealliance/wasm-tools) from 0.224.1 to 0.235.0. - [Release notes](https://github.com/bytecodealliance/wasm-tools/releases) - [Commits](https://github.com/bytecodealliance/wasm-tools/commits) --- updated-dependencies: - dependency-name: wasmparser dependency-version: 0.235.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- src/hyperlight_component_macro/Cargo.toml | 2 +- src/hyperlight_component_util/Cargo.toml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 26019e9d4..c545d3145 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3666,9 +3666,9 @@ dependencies = [ [[package]] name = "wasmparser" -version = "0.224.1" +version = "0.235.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04f17a5917c2ddd3819e84c661fae0d6ba29d7b9c1f0e96c708c65a9c4188e11" +checksum = "161296c618fa2d63f6ed5fffd1112937e803cb9ec71b32b01a76321555660917" dependencies = [ "bitflags 2.9.1", "hashbrown", diff --git a/src/hyperlight_component_macro/Cargo.toml b/src/hyperlight_component_macro/Cargo.toml index b23c0fef9..8c90c88b3 100644 --- a/src/hyperlight_component_macro/Cargo.toml +++ b/src/hyperlight_component_macro/Cargo.toml @@ -16,7 +16,7 @@ name = "hyperlight_component_macro" proc-macro = true [dependencies] -wasmparser = { version = "0.224.0" } +wasmparser = { version = "0.235.0" } quote = { version = "1.0.38" } proc-macro2 = { version = "1.0.95" } syn = { version = "2.0.104" } diff --git a/src/hyperlight_component_util/Cargo.toml b/src/hyperlight_component_util/Cargo.toml index ece9bdb79..57451dbcd 100644 --- a/src/hyperlight_component_util/Cargo.toml +++ b/src/hyperlight_component_util/Cargo.toml @@ -15,7 +15,7 @@ Shared implementation for the procedural macros that generate Hyperlight host an name = "hyperlight_component_util" [dependencies] -wasmparser = { version = "0.224.0" } +wasmparser = { version = "0.235.0" } quote = { version = "1.0.38" } proc-macro2 = { version = "1.0.95" } syn = { version = "2.0.104" } From 157d84d67c6111a34fc1179363919096c0b2e715 Mon Sep 17 00:00:00 2001 From: James Sturtevant Date: Fri, 27 Jun 2025 16:38:45 -0700 Subject: [PATCH 2/5] Updates for wasmparser apis This was a bit more involved due to a big change in the way function return types are handled. The orginal change was done in https://github.com/WebAssembly/component-model/pull/368 and put initially put behind a feature flag in https://github.com/bytecodealliance/wasm-tools/pull/1670. In 0.226.0 version of wasmparser this feature flag was removed simplify the return results. This in turn simplifies the handling of the results here as well. Signed-off-by: James Sturtevant --- .../src/elaborate.rs | 35 ++++++++----------- src/hyperlight_component_util/src/etypes.rs | 8 +---- src/hyperlight_component_util/src/hl.rs | 16 ++++----- src/hyperlight_component_util/src/rtypes.rs | 9 +++-- .../src/substitute.rs | 9 ++--- src/hyperlight_component_util/src/wf.rs | 6 ++-- src/tests/rust_guests/witguest/Cargo.lock | 4 +-- 7 files changed, 34 insertions(+), 53 deletions(-) diff --git a/src/hyperlight_component_util/src/elaborate.rs b/src/hyperlight_component_util/src/elaborate.rs index c38051725..bff05737a 100644 --- a/src/hyperlight_component_util/src/elaborate.rs +++ b/src/hyperlight_component_util/src/elaborate.rs @@ -24,14 +24,14 @@ limitations under the License. //! substitute.rs for more details of the approach here). use wasmparser::{ - ComponentAlias, ComponentDefinedType, ComponentFuncResult, ComponentFuncType, - ComponentOuterAliasKind, ComponentType, ComponentTypeDeclaration, ComponentTypeRef, - ComponentValType, CompositeInnerType, CoreType, InstanceTypeDeclaration, ModuleTypeDeclaration, - OuterAliasKind, PrimitiveValType, TypeBounds, TypeRef, + ComponentAlias, ComponentDefinedType, ComponentFuncType, ComponentOuterAliasKind, + ComponentType, ComponentTypeDeclaration, ComponentTypeRef, ComponentValType, + CompositeInnerType, CoreType, InstanceTypeDeclaration, ModuleTypeDeclaration, OuterAliasKind, + PrimitiveValType, TypeBounds, TypeRef, }; use crate::etypes::{ - self, BoundedTyvar, Component, CoreDefined, CoreExportDecl, CoreExternDesc, CoreModule, + BoundedTyvar, Component, CoreDefined, CoreExportDecl, CoreExternDesc, CoreModule, CoreOrComponentExternDesc, Ctx, Defined, ExternDecl, ExternDesc, FloatWidth, Func, Handleable, Instance, IntWidth, Name, Param, QualifiedInstance, RecordField, Resource, ResourceId, TypeBound, Tyvar, Value, VariantCase, @@ -366,6 +366,7 @@ impl<'p, 'a> Ctx<'p, 'a> { PrimitiveValType::F64 => Value::F(FloatWidth::F64), PrimitiveValType::Char => Value::Char, PrimitiveValType::String => Value::String, + PrimitiveValType::ErrorContext => panic!("async not yet supported"), }), } } @@ -428,9 +429,12 @@ impl<'p, 'a> Ctx<'p, 'a> { Defined::Handleable(h) => Ok(Value::Borrow(h.clone())), _ => Err(Error::HandleToNonResource), }, - ComponentDefinedType::Future(_) - | ComponentDefinedType::Stream(_) - | ComponentDefinedType::ErrorContext => panic!("async not yet supported"), + ComponentDefinedType::Future(_) | ComponentDefinedType::Stream(_) => { + panic!("async not yet supported") + } + ComponentDefinedType::FixedSizeList(vt, _) => { + Ok(Value::List(Box::new(self.elab_value(vt)?))) + } } } @@ -446,18 +450,9 @@ impl<'p, 'a> Ctx<'p, 'a> { }) }) .collect::, Error<'a>>>()?, - result: match &ft.results { - ComponentFuncResult::Unnamed(vt) => etypes::Result::Unnamed(self.elab_value(vt)?), - ComponentFuncResult::Named(rs) => etypes::Result::Named( - rs.iter() - .map(|(n, vt)| { - Ok(Param { - name: Name { name: n }, - ty: self.elab_value(vt)?, - }) - }) - .collect::, Error<'a>>>()?, - ), + result: match &ft.result { + Some(vt) => Some(self.elab_value(vt)?), + None => None, }, }) } diff --git a/src/hyperlight_component_util/src/etypes.rs b/src/hyperlight_component_util/src/etypes.rs index 0cec42887..62693c67a 100644 --- a/src/hyperlight_component_util/src/etypes.rs +++ b/src/hyperlight_component_util/src/etypes.rs @@ -136,17 +136,11 @@ pub struct Param<'a> { pub ty: Value<'a>, } -#[derive(Debug, Clone)] -pub enum Result<'a> { - Unnamed(Value<'a>), - Named(Vec>), -} - /// functype_e in the specification #[derive(Debug, Clone)] pub struct Func<'a> { pub params: Vec>, - pub result: Result<'a>, + pub result: Option>, } /// In the spec, this does not exist, but a validation rule ensures an diff --git a/src/hyperlight_component_util/src/hl.rs b/src/hyperlight_component_util/src/hl.rs index 5a8e984f3..fa1a081aa 100644 --- a/src/hyperlight_component_util/src/hl.rs +++ b/src/hyperlight_component_util/src/hl.rs @@ -19,7 +19,7 @@ use proc_macro2::{Ident, TokenStream}; use quote::{format_ident, quote}; use crate::emit::{State, kebab_to_cons, kebab_to_var}; -use crate::etypes::{self, Defined, Handleable, TypeBound, Tyvar, Value}; +use crate::etypes::{Defined, Handleable, TypeBound, Tyvar, Value}; use crate::rtypes; /// Construct a string that can be used "on the wire" to identify a @@ -653,14 +653,13 @@ pub fn emit_hl_unmarshal_param(s: &mut State, id: Ident, pt: &Value) -> TokenStr /// /// Precondition: the result type must only be a named result if there /// are no names in it (i.e. a unit type) -pub fn emit_hl_unmarshal_result(s: &mut State, id: Ident, rt: &etypes::Result) -> TokenStream { +pub fn emit_hl_unmarshal_result(s: &mut State, id: Ident, rt: &Option>) -> TokenStream { match rt { - etypes::Result::Named(rs) if rs.is_empty() => quote! { () }, - etypes::Result::Unnamed(vt) => { + Some(vt) => { let toks = emit_hl_unmarshal_value(s, id, vt); quote! { { #toks }.0 } } - _ => panic!("named results not supported"), + None => quote! { () }, } } @@ -678,13 +677,12 @@ pub fn emit_hl_marshal_param(s: &mut State, id: Ident, pt: &Value) -> TokenStrea /// /// Precondition: the result type must only be a named result if there /// are no names in it (a unit type) -pub fn emit_hl_marshal_result(s: &mut State, id: Ident, rt: &etypes::Result) -> TokenStream { +pub fn emit_hl_marshal_result(s: &mut State, id: Ident, rt: &Option>) -> TokenStream { match rt { - etypes::Result::Named(rs) if rs.is_empty() => quote! { ::alloc::vec::Vec::new() }, - etypes::Result::Unnamed(vt) => { + None => quote! { ::alloc::vec::Vec::new() }, + Some(vt) => { let toks = emit_hl_marshal_value(s, id, vt); quote! { { #toks } } } - _ => panic!("named results not supported"), } } diff --git a/src/hyperlight_component_util/src/rtypes.rs b/src/hyperlight_component_util/src/rtypes.rs index a6b2266a3..e90d8ad06 100644 --- a/src/hyperlight_component_util/src/rtypes.rs +++ b/src/hyperlight_component_util/src/rtypes.rs @@ -30,7 +30,7 @@ use crate::emit::{ }; use crate::etypes::{ Component, Defined, ExternDecl, ExternDesc, Func, Handleable, ImportExport, Instance, Param, - Result, TypeBound, Tyvar, Value, + TypeBound, Tyvar, Value, }; /// When referring to an instance or resource trait, emit a token @@ -521,11 +521,10 @@ pub fn emit_func_param(s: &mut State, p: &Param) -> TokenStream { /// /// Precondition: the result type must only be a named result if there /// are no names in it (i.e. a unit type) -pub fn emit_func_result(s: &mut State, r: &Result) -> TokenStream { +pub fn emit_func_result(s: &mut State, r: &Option>) -> TokenStream { match r { - Result::Unnamed(vt) => emit_value(s, vt), - Result::Named(rs) if rs.is_empty() => quote! { () }, - _ => panic!("multiple named function results are not currently supported"), + Some(vt) => emit_value(s, vt), + None => quote! { () }, } } diff --git a/src/hyperlight_component_util/src/substitute.rs b/src/hyperlight_component_util/src/substitute.rs index 94f95cf7b..c0dca8429 100644 --- a/src/hyperlight_component_util/src/substitute.rs +++ b/src/hyperlight_component_util/src/substitute.rs @@ -134,13 +134,10 @@ where pts.iter().map(|pt| self.param(pt)).collect() } - fn result( - &self, - rt: &crate::etypes::Result<'a>, - ) -> Result, Self::Error> { + fn result(&self, rt: &Option>) -> Result>, Self::Error> { Ok(match rt { - crate::etypes::Result::Unnamed(vt) => crate::etypes::Result::Unnamed(self.value(vt)?), - crate::etypes::Result::Named(pts) => crate::etypes::Result::Named(self.params(pts)?), + Some(vt) => Some(self.value(vt)?), + None => None, }) } diff --git a/src/hyperlight_component_util/src/wf.rs b/src/hyperlight_component_util/src/wf.rs index db15a7613..b93d1cdfc 100644 --- a/src/hyperlight_component_util/src/wf.rs +++ b/src/hyperlight_component_util/src/wf.rs @@ -268,10 +268,8 @@ impl<'p, 'a> Ctx<'p, 'a> { .iter() .try_for_each(|fp: &'r Param<'a>| self.wf_value(param_pos, &fp.ty))?; match &ft.result { - crate::etypes::Result::Unnamed(vt) => self.wf_value(result_pos, vt), - crate::etypes::Result::Named(ps) => ps - .iter() - .try_for_each(|fp: &'r Param<'a>| self.wf_value(result_pos, &fp.ty)), + Some(vt) => self.wf_value(result_pos, vt), + None => Ok(()), } } fn wf_type_bound<'r>( diff --git a/src/tests/rust_guests/witguest/Cargo.lock b/src/tests/rust_guests/witguest/Cargo.lock index a1edc4b10..bcb5b4813 100644 --- a/src/tests/rust_guests/witguest/Cargo.lock +++ b/src/tests/rust_guests/witguest/Cargo.lock @@ -500,9 +500,9 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "wasmparser" -version = "0.224.1" +version = "0.235.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04f17a5917c2ddd3819e84c661fae0d6ba29d7b9c1f0e96c708c65a9c4188e11" +checksum = "161296c618fa2d63f6ed5fffd1112937e803cb9ec71b32b01a76321555660917" dependencies = [ "bitflags", "hashbrown", From 231e8bff6d4d620b5fcea62d0ab0186721996660 Mon Sep 17 00:00:00 2001 From: James Sturtevant Date: Tue, 1 Jul 2025 00:45:11 +0000 Subject: [PATCH 3/5] fixup! Updates for wasmparser apis Signed-off-by: James Sturtevant --- src/hyperlight_component_util/src/etypes.rs | 4 +++- src/hyperlight_component_util/src/hl.rs | 6 +++--- src/hyperlight_component_util/src/rtypes.rs | 6 +++--- src/hyperlight_component_util/src/substitute.rs | 5 ++++- 4 files changed, 13 insertions(+), 8 deletions(-) diff --git a/src/hyperlight_component_util/src/etypes.rs b/src/hyperlight_component_util/src/etypes.rs index 62693c67a..78ce056ab 100644 --- a/src/hyperlight_component_util/src/etypes.rs +++ b/src/hyperlight_component_util/src/etypes.rs @@ -136,11 +136,13 @@ pub struct Param<'a> { pub ty: Value<'a>, } +pub type Result<'a> = Option>; + /// functype_e in the specification #[derive(Debug, Clone)] pub struct Func<'a> { pub params: Vec>, - pub result: Option>, + pub result: Result<'a>, } /// In the spec, this does not exist, but a validation rule ensures an diff --git a/src/hyperlight_component_util/src/hl.rs b/src/hyperlight_component_util/src/hl.rs index fa1a081aa..21fc71ad5 100644 --- a/src/hyperlight_component_util/src/hl.rs +++ b/src/hyperlight_component_util/src/hl.rs @@ -19,7 +19,7 @@ use proc_macro2::{Ident, TokenStream}; use quote::{format_ident, quote}; use crate::emit::{State, kebab_to_cons, kebab_to_var}; -use crate::etypes::{Defined, Handleable, TypeBound, Tyvar, Value}; +use crate::etypes::{self, Defined, Handleable, TypeBound, Tyvar, Value}; use crate::rtypes; /// Construct a string that can be used "on the wire" to identify a @@ -653,7 +653,7 @@ pub fn emit_hl_unmarshal_param(s: &mut State, id: Ident, pt: &Value) -> TokenStr /// /// Precondition: the result type must only be a named result if there /// are no names in it (i.e. a unit type) -pub fn emit_hl_unmarshal_result(s: &mut State, id: Ident, rt: &Option>) -> TokenStream { +pub fn emit_hl_unmarshal_result(s: &mut State, id: Ident, rt: &etypes::Result<'_>) -> TokenStream { match rt { Some(vt) => { let toks = emit_hl_unmarshal_value(s, id, vt); @@ -677,7 +677,7 @@ pub fn emit_hl_marshal_param(s: &mut State, id: Ident, pt: &Value) -> TokenStrea /// /// Precondition: the result type must only be a named result if there /// are no names in it (a unit type) -pub fn emit_hl_marshal_result(s: &mut State, id: Ident, rt: &Option>) -> TokenStream { +pub fn emit_hl_marshal_result(s: &mut State, id: Ident, rt: &etypes::Result) -> TokenStream { match rt { None => quote! { ::alloc::vec::Vec::new() }, Some(vt) => { diff --git a/src/hyperlight_component_util/src/rtypes.rs b/src/hyperlight_component_util/src/rtypes.rs index e90d8ad06..907f88b12 100644 --- a/src/hyperlight_component_util/src/rtypes.rs +++ b/src/hyperlight_component_util/src/rtypes.rs @@ -29,8 +29,8 @@ use crate::emit::{ split_wit_name, }; use crate::etypes::{ - Component, Defined, ExternDecl, ExternDesc, Func, Handleable, ImportExport, Instance, Param, - TypeBound, Tyvar, Value, + self, Component, Defined, ExternDecl, ExternDesc, Func, Handleable, ImportExport, Instance, + Param, TypeBound, Tyvar, Value, }; /// When referring to an instance or resource trait, emit a token @@ -521,7 +521,7 @@ pub fn emit_func_param(s: &mut State, p: &Param) -> TokenStream { /// /// Precondition: the result type must only be a named result if there /// are no names in it (i.e. a unit type) -pub fn emit_func_result(s: &mut State, r: &Option>) -> TokenStream { +pub fn emit_func_result(s: &mut State, r: &etypes::Result<'_>) -> TokenStream { match r { Some(vt) => emit_value(s, vt), None => quote! { () }, diff --git a/src/hyperlight_component_util/src/substitute.rs b/src/hyperlight_component_util/src/substitute.rs index c0dca8429..f885dcb55 100644 --- a/src/hyperlight_component_util/src/substitute.rs +++ b/src/hyperlight_component_util/src/substitute.rs @@ -134,7 +134,10 @@ where pts.iter().map(|pt| self.param(pt)).collect() } - fn result(&self, rt: &Option>) -> Result>, Self::Error> { + fn result( + &self, + rt: &crate::etypes::Result<'a>, + ) -> Result, Self::Error> { Ok(match rt { Some(vt) => Some(self.value(vt)?), None => None, From 4bab02e6ebdb02bb29f31e2e365ae16f64b70659 Mon Sep 17 00:00:00 2001 From: James Sturtevant Date: Tue, 1 Jul 2025 17:14:22 +0000 Subject: [PATCH 4/5] Add test to make sure fixed length works Signed-off-by: James Sturtevant --- src/hyperlight_host/tests/wit_test.rs | 4 ++++ src/tests/rust_guests/witguest/guest.wit | 1 + src/tests/rust_guests/witguest/src/main.rs | 3 +++ 3 files changed, 8 insertions(+) diff --git a/src/hyperlight_host/tests/wit_test.rs b/src/hyperlight_host/tests/wit_test.rs index e42441dd8..58572cad4 100644 --- a/src/hyperlight_host/tests/wit_test.rs +++ b/src/hyperlight_host/tests/wit_test.rs @@ -155,6 +155,9 @@ impl test::wit::Roundtrip for Host { ) -> test::wit::roundtrip::Testenum { x } + fn roundtrip_fix_list(&mut self, x: Vec) -> Vec { + x + } fn roundtrip_no_result(&mut self, _x: u32) {} } @@ -331,6 +334,7 @@ mod wit_test { make_test! { roundtrip_flags_large, in arb_largeflags() } make_test! { roundtrip_variant, in arb_testvariant() } make_test! { roundtrip_enum, in arb_testenum() } + make_test! { roundtrip_fix_list, : Vec } #[test] fn test_simple_func() { diff --git a/src/tests/rust_guests/witguest/guest.wit b/src/tests/rust_guests/witguest/guest.wit index 30b4969c5..b99e35ef9 100644 --- a/src/tests/rust_guests/witguest/guest.wit +++ b/src/tests/rust_guests/witguest/guest.wit @@ -26,6 +26,7 @@ interface roundtrip { roundtrip-option: func(x: option) -> option; roundtrip-result: func(x: result) -> result; roundtrip-no-result: func(x: u32); + roundtrip-fix-list: func(x: list) -> list; record testrecord { contents: string, diff --git a/src/tests/rust_guests/witguest/src/main.rs b/src/tests/rust_guests/witguest/src/main.rs index 1edf44ec1..cb71aa0e4 100644 --- a/src/tests/rust_guests/witguest/src/main.rs +++ b/src/tests/rust_guests/witguest/src/main.rs @@ -113,6 +113,9 @@ impl test::wit::Roundtrip for Guest { ) -> test::wit::roundtrip::Testenum { (Host {}).roundtrip_enum(x) } + fn roundtrip_fix_list(&mut self, x: Vec) -> Vec { + (Host {}).roundtrip_fix_list(x) + } fn roundtrip_no_result(&mut self, x: u32) { (Host {}).roundtrip_no_result(x) } From f7bc8435f0c06ef8a32b8840fa7fb2a152106ad1 Mon Sep 17 00:00:00 2001 From: James Sturtevant Date: Tue, 1 Jul 2025 19:36:14 +0000 Subject: [PATCH 5/5] Handle fixed list with different API Signed-off-by: James Sturtevant --- .../src/elaborate.rs | 4 +-- src/hyperlight_component_util/src/etypes.rs | 1 + src/hyperlight_component_util/src/hl.rs | 33 +++++++++++++++++++ src/hyperlight_component_util/src/rtypes.rs | 5 +++ .../src/substitute.rs | 1 + src/hyperlight_component_util/src/wf.rs | 1 + src/hyperlight_host/tests/wit_test.rs | 10 ++++-- src/tests/rust_guests/witguest/guest.wit | 1 + src/tests/rust_guests/witguest/src/main.rs | 7 +++- 9 files changed, 57 insertions(+), 6 deletions(-) diff --git a/src/hyperlight_component_util/src/elaborate.rs b/src/hyperlight_component_util/src/elaborate.rs index bff05737a..28a5f0f0e 100644 --- a/src/hyperlight_component_util/src/elaborate.rs +++ b/src/hyperlight_component_util/src/elaborate.rs @@ -432,8 +432,8 @@ impl<'p, 'a> Ctx<'p, 'a> { ComponentDefinedType::Future(_) | ComponentDefinedType::Stream(_) => { panic!("async not yet supported") } - ComponentDefinedType::FixedSizeList(vt, _) => { - Ok(Value::List(Box::new(self.elab_value(vt)?))) + ComponentDefinedType::FixedSizeList(vt, size) => { + Ok(Value::FixList(Box::new(self.elab_value(vt)?), *size)) } } } diff --git a/src/hyperlight_component_util/src/etypes.rs b/src/hyperlight_component_util/src/etypes.rs index 78ce056ab..5723eaf9a 100644 --- a/src/hyperlight_component_util/src/etypes.rs +++ b/src/hyperlight_component_util/src/etypes.rs @@ -83,6 +83,7 @@ pub enum Value<'a> { Char, String, List(Box>), + FixList(Box>, u32), Record(Vec>), Tuple(Vec>), Flags(Vec>), diff --git a/src/hyperlight_component_util/src/hl.rs b/src/hyperlight_component_util/src/hl.rs index 21fc71ad5..781328688 100644 --- a/src/hyperlight_component_util/src/hl.rs +++ b/src/hyperlight_component_util/src/hl.rs @@ -223,6 +223,20 @@ pub fn emit_hl_unmarshal_value(s: &mut State, id: Ident, vt: &Value) -> TokenStr (#retid, cursor) } } + Value::FixList(vt, _size) => { + let inid = format_ident!("{}_elem", id); + let vtun = emit_hl_unmarshal_value(s, inid.clone(), vt); + quote! { + let mut cursor = 0; + let arr = ::core::array::from_fn(|_i| { + let #inid = &#id[cursor..]; + let (x, b) = { #vtun }; + cursor += b; + x + }); + (arr, cursor) + } + } Value::Record(_) => panic!("record not at top level of valtype"), Value::Tuple(vts) => { let inid = format_ident!("{}_elem", id); @@ -515,6 +529,25 @@ pub fn emit_hl_marshal_value(s: &mut State, id: Ident, vt: &Value) -> TokenStrea #retid } } + Value::FixList(vt, _size) => { + // Optimize for byte arrays ie. [u8; N] + if matches!(vt.as_ref(), Value::S(_) | Value::U(_) | Value::F(_)) { + quote! { + alloc::vec::Vec::from(#id.as_slice()) + } + } else { + let retid = format_ident!("{}_fixlist", id); + let inid = format_ident!("{}_elem", id); + let vtun = emit_hl_marshal_value(s, inid.clone(), vt); + quote! { + let mut #retid = alloc::vec::Vec::new(); + for #inid in #id { + #retid.extend({ #vtun }) + } + #retid + } + } + } Value::Record(_) => panic!("record not at top level of valtype"), Value::Tuple(vts) => { let retid = format_ident!("{}_tuple", id); diff --git a/src/hyperlight_component_util/src/rtypes.rs b/src/hyperlight_component_util/src/rtypes.rs index 907f88b12..e9b8ded61 100644 --- a/src/hyperlight_component_util/src/rtypes.rs +++ b/src/hyperlight_component_util/src/rtypes.rs @@ -281,6 +281,11 @@ pub fn emit_value(s: &mut State, vt: &Value) -> TokenStream { let vt = emit_value(s, vt); quote! { alloc::vec::Vec<#vt> } } + Value::FixList(vt, size) => { + let vt = emit_value(s, vt); + let size = *size as usize; + quote! { [#vt; #size] } + } Value::Record(_) => panic!("record not at top level of valtype"), Value::Tuple(vts) => { let vts = vts.iter().map(|vt| emit_value(s, vt)).collect::>(); diff --git a/src/hyperlight_component_util/src/substitute.rs b/src/hyperlight_component_util/src/substitute.rs index f885dcb55..5ea07d609 100644 --- a/src/hyperlight_component_util/src/substitute.rs +++ b/src/hyperlight_component_util/src/substitute.rs @@ -96,6 +96,7 @@ where Value::Char => Value::Char, Value::String => Value::String, Value::List(vt) => Value::List(Box::new(self.value(vt)?)), + Value::FixList(vt, size) => Value::FixList(Box::new(self.value(vt)?), *size), Value::Record(rfs) => Value::Record(self.record_fields(rfs)?), Value::Variant(vcs) => Value::Variant(self.variant_cases(vcs)?), Value::Flags(ns) => Value::Flags(ns.clone()), diff --git a/src/hyperlight_component_util/src/wf.rs b/src/hyperlight_component_util/src/wf.rs index b93d1cdfc..20321d6d7 100644 --- a/src/hyperlight_component_util/src/wf.rs +++ b/src/hyperlight_component_util/src/wf.rs @@ -213,6 +213,7 @@ impl<'p, 'a> Ctx<'p, 'a> { Value::Char => Ok(()), Value::String => Ok(()), Value::List(vt) => self.wf_value(p_, vt), + Value::FixList(vt, _) => self.wf_value(p_, vt), Value::Record(rfs) => anon_err.and(self.wf_record_fields(p_, rfs)), Value::Variant(vcs) => anon_err.and(self.wf_variant_cases(p_, vcs)), Value::Flags(ns) => anon_err.and(error_if_duplicates_by( diff --git a/src/hyperlight_host/tests/wit_test.rs b/src/hyperlight_host/tests/wit_test.rs index 58572cad4..403553379 100644 --- a/src/hyperlight_host/tests/wit_test.rs +++ b/src/hyperlight_host/tests/wit_test.rs @@ -155,7 +155,10 @@ impl test::wit::Roundtrip for Host { ) -> test::wit::roundtrip::Testenum { x } - fn roundtrip_fix_list(&mut self, x: Vec) -> Vec { + fn roundtrip_fix_list(&mut self, x: [u8; 4]) -> [u8; 4] { + x + } + fn roundtrip_fix_list_string(&mut self, x: [String; 4]) -> [String; 4] { x } @@ -334,10 +337,11 @@ mod wit_test { make_test! { roundtrip_flags_large, in arb_largeflags() } make_test! { roundtrip_variant, in arb_testvariant() } make_test! { roundtrip_enum, in arb_testenum() } - make_test! { roundtrip_fix_list, : Vec } + make_test! { roundtrip_fix_list, : [u8; 4] } + make_test! { roundtrip_fix_list_string, : [String; 4] } #[test] - fn test_simple_func() { + fn test_roundtrip_no_result() { sb().roundtrip().roundtrip_no_result(42); } diff --git a/src/tests/rust_guests/witguest/guest.wit b/src/tests/rust_guests/witguest/guest.wit index b99e35ef9..07afc0d73 100644 --- a/src/tests/rust_guests/witguest/guest.wit +++ b/src/tests/rust_guests/witguest/guest.wit @@ -27,6 +27,7 @@ interface roundtrip { roundtrip-result: func(x: result) -> result; roundtrip-no-result: func(x: u32); roundtrip-fix-list: func(x: list) -> list; + roundtrip-fix-list-string: func(x: list) -> list; record testrecord { contents: string, diff --git a/src/tests/rust_guests/witguest/src/main.rs b/src/tests/rust_guests/witguest/src/main.rs index cb71aa0e4..d9e610029 100644 --- a/src/tests/rust_guests/witguest/src/main.rs +++ b/src/tests/rust_guests/witguest/src/main.rs @@ -21,6 +21,8 @@ extern crate alloc; extern crate hyperlight_guest; mod bindings; +use alloc::string::String; + use bindings::*; struct Guest {} @@ -113,9 +115,12 @@ impl test::wit::Roundtrip for Guest { ) -> test::wit::roundtrip::Testenum { (Host {}).roundtrip_enum(x) } - fn roundtrip_fix_list(&mut self, x: Vec) -> Vec { + fn roundtrip_fix_list(&mut self, x: [u8; 4]) -> [u8; 4] { (Host {}).roundtrip_fix_list(x) } + fn roundtrip_fix_list_string(&mut self, x: [String; 4]) -> [String; 4] { + (Host {}).roundtrip_fix_list_string(x) + } fn roundtrip_no_result(&mut self, x: u32) { (Host {}).roundtrip_no_result(x) }