mirror of
https://github.com/fluencelabs/marine-rs-sdk-test
synced 2024-12-04 23:30:18 +00:00
add ref types
This commit is contained in:
parent
5e3c881250
commit
ba2c5a80fd
@ -20,6 +20,7 @@ mod fn_prolog;
|
||||
mod foreign_mod_arg;
|
||||
mod foreign_mod_epilog;
|
||||
mod foreign_mod_prolog;
|
||||
mod traits;
|
||||
mod vector_utils;
|
||||
|
||||
pub(crate) use fn_arg::*;
|
||||
@ -34,78 +35,38 @@ 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)]
|
||||
pub enum ParsedType {
|
||||
I8,
|
||||
I16,
|
||||
I32,
|
||||
I64,
|
||||
U8,
|
||||
U16,
|
||||
U32,
|
||||
U64,
|
||||
F32,
|
||||
F64,
|
||||
Boolean,
|
||||
Utf8String,
|
||||
Vector(Box<ParsedType>),
|
||||
Record(String), // short type name
|
||||
Option(String),
|
||||
Result(String),
|
||||
I8(PassingStyle),
|
||||
I16(PassingStyle),
|
||||
I32(PassingStyle),
|
||||
I64(PassingStyle),
|
||||
U8(PassingStyle),
|
||||
U16(PassingStyle),
|
||||
U32(PassingStyle),
|
||||
U64(PassingStyle),
|
||||
F32(PassingStyle),
|
||||
F64(PassingStyle),
|
||||
Boolean(PassingStyle),
|
||||
Utf8Str(PassingStyle),
|
||||
Utf8String(PassingStyle),
|
||||
Vector(Box<ParsedType>, PassingStyle),
|
||||
Record(String, PassingStyle), // short type name
|
||||
}
|
||||
|
||||
enum ArgPassingStyle {
|
||||
pub enum PassingStyle {
|
||||
ByValue,
|
||||
ByRef
|
||||
}
|
||||
|
||||
struct Arg {
|
||||
passing_style: ArgPassingStyle,
|
||||
parsed_type: ParsedType,
|
||||
ByRef,
|
||||
ByMutRef,
|
||||
}
|
||||
|
||||
impl ParsedType {
|
||||
pub fn from_type(input_type: &syn::Type) -> syn::Result<Self> {
|
||||
use quote::ToTokens;
|
||||
|
||||
// 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),
|
||||
_ => Err(Error::new(
|
||||
args.span(),
|
||||
"It has to be a bracketed value after Vec",
|
||||
)),
|
||||
}?;
|
||||
|
||||
let arg = generic_arg.args.first().ok_or_else(|| {
|
||||
Error::new(
|
||||
generic_arg.span(),
|
||||
"Unsuitable type in Vec brackets - only Vec<u8> is supported",
|
||||
)
|
||||
})?;
|
||||
|
||||
// converts T to syn::Type
|
||||
match arg {
|
||||
syn::GenericArgument::Type(ty) => Ok(ty),
|
||||
_ => Err(Error::new(
|
||||
arg.span(),
|
||||
"Unsuitable type in Vec brackets - only Vec<u8> is supported",
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
let path = match input_type {
|
||||
syn::Type::Path(path) => Ok(&path.path),
|
||||
_ => Err(Error::new(
|
||||
input_type.span(),
|
||||
"Incorrect argument type - passing only by value is supported now",
|
||||
)),
|
||||
}?;
|
||||
let (path, passing_style) = type_to_path_passing_style(input_type)?;
|
||||
|
||||
let type_segment = path
|
||||
.segments
|
||||
@ -115,23 +76,23 @@ impl ParsedType {
|
||||
.ok_or_else(|| Error::new(path.span(), "Type should be specified"))?;
|
||||
|
||||
match type_segment.ident.to_string().as_str() {
|
||||
"i8" => Ok(ParsedType::I8),
|
||||
"i16" => Ok(ParsedType::I16),
|
||||
"i32" => Ok(ParsedType::I32),
|
||||
"i64" => Ok(ParsedType::I64),
|
||||
"u8" => Ok(ParsedType::U8),
|
||||
"u16" => Ok(ParsedType::U16),
|
||||
"u32" => Ok(ParsedType::U32),
|
||||
"u64" => Ok(ParsedType::U64),
|
||||
"f32" => Ok(ParsedType::F32),
|
||||
"f64" => Ok(ParsedType::F64),
|
||||
"bool" => Ok(ParsedType::Boolean),
|
||||
"String" => Ok(ParsedType::Utf8String),
|
||||
"i8" => Ok(ParsedType::I8(passing_style)),
|
||||
"i16" => Ok(ParsedType::I16(passing_style)),
|
||||
"i32" => Ok(ParsedType::I32(passing_style)),
|
||||
"i64" => Ok(ParsedType::I64(passing_style)),
|
||||
"u8" => Ok(ParsedType::U8(passing_style)),
|
||||
"u16" => Ok(ParsedType::U16(passing_style)),
|
||||
"u32" => Ok(ParsedType::U32(passing_style)),
|
||||
"u64" => Ok(ParsedType::U64(passing_style)),
|
||||
"f32" => Ok(ParsedType::F32(passing_style)),
|
||||
"f64" => Ok(ParsedType::F64(passing_style)),
|
||||
"bool" => Ok(ParsedType::Boolean(passing_style)),
|
||||
"String" => Ok(ParsedType::Utf8String(passing_style)),
|
||||
"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)))
|
||||
Ok(ParsedType::Vector(Box::new(parsed_type), passing_style))
|
||||
}
|
||||
_ if !type_segment.arguments.is_empty() => Err(Error::new(
|
||||
type_segment.span(),
|
||||
@ -139,6 +100,7 @@ impl ParsedType {
|
||||
)),
|
||||
_ => Ok(ParsedType::Record(
|
||||
(&type_segment.ident).into_token_stream().to_string(),
|
||||
passing_style,
|
||||
)),
|
||||
}
|
||||
}
|
||||
@ -162,74 +124,79 @@ impl ParsedType {
|
||||
|
||||
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,
|
||||
ParsedType::Boolean(_)
|
||||
| ParsedType::I8(_)
|
||||
| ParsedType::I16(_)
|
||||
| ParsedType::I32(_)
|
||||
| ParsedType::I64(_)
|
||||
| ParsedType::U8(_)
|
||||
| ParsedType::U16(_)
|
||||
| ParsedType::U32(_)
|
||||
| ParsedType::U64(_)
|
||||
| ParsedType::F32(_)
|
||||
| ParsedType::F64(_) => false,
|
||||
ParsedType::Utf8Str(_)
|
||||
| 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 type_to_path_passing_style(input_type: &syn::Type) -> syn::Result<(&syn::Path, PassingStyle)> {
|
||||
match input_type {
|
||||
syn::Type::Path(path) => Ok((&path.path, PassingStyle::ByRef)),
|
||||
syn::Type::Reference(type_reference) => match &*type_reference.elem {
|
||||
syn::Type::Path(path) => {
|
||||
if type_reference.lifetime.is_some() {
|
||||
return Err(Error::new(
|
||||
input_type.span(),
|
||||
"Lifetime is unsupported at the moment",
|
||||
));
|
||||
}
|
||||
let passing_style = match type_reference.mutability {
|
||||
Some(_) => PassingStyle::ByMutRef,
|
||||
None => PassingStyle::ByRef,
|
||||
};
|
||||
|
||||
fn to_token_stream(&self) -> proc_macro2::TokenStream {
|
||||
use quote::quote;
|
||||
|
||||
match self {
|
||||
ParsedType::I8 => quote! { i8 },
|
||||
ParsedType::I16 => quote! { i16 },
|
||||
ParsedType::I32 => quote! { i32 },
|
||||
ParsedType::I64 => quote! { i64 },
|
||||
ParsedType::U8 => quote! { u8 },
|
||||
ParsedType::U16 => quote! { u16 },
|
||||
ParsedType::U32 => quote! { u32 },
|
||||
ParsedType::U64 => quote! { u64 },
|
||||
ParsedType::F32 => quote! { f32 },
|
||||
ParsedType::F64 => quote! { f64 },
|
||||
ParsedType::Boolean => quote! { bool },
|
||||
ParsedType::Utf8String => quote! { String },
|
||||
ParsedType::Vector(ty) => {
|
||||
let quoted_type = ty.to_token_stream();
|
||||
quote! { Vec<#quoted_type> }
|
||||
Ok((&path.path, passing_style))
|
||||
}
|
||||
ParsedType::Record(name) => {
|
||||
let ty = crate::new_ident!(name);
|
||||
quote! { #ty }
|
||||
}
|
||||
}
|
||||
_ => Err(Error::new(
|
||||
input_type.span(),
|
||||
"Incorrect argument type, only path is available on this position",
|
||||
)),
|
||||
},
|
||||
_ => Err(Error::new(
|
||||
input_type.span(),
|
||||
"Incorrect argument type, only path or reference are available on this position",
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Display for ParsedType {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {
|
||||
match self {
|
||||
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),
|
||||
}?;
|
||||
// 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),
|
||||
_ => Err(Error::new(
|
||||
args.span(),
|
||||
"It has to be a bracketed value after Vec",
|
||||
)),
|
||||
}?;
|
||||
|
||||
Ok(())
|
||||
let arg = generic_arg.args.first().ok_or_else(|| {
|
||||
Error::new(
|
||||
generic_arg.span(),
|
||||
"Unsuitable type in Vec brackets, lifetimes, bindings, constraints and consts are unsupported",
|
||||
)
|
||||
})?;
|
||||
|
||||
// converts T to syn::Type
|
||||
match arg {
|
||||
syn::GenericArgument::Type(ty) => Ok(ty),
|
||||
_ => Err(Error::new(
|
||||
arg.span(),
|
||||
"Unsuitable type in Vec brackets, lifetimes, bindings, constraints and consts are unsupported",
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
152
crates/wit/src/parsed_type/traits.rs
Normal file
152
crates/wit/src/parsed_type/traits.rs
Normal file
@ -0,0 +1,152 @@
|
||||
/*
|
||||
* Copyright 2018 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::PassingStyle;
|
||||
use super::ParsedType;
|
||||
|
||||
use quote::quote;
|
||||
use syn::parse::Error;
|
||||
use syn::spanned::Spanned;
|
||||
use proc_macro2::TokenStream;
|
||||
|
||||
use std::fmt;
|
||||
|
||||
impl quote::ToTokens for PassingStyle {
|
||||
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||
tokens.extend(self.to_token_stream());
|
||||
}
|
||||
|
||||
fn to_token_stream(&self) -> proc_macro2::TokenStream {
|
||||
match self {
|
||||
PassingStyle::ByValue => quote! {},
|
||||
PassingStyle::ByRef => quote! { & },
|
||||
PassingStyle::ByMutRef => quote! { &mut },
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
match self {
|
||||
ParsedType::I8(passing_style) => quote! { #passing_style i8 },
|
||||
ParsedType::I16(passing_style) => quote! { #passing_style i16 },
|
||||
ParsedType::I32(passing_style) => quote! { #passing_style i32 },
|
||||
ParsedType::I64(passing_style) => quote! { #passing_style i64 },
|
||||
ParsedType::U8(passing_style) => quote! { #passing_style u8 },
|
||||
ParsedType::U16(passing_style) => quote! { #passing_style u16 },
|
||||
ParsedType::U32(passing_style) => quote! { #passing_style u32 },
|
||||
ParsedType::U64(passing_style) => quote! { #passing_style u64 },
|
||||
ParsedType::F32(passing_style) => quote! { #passing_style f32 },
|
||||
ParsedType::F64(passing_style) => quote! { #passing_style f64 },
|
||||
ParsedType::Boolean(passing_style) => quote! { #passing_style bool },
|
||||
ParsedType::Utf8Str(passing_style) => quote! { #passing_style str },
|
||||
ParsedType::Utf8String(passing_style) => quote! { #passing_style String },
|
||||
ParsedType::Vector(ty, passing_style) => {
|
||||
let quoted_type = ty.to_token_stream();
|
||||
quote! { #passing_style Vec<#quoted_type> }
|
||||
}
|
||||
ParsedType::Record(name, passing_style) => {
|
||||
let ty = crate::new_ident!(name);
|
||||
quote! { #passing_style #ty }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for ParsedType {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
|
||||
match self {
|
||||
ParsedType::Boolean(passing_style) => {
|
||||
passing_style.fmt(f)?;
|
||||
f.write_str("bool")
|
||||
}
|
||||
ParsedType::I8(passing_style) => {
|
||||
passing_style.fmt(f)?;
|
||||
f.write_str("i8")
|
||||
}
|
||||
ParsedType::I16(passing_style) => {
|
||||
passing_style.fmt(f)?;
|
||||
f.write_str("i16")
|
||||
}
|
||||
ParsedType::I32(passing_style) => {
|
||||
passing_style.fmt(f)?;
|
||||
f.write_str("i32")
|
||||
}
|
||||
ParsedType::I64(passing_style) => {
|
||||
passing_style.fmt(f)?;
|
||||
f.write_str("i64")
|
||||
}
|
||||
ParsedType::U8(passing_style) => {
|
||||
passing_style.fmt(f)?;
|
||||
f.write_str("u8")
|
||||
}
|
||||
ParsedType::U16(passing_style) => {
|
||||
passing_style.fmt(f)?;
|
||||
f.write_str("u16")
|
||||
}
|
||||
ParsedType::U32(passing_style) => {
|
||||
passing_style.fmt(f)?;
|
||||
f.write_str("u32")
|
||||
}
|
||||
ParsedType::U64(passing_style) => {
|
||||
passing_style.fmt(f)?;
|
||||
f.write_str("u64")
|
||||
}
|
||||
ParsedType::F32(passing_style) => {
|
||||
passing_style.fmt(f)?;
|
||||
f.write_str("f32")
|
||||
}
|
||||
ParsedType::F64(passing_style) => {
|
||||
passing_style.fmt(f)?;
|
||||
f.write_str("u64")
|
||||
}
|
||||
ParsedType::Utf8Str(passing_style) => {
|
||||
passing_style.fmt(f)?;
|
||||
f.write_str("str")
|
||||
}
|
||||
ParsedType::Utf8String(passing_style) => {
|
||||
passing_style.fmt(f)?;
|
||||
f.write_str("String")
|
||||
}
|
||||
ParsedType::Vector(ty, passing_style) => {
|
||||
passing_style.fmt(f)?;
|
||||
f.write_str("Vec<")?;
|
||||
ty.fmt(f)?;
|
||||
f.write_str(">")
|
||||
}
|
||||
ParsedType::Record(record_name, passing_style) => {
|
||||
passing_style.fmt(f)?;
|
||||
f.write_str(&record_name)
|
||||
}
|
||||
}?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for PassingStyle {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
|
||||
match self {
|
||||
PassingStyle::ByValue => Ok(()),
|
||||
PassingStyle::ByRef => f.write_str("&"),
|
||||
PassingStyle::ByMutRef => f.write_str("&mut"),
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user