From 141807945eb0f356b22d82e3aee509886d127cee Mon Sep 17 00:00:00 2001 From: vms Date: Tue, 28 Jul 2020 16:49:10 +0300 Subject: [PATCH] introduce trait FCERecordSerializer --- crates/main/src/lib.rs | 13 ++++++++ crates/wit/src/lib.rs | 1 + crates/wit/src/parsed_type/fn_epilog.rs | 7 ++-- crates/wit/src/parsed_type/fn_prolog.rs | 7 ++-- crates/wit/src/parsed_type/foreign_mod_arg.rs | 8 ++--- .../wit/src/parsed_type/foreign_mod_epilog.rs | 7 ++-- crates/wit/src/token_stream_generator.rs | 2 -- .../token_stream_generator/fn_generator.rs | 4 +++ .../foreign_mod_generator.rs | 4 +++ .../record_generator.rs | 33 ++++++------------- .../record_generator/record_deserializer.rs | 19 ++++------- .../record_generator/record_serializer.rs | 26 ++++----------- src/lib.rs | 2 ++ 13 files changed, 55 insertions(+), 78 deletions(-) diff --git a/crates/main/src/lib.rs b/crates/main/src/lib.rs index 6dba033..d2c8a4c 100644 --- a/crates/main/src/lib.rs +++ b/crates/main/src/lib.rs @@ -45,6 +45,19 @@ pub use result::get_result_size; pub use result::set_result_ptr; pub use result::set_result_size; +/// This trait is used to convert structs to a form compatible with +/// record.lift_memory and record.lower_memory instructions. +/// Normally, this trait shouldn't be used directly. +pub trait FCEStructSerializable { + // Serialize the provided record to a Vec, returns pointer to it in a form compatible with + // record.lift_memory. + // The caller should manage the lifetime of returned pointer. + fn __fce_generated_serialize(self) -> *const u8; + + // Deserialize record from a pointer (normally, come from record.lower_memory). + unsafe fn __fce_generated_deserialize(record_ptr: *const u8) -> Self; +} + #[allow(unused_variables)] pub(crate) fn log>(msg: S) { // logs will be printed only if debug feature is enabled diff --git a/crates/wit/src/lib.rs b/crates/wit/src/lib.rs index faf6e47..4ae36a1 100644 --- a/crates/wit/src/lib.rs +++ b/crates/wit/src/lib.rs @@ -20,6 +20,7 @@ nonstandard_style, unused_imports, unused_mut, + unused_variables, unused_unsafe, unreachable_patterns )] diff --git a/crates/wit/src/parsed_type/fn_epilog.rs b/crates/wit/src/parsed_type/fn_epilog.rs index e40e4b7..9aa1d79 100644 --- a/crates/wit/src/parsed_type/fn_epilog.rs +++ b/crates/wit/src/parsed_type/fn_epilog.rs @@ -16,7 +16,6 @@ use super::ParsedType; use crate::new_ident; -use crate::token_stream_generator::GENERATED_RECORD_SERIALIZER_PREFIX; use quote::quote; @@ -97,11 +96,9 @@ fn generate_epilog(ty: &Option) -> proc_macro2::TokenStream { Some(ty) if !ty.is_complex_type() => quote! { return result as _; }, - Some(ParsedType::Record(record_name)) => { - let record_serializer = - crate::new_ident!(GENERATED_RECORD_SERIALIZER_PREFIX.to_string() + record_name); + Some(ParsedType::Record(_)) => { quote! { - let result_ptr = crate::#record_serializer(result); + let result_ptr = result.__fce_generated_serialize(); fluence::internal::set_result_ptr(result_ptr as _); } } diff --git a/crates/wit/src/parsed_type/fn_prolog.rs b/crates/wit/src/parsed_type/fn_prolog.rs index e6b6537..5d3cde1 100644 --- a/crates/wit/src/parsed_type/fn_prolog.rs +++ b/crates/wit/src/parsed_type/fn_prolog.rs @@ -16,7 +16,6 @@ use super::ParsedType; use super::FnArgGlueCodeGenerator; -use crate::token_stream_generator::GENERATED_RECORD_DESERIALIZER_PREFIX; use crate::new_ident; use crate::wasm_type::WasmType; @@ -106,11 +105,9 @@ fn generate_type_prolog( let #generated_arg_id = Vec::from_raw_parts(#ptr as _, #size as _, #size as _); }, ParsedType::Record(record_name) => { - let record_deserializer = crate::new_ident!( - GENERATED_RECORD_DESERIALIZER_PREFIX.to_string() + record_name - ); + let record_ident = new_ident!(record_name); quote! { - let #generated_arg_id = crate::#record_deserializer(#ptr); + let #generated_arg_id = #record_ident::__fce_generated_deserialize(#ptr as _); } } _ => panic!( diff --git a/crates/wit/src/parsed_type/foreign_mod_arg.rs b/crates/wit/src/parsed_type/foreign_mod_arg.rs index bd743b1..7f122d4 100644 --- a/crates/wit/src/parsed_type/foreign_mod_arg.rs +++ b/crates/wit/src/parsed_type/foreign_mod_arg.rs @@ -31,13 +31,9 @@ impl ForeignModArgGlueCodeGenerator for ParsedType { ParsedType::Utf8String | ParsedType::ByteVector => { quote! { #arg.as_ptr() as _, #arg.len() as _ } } - ParsedType::Record(record_name) => { - let record_serializer = crate::new_ident!( - crate::token_stream_generator::GENERATED_RECORD_SERIALIZER_PREFIX.to_string() - + record_name - ); + ParsedType::Record(_) => { quote! { - crate::#record_serializer(#arg) + #arg.__fce_generated_serialize() as _ } } _ => quote! { arg }, diff --git a/crates/wit/src/parsed_type/foreign_mod_epilog.rs b/crates/wit/src/parsed_type/foreign_mod_epilog.rs index da73fd9..1368370 100644 --- a/crates/wit/src/parsed_type/foreign_mod_epilog.rs +++ b/crates/wit/src/parsed_type/foreign_mod_epilog.rs @@ -59,12 +59,9 @@ impl ForeignModEpilogGlueCodeGenerator for Option { ) }, Some(ParsedType::Record(record_name)) => { - let record_deserializer = crate::new_ident!( - crate::token_stream_generator::GENERATED_RECORD_DESERIALIZER_PREFIX.to_string() - + record_name - ); + let record_ident = new_ident!(record_name); quote! { - crate::#record_deserializer(fluence::internal::get_result_ptr() as _) + #record_ident::__fce_generated_deserialize(fluence::internal::get_result_ptr() as _) } } _ => panic!( diff --git a/crates/wit/src/token_stream_generator.rs b/crates/wit/src/token_stream_generator.rs index c5e8962..de0c330 100644 --- a/crates/wit/src/token_stream_generator.rs +++ b/crates/wit/src/token_stream_generator.rs @@ -23,8 +23,6 @@ use crate::fce_ast_types::FCEAst; use proc_macro2::TokenStream; pub const GENERATED_WRAPPER_FUNC_PREFIX: &str = "__fce_generated_wrapper_func_"; -pub const GENERATED_RECORD_SERIALIZER_PREFIX: &str = "__fce_generated_record_serializer_"; -pub const GENERATED_RECORD_DESERIALIZER_PREFIX: &str = "__fce_generated_record_deserializer_"; pub const GENERATED_SECTION_PREFIX: &str = "__fce_generated_section__"; pub const GENERATED_GLOBAL_PREFIX: &str = "__fce_generated_static_global_"; diff --git a/crates/wit/src/token_stream_generator/fn_generator.rs b/crates/wit/src/token_stream_generator/fn_generator.rs index 6e5de32..055e13d 100644 --- a/crates/wit/src/token_stream_generator/fn_generator.rs +++ b/crates/wit/src/token_stream_generator/fn_generator.rs @@ -68,6 +68,10 @@ impl quote::ToTokens for fce_ast_types::AstFunctionItem { #[doc(hidden)] #[allow(clippy::all)] pub unsafe fn #func_name(#(#raw_arg_names: #raw_arg_types),*) #fn_return_type { + // brings serialize/deserialize methods for records + #[allow(dead_code)] + use fluence::internal::FCEStructSerializable; + // arguments conversation from Wasm types to Rust types #prolog diff --git a/crates/wit/src/token_stream_generator/foreign_mod_generator.rs b/crates/wit/src/token_stream_generator/foreign_mod_generator.rs index a693978..4b53338 100644 --- a/crates/wit/src/token_stream_generator/foreign_mod_generator.rs +++ b/crates/wit/src/token_stream_generator/foreign_mod_generator.rs @@ -121,6 +121,10 @@ fn generate_wrapper_functions(extern_item: &fce_ast_types::AstExternModItem) -> #[doc(hidden)] #[allow(clippy::all)] #visibility fn #func_name(#(#arg_names: #arg_types), *) #return_type { + // brings serialize/deserialize methods for records + #[allow(dead_code)] + use fluence::internal::FCEStructSerializable; + unsafe { // calling the original function with converted args #return_expression #import_func_name(#(#raw_args), *); diff --git a/crates/wit/src/token_stream_generator/record_generator.rs b/crates/wit/src/token_stream_generator/record_generator.rs index 4bc2a65..ea071ec 100644 --- a/crates/wit/src/token_stream_generator/record_generator.rs +++ b/crates/wit/src/token_stream_generator/record_generator.rs @@ -20,9 +20,6 @@ mod record_deserializer; use record_serializer::*; use record_deserializer::*; -use super::GENERATED_RECORD_SERIALIZER_PREFIX; -use super::GENERATED_RECORD_DESERIALIZER_PREFIX; - use crate::new_ident; use crate::fce_ast_types; @@ -38,6 +35,7 @@ impl quote::ToTokens for fce_ast_types::AstRecordItem { global_static_name, section_name ); + let record_name = new_ident!(self.name); let serializer_fn = generate_serializer_fn(self); let deserializer_fn = generate_deserializer_fn(self); @@ -48,12 +46,11 @@ impl quote::ToTokens for fce_ast_types::AstRecordItem { #[cfg(target_arch = "wasm32")] #[doc(hidden)] #[allow(clippy::all)] - #serializer_fn + impl fluence::internal::FCEStructSerializable for #record_name { + #serializer_fn - #[cfg(target_arch = "wasm32")] - #[doc(hidden)] - #[allow(clippy::all)] - #deserializer_fn + #deserializer_fn + } #[cfg(target_arch = "wasm32")] #[doc(hidden)] @@ -67,16 +64,10 @@ impl quote::ToTokens for fce_ast_types::AstRecordItem { } fn generate_serializer_fn(record: &fce_ast_types::AstRecordItem) -> proc_macro2::TokenStream { - let serializer_fn_name = - new_ident!(GENERATED_RECORD_SERIALIZER_PREFIX.to_string() + &record.name); - - let RecordSerializerDescriptor { - serializer, - record_type, - } = record.generate_serializer(&record.name); + let serializer = record.generate_serializer(); quote::quote! { - pub(in crate) fn #serializer_fn_name(record: #record_type) -> i32 { + fn __fce_generated_serialize(self) -> *const u8 { let mut raw_record = Vec::new(); #serializer @@ -90,21 +81,17 @@ fn generate_serializer_fn(record: &fce_ast_types::AstRecordItem) -> proc_macro2: } fn generate_deserializer_fn(record: &fce_ast_types::AstRecordItem) -> proc_macro2::TokenStream { - let deserializer_fn_name = - new_ident!(GENERATED_RECORD_DESERIALIZER_PREFIX.to_string() + &record.name); - let RecordDeserializerDescriptor { deserializer, type_constructor, - return_type, - } = record.generate_deserializer(&record.name); + } = record.generate_deserializer(); let record_size = crate::utils::get_record_size(record.fields.iter().map(|ast_field| &ast_field.ty)); quote::quote! { - pub(in crate) unsafe fn #deserializer_fn_name(offset: i32) -> #return_type { - let raw_record: Vec = Vec::from_raw_parts(offset as _, #record_size, #record_size); + unsafe fn __fce_generated_deserialize(record_ptr: *const u8) -> Self { + let raw_record: Vec = Vec::from_raw_parts(record_ptr as _, #record_size, #record_size); #deserializer diff --git a/crates/wit/src/token_stream_generator/record_generator/record_deserializer.rs b/crates/wit/src/token_stream_generator/record_generator/record_deserializer.rs index 977e3e1..5d85ac2 100644 --- a/crates/wit/src/token_stream_generator/record_generator/record_deserializer.rs +++ b/crates/wit/src/token_stream_generator/record_generator/record_deserializer.rs @@ -17,25 +17,21 @@ use crate::new_ident; use crate::parsed_type::ParsedType; use crate::fce_ast_types; -use crate::token_stream_generator::GENERATED_RECORD_DESERIALIZER_PREFIX; use quote::quote; pub(super) struct RecordDeserializerDescriptor { pub(super) deserializer: proc_macro2::TokenStream, pub(super) type_constructor: proc_macro2::TokenStream, - pub(super) return_type: syn::Ident, } /// This trait could be used to generate various parts of a record serializer func. pub(super) trait RecordDeserializerGlueCodeGenerator { - fn generate_deserializer(&self, record_name: &str) -> RecordDeserializerDescriptor; + fn generate_deserializer(&self) -> RecordDeserializerDescriptor; } impl RecordDeserializerGlueCodeGenerator for fce_ast_types::AstRecordItem { - fn generate_deserializer(&self, record_name: &str) -> RecordDeserializerDescriptor { - let return_type = new_ident!(record_name); - + fn generate_deserializer(&self) -> RecordDeserializerDescriptor { let mut field_values = Vec::with_capacity(self.fields.len()); let mut deserializer = proc_macro2::TokenStream::new(); let mut value_id: usize = 0; @@ -118,11 +114,9 @@ impl RecordDeserializerGlueCodeGenerator for fce_ast_types::AstRecordItem { } ParsedType::Record(record_name) => { let ptr_id = value_id; - let record_deserializer = - new_ident!(GENERATED_RECORD_DESERIALIZER_PREFIX.to_string() + record_name); - + let record_ident = new_ident!(record_name); quote! { - let #field = crate::#record_deserializer(raw_record[#ptr_id] as _); + let #field = #record_ident::__fce_generated_deserialize(raw_record[#ptr_id] as _); } } }; @@ -143,14 +137,14 @@ impl RecordDeserializerGlueCodeGenerator for fce_ast_types::AstRecordItem { .collect::>(); quote! { - #return_type { + Self { #(#field_names: #field_values),* } } } Some(_) => { quote! { - #return_type ( + Self ( #(#field_values),* ) } @@ -161,7 +155,6 @@ impl RecordDeserializerGlueCodeGenerator for fce_ast_types::AstRecordItem { RecordDeserializerDescriptor { deserializer, type_constructor, - return_type, } } } diff --git a/crates/wit/src/token_stream_generator/record_generator/record_serializer.rs b/crates/wit/src/token_stream_generator/record_generator/record_serializer.rs index a65f172..8b75eb8 100644 --- a/crates/wit/src/token_stream_generator/record_generator/record_serializer.rs +++ b/crates/wit/src/token_stream_generator/record_generator/record_serializer.rs @@ -17,22 +17,16 @@ use crate::new_ident; use crate::parsed_type::ParsedType; use crate::fce_ast_types; -use crate::token_stream_generator::GENERATED_RECORD_SERIALIZER_PREFIX; use quote::quote; -pub(super) struct RecordSerializerDescriptor { - pub(super) serializer: proc_macro2::TokenStream, - pub(super) record_type: syn::Ident, -} - /// This trait could be used to generate various parts of a record serializer func. pub(super) trait RecordSerializerGlueCodeGenerator { - fn generate_serializer(&self, record_name: &str) -> RecordSerializerDescriptor; + fn generate_serializer(&self) -> proc_macro2::TokenStream; } impl RecordSerializerGlueCodeGenerator for fce_ast_types::AstRecordItem { - fn generate_serializer(&self, record_name: &str) -> RecordSerializerDescriptor { + fn generate_serializer(&self) -> proc_macro2::TokenStream { let mut serializer = proc_macro2::TokenStream::new(); for (id, field) in self.fields.iter().enumerate() { let field_ident = field_ident(field, id); @@ -50,11 +44,9 @@ impl RecordSerializerGlueCodeGenerator for fce_ast_types::AstRecordItem { std::mem::forget(#field_ident); } } - ParsedType::Record(record_name) => { - let record_serializer = - new_ident!(GENERATED_RECORD_SERIALIZER_PREFIX.to_string() + &record_name); + ParsedType::Record(_) => { quote! { - raw_record.push(crate::#record_serializer(#field_ident) as _); + raw_record.push(#field_ident.__fce_generated_serialize() as _); } } _ => quote! { @@ -64,12 +56,8 @@ impl RecordSerializerGlueCodeGenerator for fce_ast_types::AstRecordItem { serializer.extend(field_serialization); } - let record_type = new_ident!(record_name); - RecordSerializerDescriptor { - serializer, - record_type, - } + serializer } } @@ -77,11 +65,11 @@ fn field_ident(field: &fce_ast_types::AstRecordField, id: usize) -> proc_macro2: match &field.name { Some(name) => { let name = new_ident!(name); - quote! { record.#name } + quote! { self.#name } } None => { let id = new_ident!(format!("{}", id)); - quote! { record.#id } + quote! { self.#id } } } } diff --git a/src/lib.rs b/src/lib.rs index 61a856d..d6d6d31 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -45,4 +45,6 @@ pub mod internal { pub use fluence_sdk_main::get_result_size; pub use fluence_sdk_main::set_result_ptr; pub use fluence_sdk_main::set_result_size; + + pub use fluence_sdk_main::FCEStructSerializable; }