From f3ac592dce906441e538a6ba37e91c851c975fd9 Mon Sep 17 00:00:00 2001 From: Yaroslav Bolyukin Date: Tue, 20 Jul 2021 18:46:11 +0000 Subject: [PATCH] refactor: external generation of call parsers --- --- 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] --- a/crates/evm-coder-macros/src/solidity_interface.rs +++ b/crates/evm-coder-macros/src/solidity_interface.rs @@ -4,7 +4,10 @@ use darling::FromMeta; use inflector::cases; use std::fmt::Write; -use syn::{FnArg, Ident, ItemTrait, Meta, NestedMeta, PatType, Path, ReturnType, TraitItem, TraitItemMethod, Type, Visibility, spanned::Spanned}; +use syn::{ + FnArg, Ident, ImplItem, ImplItemMethod, ItemImpl, Meta, NestedMeta, PatType, Path, ReturnType, + Type, spanned::Spanned, +}; use crate::{ fn_selector_str, parse_ident_from_pat, parse_ident_from_path, parse_ident_from_type, @@ -51,21 +54,13 @@ fn expand_variant_call(&self) -> proc_macro2::TokenStream { let name = &self.name; - let snake_call_name = &self.snake_call_name; + let pascal_call_name = &self.pascal_call_name; quote! { - InternalCall::#name(call) => return self.#snake_call_name(Msg { + InternalCall::#name(call) => return >::call(self, Msg { call, caller: c.caller, value: c.value, }) - } - } - - fn expand_call_inner(&self) -> proc_macro2::TokenStream { - let snake_call_name = &self.snake_call_name; - let pascal_call_name = &self.pascal_call_name; - quote! { - fn #snake_call_name(&mut self, c: Msg<#pascal_call_name>) -> Result<::evm_coder::abi::AbiWriter>; } } @@ -97,6 +92,7 @@ #[derive(FromMeta)] pub struct InterfaceInfo { + name: Ident, #[darling(default)] is: IsList, #[darling(default)] @@ -192,7 +188,7 @@ result: Type, } impl Method { - fn try_from(value: &TraitItemMethod) -> syn::Result { + fn try_from(value: &ImplItemMethod) -> syn::Result { let mut info = MethodInfo { rename_selector: None, }; @@ -386,36 +382,31 @@ } pub struct SolidityInterface { - vis: Visibility, - name: Ident, + name: Box, + ident: Ident, info: InterfaceInfo, methods: Vec, - items: Vec, } impl SolidityInterface { - pub fn try_from(info: InterfaceInfo, value: &ItemTrait) -> syn::Result { + pub fn try_from(info: InterfaceInfo, value: &ItemImpl) -> syn::Result { let mut methods = Vec::new(); for item in &value.items { - match item { - TraitItem::Method(method) => methods.push(Method::try_from(method)?), - _ => {} + if let ImplItem::Method(method) = item { + methods.push(Method::try_from(method)?) } } Ok(Self { - vis: value.vis.clone(), - name: value.ident.clone(), + name: value.self_ty.clone(), + ident: parse_ident_from_type(&value.self_ty)?.clone(), info, methods, - items: value.items.clone(), }) } pub fn expand(self) -> proc_macro2::TokenStream { - let vis = self.vis; let name = self.name; - let items = self.items; - let call_name = pascal_ident_to_call(&name); + let call_name = pascal_ident_to_call(&self.info.name); let call_sub = self .info @@ -424,13 +415,6 @@ .iter() .chain(self.info.is.0.iter()) .map(Is::expand_call_def); - let call_inner = self - .info - .inline_is - .0 - .iter() - .chain(self.info.is.0.iter()) - .map(Is::expand_call_inner); let call_parse = self .info .inline_is @@ -459,7 +443,7 @@ quote! { #[derive(Debug)] - #vis enum #call_name { + pub enum #call_name { #( #calls, )* @@ -486,7 +470,7 @@ ) } } - impl ::evm_coder::Call for #call_name { + impl ::evm_coder::Call for #call_name { fn parse(method_id: u32, reader: &mut ::evm_coder::abi::AbiReader) -> ::evm_coder::execution::Result> { use ::evm_coder::abi::AbiRead; match method_id { @@ -500,17 +484,8 @@ )else* return Ok(None); } - } - #vis trait #name { - #( - #items - )* - #( - #call_inner - )* } - impl ::evm_coder::Callable for T where T: #name { - type Call = #call_name; + impl ::evm_coder::Callable<#call_name> for #name { #[allow(unreachable_code)] // In case of no inner calls fn call(&mut self, c: Msg<#call_name>) -> Result<::evm_coder::abi::AbiWriter> { use ::evm_coder::abi::AbiWrite; @@ -530,7 +505,7 @@ } Ok(writer) } - } + } } } } --- 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>; } -pub trait Callable { - type Call: Call; - fn call(&mut self, call: types::Msg) -> execution::Result; +pub trait Callable { + fn call(&mut self, call: types::Msg) -> execution::Result; } #[cfg(test)] --- 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; +struct Impls; + +#[solidity_interface(name = "OurInterface")] +impl Impls { + fn fn_a(&self, input: uint256) -> Result { + todo!() + } } -#[solidity_interface] -trait OurInterface1 { - fn fn_b(&self, input: uint128) -> Result; +#[solidity_interface(name = "OurInterface1")] +impl Impls { + fn fn_b(&self, input: uint128) -> Result { + 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; - fn fn_d(&self, value: uint32) -> Result; + fn fn_c(&self, input: uint32) -> Result { + todo!() + } + fn fn_d(&self, value: uint32) -> Result { + todo!() + } - fn caller_sensitive(&self, caller: caller) -> Result; - fn payable(&mut self, value: value) -> Result; + fn caller_sensitive(&self, caller: caller) -> Result { + todo!() + } + fn payable(&mut self, value: value) -> Result { + todo!() + } } #[derive(ToLog)] @@ -39,18 +53,32 @@ }, } -#[solidity_interface] -trait ERC20 { - fn decimals(&self) -> Result; - fn balance_of(&self, owner: address) -> Result; - fn transfer(&mut self, caller: caller, to: address, value: uint256) -> Result; +struct ERC20; + +#[solidity_interface(name = "ERC20")] +impl ERC20 { + fn decimals(&self) -> Result { + todo!() + } + fn balance_of(&self, owner: address) -> Result { + todo!() + } + fn transfer(&mut self, caller: caller, to: address, value: uint256) -> Result { + todo!() + } fn transfer_from( &mut self, caller: caller, from: address, to: address, value: uint256, - ) -> Result; - fn approve(&mut self, caller: caller, spender: address, value: uint256) -> Result; - fn allowance(&self, owner: address, spender: address) -> Result; + ) -> Result { + todo!() + } + fn approve(&mut self, caller: caller, spender: address, value: uint256) -> Result { + todo!() + } + fn allowance(&self, owner: address, spender: address) -> Result { + todo!() + } } -- gitstuff