difftreelog
feat generate solidity and abi traits for enums
in: master
3 files changed
crates/evm-coder/procedural/src/abi_derive.rsdiffbeforeafterboth44 let struct_from_tuple = struct_from_tuple(name, is_named_fields, field_names.clone());44 let struct_from_tuple = struct_from_tuple(name, is_named_fields, field_names.clone());454546 let can_be_plcaed_in_vec = impl_can_be_placed_in_vec(name);46 let can_be_plcaed_in_vec = impl_can_be_placed_in_vec(name);47 let abi_type = impl_abi_type(name, tuple_type.clone());47 let abi_type = impl_struct_abi_type(name, tuple_type.clone());48 let abi_read = impl_abi_read(name, tuple_type, tuple_names, struct_from_tuple);48 let abi_read = impl_struct_abi_read(name, tuple_type, tuple_names, struct_from_tuple);49 let abi_write = impl_abi_write(name, is_named_fields, tuple_ref_type, tuple_data);49 let abi_write = impl_struct_abi_write(name, is_named_fields, tuple_ref_type, tuple_data);50 let solidity_type = impl_solidity_type(name, field_types.clone(), params_count);50 let solidity_type = impl_struct_solidity_type(name, field_types.clone(), params_count);51 let solidity_type_name = impl_solidity_type_name(name, field_types.clone(), params_count);51 let solidity_type_name =52 impl_struct_solidity_type_name(name, field_types.clone(), params_count);52 let solidity_struct_collect =53 let solidity_struct_collect =53 impl_solidity_struct_collect(name, field_names, field_types, field_docs, &docs)?;54 impl_struct_solidity_struct_collect(name, field_names, field_types, field_docs, &docs)?;545555 Ok(quote! {56 Ok(quote! {56 #can_be_plcaed_in_vec57 #can_be_plcaed_in_vec69) -> syn::Result<proc_macro2::TokenStream> {70) -> syn::Result<proc_macro2::TokenStream> {70 let name = &ast.ident;71 let name = &ast.ident;71 check_repr_u8(name, &ast.attrs)?;72 check_repr_u8(name, &ast.attrs)?;72 check_option_validity(de)?;73 let option_count = check_and_count_option(de)?;7374 dbg!(&de);74 let enum_options = de.variants.iter().map(|v| &v.ident);7576 let from = impl_enum_from_u8(name, enum_options.clone());77 let solidity_option = impl_solidity_option(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, enum_options.clone());83 let solidity_struct_collect =84 impl_enum_solidity_struct_collect(name, enum_options, option_count);758576 Ok(quote!())86 Ok(quote! {87 #from88 #solidity_option89 #can_be_plcaed_in_vec90 #abi_type91 #abi_read92 #abi_write93 #solidity_type_name94 #solidity_struct_collect95 })77}96}9798fn impl_solidity_option<'a>(99 name: &proc_macro2::Ident,100 enum_options: impl Iterator<Item = &'a syn::Ident>,101) -> proc_macro2::TokenStream {102 let enum_options = enum_options.map(|opt| {103 let s = name.to_string() + "." + opt.to_string().as_str();104 let as_string = proc_macro2::Literal::string(s.as_str());105 quote!(#name::#opt => #as_string,)106 });107 quote!(108 impl ::evm_coder::solidity::SolidityEnum for #name {109 fn solidity_option(&self) -> &str {110 match <#name>::default() {111 #(#enum_options)*112 }113 }114 }115 )116}117118fn impl_enum_from_u8<'a>(119 name: &proc_macro2::Ident,120 enum_options: impl Iterator<Item = &'a syn::Ident>,121) -> proc_macro2::TokenStream {122 let enum_options = enum_options.enumerate().map(|(i, opt)| {123 let n = proc_macro2::Literal::u8_suffixed(i as u8);124 quote! {#n => Ok(#name::#opt),}125 });126 quote!(127 impl TryFrom<u8> for #name {128 type Error = &'static str;129130 fn try_from(value: u8) -> ::std::result::Result<Self, Self::Error> {131 const err: &'static str = "Not convertible";132 match value {133 #(#enum_options)*134 _ => Err(err)135 }136 }137 }138 )139}140141fn impl_enum_abi_type(name: &syn::Ident) -> proc_macro2::TokenStream {142 quote! {143 impl ::evm_coder::abi::AbiType for #name {144 const SIGNATURE: ::evm_coder::custom_signature::SignatureUnit = <u8 as ::evm_coder::abi::AbiType>::SIGNATURE;145146 fn is_dynamic() -> bool {147 <u8 as ::evm_coder::abi::AbiType>::is_dynamic()148 }149 fn size() -> usize {150 <u8 as ::evm_coder::abi::AbiType>::size()151 }152 }153 }154}155156fn impl_enum_abi_read(name: &syn::Ident) -> proc_macro2::TokenStream {157 quote!(158 impl ::evm_coder::abi::AbiRead for #name {159 fn abi_read(reader: &mut ::evm_coder::abi::AbiReader) -> ::evm_coder::execution::Result<Self> {160 Ok(161 <u8 as ::evm_coder::abi::AbiRead>::abi_read(reader)?162 .try_into()?163 )164 }165 }166 )167}168169fn impl_enum_abi_write(name: &syn::Ident) -> proc_macro2::TokenStream {170 quote!(171 impl ::evm_coder::abi::AbiWrite for #name {172 fn abi_write(&self, writer: &mut ::evm_coder::abi::AbiWriter) {173 ::evm_coder::abi::AbiWrite::abi_write(&(*self as u8), writer);174 }175 }176 )177}178179fn impl_enum_solidity_type_name<'a>(180 name: &syn::Ident,181 enum_options: impl Iterator<Item = &'a syn::Ident>,182) -> proc_macro2::TokenStream {183 let enum_options = enum_options.map(|opt| quote!(,));184 quote!(185 #[cfg(feature = "stubgen")]186 impl ::evm_coder::solidity::SolidityTypeName for #name {187 fn solidity_name(188 writer: &mut impl ::core::fmt::Write,189 tc: &::evm_coder::solidity::TypeCollector,190 ) -> ::core::fmt::Result {191 write!(writer, "{}", tc.collect_struct::<Self>())192 }193194 fn is_simple() -> bool {195 true196 }197198 fn solidity_default(199 writer: &mut impl ::core::fmt::Write,200 tc: &::evm_coder::solidity::TypeCollector,201 ) -> ::core::fmt::Result {202 write!(writer, "{}", <#name as ::evm_coder::solidity::SolidityEnum>::solidity_option(&<#name>::default()))203 }204 }205 )206}207208fn impl_enum_solidity_struct_collect<'a>(209 name: &syn::Ident,210 enum_options: impl Iterator<Item = &'a syn::Ident>,211 option_count: usize,212) -> proc_macro2::TokenStream {213 let string_name = name.to_string();214 let enum_options = enum_options.enumerate().map(|(i, opt)| {215 let opt = proc_macro2::Literal::string(opt.to_string().as_str());216 let comma = if i != option_count - 1 { "," } else { "" };217 quote! {218 writeln!(str, "\t{}{}", #opt, #comma).expect("Enum format option");219 }220 });221 quote!(222 #[cfg(feature = "stubgen")]223 impl ::evm_coder::solidity::StructCollect for #name {224 fn name() -> String {225 #string_name.into()226 }227228 fn declaration() -> String {229 use std::fmt::Write;230231 let mut str = String::new();232 // #(#docs)*233 writeln!(str, "enum {} {{", <Self as ::evm_coder::solidity::StructCollect>::name()).unwrap();234 #(#enum_options)*235 writeln!(str, "}}").unwrap();236 str237 }238 }239 )240}7824179fn check_option_validity(de: &syn::DataEnum) -> syn::Result<()> {242fn check_and_count_option(de: &syn::DataEnum) -> syn::Result<usize> {243 let mut count = 0;80 for error in de.variants.iter().filter_map(|v| {244 for error in de.variants.iter().filter_map(|v| {81 if !v.fields.is_empty() {245 if !v.fields.is_empty() {82 Some(Err(syn::Error::new(246 Some(Err(syn::Error::new(89 "Enumeration options should not have an explicit specified value",253 "Enumeration options should not have an explicit specified value",90 )))254 )))91 } else {255 } else {256 count += 1;92 None257 None93 }258 }94 }) {259 }) {95 return error;260 return error;96 }261 }9726298 Ok(())263 Ok(count)99}264}100265101fn check_repr_u8(name: &syn::Ident, attrs: &Vec<syn::Attribute>) -> syn::Result<()> {266fn check_repr_u8(name: &syn::Ident, attrs: &Vec<syn::Attribute>) -> syn::Result<()> {271 }436 }272}437}273438274fn impl_abi_type(439fn impl_struct_abi_type(275 name: &syn::Ident,440 name: &syn::Ident,276 tuple_type: proc_macro2::TokenStream,441 tuple_type: proc_macro2::TokenStream,277) -> proc_macro2::TokenStream {442) -> proc_macro2::TokenStream {288 }453 }289}454}290455291fn impl_abi_read(456fn impl_struct_abi_read(292 name: &syn::Ident,457 name: &syn::Ident,293 tuple_type: proc_macro2::TokenStream,458 tuple_type: proc_macro2::TokenStream,294 tuple_names: proc_macro2::TokenStream,459 tuple_names: proc_macro2::TokenStream,304 )469 )305}470}306471307fn impl_abi_write(472fn impl_struct_abi_write(308 name: &syn::Ident,473 name: &syn::Ident,309 _is_named_fields: bool,474 _is_named_fields: bool,310 tuple_type: proc_macro2::TokenStream,475 tuple_type: proc_macro2::TokenStream,319 )484 )320}485}321486322fn impl_solidity_type<'a>(487fn impl_struct_solidity_type<'a>(323 name: &syn::Ident,488 name: &syn::Ident,324 field_types: impl Iterator<Item = &'a syn::Type> + Clone,489 field_types: impl Iterator<Item = &'a syn::Type> + Clone,325 params_count: usize,490 params_count: usize,347 }512 }348}513}349514350fn impl_solidity_type_name<'a>(515fn impl_struct_solidity_type_name<'a>(351 name: &syn::Ident,516 name: &syn::Ident,352 field_types: impl Iterator<Item = &'a syn::Type> + Clone,517 field_types: impl Iterator<Item = &'a syn::Type> + Clone,353 params_count: usize,518 params_count: usize,390 }555 }391}556}392557393fn impl_solidity_struct_collect<'a>(558fn impl_struct_solidity_struct_collect<'a>(394 name: &syn::Ident,559 name: &syn::Ident,395 field_names: impl Iterator<Item = proc_macro2::Ident> + Clone,560 field_names: impl Iterator<Item = proc_macro2::Ident> + Clone,396 field_types: impl Iterator<Item = &'a syn::Type> + Clone,561 field_types: impl Iterator<Item = &'a syn::Type> + Clone,crates/evm-coder/src/solidity/traits.rsdiffbeforeafterboth--- a/crates/evm-coder/src/solidity/traits.rs
+++ b/crates/evm-coder/src/solidity/traits.rs
@@ -8,6 +8,10 @@
fn declaration() -> String;
}
+pub trait SolidityEnum: 'static {
+ fn solidity_option(&self) -> &str;
+}
+
pub trait SolidityTypeName: 'static {
fn solidity_name(writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result;
/// "simple" types are stored inline, no `memory` modifier should be used in solidity
crates/evm-coder/tests/abi_derive_generation.rsdiffbeforeafterboth--- a/crates/evm-coder/tests/abi_derive_generation.rs
+++ b/crates/evm-coder/tests/abi_derive_generation.rs
@@ -75,7 +75,7 @@
#[test]
#[cfg(feature = "stubgen")]
- fn struct_collect_TypeStruct3DerivedMixedParam() {
+ fn struct_collect_type_struct3_derived_mixed_param() {
assert_eq!(
<TypeStruct3DerivedMixedParam as ::evm_coder::solidity::StructCollect>::name(),
"TypeStruct3DerivedMixedParam"
@@ -296,7 +296,7 @@
#[test]
#[cfg(feature = "stubgen")]
- fn struct_collect_TupleStruct3DerivedMixedParam() {
+ fn struct_collect_tuple_struct3_derived_mixed_param() {
assert_eq!(
<TupleStruct3DerivedMixedParam as ::evm_coder::solidity::StructCollect>::name(),
"TupleStruct3DerivedMixedParam"
@@ -739,11 +739,12 @@
mod test_enum {
use evm_coder::AbiCoder;
- #[derive(AbiCoder)]
+ #[derive(AbiCoder, Default)]
#[repr(u8)]
enum Color {
Red,
Green,
+ #[default]
Blue,
}