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

difftreelog

source

crates/evm-coder/procedural/src/abi_derive/mod.rs3.5 KiBsourcehistory
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}