mirror of
https://github.com/fluencelabs/marine-rs-sdk
synced 2025-03-15 06:20:50 +00:00
commit
5ac0c45507
@ -9,6 +9,7 @@ readme = "Readme.md"
|
||||
keywords = ["fluence", "sdk", "webassembly"]
|
||||
categories = ["api-bindings", "wasm"]
|
||||
license = "Apache-2.0"
|
||||
edition = "2018"
|
||||
|
||||
[package.metadata.docs.rs] # https://docs.rs/about
|
||||
all-features = true
|
||||
@ -19,6 +20,7 @@ path = "src/lib.rs"
|
||||
[dependencies]
|
||||
fluence-sdk-macro = { path = "crates/macro", version = "=0.2.3" }
|
||||
fluence-sdk-main = { path = "crates/main", version = "=0.2.3" }
|
||||
safe-transmute = "0.11.0"
|
||||
|
||||
[features]
|
||||
# Print some internal logs by log_utf8_string
|
||||
|
@ -20,17 +20,21 @@ mod fn_prolog;
|
||||
mod foreign_mod_arg;
|
||||
mod foreign_mod_epilog;
|
||||
mod foreign_mod_prolog;
|
||||
mod vector_utils;
|
||||
|
||||
pub(crate) use fn_arg::*;
|
||||
pub(crate) use fn_epilog::*;
|
||||
pub(crate) use fn_prolog::*;
|
||||
pub(crate) use foreign_mod_prolog::*;
|
||||
pub(crate) use foreign_mod_epilog::*;
|
||||
pub(crate) use vector_utils::*;
|
||||
|
||||
use serde::Serialize;
|
||||
use serde::Deserialize;
|
||||
use syn::parse::Error;
|
||||
use syn::spanned::Spanned;
|
||||
use proc_macro2::TokenStream;
|
||||
use serde::export::Formatter;
|
||||
|
||||
/// An internal representation of supported Rust types.
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
@ -47,15 +51,16 @@ pub enum ParsedType {
|
||||
F64,
|
||||
Boolean,
|
||||
Utf8String,
|
||||
ByteVector,
|
||||
Vector(Box<ParsedType>),
|
||||
Record(String), // short type name
|
||||
}
|
||||
|
||||
impl ParsedType {
|
||||
pub fn from_type(input_type: &syn::Type) -> syn::Result<Self> {
|
||||
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
|
||||
let generic_arg = match args {
|
||||
syn::PathArguments::AngleBracketed(args) => Ok(args),
|
||||
@ -73,41 +78,13 @@ impl ParsedType {
|
||||
})?;
|
||||
|
||||
// converts T to syn::Type
|
||||
let arg_type = match arg {
|
||||
match arg {
|
||||
syn::GenericArgument::Type(ty) => Ok(ty),
|
||||
_ => Err(Error::new(
|
||||
arg.span(),
|
||||
"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 {
|
||||
@ -138,16 +115,12 @@ impl ParsedType {
|
||||
"f64" => Ok(ParsedType::F64),
|
||||
"bool" => Ok(ParsedType::Boolean),
|
||||
"String" => Ok(ParsedType::Utf8String),
|
||||
"Vec" => match parse_vec_bracket(&type_segment.arguments) {
|
||||
Ok(value) => match value.as_str() {
|
||||
"u8" => Ok(ParsedType::ByteVector),
|
||||
_ => Err(Error::new(
|
||||
value.span(),
|
||||
"Unsuitable type in Vec brackets - only Vec<u8> is supported",
|
||||
)),
|
||||
},
|
||||
Err(e) => Err(e),
|
||||
},
|
||||
"Vec" => {
|
||||
let vec_type = parse_vec_bracket(&type_segment.arguments)?;
|
||||
let parsed_type = ParsedType::from_type(vec_type)?;
|
||||
|
||||
Ok(ParsedType::Vector(Box::new(parsed_type)))
|
||||
}
|
||||
_ if !type_segment.arguments.is_empty() => Err(Error::new(
|
||||
type_segment.span(),
|
||||
"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;
|
||||
|
||||
match self {
|
||||
@ -191,28 +187,37 @@ impl ParsedType {
|
||||
ParsedType::F64 => quote! { f64 },
|
||||
ParsedType::Boolean => quote! { bool },
|
||||
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) => {
|
||||
let ty = crate::new_ident!(name);
|
||||
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 {
|
||||
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::ByteVector | ParsedType::Record(_) => true,
|
||||
}
|
||||
ParsedType::Boolean => f.write_str("bool"),
|
||||
ParsedType::I8 => f.write_str("i8"),
|
||||
ParsedType::I16 => f.write_str("i16"),
|
||||
ParsedType::I32 => f.write_str("i32"),
|
||||
ParsedType::I64 => f.write_str("i64"),
|
||||
ParsedType::U8 => f.write_str("u8"),
|
||||
ParsedType::U16 => f.write_str("u16"),
|
||||
ParsedType::U32 => f.write_str("u32"),
|
||||
ParsedType::U64 => f.write_str("u64"),
|
||||
ParsedType::F32 => f.write_str("f32"),
|
||||
ParsedType::F64 => f.write_str("u64"),
|
||||
ParsedType::Utf8String => f.write_str("String"),
|
||||
ParsedType::Vector(_) => f.write_str("Vec"),
|
||||
ParsedType::Record(record_name) => f.write_str(&record_name),
|
||||
}?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
@ -37,7 +37,7 @@ impl FnArgGlueCodeGenerator for (String, ParsedType) {
|
||||
ParsedType::Record(_) => vec![RustType::U32],
|
||||
ParsedType::F32 => vec![RustType::F32],
|
||||
ParsedType::F64 => vec![RustType::F64],
|
||||
ParsedType::Utf8String | ParsedType::ByteVector => vec![RustType::U32, RustType::U32],
|
||||
ParsedType::Utf8String | ParsedType::Vector(_) => vec![RustType::U32, RustType::U32],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -66,7 +66,7 @@ fn generate_fn_return_type(ty: &Option<ParsedType>) -> proc_macro2::TokenStream
|
||||
Some(ParsedType::F64) => Some("f64"),
|
||||
None
|
||||
| Some(ParsedType::Utf8String)
|
||||
| Some(ParsedType::ByteVector)
|
||||
| Some(ParsedType::Vector(_))
|
||||
| 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 {
|
||||
match ty {
|
||||
None => quote!(),
|
||||
Some(ty) if !ty.is_complex_type() => quote! {
|
||||
return result as _;
|
||||
},
|
||||
Some(ParsedType::Record(_)) => {
|
||||
quote! {
|
||||
let result_ptr = result.__fce_generated_serialize();
|
||||
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_size(result.len() as _);
|
||||
std::mem::forget(result);
|
||||
},
|
||||
_ => {
|
||||
panic!("perhaps new type's been added to ParsedType, and this match became incomplete")
|
||||
Some(ParsedType::Vector(ty)) => {
|
||||
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 _;
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -107,9 +107,20 @@ fn generate_type_prolog(
|
||||
ParsedType::Utf8String => quote! {
|
||||
let #generated_arg_id = String::from_raw_parts(#ptr as _, #size as _ , #size as _);
|
||||
},
|
||||
ParsedType::ByteVector => quote! {
|
||||
let #generated_arg_id = Vec::from_raw_parts(#ptr as _, #size as _, #size as _);
|
||||
},
|
||||
ParsedType::Vector(ty) => {
|
||||
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) => {
|
||||
let record_ident = new_ident!(record_name);
|
||||
quote! {
|
||||
|
@ -28,14 +28,12 @@ impl ForeignModArgGlueCodeGenerator for ParsedType {
|
||||
let arg = crate::new_ident!(format!("arg_{}", arg_start_id));
|
||||
|
||||
match self {
|
||||
ParsedType::Utf8String | ParsedType::ByteVector => {
|
||||
ParsedType::Vector(_) | ParsedType::Utf8String => {
|
||||
quote! { #arg.as_ptr() as _, #arg.len() as _ }
|
||||
}
|
||||
ParsedType::Record(_) => {
|
||||
quote! {
|
||||
#arg.__fce_generated_serialize() as _
|
||||
}
|
||||
}
|
||||
ParsedType::Record(_) => quote! {
|
||||
#arg.__fce_generated_serialize() as _
|
||||
},
|
||||
ParsedType::Boolean => quote! { #arg as _ },
|
||||
_ => quote! { #arg },
|
||||
}
|
||||
|
@ -29,6 +29,8 @@ pub(crate) trait ForeignModEpilogGlueCodeGenerator {
|
||||
|
||||
impl ForeignModEpilogGlueCodeGenerator for Option<ParsedType> {
|
||||
fn generate_wrapper_return_type(&self) -> proc_macro2::TokenStream {
|
||||
use quote::ToTokens;
|
||||
|
||||
match self {
|
||||
Some(ty) => {
|
||||
let ty = ty.to_token_stream();
|
||||
@ -54,13 +56,22 @@ impl ForeignModEpilogGlueCodeGenerator for Option<ParsedType> {
|
||||
fluence::internal::get_result_size() as _
|
||||
)
|
||||
},
|
||||
Some(ParsedType::ByteVector) => quote! {
|
||||
Vec::from_raw_parts(
|
||||
fluence::internal::get_result_ptr() as _,
|
||||
fluence::internal::get_result_size() as _,
|
||||
fluence::internal::get_result_size() as _
|
||||
)
|
||||
},
|
||||
Some(ParsedType::Vector(ty)) => {
|
||||
let generated_deserializer_name = String::from("__fce_generated_vec_deserializer");
|
||||
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
|
||||
#generated_deserializer_ident(
|
||||
fluence::internal::get_result_ptr() as _,
|
||||
fluence::internal::get_result_size() as _,
|
||||
)
|
||||
}
|
||||
}
|
||||
Some(ParsedType::Record(record_name)) => {
|
||||
let record_ident = new_ident!(record_name);
|
||||
|
||||
|
@ -60,6 +60,7 @@ pub(crate) trait ForeignModPrologGlueCodeGenerator {
|
||||
impl ForeignModPrologGlueCodeGenerator for Vec<(String, ParsedType)> {
|
||||
fn generate_wrapper_prolog(&self) -> WrapperDescriptor {
|
||||
use crate::parsed_type::foreign_mod_arg::ForeignModArgGlueCodeGenerator;
|
||||
use quote::ToTokens;
|
||||
|
||||
let arg_types: Vec<proc_macro2::TokenStream> = self
|
||||
.iter()
|
||||
@ -70,14 +71,30 @@ impl ForeignModPrologGlueCodeGenerator for Vec<(String, ParsedType)> {
|
||||
.iter()
|
||||
.enumerate()
|
||||
.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());
|
||||
|
||||
match ty {
|
||||
ParsedType::ByteVector | ParsedType::Utf8String => {
|
||||
ParsedType::Utf8String => {
|
||||
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); });
|
||||
},
|
||||
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); });
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
|
211
crates/wit/src/parsed_type/vector_utils.rs
Normal file
211
crates/wit/src/parsed_type/vector_utils.rs
Normal 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
|
||||
}
|
||||
}
|
||||
}
|
@ -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 _) };
|
||||
}
|
||||
}
|
||||
ParsedType::ByteVector => {
|
||||
ParsedType::Vector(ty) => {
|
||||
let ptr_id = value_id;
|
||||
let size_id = 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! {
|
||||
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) => {
|
||||
|
@ -37,13 +37,34 @@ impl RecordSerializerGlueCodeGenerator for fce_ast_types::AstRecordItem {
|
||||
raw_record.push(#field_ident.to_bits());
|
||||
}
|
||||
}
|
||||
ParsedType::Utf8String | ParsedType::ByteVector => {
|
||||
ParsedType::Utf8String => {
|
||||
quote! {
|
||||
raw_record.push(#field_ident.as_ptr() as _);
|
||||
raw_record.push(#field_ident.len() as _);
|
||||
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(_) => {
|
||||
quote! {
|
||||
raw_record.push(#field_ident.__fce_generated_serialize() as _);
|
||||
|
@ -54,7 +54,7 @@ pub fn get_record_size<'a>(
|
||||
|
||||
for field in fields {
|
||||
let params_count = match field {
|
||||
ParsedType::ByteVector | ParsedType::Utf8String => 2,
|
||||
ParsedType::Vector(_) | ParsedType::Utf8String => 2,
|
||||
_ => 1,
|
||||
};
|
||||
|
||||
|
@ -67,9 +67,6 @@
|
||||
)]
|
||||
#![warn(rust_2018_idioms)]
|
||||
|
||||
extern crate fluence_sdk_macro;
|
||||
extern crate fluence_sdk_main;
|
||||
|
||||
pub use fluence_sdk_macro::fce;
|
||||
pub use fluence_sdk_main::CallParameters;
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
@ -84,4 +81,5 @@ 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 safe_transmute::transmute_vec;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user