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

difftreelog

refactor external generation of call parsers

Yaroslav Bolyukin2021-07-20parent: #99e7a93.patch.diff
in: master

4 files changed

modifiedcrates/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]
modifiedcrates/evm-coder-macros/src/solidity_interface.rsdiffbeforeafterboth
4use 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};
811
9use crate::{12use crate::{
5154
52 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 }
63
64 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 }
7166
72 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;
9792
98#[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}
387383
388pub 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();
398393
399 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;
417408
418 let call_name = pascal_ident_to_call(&name);409 let call_name = pascal_ident_to_call(&self.info.name);
419410
420 let call_sub = self411 let call_sub = self
421 .info412 .info
424 .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 = self
428 .info
429 .inline_is
430 .0
431 .iter()
432 .chain(self.info.is.0.iter())
433 .map(Is::expand_call_inner);
434 let call_parse = self418 let call_parse = self
435 .info419 .info
436 .inline_is420 .inline_is
459443
460 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 #items
507 )*
508 #(
509 #call_inner
510 )*
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 calls
515 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;
modifiedcrates/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)]
modifiedcrates/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!()
+    }
 }