difftreelog
refactor external generation of call parsers
in: master
4 files changed
crates/evm-coder-macros/src/lib.rsdiffbeforeafterboth--- a/crates/evm-coder-macros/src/lib.rs
+++ b/crates/evm-coder-macros/src/lib.rs
@@ -5,10 +5,7 @@
use proc_macro::TokenStream;
use quote::quote;
use sha3::{Digest, Keccak256};
-use syn::{
- AttributeArgs, DeriveInput, GenericArgument, Ident, ItemTrait, Pat, Path, PathArguments,
- PathSegment, Type, parse_macro_input, spanned::Spanned,
-};
+use syn::{AttributeArgs, DeriveInput, GenericArgument, Ident, ItemImpl, Pat, Path, PathArguments, PathSegment, Type, parse_macro_input, spanned::Spanned};
mod solidity_interface;
mod to_log;
@@ -189,16 +186,21 @@
let args = parse_macro_input!(args as AttributeArgs);
let args = solidity_interface::InterfaceInfo::from_list(&args).unwrap();
- let input: ItemTrait = match syn::parse(stream) {
+ let input: ItemImpl = match syn::parse(stream) {
Ok(t) => t,
Err(e) => return e.to_compile_error().into(),
};
- match solidity_interface::SolidityInterface::try_from(args, &input) {
+ let expanded = match solidity_interface::SolidityInterface::try_from(args, &input) {
Ok(v) => v.expand(),
Err(e) => e.to_compile_error(),
- }
- .into()
+ };
+
+ (quote! {
+ #input
+
+ #expanded
+ }).into()
}
#[proc_macro_attribute]
crates/evm-coder-macros/src/solidity_interface.rsdiffbeforeafterboth4use darling::FromMeta;4use darling::FromMeta;5use inflector::cases;5use inflector::cases;6use std::fmt::Write;6use std::fmt::Write;7use syn::{FnArg, Ident, ItemTrait, Meta, NestedMeta, PatType, Path, ReturnType, TraitItem, TraitItemMethod, Type, Visibility, spanned::Spanned};7use syn::{8 FnArg, Ident, ImplItem, ImplItemMethod, ItemImpl, Meta, NestedMeta, PatType, Path, ReturnType,9 Type, spanned::Spanned,10};8119use crate::{12use crate::{515452 fn expand_variant_call(&self) -> proc_macro2::TokenStream {55 fn expand_variant_call(&self) -> proc_macro2::TokenStream {53 let name = &self.name;56 let name = &self.name;54 let snake_call_name = &self.snake_call_name;57 let pascal_call_name = &self.pascal_call_name;55 quote! {58 quote! {56 InternalCall::#name(call) => return self.#snake_call_name(Msg {59 InternalCall::#name(call) => return <Self as ::evm_coder::Callable<#pascal_call_name>>::call(self, Msg {57 call,60 call,58 caller: c.caller,61 caller: c.caller,59 value: c.value,62 value: c.value,60 })63 })61 }64 }62 }65 }6364 fn expand_call_inner(&self) -> proc_macro2::TokenStream {65 let snake_call_name = &self.snake_call_name;66 let pascal_call_name = &self.pascal_call_name;67 quote! {68 fn #snake_call_name(&mut self, c: Msg<#pascal_call_name>) -> Result<::evm_coder::abi::AbiWriter>;69 }70 }716672 fn expand_parse(&self) -> proc_macro2::TokenStream {67 fn expand_parse(&self) -> proc_macro2::TokenStream {73 let name = &self.name;68 let name = &self.name;979298#[derive(FromMeta)]93#[derive(FromMeta)]99pub struct InterfaceInfo {94pub struct InterfaceInfo {95 name: Ident,100 #[darling(default)]96 #[darling(default)]101 is: IsList,97 is: IsList,102 #[darling(default)]98 #[darling(default)]192 result: Type,188 result: Type,193}189}194impl Method {190impl Method {195 fn try_from(value: &TraitItemMethod) -> syn::Result<Self> {191 fn try_from(value: &ImplItemMethod) -> syn::Result<Self> {196 let mut info = MethodInfo {192 let mut info = MethodInfo {197 rename_selector: None,193 rename_selector: None,198 };194 };386}382}387383388pub struct SolidityInterface {384pub struct SolidityInterface {389 vis: Visibility,385 name: Box<syn::Type>,390 name: Ident,386 ident: Ident,391 info: InterfaceInfo,387 info: InterfaceInfo,392 methods: Vec<Method>,388 methods: Vec<Method>,393 items: Vec<TraitItem>,394}389}395impl SolidityInterface {390impl SolidityInterface {396 pub fn try_from(info: InterfaceInfo, value: &ItemTrait) -> syn::Result<Self> {391 pub fn try_from(info: InterfaceInfo, value: &ItemImpl) -> syn::Result<Self> {397 let mut methods = Vec::new();392 let mut methods = Vec::new();398393399 for item in &value.items {394 for item in &value.items {400 match item {395 if let ImplItem::Method(method) = item {401 TraitItem::Method(method) => methods.push(Method::try_from(method)?),396 methods.push(Method::try_from(method)?)402 _ => {}403 }397 }404 }398 }405 Ok(Self {399 Ok(Self {406 vis: value.vis.clone(),400 name: value.self_ty.clone(),407 name: value.ident.clone(),401 ident: parse_ident_from_type(&value.self_ty)?.clone(),408 info,402 info,409 methods,403 methods,410 items: value.items.clone(),411 })404 })412 }405 }413 pub fn expand(self) -> proc_macro2::TokenStream {406 pub fn expand(self) -> proc_macro2::TokenStream {414 let vis = self.vis;415 let name = self.name;407 let name = self.name;416 let items = self.items;417408418 let call_name = pascal_ident_to_call(&name);409 let call_name = pascal_ident_to_call(&self.info.name);419410420 let call_sub = self411 let call_sub = self421 .info412 .info424 .iter()415 .iter()425 .chain(self.info.is.0.iter())416 .chain(self.info.is.0.iter())426 .map(Is::expand_call_def);417 .map(Is::expand_call_def);427 let call_inner = self428 .info429 .inline_is430 .0431 .iter()432 .chain(self.info.is.0.iter())433 .map(Is::expand_call_inner);434 let call_parse = self418 let call_parse = self435 .info419 .info436 .inline_is420 .inline_is459443460 quote! {444 quote! {461 #[derive(Debug)]445 #[derive(Debug)]462 #vis enum #call_name {446 pub enum #call_name {463 #(447 #(464 #calls,448 #calls,465 )*449 )*501 return Ok(None);485 return Ok(None);502 }486 }503 }487 }504 #vis trait #name {505 #(506 #items507 )*508 #(509 #call_inner510 )*511 }512 impl<T> ::evm_coder::Callable for T where T: #name {488 impl ::evm_coder::Callable<#call_name> for #name {513 type Call = #call_name;514 #[allow(unreachable_code)] // In case of no inner calls489 #[allow(unreachable_code)] // In case of no inner calls515 fn call(&mut self, c: Msg<#call_name>) -> Result<::evm_coder::abi::AbiWriter> {490 fn call(&mut self, c: Msg<#call_name>) -> Result<::evm_coder::abi::AbiWriter> {516 use ::evm_coder::abi::AbiWrite;491 use ::evm_coder::abi::AbiWrite;crates/evm-coder/src/lib.rsdiffbeforeafterboth--- a/crates/evm-coder/src/lib.rs
+++ b/crates/evm-coder/src/lib.rs
@@ -57,9 +57,8 @@
fn parse(selector: u32, input: &mut AbiReader) -> execution::Result<Option<Self>>;
}
-pub trait Callable {
- type Call: Call;
- fn call(&mut self, call: types::Msg<Self::Call>) -> execution::Result<AbiWriter>;
+pub trait Callable<C: Call> {
+ fn call(&mut self, call: types::Msg<C>) -> execution::Result<AbiWriter>;
}
#[cfg(test)]
crates/evm-coder/tests/a.rsdiffbeforeafterboth--- a/crates/evm-coder/tests/a.rs
+++ b/crates/evm-coder/tests/a.rs
@@ -3,24 +3,38 @@
use evm_coder::{solidity_interface, types::*, ToLog, execution::Result};
use evm_coder_macros::solidity;
-#[solidity_interface]
-trait OurInterface {
- fn fn_a(&self, input: uint256) -> Result<bool>;
+struct Impls;
+
+#[solidity_interface(name = "OurInterface")]
+impl Impls {
+ fn fn_a(&self, input: uint256) -> Result<bool> {
+ todo!()
+ }
}
-#[solidity_interface]
-trait OurInterface1 {
- fn fn_b(&self, input: uint128) -> Result<uint32>;
+#[solidity_interface(name = "OurInterface1")]
+impl Impls {
+ fn fn_b(&self, input: uint128) -> Result<uint32> {
+ todo!()
+ }
}
-#[solidity_interface(is(OurInterface), inline_is(OurInterface1), events(ERC721Log))]
-trait OurInterface2 {
+#[solidity_interface(name = "OurInterface2", is(OurInterface), inline_is(OurInterface1), events(ERC721Log))]
+impl Impls {
#[solidity(rename_selector = "fnK")]
- fn fn_c(&self, input: uint32) -> Result<uint8>;
- fn fn_d(&self, value: uint32) -> Result<uint32>;
+ fn fn_c(&self, input: uint32) -> Result<uint8> {
+ todo!()
+ }
+ fn fn_d(&self, value: uint32) -> Result<uint32> {
+ todo!()
+ }
- fn caller_sensitive(&self, caller: caller) -> Result<uint8>;
- fn payable(&mut self, value: value) -> Result<uint8>;
+ fn caller_sensitive(&self, caller: caller) -> Result<uint8> {
+ todo!()
+ }
+ fn payable(&mut self, value: value) -> Result<uint8> {
+ todo!()
+ }
}
#[derive(ToLog)]
@@ -39,18 +53,32 @@
},
}
-#[solidity_interface]
-trait ERC20 {
- fn decimals(&self) -> Result<uint8>;
- fn balance_of(&self, owner: address) -> Result<uint256>;
- fn transfer(&mut self, caller: caller, to: address, value: uint256) -> Result<bool>;
+struct ERC20;
+
+#[solidity_interface(name = "ERC20")]
+impl ERC20 {
+ fn decimals(&self) -> Result<uint8> {
+ todo!()
+ }
+ fn balance_of(&self, owner: address) -> Result<uint256> {
+ todo!()
+ }
+ fn transfer(&mut self, caller: caller, to: address, value: uint256) -> Result<bool> {
+ todo!()
+ }
fn transfer_from(
&mut self,
caller: caller,
from: address,
to: address,
value: uint256,
- ) -> Result<bool>;
- fn approve(&mut self, caller: caller, spender: address, value: uint256) -> Result<bool>;
- fn allowance(&self, owner: address, spender: address) -> Result<uint256>;
+ ) -> Result<bool> {
+ todo!()
+ }
+ fn approve(&mut self, caller: caller, spender: address, value: uint256) -> Result<bool> {
+ todo!()
+ }
+ fn allowance(&self, owner: address, spender: address) -> Result<uint256> {
+ todo!()
+ }
}