From 5b26474d4942a34c702c16427f6831e4230c150f Mon Sep 17 00:00:00 2001 From: vms Date: Mon, 19 Apr 2021 19:50:01 +0300 Subject: [PATCH] update record der --- .../record_generator.rs | 4 +- .../record_generator/field_values_builder.rs | 257 ++++++++++++++++++ .../record_generator/record_deserializer.rs | 128 +-------- crates/wit/src/utils.rs | 13 +- 4 files changed, 273 insertions(+), 129 deletions(-) create mode 100644 crates/wit/src/token_stream_generator/record_generator/field_values_builder.rs diff --git a/crates/wit/src/token_stream_generator/record_generator.rs b/crates/wit/src/token_stream_generator/record_generator.rs index a798835..642c534 100644 --- a/crates/wit/src/token_stream_generator/record_generator.rs +++ b/crates/wit/src/token_stream_generator/record_generator.rs @@ -16,9 +16,11 @@ mod record_serializer; mod record_deserializer; +mod field_values_builder; -use record_serializer::*; +use field_values_builder::*; use record_deserializer::*; +use record_serializer::*; use crate::new_ident; use crate::ast_types::AstRecordItem; diff --git a/crates/wit/src/token_stream_generator/record_generator/field_values_builder.rs b/crates/wit/src/token_stream_generator/record_generator/field_values_builder.rs new file mode 100644 index 0000000..01ec83d --- /dev/null +++ b/crates/wit/src/token_stream_generator/record_generator/field_values_builder.rs @@ -0,0 +1,257 @@ +use crate::new_ident; +use crate::parsed_type::ParsedType; +use crate::ast_types::*; + +use proc_macro2::TokenStream; +use quote::quote; + +pub(super) struct FieldValuesBuilder { + value_id: usize, + fields_der: TokenStream, + field_value_idents: Vec, +} + +/// Contains all necessary info to construct record fields. +pub(super) struct FieldValuesOutcome { + /// Generated deserializer for each record field. + pub(super) fields_der: TokenStream, + + /// Idents of each record field. + pub(super) field_value_idents: Vec, +} + +impl FieldValuesBuilder { + pub(super) fn build<'a>( + fields: impl ExactSizeIterator, + ) -> FieldValuesOutcome { + let values_builder = Self::new(fields.len()); + values_builder.build_impl(fields) + } + + fn new(fields_count: usize) -> Self { + Self { + value_id: 0, + fields_der: TokenStream::new(), + field_value_idents: Vec::with_capacity(fields_count), + } + } + + fn build_impl<'r>( + mut self, + fields: impl ExactSizeIterator, + ) -> FieldValuesOutcome { + for (id, ast_field) in fields.enumerate() { + let field_value_ident = new_ident!(format!("field_{}", id)); + let field_der = self.field_der(ast_field, &field_value_ident); + + self.field_value_idents.push(field_value_ident); + self.fields_der.extend(field_der); + } + + let outcome = FieldValuesOutcome { + fields_der: self.fields_der, + field_value_idents: self.field_value_idents, + }; + + outcome + } + + fn field_der(&mut self, ast_field: &AstRecordField, field: &syn::Ident) -> TokenStream { + let der = match &ast_field.ty { + ParsedType::Boolean(_) => self.bool_der(field), + ParsedType::I8(_) => self.i8_der(field), + ParsedType::I16(_) => self.i16_der(field), + ParsedType::I32(_) => self.i32_der(field), + ParsedType::I64(_) => self.i64_der(field), + ParsedType::U8(_) => self.u8_der(field), + ParsedType::U16(_) => self.u16_der(field), + ParsedType::U32(_) => self.u32_der(field), + ParsedType::U64(_) => self.u64_der(field), + ParsedType::F32(_) => self.f32_der(field), + ParsedType::F64(_) => self.f64_der(field), + ParsedType::Utf8Str(_) | ParsedType::Utf8String(_) => self.string_der(field), + ParsedType::Vector(ty, _) => self.vector_der(ty, field), + ParsedType::Record(name, _) => self.record_der(name, field), + }; + + der + } + + fn bool_der(&mut self, field: &syn::Ident) -> TokenStream { + let value_id = self.value_id; + let result = quote! { let #field = raw_record[#value_id] != 0; }; + self.value_id += 1; + result + } + + fn i8_der(&mut self, field: &syn::Ident) -> TokenStream { + let value_id = self.value_id; + let result = quote! { let #field = raw_record[#value_id] as i8; }; + self.value_id += 1; + result + } + + fn i16_der(&mut self, field: &syn::Ident) -> TokenStream { + let value_id = self.value_id; + let result = quote! { let #field = i16::from_le_bytes([ + raw_record[#value_id], + raw_record[#value_id + 1], + ]); + }; + + self.value_id += 2; + result + } + + fn i32_der(&mut self, field: &syn::Ident) -> TokenStream { + let value_id = self.value_id; + let result = quote! { let #field = i32::from_le_bytes([ + raw_record[#value_id], + raw_record[#value_id + 1], + raw_record[#value_id + 2], + raw_record[#value_id + 3], + ]); + }; + + self.value_id += 4; + result + } + + fn i64_der(&mut self, field: &syn::Ident) -> TokenStream { + let value_id = self.value_id; + let result = quote! { let #field = i64::from_le_bytes([ + raw_record[#value_id], + raw_record[#value_id + 1], + raw_record[#value_id + 2], + raw_record[#value_id + 3], + raw_record[#value_id + 4], + raw_record[#value_id + 5], + raw_record[#value_id + 6], + raw_record[#value_id + 7], + ]); + }; + + self.value_id += 8; + result + } + + fn u8_der(&mut self, field: &syn::Ident) -> TokenStream { + let value_id = self.value_id; + let result = quote! { let #field = raw_record[#value_id] as u8; }; + self.value_id += 1; + result + } + + fn u16_der(&mut self, field: &syn::Ident) -> TokenStream { + let value_id = self.value_id; + let result = quote! { let #field = u16::from_le_bytes([ + raw_record[#value_id], + raw_record[#value_id + 1], + ]); + }; + + self.value_id += 2; + result + } + + fn u32_der(&mut self, field: &syn::Ident) -> TokenStream { + let value_id = self.value_id; + let result = quote! { let #field = u32::from_le_bytes([ + raw_record[#value_id], + raw_record[#value_id + 1], + raw_record[#value_id + 2], + raw_record[#value_id + 3], + ]); + }; + + self.value_id += 4; + result + } + + fn u64_der(&mut self, field: &syn::Ident) -> TokenStream { + let value_id = self.value_id; + let result = quote! { let #field = u64::from_le_bytes([ + raw_record[#value_id], + raw_record[#value_id + 1], + raw_record[#value_id + 2], + raw_record[#value_id + 3], + raw_record[#value_id + 4], + raw_record[#value_id + 5], + raw_record[#value_id + 6], + raw_record[#value_id + 7], + ]); + }; + + self.value_id += 8; + result + } + + fn f32_der(&mut self, field: &syn::Ident) -> TokenStream { + let value_id = self.value_id; + let result = quote! { let #field = f32::from_le_bytes([ + raw_record[#value_id], + raw_record[#value_id + 1], + raw_record[#value_id + 2], + raw_record[#value_id + 3], + ]); + }; + + self.value_id += 4; + result + } + + fn f64_der(&mut self, field: &syn::Ident) -> TokenStream { + let value_id = self.value_id; + let result = quote! { let #field = f64::from_le_bytes([ + raw_record[#value_id], + raw_record[#value_id + 1], + raw_record[#value_id + 2], + raw_record[#value_id + 3], + raw_record[#value_id + 4], + raw_record[#value_id + 5], + raw_record[#value_id + 6], + raw_record[#value_id + 7], + ]); + }; + + self.value_id += 8; + result + } + + fn string_der(&mut self, field: &syn::Ident) -> TokenStream { + let ptr_id = self.value_id; + let size_id = self.value_id + 1; + self.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 _) }; + } + } + + fn vector_der(&mut self, ty: &ParsedType, field: &syn::Ident) -> TokenStream { + let generated_der_name = format!("__fce_generated_vec_deserializer_{}", self.value_id); + let generated_der_name = crate::utils::prepare_ident(generated_der_name); + let generated_der_ident = new_ident!(generated_der_name); + + let vector_deserializer = + crate::parsed_type::generate_vector_deserializer(ty, &generated_der_name); + + let ptr_id = self.value_id; + let size_id = self.value_id + 1; + self.value_id += 1; + + quote! { + #vector_deserializer + let #field = unsafe { #generated_der_ident(raw_record[#ptr_id] as _, raw_record[#size_id] as _) }; + } + } + + fn record_der(&mut self, name: &str, field: &syn::Ident) -> TokenStream { + let ptr_id = self.value_id; + let record_ident = new_ident!(name); + + quote! { + let #field = #record_ident::__fce_generated_deserialize(raw_record[#ptr_id] as _); + } + } +} 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 a553890..fd98fc3 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 @@ -15,15 +15,16 @@ */ use crate::new_ident; -use crate::parsed_type::ParsedType; use crate::ast_types::*; +use super::FieldValuesBuilder; +use proc_macro2::TokenStream; use quote::quote; #[derive(Default)] pub(super) struct RecordDerDescriptor { - pub(super) fields_der: proc_macro2::TokenStream, - pub(super) record_ctor: proc_macro2::TokenStream, + pub(super) fields_der: TokenStream, + pub(super) record_ctor: TokenStream, } /// This trait could be used to generate various parts of a record serializer func. @@ -61,127 +62,10 @@ fn record_der_from_unnamed(fields: &[AstRecordField]) -> RecordDerDescriptor { } } -struct FieldValuesBuilder { - value_id: usize, - fields_der: proc_macro2::TokenStream, - field_value_idents: Vec, -} - -/// Contains all necessary info to construct record fields. -struct FieldValuesOutcome { - /// Generated deserializer for each record field. - fields_der: proc_macro2::TokenStream, - - /// Idents of each record field. - field_value_idents: Vec, -} - -impl FieldValuesBuilder { - pub(self) fn build<'a>( - fields: impl ExactSizeIterator, - ) -> FieldValuesOutcome { - let values_builder = Self::new(fields.len()); - values_builder.build_impl(fields) - } - - fn new(fields_count: usize) -> Self { - Self { - value_id: 0, - fields_der: proc_macro2::TokenStream::new(), - field_value_idents: Vec::with_capacity(fields_count), - } - } - - fn build_impl<'r>( - mut self, - fields: impl ExactSizeIterator, - ) -> FieldValuesOutcome { - for (id, ast_field) in fields.enumerate() { - let field_value_ident = new_ident!(format!("field_{}", id)); - let field_der = self.field_der(ast_field, &field_value_ident); - - self.field_value_idents.push(field_value_ident); - self.fields_der.extend(field_der); - } - - let outcome = FieldValuesOutcome { - fields_der: self.fields_der, - field_value_idents: self.field_value_idents, - }; - - outcome - } - - fn field_der( - &mut self, - ast_field: &AstRecordField, - field: &syn::Ident, - ) -> proc_macro2::TokenStream { - let value_id = self.value_id; - let der = match &ast_field.ty { - ParsedType::Boolean(_) => quote! { let #field = raw_record[#value_id] != 0; }, - 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]); }, - ParsedType::Utf8Str(_) | ParsedType::Utf8String(_) => self.string_der(field), - ParsedType::Vector(ty, _) => self.vector_der(ty, field), - ParsedType::Record(name, _) => self.record_der(name, field), - }; - - self.value_id += 1; - - der - } - - fn string_der(&mut self, field: &syn::Ident) -> proc_macro2::TokenStream { - let ptr_id = self.value_id; - let size_id = self.value_id + 1; - self.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 _) }; - } - } - - fn vector_der(&mut self, ty: &ParsedType, field: &syn::Ident) -> proc_macro2::TokenStream { - let generated_der_name = format!("__fce_generated_vec_deserializer_{}", self.value_id); - let generated_der_name = crate::utils::prepare_ident(generated_der_name); - let generated_der_ident = new_ident!(generated_der_name); - - let vector_deserializer = - crate::parsed_type::generate_vector_deserializer(ty, &generated_der_name); - - let ptr_id = self.value_id; - let size_id = self.value_id + 1; - self.value_id += 1; - - quote! { - #vector_deserializer - let #field = unsafe { #generated_der_ident(raw_record[#ptr_id] as _, raw_record[#size_id] as _) }; - } - } - - fn record_der(&mut self, name: &str, field: &syn::Ident) -> proc_macro2::TokenStream { - let ptr_id = self.value_id; - let record_ident = new_ident!(name); - - quote! { - let #field = #record_ident::__fce_generated_deserialize(raw_record[#ptr_id] as _); - } - } -} - fn field_ctors_from_named<'a, 'v>( ast_fields: impl ExactSizeIterator, field_values: impl ExactSizeIterator, -) -> proc_macro2::TokenStream { +) -> TokenStream { let field_names = ast_fields .map(|ast_field| { new_ident!(ast_field @@ -200,7 +84,7 @@ fn field_ctors_from_named<'a, 'v>( fn field_ctor_from_unnamed<'v>( field_values: impl ExactSizeIterator, -) -> proc_macro2::TokenStream { +) -> TokenStream { quote! { Self { #(#field_values),* diff --git a/crates/wit/src/utils.rs b/crates/wit/src/utils.rs index 9a851a9..76007a4 100644 --- a/crates/wit/src/utils.rs +++ b/crates/wit/src/utils.rs @@ -60,13 +60,14 @@ pub fn get_record_size<'a>( let mut size = 0; for field in fields { - let params_count = match field { - ParsedType::Vector(..) | ParsedType::Utf8Str(_) | ParsedType::Utf8String(_) => 2, - _ => 1, + size += match field { + ParsedType::U8(_) | ParsedType::I8(_) | ParsedType::Boolean(_) => 1, + ParsedType::U16(_) | ParsedType::I16(_) => 2, + ParsedType::U32(_) | ParsedType::I32(_) | ParsedType::F32(_) => 4, + ParsedType::U64(_) | ParsedType::I64(_) | ParsedType::F64(_) => 8, + ParsedType::Record(..) => 4, + ParsedType::Vector(..) | ParsedType::Utf8Str(_) | ParsedType::Utf8String(_) => 2 * 4, }; - - // internally record is being serialized to a vector of u64. - size += std::mem::size_of::() * params_count; } size