mirror of
https://github.com/fluencelabs/marine-rs-sdk-test
synced 2024-12-04 15:20:18 +00:00
move record logic to a separate module
This commit is contained in:
parent
e589d52c72
commit
0c09b32bb7
@ -14,12 +14,17 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
mod record_serializer;
|
||||
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;
|
||||
use crate::ParsedType;
|
||||
|
||||
impl quote::ToTokens for fce_ast_types::AstRecordItem {
|
||||
fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
|
||||
@ -34,15 +39,21 @@ impl quote::ToTokens for fce_ast_types::AstRecordItem {
|
||||
section_name
|
||||
);
|
||||
|
||||
let serializer = generate_serializer(self);
|
||||
let deserializer = generate_deserializer(self);
|
||||
let serializer_fn = generate_serializer_fn(self);
|
||||
let deserializer_fn = generate_deserializer_fn(self);
|
||||
|
||||
let glue_code = quote::quote! {
|
||||
#original
|
||||
|
||||
#serializer
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
#[doc(hidden)]
|
||||
#[allow(clippy::all)]
|
||||
#serializer_fn
|
||||
|
||||
#deserializer
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
#[doc(hidden)]
|
||||
#[allow(clippy::all)]
|
||||
#deserializer_fn
|
||||
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
#[doc(hidden)]
|
||||
@ -55,60 +66,17 @@ impl quote::ToTokens for fce_ast_types::AstRecordItem {
|
||||
}
|
||||
}
|
||||
|
||||
fn field_ident(field: &fce_ast_types::AstRecordField, id: usize) -> proc_macro2::TokenStream {
|
||||
match &field.name {
|
||||
Some(name) => {
|
||||
let name = new_ident!(name);
|
||||
quote::quote! { record.#name }
|
||||
}
|
||||
None => {
|
||||
let id = new_ident!(format!("{}", id));
|
||||
quote::quote! { record.#id }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn generate_serializer(record: &fce_ast_types::AstRecordItem) -> proc_macro2::TokenStream {
|
||||
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 ty = new_ident!(record.name);
|
||||
|
||||
let mut serializer = proc_macro2::TokenStream::new();
|
||||
for (id, field) in record.fields.iter().enumerate() {
|
||||
let field_ident = field_ident(field, id);
|
||||
|
||||
let field_serialization = match &field.ty {
|
||||
ParsedType::F64 => {
|
||||
quote::quote! {
|
||||
raw_record.push(#field_ident.to_bits());
|
||||
}
|
||||
}
|
||||
ParsedType::Utf8String | ParsedType::ByteVector => {
|
||||
quote::quote! {
|
||||
raw_record.push(#field_ident.as_ptr() as _);
|
||||
raw_record.push(#field_ident.len() as _);
|
||||
}
|
||||
}
|
||||
ParsedType::Record(record_name) => {
|
||||
let serializer_name =
|
||||
new_ident!(GENERATED_RECORD_SERIALIZER_PREFIX.to_string() + record_name);
|
||||
quote::quote! {
|
||||
raw_record.push(#serializer_name(#field_ident) as _);
|
||||
}
|
||||
}
|
||||
_ => quote::quote! {
|
||||
raw_record.push(#field_ident as u64);
|
||||
},
|
||||
};
|
||||
|
||||
serializer.extend(field_serialization);
|
||||
}
|
||||
let RecordSerializerDescriptor {
|
||||
serializer,
|
||||
record_type,
|
||||
} = record.generate_serializer(&record.name);
|
||||
|
||||
quote::quote! {
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
#[doc(hidden)]
|
||||
#[allow(clippy::all)]
|
||||
pub(crate) fn #serializer_fn_name(record: #ty) -> i32 {
|
||||
pub(crate) fn #serializer_fn_name(record: #record_type) -> i32 {
|
||||
let mut raw_record = Vec::new();
|
||||
|
||||
#serializer
|
||||
@ -121,138 +89,18 @@ fn generate_serializer(record: &fce_ast_types::AstRecordItem) -> proc_macro2::To
|
||||
}
|
||||
}
|
||||
|
||||
fn generate_deserializer(record: &fce_ast_types::AstRecordItem) -> proc_macro2::TokenStream {
|
||||
let ret_type = new_ident!(record.name);
|
||||
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 mut field_values = Vec::with_capacity(record.fields.len());
|
||||
let mut deserializer = proc_macro2::TokenStream::new();
|
||||
let mut value_id: usize = 0;
|
||||
|
||||
for (id, ast_field) in record.fields.iter().enumerate() {
|
||||
let field = new_ident!(format!("field_{}", id));
|
||||
let field_d = match &ast_field.ty {
|
||||
ParsedType::Boolean => {
|
||||
quote::quote! {
|
||||
let #field = raw_record[#value_id] as bool;
|
||||
}
|
||||
}
|
||||
ParsedType::I8 => {
|
||||
quote::quote! {
|
||||
let #field = raw_record[#value_id] as i8;
|
||||
}
|
||||
}
|
||||
ParsedType::I16 => {
|
||||
quote::quote! {
|
||||
let #field = raw_record[#value_id] as i16;
|
||||
}
|
||||
}
|
||||
ParsedType::I32 => {
|
||||
quote::quote! {
|
||||
let #field = raw_record[#value_id] as i32;
|
||||
}
|
||||
}
|
||||
ParsedType::I64 => {
|
||||
quote::quote! {
|
||||
let #field = raw_record[#value_id] as i64;
|
||||
}
|
||||
}
|
||||
ParsedType::U8 => {
|
||||
quote::quote! {
|
||||
let #field = raw_record[#value_id] as u8;
|
||||
}
|
||||
}
|
||||
ParsedType::U16 => {
|
||||
quote::quote! {
|
||||
let #field = raw_record[#value_id] as u16;
|
||||
}
|
||||
}
|
||||
ParsedType::U32 => {
|
||||
quote::quote! {
|
||||
let #field = raw_record[#value_id] as u32;
|
||||
}
|
||||
}
|
||||
ParsedType::U64 => {
|
||||
quote::quote! {
|
||||
let #field = raw_record[#value_id] as u64;
|
||||
}
|
||||
}
|
||||
ParsedType::F32 => {
|
||||
quote::quote! {
|
||||
let #field = raw_record[#value_id] as f32;
|
||||
}
|
||||
}
|
||||
ParsedType::F64 => {
|
||||
quote::quote! {
|
||||
let #field = f64::from_bits(raw_record[#value_id as _]);
|
||||
}
|
||||
}
|
||||
ParsedType::Utf8String => {
|
||||
let ptr_id = value_id;
|
||||
let size_id = value_id + 1;
|
||||
value_id += 1;
|
||||
|
||||
quote::quote! {
|
||||
let #field = unsafe { String::from_raw_parts(raw_record[#ptr_id] as _, raw_record[#size_id] as _, raw_record[#size_id] as _) };
|
||||
}
|
||||
}
|
||||
ParsedType::ByteVector => {
|
||||
let ptr_id = value_id;
|
||||
let size_id = value_id + 1;
|
||||
value_id += 1;
|
||||
|
||||
quote::quote! {
|
||||
let #field = unsafe { Vec::from_raw_parts(raw_record[#ptr_id] as _, raw_record[#size_id] as _, raw_record[#size_id] as _) };
|
||||
}
|
||||
}
|
||||
ParsedType::Record(record_name) => {
|
||||
let ptr_id = value_id;
|
||||
let size_id = value_id + 1;
|
||||
value_id += 1;
|
||||
let deserializer_name =
|
||||
new_ident!(GENERATED_RECORD_DESERIALIZER_PREFIX.to_string() + record_name);
|
||||
|
||||
quote::quote! {
|
||||
let #field = #deserializer_name(raw_record[#ptr_id] as _, raw_record[#size_id] as _);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
field_values.push(field);
|
||||
deserializer.extend(field_d);
|
||||
value_id += 1;
|
||||
}
|
||||
|
||||
let type_constructor = match record.fields.first() {
|
||||
Some(ast_field) if ast_field.name.is_some() => {
|
||||
let field_names = record
|
||||
.fields
|
||||
.iter()
|
||||
.map(|field| new_ident!(field.name.clone().expect("all fields should have name")))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
quote::quote! {
|
||||
#ret_type {
|
||||
#(#field_names: #field_values),*
|
||||
}
|
||||
}
|
||||
}
|
||||
Some(_) => {
|
||||
quote::quote! {
|
||||
#ret_type (
|
||||
#(#field_values),*
|
||||
)
|
||||
}
|
||||
}
|
||||
_ => quote::quote! {},
|
||||
};
|
||||
let RecordDeserializerDescriptor {
|
||||
deserializer,
|
||||
type_constructor,
|
||||
return_type,
|
||||
} = record.generate_deserializer(&record.name);
|
||||
|
||||
quote::quote! {
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
#[doc(hidden)]
|
||||
#[allow(clippy::all)]
|
||||
unsafe fn #deserializer_fn_name(offset: i32, size: i32) -> #ret_type {
|
||||
unsafe fn #deserializer_fn_name(offset: i32, size: i32) -> #return_type {
|
||||
let raw_record: Vec<u64> = Vec::from_raw_parts(offset as _, size as _, size as _);
|
||||
|
||||
#deserializer
|
||||
|
@ -0,0 +1,169 @@
|
||||
/*
|
||||
* Copyright 2020 Fluence Labs Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
impl RecordDeserializerGlueCodeGenerator for fce_ast_types::AstRecordItem {
|
||||
fn generate_deserializer(&self, record_name: &str) -> RecordDeserializerDescriptor {
|
||||
let return_type = new_ident!(record_name);
|
||||
|
||||
let mut field_values = Vec::with_capacity(self.fields.len());
|
||||
let mut deserializer = proc_macro2::TokenStream::new();
|
||||
let mut value_id: usize = 0;
|
||||
|
||||
for (id, ast_field) in self.fields.iter().enumerate() {
|
||||
let field = new_ident!(format!("field_{}", id));
|
||||
let field_d = match &ast_field.ty {
|
||||
ParsedType::Boolean => {
|
||||
quote! {
|
||||
let #field = raw_record[#value_id] as bool;
|
||||
}
|
||||
}
|
||||
ParsedType::I8 => {
|
||||
quote! {
|
||||
let #field = raw_record[#value_id] as i8;
|
||||
}
|
||||
}
|
||||
ParsedType::I16 => {
|
||||
quote! {
|
||||
let #field = raw_record[#value_id] as i16;
|
||||
}
|
||||
}
|
||||
ParsedType::I32 => {
|
||||
quote! {
|
||||
let #field = raw_record[#value_id] as i32;
|
||||
}
|
||||
}
|
||||
ParsedType::I64 => {
|
||||
quote! {
|
||||
let #field = raw_record[#value_id] as i64;
|
||||
}
|
||||
}
|
||||
ParsedType::U8 => {
|
||||
quote! {
|
||||
let #field = raw_record[#value_id] as u8;
|
||||
}
|
||||
}
|
||||
ParsedType::U16 => {
|
||||
quote! {
|
||||
let #field = raw_record[#value_id] as u16;
|
||||
}
|
||||
}
|
||||
ParsedType::U32 => {
|
||||
quote! {
|
||||
let #field = raw_record[#value_id] as u32;
|
||||
}
|
||||
}
|
||||
ParsedType::U64 => {
|
||||
quote! {
|
||||
let #field = raw_record[#value_id] as u64;
|
||||
}
|
||||
}
|
||||
ParsedType::F32 => {
|
||||
quote! {
|
||||
let #field = raw_record[#value_id] as f32;
|
||||
}
|
||||
}
|
||||
ParsedType::F64 => {
|
||||
quote! {
|
||||
let #field = f64::from_bits(raw_record[#value_id as _]);
|
||||
}
|
||||
}
|
||||
ParsedType::Utf8String => {
|
||||
let ptr_id = value_id;
|
||||
let size_id = value_id + 1;
|
||||
value_id += 1;
|
||||
|
||||
quote! {
|
||||
let #field = unsafe { String::from_raw_parts(raw_record[#ptr_id] as _, raw_record[#size_id] as _, raw_record[#size_id] as _) };
|
||||
}
|
||||
}
|
||||
ParsedType::ByteVector => {
|
||||
let ptr_id = value_id;
|
||||
let size_id = value_id + 1;
|
||||
value_id += 1;
|
||||
|
||||
quote! {
|
||||
let #field = unsafe { Vec::from_raw_parts(raw_record[#ptr_id] as _, raw_record[#size_id] as _, raw_record[#size_id] as _) };
|
||||
}
|
||||
}
|
||||
ParsedType::Record(record_name) => {
|
||||
let ptr_id = value_id;
|
||||
let size_id = value_id + 1;
|
||||
value_id += 1;
|
||||
let deserializer_name =
|
||||
new_ident!(GENERATED_RECORD_DESERIALIZER_PREFIX.to_string() + record_name);
|
||||
|
||||
quote! {
|
||||
let #field = #deserializer_name(raw_record[#ptr_id] as _, raw_record[#size_id] as _);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
field_values.push(field);
|
||||
deserializer.extend(field_d);
|
||||
value_id += 1;
|
||||
}
|
||||
|
||||
let type_constructor = match self.fields.first() {
|
||||
Some(ast_field) if ast_field.name.is_some() => {
|
||||
let field_names = self
|
||||
.fields
|
||||
.iter()
|
||||
.map(|field| {
|
||||
new_ident!(field.name.clone().expect("all fields should have name"))
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
quote! {
|
||||
#return_type {
|
||||
#(#field_names: #field_values),*
|
||||
}
|
||||
}
|
||||
}
|
||||
Some(_) => {
|
||||
quote! {
|
||||
#return_type (
|
||||
#(#field_values),*
|
||||
)
|
||||
}
|
||||
}
|
||||
_ => quote! {},
|
||||
};
|
||||
|
||||
RecordDeserializerDescriptor {
|
||||
deserializer,
|
||||
type_constructor,
|
||||
return_type,
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Copyright 2020 Fluence Labs Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
impl RecordSerializerGlueCodeGenerator for fce_ast_types::AstRecordItem {
|
||||
fn generate_serializer(&self, record_name: &str) -> RecordSerializerDescriptor {
|
||||
let mut serializer = proc_macro2::TokenStream::new();
|
||||
for (id, field) in self.fields.iter().enumerate() {
|
||||
let field_ident = field_ident(field, id);
|
||||
|
||||
let field_serialization = match &field.ty {
|
||||
ParsedType::F64 => {
|
||||
quote! {
|
||||
raw_record.push(#field_ident.to_bits());
|
||||
}
|
||||
}
|
||||
ParsedType::Utf8String | ParsedType::ByteVector => {
|
||||
quote! {
|
||||
raw_record.push(#field_ident.as_ptr() as _);
|
||||
raw_record.push(#field_ident.len() as _);
|
||||
}
|
||||
}
|
||||
ParsedType::Record(record_name) => {
|
||||
let serializer_name =
|
||||
new_ident!(GENERATED_RECORD_SERIALIZER_PREFIX.to_string() + &record_name);
|
||||
quote! {
|
||||
raw_record.push(#serializer_name(#field_ident) as _);
|
||||
}
|
||||
}
|
||||
_ => quote! {
|
||||
raw_record.push(#field_ident as u64);
|
||||
},
|
||||
};
|
||||
|
||||
serializer.extend(field_serialization);
|
||||
}
|
||||
let record_type = new_ident!(record_name);
|
||||
|
||||
RecordSerializerDescriptor {
|
||||
serializer,
|
||||
record_type,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn field_ident(field: &fce_ast_types::AstRecordField, id: usize) -> proc_macro2::TokenStream {
|
||||
match &field.name {
|
||||
Some(name) => {
|
||||
let name = new_ident!(name);
|
||||
quote! { record.#name }
|
||||
}
|
||||
None => {
|
||||
let id = new_ident!(format!("{}", id));
|
||||
quote! { record.#id }
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user