From 69987786893f06603ccf0eb89a2f343594526f51 Mon Sep 17 00:00:00 2001 From: Celso Bonutti Date: Thu, 22 Jul 2021 18:08:36 -0300 Subject: [PATCH 1/6] feat: parses and builds enum with value ast --- crates/backend/src/ast.rs | 2 ++ crates/backend/src/codegen.rs | 18 +++++++++++++----- crates/macro-support/src/parser.rs | 6 +----- 3 files changed, 16 insertions(+), 10 deletions(-) diff --git a/crates/backend/src/ast.rs b/crates/backend/src/ast.rs index 807c37d908e..4af237f91bf 100644 --- a/crates/backend/src/ast.rs +++ b/crates/backend/src/ast.rs @@ -369,6 +369,8 @@ pub struct Enum { pub struct Variant { /// The name of this variant pub name: Ident, + /// The fields of this variant + pub fields: syn::Fields, /// The backing value of this variant pub value: u32, /// The doc comments on this variant, if any diff --git a/crates/backend/src/codegen.rs b/crates/backend/src/codegen.rs index 57228711749..6bc1ecaec27 100644 --- a/crates/backend/src/codegen.rs +++ b/crates/backend/src/codegen.rs @@ -1165,8 +1165,9 @@ impl ToTokens for ast::Enum { let hole = &self.hole; let cast_clauses = self.variants.iter().map(|variant| { let variant_name = &variant.name; + let variant_value = &variant.value; quote! { - if js == #enum_name::#variant_name as u32 { + if js == #variant_value { #enum_name::#variant_name } } @@ -1178,7 +1179,9 @@ impl ToTokens for ast::Enum { #[inline] fn into_abi(self) -> u32 { - self as u32 + use wasm_bindgen::__rt::std::boxed::Box; + use wasm_bindgen::__rt::WasmRefCell; + Box::into_raw(Box::new(WasmRefCell::new(self))) as u32 } } @@ -1188,9 +1191,14 @@ impl ToTokens for ast::Enum { #[inline] unsafe fn from_abi(js: u32) -> Self { - #(#cast_clauses else)* { - wasm_bindgen::throw_str("invalid enum value passed") - } + use wasm_bindgen::__rt::std::boxed::Box; + use wasm_bindgen::__rt::{assert_not_null, WasmRefCell}; + + let ptr = js as *mut WasmRefCell<#enum_name>; + assert_not_null(ptr); + let js = Box::from_raw(ptr); + (*js).borrow_mut(); // make sure no one's borrowing + js.into_inner() } } diff --git a/crates/macro-support/src/parser.rs b/crates/macro-support/src/parser.rs index eb14712d6e9..beb31290188 100644 --- a/crates/macro-support/src/parser.rs +++ b/crates/macro-support/src/parser.rs @@ -1159,11 +1159,6 @@ impl<'a> MacroParse<(&'a mut TokenStream, BindgenAttrs)> for syn::ItemEnum { .iter() .enumerate() .map(|(i, v)| { - match v.fields { - syn::Fields::Unit => (), - _ => bail_span!(v.fields, "only C-Style enums allowed with #[wasm_bindgen]"), - } - // Require that everything either has a discriminant or doesn't. // We don't really want to get in the business of emulating how // rustc assigns values to enums. @@ -1203,6 +1198,7 @@ impl<'a> MacroParse<(&'a mut TokenStream, BindgenAttrs)> for syn::ItemEnum { name: v.ident.clone(), value, comments, + fields: v.fields.clone(), }) }) .collect::, Diagnostic>>()?; From 9842ea8954170875a29e6ba889aa66d596f9ef87 Mon Sep 17 00:00:00 2001 From: Celso Bonutti Date: Fri, 23 Jul 2021 17:46:06 -0300 Subject: [PATCH 2/6] temp: move to desktop --- crates/backend/src/codegen.rs | 44 +++++++++++++++++++++-------------- src/convert/slices.rs | 2 +- 2 files changed, 27 insertions(+), 19 deletions(-) diff --git a/crates/backend/src/codegen.rs b/crates/backend/src/codegen.rs index 6bc1ecaec27..a2e045c108f 100644 --- a/crates/backend/src/codegen.rs +++ b/crates/backend/src/codegen.rs @@ -1166,52 +1166,60 @@ impl ToTokens for ast::Enum { let cast_clauses = self.variants.iter().map(|variant| { let variant_name = &variant.name; let variant_value = &variant.value; + let fields = &variant.fields.clone(); + let variant_fields_into_array = fields.iter().enumerate().map(|(index, field)| { + quote! { + #field::from_abi(variant[(#index + 1)]) + } + }); + quote! { - if js == #variant_value { - #enum_name::#variant_name + if variant[0] == #variant_value { + #enum_name::#variant_name(#(#variant_fields_into_array)*,) } } }); (quote! { + use wasm_bindgen::convert::{WasmAbi, traits::*}; + #[allow(clippy::all)] impl wasm_bindgen::convert::IntoWasmAbi for #enum_name { - type Abi = u32; + type Abi = WasmSlice; #[inline] - fn into_abi(self) -> u32 { - use wasm_bindgen::__rt::std::boxed::Box; - use wasm_bindgen::__rt::WasmRefCell; - Box::into_raw(Box::new(WasmRefCell::new(self))) as u32 + fn into_abi(self) -> WasmSlice { + WasmSlice::null_slice() } } #[allow(clippy::all)] impl wasm_bindgen::convert::FromWasmAbi for #enum_name { - type Abi = u32; + type Abi = WasmSlice; #[inline] - unsafe fn from_abi(js: u32) -> Self { - use wasm_bindgen::__rt::std::boxed::Box; - use wasm_bindgen::__rt::{assert_not_null, WasmRefCell}; + unsafe fn from_abi(js: WasmSlice) -> Self { + let ptr = <*mut u32>::from_abi(js.ptr); + let len = js.len as usize; + let variant = Vec::from_raw_parts(ptr, len, len).into_boxed_slice(); - let ptr = js as *mut WasmRefCell<#enum_name>; - assert_not_null(ptr); - let js = Box::from_raw(ptr); - (*js).borrow_mut(); // make sure no one's borrowing - js.into_inner() + #(#cast_clauses else)* { + wasm_bindgen::throw_str("invalid enum value passed") + } } } #[allow(clippy::all)] impl wasm_bindgen::convert::OptionFromWasmAbi for #enum_name { #[inline] - fn is_none(val: &u32) -> bool { *val == #hole } + fn is_none(val: &WasmSlice) -> bool { + <*mut u32>::from_abi(val.ptr) == (#hole as u32) + } } #[allow(clippy::all)] impl wasm_bindgen::convert::OptionIntoWasmAbi for #enum_name { #[inline] - fn none() -> Self::Abi { #hole } + fn none() -> Self::Abi { WasmSlice { ptr: 0, len: 0 } } } #[allow(clippy::all)] diff --git a/src/convert/slices.rs b/src/convert/slices.rs index 9d0970f4e6a..67081ea31b3 100644 --- a/src/convert/slices.rs +++ b/src/convert/slices.rs @@ -23,7 +23,7 @@ pub struct WasmSlice { unsafe impl WasmAbi for WasmSlice {} #[inline] -fn null_slice() -> WasmSlice { +pub fn null_slice() -> WasmSlice { WasmSlice { ptr: 0, len: 0 } } From 0992662729e5a8392f3f429b9fb17ddb95c2a1e9 Mon Sep 17 00:00:00 2001 From: Celso Bonutti Date: Fri, 23 Jul 2021 19:54:03 -0300 Subject: [PATCH 3/6] feat: adds WASM ABI transformation for enums --- crates/backend/src/codegen.rs | 45 +++++++++++++++++++++++++++++++---- 1 file changed, 40 insertions(+), 5 deletions(-) diff --git a/crates/backend/src/codegen.rs b/crates/backend/src/codegen.rs index a2e045c108f..b7f86d9e3d8 100644 --- a/crates/backend/src/codegen.rs +++ b/crates/backend/src/codegen.rs @@ -1161,11 +1161,14 @@ impl<'a> ToTokens for DescribeImport<'a> { impl ToTokens for ast::Enum { fn to_tokens(&self, into: &mut TokenStream) { + use quote::format_ident; + let enum_name = &self.rust_name; let hole = &self.hole; let cast_clauses = self.variants.iter().map(|variant| { let variant_name = &variant.name; let variant_value = &variant.value; + let fields = &variant.fields.clone(); let variant_fields_into_array = fields.iter().enumerate().map(|(index, field)| { quote! { @@ -1175,20 +1178,52 @@ impl ToTokens for ast::Enum { quote! { if variant[0] == #variant_value { - #enum_name::#variant_name(#(#variant_fields_into_array)*,) + #enum_name::#variant_name(#(#variant_fields_into_array),*) } } }); + let into_clauses = self.variants.iter().map(|variant| { + let variant_name = &variant.name; + let variant_value = &variant.value; + + let fields = &variant.fields.clone(); + let variant_array_into_tuple = fields.iter().enumerate().map(|(index, _)| { + let varname = format_ident!("arg{}", index); + quote! { + #varname + } + }); + + let variant_types_into_vector = fields.iter().enumerate().map(|(index, field)| { + let varname = format_ident!("arg{}", index); + quote! { + #field::into_abi(#varname) + } + }); + + quote! { + #enum_name::#variant_name(#(#variant_array_into_tuple),*) => vec![#variant_value, #(#variant_types_into_vector),*] + } + }); (quote! { - use wasm_bindgen::convert::{WasmAbi, traits::*}; + use wasm_bindgen::convert::{WasmAbi, WasmSlice}; #[allow(clippy::all)] impl wasm_bindgen::convert::IntoWasmAbi for #enum_name { type Abi = WasmSlice; - #[inline] fn into_abi(self) -> WasmSlice { - WasmSlice::null_slice() + let vector = match self { + #(#into_clauses),* + }; + + let ptr = vector.as_ptr(); + let len = vector.len(); + core::mem::forget(vector); + WasmSlice { + ptr: ptr.into_abi(), + len: len as u32, + } } } @@ -1212,7 +1247,7 @@ impl ToTokens for ast::Enum { impl wasm_bindgen::convert::OptionFromWasmAbi for #enum_name { #[inline] fn is_none(val: &WasmSlice) -> bool { - <*mut u32>::from_abi(val.ptr) == (#hole as u32) + val.ptr == (#hole as u32) } } From 01126970bb7393ad037c32d12bcf5f0ebdbda020 Mon Sep 17 00:00:00 2001 From: Celso Bonutti Date: Fri, 23 Jul 2021 20:02:10 -0300 Subject: [PATCH 4/6] refactor: updates names in enum with value ABI transformation --- crates/backend/src/codegen.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/backend/src/codegen.rs b/crates/backend/src/codegen.rs index b7f86d9e3d8..a1f5e155224 100644 --- a/crates/backend/src/codegen.rs +++ b/crates/backend/src/codegen.rs @@ -1187,14 +1187,14 @@ impl ToTokens for ast::Enum { let variant_value = &variant.value; let fields = &variant.fields.clone(); - let variant_array_into_tuple = fields.iter().enumerate().map(|(index, _)| { + let field_vector_into_tuple = fields.iter().enumerate().map(|(index, _)| { let varname = format_ident!("arg{}", index); quote! { #varname } }); - let variant_types_into_vector = fields.iter().enumerate().map(|(index, field)| { + let fields_into_vector = fields.iter().enumerate().map(|(index, field)| { let varname = format_ident!("arg{}", index); quote! { #field::into_abi(#varname) @@ -1202,7 +1202,7 @@ impl ToTokens for ast::Enum { }); quote! { - #enum_name::#variant_name(#(#variant_array_into_tuple),*) => vec![#variant_value, #(#variant_types_into_vector),*] + #enum_name::#variant_name(#(#field_vector_into_tuple),*) => vec![#variant_value, #(#fields_into_vector),*] } }); (quote! { From d4ac212c825790ef3f241781958e788e13d82399 Mon Sep 17 00:00:00 2001 From: Celso Bonutti Date: Fri, 23 Jul 2021 20:06:37 -0300 Subject: [PATCH 5/6] refactor: removes unnecessary mapping for enum ABI vector construction --- crates/backend/src/codegen.rs | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/crates/backend/src/codegen.rs b/crates/backend/src/codegen.rs index a1f5e155224..7b038db5374 100644 --- a/crates/backend/src/codegen.rs +++ b/crates/backend/src/codegen.rs @@ -1194,15 +1194,11 @@ impl ToTokens for ast::Enum { } }); - let fields_into_vector = fields.iter().enumerate().map(|(index, field)| { - let varname = format_ident!("arg{}", index); - quote! { - #field::into_abi(#varname) - } - }); + let field_names = field_vector_into_tuple.clone(); quote! { - #enum_name::#variant_name(#(#field_vector_into_tuple),*) => vec![#variant_value, #(#fields_into_vector),*] + #enum_name::#variant_name(#(#field_vector_into_tuple),*) + => vec![#variant_value, #((#field_names).into_abi()),*] } }); (quote! { From 0a738ff135a594f571201d2d087f207276417352 Mon Sep 17 00:00:00 2001 From: Celso Bonutti Date: Fri, 30 Jul 2021 16:45:20 -0300 Subject: [PATCH 6/6] feat: encodes enum variants as u32 arrays --- crates/backend/src/codegen.rs | 26 +++++---- crates/cli-support/src/descriptor.rs | 30 ++++++++++- crates/cli-support/src/js/binding.rs | 1 + crates/cli-support/src/wit/incoming.rs | 24 +++++++-- crates/cli-support/src/wit/outgoing.rs | 31 ++++++++--- crates/cli-support/src/wit/standard.rs | 10 +++- src/convert/mod.rs | 2 +- src/convert/slices.rs | 73 ++++++++++++++++++++++++++ 8 files changed, 169 insertions(+), 28 deletions(-) diff --git a/crates/backend/src/codegen.rs b/crates/backend/src/codegen.rs index 7b038db5374..ee6264c10a5 100644 --- a/crates/backend/src/codegen.rs +++ b/crates/backend/src/codegen.rs @@ -1170,14 +1170,14 @@ impl ToTokens for ast::Enum { let variant_value = &variant.value; let fields = &variant.fields.clone(); - let variant_fields_into_array = fields.iter().enumerate().map(|(index, field)| { + let variant_fields_into_array = fields.iter().map(|field| { quote! { - #field::from_abi(variant[(#index + 1)]) + #field::from_abi(<#field as FromWasmAbi>::Abi::pop_from_u32_vector(&mut vector)) } }); quote! { - if variant[0] == #variant_value { + if vector.pop().unwrap() == #variant_value { #enum_name::#variant_name(#(#variant_fields_into_array),*) } } @@ -1189,20 +1189,24 @@ impl ToTokens for ast::Enum { let fields = &variant.fields.clone(); let field_vector_into_tuple = fields.iter().enumerate().map(|(index, _)| { let varname = format_ident!("arg{}", index); - quote! { - #varname - } + quote! { + #varname + } }); let field_names = field_vector_into_tuple.clone(); quote! { #enum_name::#variant_name(#(#field_vector_into_tuple),*) - => vec![#variant_value, #((#field_names).into_abi()),*] + => { + let mut vector = vec![(#variant_value).into_abi()]; + #((#field_names).into_abi().push_into_u32_vector(&mut vector));*; + vector + } } }); (quote! { - use wasm_bindgen::convert::{WasmAbi, WasmSlice}; + use wasm_bindgen::convert::{WasmAbi, WasmSlice, FromWasmAbi, VectorEncoding}; #[allow(clippy::all)] impl wasm_bindgen::convert::IntoWasmAbi for #enum_name { @@ -1231,10 +1235,11 @@ impl ToTokens for ast::Enum { unsafe fn from_abi(js: WasmSlice) -> Self { let ptr = <*mut u32>::from_abi(js.ptr); let len = js.len as usize; - let variant = Vec::from_raw_parts(ptr, len, len).into_boxed_slice(); + let mut vector = Vec::from_raw_parts(ptr, len, len); + let err = format!("{:?}", vector.len()).as_str(); #(#cast_clauses else)* { - wasm_bindgen::throw_str("invalid enum value passed") + wasm_bindgen::throw_str(err,) } } } @@ -1258,7 +1263,6 @@ impl ToTokens for ast::Enum { fn describe() { use wasm_bindgen::describe::*; inform(ENUM); - inform(#hole); } } }) diff --git a/crates/cli-support/src/descriptor.rs b/crates/cli-support/src/descriptor.rs index 5950242376a..ad793c0147a 100644 --- a/crates/cli-support/src/descriptor.rs +++ b/crates/cli-support/src/descriptor.rs @@ -64,7 +64,7 @@ pub enum Descriptor { String, Externref, NamedExternref(String), - Enum { hole: u32 }, + Enum, RustStruct(String), Char, Option(Box), @@ -104,6 +104,12 @@ pub enum VectorKind { NamedExternref(String), } +#[derive(Clone, Debug, PartialEq, Eq, Hash)] +pub struct EnumVariant { + pub name: String, + pub fields: Vec +} + impl Descriptor { pub fn decode(mut data: &[u32]) -> Descriptor { let descriptor = Descriptor::_decode(&mut data, false); @@ -135,7 +141,7 @@ impl Descriptor { CACHED_STRING => Descriptor::CachedString, STRING => Descriptor::String, EXTERNREF => Descriptor::Externref, - ENUM => Descriptor::Enum { hole: get(data) }, + ENUM => Descriptor::Enum, RUST_STRUCT => { let name = get_string(data); Descriptor::RustStruct(name) @@ -212,6 +218,26 @@ fn get_string(data: &mut &[u32]) -> String { .collect() } +// fn get_enum(data: &mut &[u32]) -> Descriptor { +// let name = get_string(data); +// let hole = get(data); +// let variants = (0..get(data)).map(|_| { + +// let variant_name = get_string(data); +// let variant_fields = (0..get(data)).map(|_| { +// Descriptor::_decode(data, false) +// }).collect(); + +// EnumVariant { +// name: variant_name, +// fields: variant_fields +// } + +// }).collect(); + +// Descriptor::Enum {name, variants, hole} +// } + impl Closure { fn decode(data: &mut &[u32]) -> Closure { let shim_idx = get(data); diff --git a/crates/cli-support/src/js/binding.rs b/crates/cli-support/src/js/binding.rs index ea79adf9279..1ded13b70d1 100644 --- a/crates/cli-support/src/js/binding.rs +++ b/crates/cli-support/src/js/binding.rs @@ -1234,5 +1234,6 @@ fn adapter2ts(ty: &AdapterType, dst: &mut String) { AdapterType::NamedExternref(name) => dst.push_str(name), AdapterType::Struct(name) => dst.push_str(name), AdapterType::Function => dst.push_str("any"), + AdapterType::Enum => dst.push_str("placeholder") } } diff --git a/crates/cli-support/src/wit/incoming.rs b/crates/cli-support/src/wit/incoming.rs index a911535f485..161432c6520 100644 --- a/crates/cli-support/src/wit/incoming.rs +++ b/crates/cli-support/src/wit/incoming.rs @@ -99,7 +99,17 @@ impl InstructionBuilder<'_, '_> { self.get(AdapterType::F64); self.output.push(AdapterType::F64); } - Descriptor::Enum { .. } => self.number(WitVT::U32, WasmVT::I32), + Descriptor::Enum { .. } => { + let kind = crate::descriptor::VectorKind::U32; + + let malloc = self.cx.malloc()?; + let mem = self.cx.memory()?; + self.instruction( + &[AdapterType::Enum.option()], + Instruction::OptionVector { kind, malloc, mem }, + &[AdapterType::I32, AdapterType::I32], + ); + } Descriptor::Ref(d) => self.incoming_ref(false, d)?, Descriptor::RefMut(d) => self.incoming_ref(true, d)?, Descriptor::Option(d) => self.incoming_option(d)?, @@ -280,11 +290,15 @@ impl InstructionBuilder<'_, '_> { &[AdapterType::I32], ); } - Descriptor::Enum { hole } => { + Descriptor::Enum { .. } => { + let kind = crate::descriptor::VectorKind::U32; + + let malloc = self.cx.malloc()?; + let mem = self.cx.memory()?; self.instruction( - &[AdapterType::U32.option()], - Instruction::I32FromOptionEnum { hole: *hole }, - &[AdapterType::I32], + &[AdapterType::Enum.option()], + Instruction::OptionVector { kind, malloc, mem }, + &[AdapterType::I32, AdapterType::I32], ); } Descriptor::RustStruct(name) => { diff --git a/crates/cli-support/src/wit/outgoing.rs b/crates/cli-support/src/wit/outgoing.rs index bba1fe81d8c..5ec9992e9c9 100644 --- a/crates/cli-support/src/wit/outgoing.rs +++ b/crates/cli-support/src/wit/outgoing.rs @@ -60,7 +60,6 @@ impl InstructionBuilder<'_, '_> { self.get(AdapterType::F64); self.output.push(AdapterType::F64); } - Descriptor::Enum { .. } => self.outgoing_i32(AdapterType::U32), Descriptor::Char => { self.instruction( @@ -155,6 +154,22 @@ impl InstructionBuilder<'_, '_> { arg ), + Descriptor::Enum { .. } => { + let kind = crate::descriptor::VectorKind::U32; + + let mem = self.cx.memory()?; + let free = self.cx.free()?; + self.instruction( + &[AdapterType::I32, AdapterType::I32], + Instruction::VectorLoad { + kind, + mem, + free, + }, + &[AdapterType::Enum], + ); + } + // nothing to do Descriptor::Unit => {} @@ -288,13 +303,13 @@ impl InstructionBuilder<'_, '_> { &[AdapterType::String.option()], ); } - Descriptor::Enum { hole } => { - self.instruction( - &[AdapterType::I32], - Instruction::OptionEnumFromI32 { hole: *hole }, - &[AdapterType::U32.option()], - ); - } + // Descriptor::Enum => { + // self.instruction( + // &[AdapterType::I32], + // Instruction::OptionEnumFromI32 { hole: *hole }, + // &[AdapterType::U32.option()], + // ); + // } Descriptor::RustStruct(name) => { self.instruction( &[AdapterType::I32], diff --git a/crates/cli-support/src/wit/standard.rs b/crates/cli-support/src/wit/standard.rs index d9c6807620d..f21e2b65f1e 100644 --- a/crates/cli-support/src/wit/standard.rs +++ b/crates/cli-support/src/wit/standard.rs @@ -86,6 +86,13 @@ pub enum AdapterType { Struct(String), NamedExternref(String), Function, + Enum, +} + +#[derive(Debug, Clone)] +pub struct EnumVariantAdapter { + pub name: String, + pub fields: Vec } #[derive(Debug, Clone)] @@ -354,7 +361,8 @@ impl AdapterType { | AdapterType::Function | AdapterType::Struct(_) | AdapterType::Bool - | AdapterType::Vector(_) => return None, + | AdapterType::Vector(_) + | AdapterType::Enum => return None, }) } diff --git a/src/convert/mod.rs b/src/convert/mod.rs index ce2c0b2c847..6685f7b77ee 100644 --- a/src/convert/mod.rs +++ b/src/convert/mod.rs @@ -7,5 +7,5 @@ mod slices; mod traits; pub use self::impls::*; -pub use self::slices::WasmSlice; +pub use self::slices::{WasmSlice, VectorEncoding}; pub use self::traits::*; diff --git a/src/convert/slices.rs b/src/convert/slices.rs index 67081ea31b3..7b092881ff6 100644 --- a/src/convert/slices.rs +++ b/src/convert/slices.rs @@ -309,3 +309,76 @@ if_std! { fn is_none(slice: &WasmSlice) -> bool { slice.ptr == 0 } } } + +pub trait VectorEncoding { + fn push_into_u32_vector(self, vector: &mut Vec); + + fn pop_from_u32_vector(vector: &mut Vec) -> Self; +} + +impl VectorEncoding for u32 { + fn push_into_u32_vector(self, vector: &mut Vec) { + vector.push(self) + } + + fn pop_from_u32_vector(vector: &mut Vec) -> Self { + vector.pop().unwrap() + } +} + +impl VectorEncoding for () { + fn push_into_u32_vector(self, vector: &mut Vec) { + vector.push(0) + } + + fn pop_from_u32_vector(vector: &mut Vec) -> Self { + vector.pop().unwrap(); + () + } +} + +impl VectorEncoding for f32 { + fn push_into_u32_vector(self, vector: &mut Vec) { + let as_u32 = self.to_bits(); + vector.push(as_u32); + } + + fn pop_from_u32_vector(vector: &mut Vec) -> Self { + f32::from_bits(vector.pop().unwrap()) + } +} + +impl VectorEncoding for f64 { + fn push_into_u32_vector(self, vector: &mut Vec) { + let as_u64 = self.to_bits(); + let hi = (as_u64 >> 32) as u32; + let lo = as_u64 as u32; + vector.push(hi); + vector.push(lo); + } + + fn pop_from_u32_vector(vector: &mut Vec) -> Self { + let hi = vector.pop().unwrap(); + let lo = vector.pop().unwrap(); + let as_u64 = (hi as u64) << 32 | (lo as u64); + f64::from_bits(as_u64) + } +} + +impl VectorEncoding for WasmSlice { + fn push_into_u32_vector(self, vector: &mut Vec) { + let WasmSlice { ptr, len } = self; + + vector.push(ptr); + vector.push(len); + } + + fn pop_from_u32_vector(vector: &mut Vec) -> Self { + let ptr = vector.pop().unwrap(); + let len = vector.pop().unwrap(); + WasmSlice { + ptr, + len + } + } +}