Merge pull request #6 from fluencelabs/array_support

Array support
This commit is contained in:
vms 2020-09-21 13:34:53 +03:00 committed by GitHub
commit 5ac0c45507
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 385 additions and 91 deletions

View File

@ -9,6 +9,7 @@ readme = "Readme.md"
keywords = ["fluence", "sdk", "webassembly"] keywords = ["fluence", "sdk", "webassembly"]
categories = ["api-bindings", "wasm"] categories = ["api-bindings", "wasm"]
license = "Apache-2.0" license = "Apache-2.0"
edition = "2018"
[package.metadata.docs.rs] # https://docs.rs/about [package.metadata.docs.rs] # https://docs.rs/about
all-features = true all-features = true
@ -19,6 +20,7 @@ path = "src/lib.rs"
[dependencies] [dependencies]
fluence-sdk-macro = { path = "crates/macro", version = "=0.2.3" } fluence-sdk-macro = { path = "crates/macro", version = "=0.2.3" }
fluence-sdk-main = { path = "crates/main", version = "=0.2.3" } fluence-sdk-main = { path = "crates/main", version = "=0.2.3" }
safe-transmute = "0.11.0"
[features] [features]
# Print some internal logs by log_utf8_string # Print some internal logs by log_utf8_string

View File

@ -20,17 +20,21 @@ mod fn_prolog;
mod foreign_mod_arg; mod foreign_mod_arg;
mod foreign_mod_epilog; mod foreign_mod_epilog;
mod foreign_mod_prolog; mod foreign_mod_prolog;
mod vector_utils;
pub(crate) use fn_arg::*; pub(crate) use fn_arg::*;
pub(crate) use fn_epilog::*; pub(crate) use fn_epilog::*;
pub(crate) use fn_prolog::*; pub(crate) use fn_prolog::*;
pub(crate) use foreign_mod_prolog::*; pub(crate) use foreign_mod_prolog::*;
pub(crate) use foreign_mod_epilog::*; pub(crate) use foreign_mod_epilog::*;
pub(crate) use vector_utils::*;
use serde::Serialize; use serde::Serialize;
use serde::Deserialize; use serde::Deserialize;
use syn::parse::Error; use syn::parse::Error;
use syn::spanned::Spanned; use syn::spanned::Spanned;
use proc_macro2::TokenStream;
use serde::export::Formatter;
/// An internal representation of supported Rust types. /// An internal representation of supported Rust types.
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
@ -47,15 +51,16 @@ pub enum ParsedType {
F64, F64,
Boolean, Boolean,
Utf8String, Utf8String,
ByteVector, Vector(Box<ParsedType>),
Record(String), // short type name Record(String), // short type name
} }
impl ParsedType { impl ParsedType {
pub fn from_type(input_type: &syn::Type) -> syn::Result<Self> { pub fn from_type(input_type: &syn::Type) -> syn::Result<Self> {
use quote::ToTokens; use quote::ToTokens;
// parses generic param T in Vec<T> to string representation
fn parse_vec_bracket(args: &syn::PathArguments) -> syn::Result<String> { // parse generic param T in Vec<T> to syn::Type
fn parse_vec_bracket(args: &syn::PathArguments) -> syn::Result<&syn::Type> {
// checks that T is angle bracketed // checks that T is angle bracketed
let generic_arg = match args { let generic_arg = match args {
syn::PathArguments::AngleBracketed(args) => Ok(args), syn::PathArguments::AngleBracketed(args) => Ok(args),
@ -73,41 +78,13 @@ impl ParsedType {
})?; })?;
// converts T to syn::Type // converts T to syn::Type
let arg_type = match arg { match arg {
syn::GenericArgument::Type(ty) => Ok(ty), syn::GenericArgument::Type(ty) => Ok(ty),
_ => Err(Error::new( _ => Err(Error::new(
arg.span(), arg.span(),
"Unsuitable type in Vec brackets - only Vec<u8> is supported", "Unsuitable type in Vec brackets - only Vec<u8> is supported",
)), )),
}?;
// converts T to syn::path
let arg_path = match arg_type {
syn::Type::Path(path) => Ok(&path.path),
_ => Err(Error::new(
arg_type.span(),
"Unsuitable type in Vec brackets - only Vec<u8> is supported",
)),
}?;
// There could be cases like Vec<some_crate::some_module::u8>
// that why this segments count check is needed
if arg_path.segments.len() != 1 {
return Err(Error::new(
arg_path.span(),
"Unsuitable type in Vec brackets - only Vec<u8> is supported",
));
} }
// converts T to String
let arg_segment = arg_path.segments.first().ok_or_else(|| {
Error::new(
arg_path.span(),
"Unsuitable type in Vec brackets - only Vec<u8> is supported",
)
})?;
Ok(arg_segment.ident.to_string())
} }
let path = match input_type { let path = match input_type {
@ -138,16 +115,12 @@ impl ParsedType {
"f64" => Ok(ParsedType::F64), "f64" => Ok(ParsedType::F64),
"bool" => Ok(ParsedType::Boolean), "bool" => Ok(ParsedType::Boolean),
"String" => Ok(ParsedType::Utf8String), "String" => Ok(ParsedType::Utf8String),
"Vec" => match parse_vec_bracket(&type_segment.arguments) { "Vec" => {
Ok(value) => match value.as_str() { let vec_type = parse_vec_bracket(&type_segment.arguments)?;
"u8" => Ok(ParsedType::ByteVector), let parsed_type = ParsedType::from_type(vec_type)?;
_ => Err(Error::new(
value.span(), Ok(ParsedType::Vector(Box::new(parsed_type)))
"Unsuitable type in Vec brackets - only Vec<u8> is supported", }
)),
},
Err(e) => Err(e),
},
_ if !type_segment.arguments.is_empty() => Err(Error::new( _ if !type_segment.arguments.is_empty() => Err(Error::new(
type_segment.span(), type_segment.span(),
"type with lifetimes or generics aren't allowed".to_string(), "type with lifetimes or generics aren't allowed".to_string(),
@ -175,7 +148,30 @@ impl ParsedType {
} }
} }
pub fn to_token_stream(&self) -> proc_macro2::TokenStream { pub fn is_complex_type(&self) -> bool {
match self {
ParsedType::Boolean
| ParsedType::I8
| ParsedType::I16
| ParsedType::I32
| ParsedType::I64
| ParsedType::U8
| ParsedType::U16
| ParsedType::U32
| ParsedType::U64
| ParsedType::F32
| ParsedType::F64 => false,
ParsedType::Utf8String | ParsedType::Vector(_) | ParsedType::Record(_) => true,
}
}
}
impl quote::ToTokens for ParsedType {
fn to_tokens(&self, tokens: &mut TokenStream) {
tokens.extend(self.to_token_stream());
}
fn to_token_stream(&self) -> proc_macro2::TokenStream {
use quote::quote; use quote::quote;
match self { match self {
@ -191,28 +187,37 @@ impl ParsedType {
ParsedType::F64 => quote! { f64 }, ParsedType::F64 => quote! { f64 },
ParsedType::Boolean => quote! { bool }, ParsedType::Boolean => quote! { bool },
ParsedType::Utf8String => quote! { String }, ParsedType::Utf8String => quote! { String },
ParsedType::ByteVector => quote! { Vec<u8> }, ParsedType::Vector(ty) => {
let quoted_type = ty.to_token_stream();
quote! { Vec<#quoted_type> }
}
ParsedType::Record(name) => { ParsedType::Record(name) => {
let ty = crate::new_ident!(name); let ty = crate::new_ident!(name);
quote! { #ty } quote! { #ty }
} }
} }
} }
}
pub fn is_complex_type(&self) -> bool { impl std::fmt::Display for ParsedType {
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {
match self { match self {
ParsedType::Boolean ParsedType::Boolean => f.write_str("bool"),
| ParsedType::I8 ParsedType::I8 => f.write_str("i8"),
| ParsedType::I16 ParsedType::I16 => f.write_str("i16"),
| ParsedType::I32 ParsedType::I32 => f.write_str("i32"),
| ParsedType::I64 ParsedType::I64 => f.write_str("i64"),
| ParsedType::U8 ParsedType::U8 => f.write_str("u8"),
| ParsedType::U16 ParsedType::U16 => f.write_str("u16"),
| ParsedType::U32 ParsedType::U32 => f.write_str("u32"),
| ParsedType::U64 ParsedType::U64 => f.write_str("u64"),
| ParsedType::F32 ParsedType::F32 => f.write_str("f32"),
| ParsedType::F64 => false, ParsedType::F64 => f.write_str("u64"),
ParsedType::Utf8String | ParsedType::ByteVector | ParsedType::Record(_) => true, ParsedType::Utf8String => f.write_str("String"),
} ParsedType::Vector(_) => f.write_str("Vec"),
ParsedType::Record(record_name) => f.write_str(&record_name),
}?;
Ok(())
} }
} }

View File

@ -37,7 +37,7 @@ impl FnArgGlueCodeGenerator for (String, ParsedType) {
ParsedType::Record(_) => vec![RustType::U32], ParsedType::Record(_) => vec![RustType::U32],
ParsedType::F32 => vec![RustType::F32], ParsedType::F32 => vec![RustType::F32],
ParsedType::F64 => vec![RustType::F64], ParsedType::F64 => vec![RustType::F64],
ParsedType::Utf8String | ParsedType::ByteVector => vec![RustType::U32, RustType::U32], ParsedType::Utf8String | ParsedType::Vector(_) => vec![RustType::U32, RustType::U32],
} }
} }
} }

View File

@ -66,7 +66,7 @@ fn generate_fn_return_type(ty: &Option<ParsedType>) -> proc_macro2::TokenStream
Some(ParsedType::F64) => Some("f64"), Some(ParsedType::F64) => Some("f64"),
None None
| Some(ParsedType::Utf8String) | Some(ParsedType::Utf8String)
| Some(ParsedType::ByteVector) | Some(ParsedType::Vector(_))
| Some(ParsedType::Record(_)) => None, | Some(ParsedType::Record(_)) => None,
}; };
@ -91,22 +91,33 @@ fn generate_return_expression(ty: &Option<ParsedType>) -> proc_macro2::TokenStre
fn generate_epilog(ty: &Option<ParsedType>) -> proc_macro2::TokenStream { fn generate_epilog(ty: &Option<ParsedType>) -> proc_macro2::TokenStream {
match ty { match ty {
None => quote!(), None => quote!(),
Some(ty) if !ty.is_complex_type() => quote! {
return result as _;
},
Some(ParsedType::Record(_)) => { Some(ParsedType::Record(_)) => {
quote! { quote! {
let result_ptr = result.__fce_generated_serialize(); let result_ptr = result.__fce_generated_serialize();
fluence::internal::set_result_ptr(result_ptr as _); fluence::internal::set_result_ptr(result_ptr as _);
} }
} }
Some(ty) if ty.is_complex_type() => quote! { Some(ParsedType::Utf8String) => quote! {
fluence::internal::set_result_ptr(result.as_ptr() as _); fluence::internal::set_result_ptr(result.as_ptr() as _);
fluence::internal::set_result_size(result.len() as _); fluence::internal::set_result_size(result.len() as _);
std::mem::forget(result); std::mem::forget(result);
}, },
_ => { Some(ParsedType::Vector(ty)) => {
panic!("perhaps new type's been added to ParsedType, and this match became incomplete") let generated_serializer_name = format!("__fce_generated_vec_serializer");
let generated_serializer_ident = new_ident!(generated_serializer_name);
let vector_serializer =
super::vector_utils::generate_vector_serializer(ty, &generated_serializer_name);
quote! {
#vector_serializer
let result = #generated_serializer_ident(result);
fluence::internal::set_result_ptr(result.as_ptr() as _);
fluence::internal::set_result_size(result.len() as _);
std::mem::forget(result);
}
} }
Some(_) => quote! {
return result as _;
},
} }
} }

View File

@ -107,9 +107,20 @@ fn generate_type_prolog(
ParsedType::Utf8String => quote! { ParsedType::Utf8String => quote! {
let #generated_arg_id = String::from_raw_parts(#ptr as _, #size as _ , #size as _); let #generated_arg_id = String::from_raw_parts(#ptr as _, #size as _ , #size as _);
}, },
ParsedType::ByteVector => quote! { ParsedType::Vector(ty) => {
let #generated_arg_id = Vec::from_raw_parts(#ptr as _, #size as _, #size as _); let generated_deserializer_name =
}, format!("__fce_generated_vec_deserializer_{}", supplied_arg_start_id);
let generated_deserializer_ident = new_ident!(generated_deserializer_name);
let vector_deserializer = super::vector_utils::generate_vector_deserializer(
ty,
&generated_deserializer_name,
);
quote! {
#vector_deserializer
let #generated_arg_id = #generated_deserializer_ident(#ptr as _, #size as _);
}
}
ParsedType::Record(record_name) => { ParsedType::Record(record_name) => {
let record_ident = new_ident!(record_name); let record_ident = new_ident!(record_name);
quote! { quote! {

View File

@ -28,14 +28,12 @@ impl ForeignModArgGlueCodeGenerator for ParsedType {
let arg = crate::new_ident!(format!("arg_{}", arg_start_id)); let arg = crate::new_ident!(format!("arg_{}", arg_start_id));
match self { match self {
ParsedType::Utf8String | ParsedType::ByteVector => { ParsedType::Vector(_) | ParsedType::Utf8String => {
quote! { #arg.as_ptr() as _, #arg.len() as _ } quote! { #arg.as_ptr() as _, #arg.len() as _ }
} }
ParsedType::Record(_) => { ParsedType::Record(_) => quote! {
quote! { #arg.__fce_generated_serialize() as _
#arg.__fce_generated_serialize() as _ },
}
}
ParsedType::Boolean => quote! { #arg as _ }, ParsedType::Boolean => quote! { #arg as _ },
_ => quote! { #arg }, _ => quote! { #arg },
} }

View File

@ -29,6 +29,8 @@ pub(crate) trait ForeignModEpilogGlueCodeGenerator {
impl ForeignModEpilogGlueCodeGenerator for Option<ParsedType> { impl ForeignModEpilogGlueCodeGenerator for Option<ParsedType> {
fn generate_wrapper_return_type(&self) -> proc_macro2::TokenStream { fn generate_wrapper_return_type(&self) -> proc_macro2::TokenStream {
use quote::ToTokens;
match self { match self {
Some(ty) => { Some(ty) => {
let ty = ty.to_token_stream(); let ty = ty.to_token_stream();
@ -54,13 +56,22 @@ impl ForeignModEpilogGlueCodeGenerator for Option<ParsedType> {
fluence::internal::get_result_size() as _ fluence::internal::get_result_size() as _
) )
}, },
Some(ParsedType::ByteVector) => quote! { Some(ParsedType::Vector(ty)) => {
Vec::from_raw_parts( let generated_deserializer_name = String::from("__fce_generated_vec_deserializer");
fluence::internal::get_result_ptr() as _, let generated_deserializer_ident = new_ident!(generated_deserializer_name);
fluence::internal::get_result_size() as _, let vector_deserializer = super::vector_utils::generate_vector_deserializer(
fluence::internal::get_result_size() as _ ty,
) &generated_deserializer_name,
}, );
quote! {
#vector_deserializer
#generated_deserializer_ident(
fluence::internal::get_result_ptr() as _,
fluence::internal::get_result_size() as _,
)
}
}
Some(ParsedType::Record(record_name)) => { Some(ParsedType::Record(record_name)) => {
let record_ident = new_ident!(record_name); let record_ident = new_ident!(record_name);

View File

@ -60,6 +60,7 @@ pub(crate) trait ForeignModPrologGlueCodeGenerator {
impl ForeignModPrologGlueCodeGenerator for Vec<(String, ParsedType)> { impl ForeignModPrologGlueCodeGenerator for Vec<(String, ParsedType)> {
fn generate_wrapper_prolog(&self) -> WrapperDescriptor { fn generate_wrapper_prolog(&self) -> WrapperDescriptor {
use crate::parsed_type::foreign_mod_arg::ForeignModArgGlueCodeGenerator; use crate::parsed_type::foreign_mod_arg::ForeignModArgGlueCodeGenerator;
use quote::ToTokens;
let arg_types: Vec<proc_macro2::TokenStream> = self let arg_types: Vec<proc_macro2::TokenStream> = self
.iter() .iter()
@ -70,14 +71,30 @@ impl ForeignModPrologGlueCodeGenerator for Vec<(String, ParsedType)> {
.iter() .iter()
.enumerate() .enumerate()
.fold((Vec::new(), proc_macro2::TokenStream::new(), proc_macro2::TokenStream::new()), |(mut arg_names, mut arg_transforms, mut arg_drops), (id, (_, ty))| { .fold((Vec::new(), proc_macro2::TokenStream::new(), proc_macro2::TokenStream::new()), |(mut arg_names, mut arg_transforms, mut arg_drops), (id, (_, ty))| {
let arg_ident = new_ident!(format!("arg_{}", id)); let arg_name = format!("arg_{}", id);
let arg_ident = new_ident!(arg_name);
arg_names.push(arg_ident.clone()); arg_names.push(arg_ident.clone());
match ty { match ty {
ParsedType::ByteVector | ParsedType::Utf8String => { ParsedType::Utf8String => {
arg_transforms.extend(quote::quote! { let mut #arg_ident = std::mem::ManuallyDrop::new(#arg_ident); }); arg_transforms.extend(quote::quote! { let mut #arg_ident = std::mem::ManuallyDrop::new(#arg_ident); });
arg_drops.extend(quote::quote! { std::mem::ManuallyDrop::drop(&mut #arg_ident); }); arg_drops.extend(quote::quote! { std::mem::ManuallyDrop::drop(&mut #arg_ident); });
}, },
ParsedType::Vector(ty) => {
let generated_serializer_name = format!("__fce_generated_vec_serializer_{}", arg_name);
let generated_serializer_ident = new_ident!(generated_serializer_name);
let vector_serializer = super::vector_utils::generate_vector_serializer(ty, &generated_serializer_name);
let arg_transform = quote::quote! {
#vector_serializer
let #arg_ident = #generated_serializer_ident(#arg_ident);
let mut #arg_ident = std::mem::ManuallyDrop::new(#arg_ident);
};
arg_transforms.extend(arg_transform);
arg_drops.extend(quote::quote! { std::mem::ManuallyDrop::drop(&mut #arg_ident); });
}
_ => {} _ => {}
} }

View File

@ -0,0 +1,211 @@
/*
* 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 super::ParsedType;
use quote::quote;
pub(crate) fn generate_vector_serializer(
value_ty: &ParsedType,
arg_name: &str,
) -> proc_macro2::TokenStream {
let values_serializer = match value_ty {
ParsedType::Boolean => {
quote! {
fluence::internal::transmute_vec::<i32, u8>(arg).unwrap()
}
}
ParsedType::I8
| ParsedType::I16
| ParsedType::I32
| ParsedType::I64
| ParsedType::U8
| ParsedType::U16
| ParsedType::U32
| ParsedType::U64 => {
quote! {
fluence::internal::transmute_vec::<#value_ty, u8>(arg).unwrap()
}
}
ParsedType::F32 => {
quote! {
let mut result: Vec<u32> = Vec::with_capacity(arg.len());
for value in arg {
result.push(value.to_bits());
}
fluence::internal::transmute_vec::<u32, u8>(result).unwrap()
}
}
ParsedType::F64 => {
quote! {
let mut result: Vec<u64> = Vec::with_capacity(arg.len());
for value in arg {
result.push(value.to_bits());
}
fluence::internal::transmute_vec::<u64, u8>(result).unwrap()
}
}
ParsedType::Utf8String => {
quote! {
let mut result: Vec<u32> = Vec::with_capacity(arg.len());
for value in arg {
result.push(value.as_ptr() as _);
result.push(value.len() as _);
}
fluence::internal::transmute_vec::<u32, u8>(result).unwrap()
}
}
ParsedType::Vector(ty) => {
let serializer_name = format!("{}_{}", arg_name, ty);
let inner_vector_serializer = generate_vector_serializer(&*ty, &serializer_name);
let serializer_ident = crate::new_ident!(serializer_name);
quote! {
#inner_vector_serializer
let mut result: Vec<u32> = Vec::with_capacity(2 * arg.len());
for value in arg {
let value = std::mem::ManuallyDrop::new(#serializer_ident(value));
result.push(value.as_ptr() as _);
result.push(value.len() as _);
}
fluence::internal::transmute_vec::<u32, u8>(result).unwrap()
}
}
ParsedType::Record(_) => {
quote! {
let mut result: Vec<u32> = Vec::with_capacity(arg.len());
for value in arg {
result.push(value.__fce_generated_serialize() as _);
}
fluence::internal::transmute_vec::<u32, u8>(result).unwrap()
}
}
};
let arg = crate::new_ident!(arg_name);
quote! {
unsafe fn #arg(arg: Vec<#value_ty>) -> Vec<u8> {
if arg.is_empty() {
return vec![];
}
#values_serializer
}
}
}
pub(crate) fn generate_vector_deserializer(
value_ty: &ParsedType,
arg_name: &str,
) -> proc_macro2::TokenStream {
let arg = crate::new_ident!(arg_name);
let values_deserializer = match value_ty {
ParsedType::Boolean => {
quote! {
fluence::internal::transmute_vec::<u8, i32>(arg).unwrap()
}
}
ParsedType::F32 => {
quote! {
let mut arg = fluence::internal::transmute_vec::<u8, u32>(arg).unwrap();
arg.into_iter().map(f32::from_bits).collect::<Vec<_>>()
}
}
ParsedType::F64 => {
quote! {
let mut arg = fluence::internal::transmute_vec::<u8, u64>(arg).unwrap();
arg.into_iter().map(f64::from_bits).collect::<Vec<_>>()
}
}
ParsedType::Utf8String => {
quote! {
let mut arg = fluence::internal::transmute_vec::<u8, u32>(arg).unwrap();
let mut arg = arg.into_iter();
let mut result = Vec::with_capacity(arg.len() / 2);
while let Some(offset) = arg.next() {
let size = arg.next().unwrap();
let value = String::from_raw_parts(offset as _, size as _, size as _);
result.push(value);
}
result
}
}
ParsedType::Vector(ty) => {
let deserializer_name = format!("{}_{}", arg_name, ty);
let inner_vector_deserializer = generate_vector_deserializer(&*ty, &deserializer_name);
let deserializer_ident = crate::new_ident!(deserializer_name);
quote! {
#inner_vector_deserializer
let mut arg = fluence::internal::transmute_vec::<u8, u32>(arg).unwrap();
let mut result = Vec::with_capacity(arg.len());
let mut arg = arg.into_iter();
while let Some(offset) = arg.next() {
let size = arg.next().unwrap();
let value = #deserializer_ident(offset, size);
result.push(value);
}
result
}
}
ParsedType::Record(record_name) => {
let record_name_ident = crate::new_ident!(record_name);
quote! {
let arg = fluence::internal::transmute_vec::<u8, u32>(arg).unwrap();
let mut result = Vec::with_capacity(arg.len());
for offset in arg {
let value = #record_name_ident::__fce_generated_deserialize(offset as _);
result.push(value);
}
result
}
}
v => {
quote! {
fluence::internal::transmute_vec::<u8, #v>(arg).unwrap()
}
}
};
quote! {
unsafe fn #arg(offset: u32, size: u32) -> Vec<#value_ty> {
let arg: Vec<u8> = Vec::from_raw_parts(offset as _, size as _, size as _);
if arg.is_empty() {
return vec![];
}
#values_deserializer
}
}
}

View File

@ -103,13 +103,22 @@ impl RecordDeserializerGlueCodeGenerator for fce_ast_types::AstRecordItem {
let #field = unsafe { String::from_raw_parts(raw_record[#ptr_id] as _, raw_record[#size_id] as _, raw_record[#size_id] as _) }; let #field = unsafe { String::from_raw_parts(raw_record[#ptr_id] as _, raw_record[#size_id] as _, raw_record[#size_id] as _) };
} }
} }
ParsedType::ByteVector => { ParsedType::Vector(ty) => {
let ptr_id = value_id; let ptr_id = value_id;
let size_id = value_id + 1; let size_id = value_id + 1;
value_id += 1; value_id += 1;
let generated_deserializer_name =
String::from("__fce_generated_vec_deserializer");
let generated_deserializer_ident = new_ident!(generated_deserializer_name);
let vector_deserializer = crate::parsed_type::generate_vector_deserializer(
ty,
&generated_deserializer_name,
);
quote! { quote! {
let #field = unsafe { Vec::from_raw_parts(raw_record[#ptr_id] as _, raw_record[#size_id] as _, raw_record[#size_id] as _) }; #vector_deserializer
let #field = unsafe { #generated_deserializer_ident(raw_record[#ptr_id] as _, raw_record[#size_id] as _) };
} }
} }
ParsedType::Record(record_name) => { ParsedType::Record(record_name) => {

View File

@ -37,13 +37,34 @@ impl RecordSerializerGlueCodeGenerator for fce_ast_types::AstRecordItem {
raw_record.push(#field_ident.to_bits()); raw_record.push(#field_ident.to_bits());
} }
} }
ParsedType::Utf8String | ParsedType::ByteVector => { ParsedType::Utf8String => {
quote! { quote! {
raw_record.push(#field_ident.as_ptr() as _); raw_record.push(#field_ident.as_ptr() as _);
raw_record.push(#field_ident.len() as _); raw_record.push(#field_ident.len() as _);
std::mem::forget(#field_ident); std::mem::forget(#field_ident);
} }
} }
ParsedType::Vector(ty) => {
let generated_serializer_name = format!(
"__fce_generated_vec_serializer_{}_{}",
field.name.as_ref().unwrap(),
id
);
let generated_serializer_ident = new_ident!(generated_serializer_name);
let vector_serializer = crate::parsed_type::generate_vector_serializer(
ty,
&generated_serializer_name,
);
let serialized_field_ident = new_ident!(format!("serialized_arg_{}", id));
quote::quote! {
#vector_serializer
let #serialized_field_ident = unsafe { #generated_serializer_ident(#field_ident) };
raw_record.push(#serialized_field_ident.as_ptr() as _);
raw_record.push(#serialized_field_ident.len() as _);
std::mem::forget(#serialized_field_ident);
}
}
ParsedType::Record(_) => { ParsedType::Record(_) => {
quote! { quote! {
raw_record.push(#field_ident.__fce_generated_serialize() as _); raw_record.push(#field_ident.__fce_generated_serialize() as _);

View File

@ -54,7 +54,7 @@ pub fn get_record_size<'a>(
for field in fields { for field in fields {
let params_count = match field { let params_count = match field {
ParsedType::ByteVector | ParsedType::Utf8String => 2, ParsedType::Vector(_) | ParsedType::Utf8String => 2,
_ => 1, _ => 1,
}; };

View File

@ -67,9 +67,6 @@
)] )]
#![warn(rust_2018_idioms)] #![warn(rust_2018_idioms)]
extern crate fluence_sdk_macro;
extern crate fluence_sdk_main;
pub use fluence_sdk_macro::fce; pub use fluence_sdk_macro::fce;
pub use fluence_sdk_main::CallParameters; pub use fluence_sdk_main::CallParameters;
#[cfg(target_arch = "wasm32")] #[cfg(target_arch = "wasm32")]
@ -84,4 +81,5 @@ pub mod internal {
pub use fluence_sdk_main::get_result_size; pub use fluence_sdk_main::get_result_size;
pub use fluence_sdk_main::set_result_ptr; pub use fluence_sdk_main::set_result_ptr;
pub use fluence_sdk_main::set_result_size; pub use fluence_sdk_main::set_result_size;
pub use safe_transmute::transmute_vec;
} }