introduce trait FCERecordSerializer

This commit is contained in:
vms 2020-07-28 16:49:10 +03:00
parent 88afe8feaa
commit 141807945e
13 changed files with 55 additions and 78 deletions

View File

@ -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<u8>, 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<S: AsRef<str>>(msg: S) {
// logs will be printed only if debug feature is enabled

View File

@ -20,6 +20,7 @@
nonstandard_style,
unused_imports,
unused_mut,
unused_variables,
unused_unsafe,
unreachable_patterns
)]

View File

@ -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<ParsedType>) -> 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 _);
}
}

View File

@ -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!(

View File

@ -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 },

View File

@ -59,12 +59,9 @@ impl ForeignModEpilogGlueCodeGenerator for Option<ParsedType> {
)
},
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!(

View File

@ -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_";

View File

@ -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

View File

@ -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), *);

View File

@ -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<u64> = Vec::from_raw_parts(offset as _, #record_size, #record_size);
unsafe fn __fce_generated_deserialize(record_ptr: *const u8) -> Self {
let raw_record: Vec<u64> = Vec::from_raw_parts(record_ptr as _, #record_size, #record_size);
#deserializer

View File

@ -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::<Vec<_>>();
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,
}
}
}

View File

@ -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 }
}
}
}

View File

@ -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;
}