git.delta.rocks / unique-network / refs/commits / aea07737fd8a

difftreelog

Merge pull request #806 from UniqueNetwork/fix/macro_check_enum_fields

Yaroslav Bolyukin2022-12-23parents: #d6d6d43 #3e69aff.patch.diff
in: master

2 files changed

modifiedcrates/evm-coder/procedural/src/abi_derive/derive_enum.rsdiffbeforeafterboth
--- a/crates/evm-coder/procedural/src/abi_derive/derive_enum.rs
+++ b/crates/evm-coder/procedural/src/abi_derive/derive_enum.rs
@@ -143,8 +143,7 @@
 	)
 }
 
-pub fn check_and_count_options(de: &syn::DataEnum) -> syn::Result<usize> {
-	let mut count = 0;
+pub fn check_enum_fields(de: &syn::DataEnum) -> syn::Result<()> {
 	for v in de.variants.iter() {
 		if !v.fields.is_empty() {
 			return Err(syn::Error::new(
@@ -156,12 +155,10 @@
 				v.ident.span(),
 				"Enumeration options should not have an explicit specified value",
 			));
-		} else {
-			count += 1;
 		}
 	}
 
-	Ok(count)
+	Ok(())
 }
 
 pub fn check_repr_u8(name: &syn::Ident, attrs: &[syn::Attribute]) -> syn::Result<()> {
modifiedcrates/evm-coder/procedural/src/abi_derive/mod.rsdiffbeforeafterboth
before · crates/evm-coder/procedural/src/abi_derive/mod.rs
1mod derive_enum;2mod derive_struct;34use quote::quote;5use derive_struct::*;6use derive_enum::*;78pub(crate) fn impl_abi_macro(ast: &syn::DeriveInput) -> syn::Result<proc_macro2::TokenStream> {9	let name = &ast.ident;10	match &ast.data {11		syn::Data::Struct(ds) => expand_struct(ds, ast),12		syn::Data::Enum(de) => expand_enum(de, ast),13		syn::Data::Union(_) => Err(syn::Error::new(name.span(), "Unions not supported")),14	}15}1617fn expand_struct(18	ds: &syn::DataStruct,19	ast: &syn::DeriveInput,20) -> syn::Result<proc_macro2::TokenStream> {21	let name = &ast.ident;22	let docs = extract_docs(&ast.attrs)?;23	let (is_named_fields, field_names, field_types, params_count) = match ds.fields {24		syn::Fields::Named(ref fields) => Ok((25			true,26			fields.named.iter().enumerate().map(map_field_to_name),27			fields.named.iter().map(map_field_to_type),28			fields.named.len(),29		)),30		syn::Fields::Unnamed(ref fields) => Ok((31			false,32			fields.unnamed.iter().enumerate().map(map_field_to_name),33			fields.unnamed.iter().map(map_field_to_type),34			fields.unnamed.len(),35		)),36		syn::Fields::Unit => Err(syn::Error::new(name.span(), "Unit structs not supported")),37	}?;3839	if params_count == 0 {40		return Err(syn::Error::new(name.span(), "Empty structs not supported"));41	};4243	let tuple_type = tuple_type(field_types.clone());44	let tuple_ref_type = tuple_ref_type(field_types.clone());45	let tuple_data = tuple_data_as_ref(is_named_fields, field_names.clone());46	let tuple_names = tuple_names(is_named_fields, field_names.clone());47	let struct_from_tuple = struct_from_tuple(name, is_named_fields, field_names.clone());4849	let can_be_plcaed_in_vec = impl_can_be_placed_in_vec(name);50	let abi_type = impl_struct_abi_type(name, tuple_type.clone());51	let abi_read = impl_struct_abi_read(name, tuple_type, tuple_names, struct_from_tuple);52	let abi_write = impl_struct_abi_write(name, is_named_fields, tuple_ref_type, tuple_data);53	let solidity_type = impl_struct_solidity_type(name, docs, ds.fields.iter());54	let solidity_type_name =55		impl_struct_solidity_type_name(name, field_types.clone(), params_count);5657	Ok(quote! {58		#can_be_plcaed_in_vec59		#abi_type60		#abi_read61		#abi_write62		#solidity_type63		#solidity_type_name64	})65}6667fn expand_enum(68	de: &syn::DataEnum,69	ast: &syn::DeriveInput,70) -> syn::Result<proc_macro2::TokenStream> {71	let name = &ast.ident;72	check_repr_u8(name, &ast.attrs)?;73	let docs = extract_docs(&ast.attrs)?;74	let enum_options = de.variants.iter();7576	let from = impl_enum_from_u8(name, enum_options.clone());77	let solidity_option = impl_solidity_option(docs, name, enum_options.clone());78	let can_be_plcaed_in_vec = impl_can_be_placed_in_vec(name);79	let abi_type = impl_enum_abi_type(name);80	let abi_read = impl_enum_abi_read(name);81	let abi_write = impl_enum_abi_write(name);82	let solidity_type_name = impl_enum_solidity_type_name(name);8384	Ok(quote! {85		#from86		#solidity_option87		#can_be_plcaed_in_vec88		#abi_type89		#abi_read90		#abi_write91		#solidity_type_name92	})93}9495fn extract_docs(attrs: &[syn::Attribute]) -> syn::Result<Vec<String>> {96	attrs97		.iter()98		.filter_map(|attr| {99			if let Some(ps) = attr.path.segments.first() {100				if ps.ident == "doc" {101					let meta = match attr.parse_meta() {102						Ok(meta) => meta,103						Err(e) => return Some(Err(e)),104					};105					match meta {106						syn::Meta::NameValue(mnv) => match &mnv.lit {107							syn::Lit::Str(ls) => return Some(Ok(ls.value())),108							_ => unreachable!(),109						},110						_ => unreachable!(),111					}112				}113			}114			None115		})116		.collect()117}
after · crates/evm-coder/procedural/src/abi_derive/mod.rs
1mod derive_enum;2mod derive_struct;34use quote::quote;5use derive_struct::*;6use derive_enum::*;78pub(crate) fn impl_abi_macro(ast: &syn::DeriveInput) -> syn::Result<proc_macro2::TokenStream> {9	let name = &ast.ident;10	match &ast.data {11		syn::Data::Struct(ds) => expand_struct(ds, ast),12		syn::Data::Enum(de) => expand_enum(de, ast),13		syn::Data::Union(_) => Err(syn::Error::new(name.span(), "Unions not supported")),14	}15}1617fn expand_struct(18	ds: &syn::DataStruct,19	ast: &syn::DeriveInput,20) -> syn::Result<proc_macro2::TokenStream> {21	let name = &ast.ident;22	let docs = extract_docs(&ast.attrs)?;23	let (is_named_fields, field_names, field_types, params_count) = match ds.fields {24		syn::Fields::Named(ref fields) => Ok((25			true,26			fields.named.iter().enumerate().map(map_field_to_name),27			fields.named.iter().map(map_field_to_type),28			fields.named.len(),29		)),30		syn::Fields::Unnamed(ref fields) => Ok((31			false,32			fields.unnamed.iter().enumerate().map(map_field_to_name),33			fields.unnamed.iter().map(map_field_to_type),34			fields.unnamed.len(),35		)),36		syn::Fields::Unit => Err(syn::Error::new(name.span(), "Unit structs not supported")),37	}?;3839	if params_count == 0 {40		return Err(syn::Error::new(name.span(), "Empty structs not supported"));41	};4243	let tuple_type = tuple_type(field_types.clone());44	let tuple_ref_type = tuple_ref_type(field_types.clone());45	let tuple_data = tuple_data_as_ref(is_named_fields, field_names.clone());46	let tuple_names = tuple_names(is_named_fields, field_names.clone());47	let struct_from_tuple = struct_from_tuple(name, is_named_fields, field_names.clone());4849	let can_be_plcaed_in_vec = impl_can_be_placed_in_vec(name);50	let abi_type = impl_struct_abi_type(name, tuple_type.clone());51	let abi_read = impl_struct_abi_read(name, tuple_type, tuple_names, struct_from_tuple);52	let abi_write = impl_struct_abi_write(name, is_named_fields, tuple_ref_type, tuple_data);53	let solidity_type = impl_struct_solidity_type(name, docs, ds.fields.iter());54	let solidity_type_name =55		impl_struct_solidity_type_name(name, field_types.clone(), params_count);5657	Ok(quote! {58		#can_be_plcaed_in_vec59		#abi_type60		#abi_read61		#abi_write62		#solidity_type63		#solidity_type_name64	})65}6667fn expand_enum(68	de: &syn::DataEnum,69	ast: &syn::DeriveInput,70) -> syn::Result<proc_macro2::TokenStream> {71	let name = &ast.ident;72	check_repr_u8(name, &ast.attrs)?;73	check_enum_fields(de)?;74	let docs = extract_docs(&ast.attrs)?;75	let enum_options = de.variants.iter();7677	let from = impl_enum_from_u8(name, enum_options.clone());78	let solidity_option = impl_solidity_option(docs, name, enum_options.clone());79	let can_be_plcaed_in_vec = impl_can_be_placed_in_vec(name);80	let abi_type = impl_enum_abi_type(name);81	let abi_read = impl_enum_abi_read(name);82	let abi_write = impl_enum_abi_write(name);83	let solidity_type_name = impl_enum_solidity_type_name(name);8485	Ok(quote! {86		#from87		#solidity_option88		#can_be_plcaed_in_vec89		#abi_type90		#abi_read91		#abi_write92		#solidity_type_name93	})94}9596fn extract_docs(attrs: &[syn::Attribute]) -> syn::Result<Vec<String>> {97	attrs98		.iter()99		.filter_map(|attr| {100			if let Some(ps) = attr.path.segments.first() {101				if ps.ident == "doc" {102					let meta = match attr.parse_meta() {103						Ok(meta) => meta,104						Err(e) => return Some(Err(e)),105					};106					match meta {107						syn::Meta::NameValue(mnv) => match &mnv.lit {108							syn::Lit::Str(ls) => return Some(Ok(ls.value())),109							_ => unreachable!(),110						},111						_ => unreachable!(),112					}113				}114			}115			None116		})117		.collect()118}