feat: detect ethers crate paths in derive macros (#366)
* feat: determine ethers crate name using metadata * use crate detection
This commit is contained in:
parent
9d38d1a412
commit
b0b4f4e09e
|
@ -328,6 +328,37 @@ dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "camino"
|
||||||
|
version = "1.0.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "52d74260d9bf6944e2208aa46841b4b8f0d7ffc0849a06837b2f510337f86b2b"
|
||||||
|
dependencies = [
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cargo-platform"
|
||||||
|
version = "0.1.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cbdb825da8a5df079a43676dbe042702f1707b1109f713a01420fbb4cc71fa27"
|
||||||
|
dependencies = [
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cargo_metadata"
|
||||||
|
version = "0.14.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c297bd3135f558552f99a0daa180876984ea2c4ffa7470314540dff8c654109a"
|
||||||
|
dependencies = [
|
||||||
|
"camino",
|
||||||
|
"cargo-platform",
|
||||||
|
"semver",
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cc"
|
name = "cc"
|
||||||
version = "1.0.68"
|
version = "1.0.68"
|
||||||
|
@ -808,8 +839,10 @@ version = "0.4.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"Inflector",
|
"Inflector",
|
||||||
"anyhow",
|
"anyhow",
|
||||||
|
"cargo_metadata",
|
||||||
"ethers-core",
|
"ethers-core",
|
||||||
"hex",
|
"hex",
|
||||||
|
"once_cell",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"reqwest",
|
"reqwest",
|
||||||
|
@ -2307,6 +2340,9 @@ name = "semver"
|
||||||
version = "1.0.4"
|
version = "1.0.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "568a8e6258aa33c13358f81fd834adb854c6f7c9468520910a9b1e8fac068012"
|
checksum = "568a8e6258aa33c13358f81fd834adb854c6f7c9468520910a9b1e8fac068012"
|
||||||
|
dependencies = [
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde"
|
name = "serde"
|
||||||
|
|
|
@ -21,6 +21,8 @@ url = "2.1"
|
||||||
serde_json = "1.0.61"
|
serde_json = "1.0.61"
|
||||||
hex = { version = "0.4.2", default-features = false, features = ["std"] }
|
hex = { version = "0.4.2", default-features = false, features = ["std"] }
|
||||||
reqwest = { version = "0.11.3", features = ["blocking"] }
|
reqwest = { version = "0.11.3", features = ["blocking"] }
|
||||||
|
once_cell = { version = "1.8.0", default-features = false }
|
||||||
|
cargo_metadata = "0.14.0"
|
||||||
|
|
||||||
[package.metadata.docs.rs]
|
[package.metadata.docs.rs]
|
||||||
all-features = true
|
all-features = true
|
||||||
|
|
|
@ -21,7 +21,7 @@ mod util;
|
||||||
|
|
||||||
pub use ethers_core::types::Address;
|
pub use ethers_core::types::Address;
|
||||||
pub use source::Source;
|
pub use source::Source;
|
||||||
pub use util::parse_address;
|
pub use util::{ethers_contract_crate, ethers_core_crate, parse_address};
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use proc_macro2::TokenStream;
|
use proc_macro2::TokenStream;
|
||||||
|
|
|
@ -1,11 +1,59 @@
|
||||||
use ethers_core::types::Address;
|
use ethers_core::types::Address;
|
||||||
|
|
||||||
use anyhow::{anyhow, Result};
|
use anyhow::{anyhow, Result};
|
||||||
|
use cargo_metadata::{CargoOpt, DependencyKind, Metadata, MetadataCommand};
|
||||||
use inflector::Inflector;
|
use inflector::Inflector;
|
||||||
|
use once_cell::sync::Lazy;
|
||||||
use proc_macro2::{Ident, Literal, Span, TokenStream};
|
use proc_macro2::{Ident, Literal, Span, TokenStream};
|
||||||
use quote::quote;
|
use quote::quote;
|
||||||
use reqwest::Client;
|
use reqwest::Client;
|
||||||
use syn::Ident as SynIdent;
|
use syn::{Ident as SynIdent, Path};
|
||||||
|
|
||||||
|
/// See `determine_ethers_crates`
|
||||||
|
///
|
||||||
|
/// This ensures that the `MetadataCommand` is only run once
|
||||||
|
static ETHERS_CRATES: Lazy<(&'static str, &'static str)> = Lazy::new(determine_ethers_crates);
|
||||||
|
|
||||||
|
/// Convenience function to turn the `ethers_core` name in `ETHERS_CRATE` into a `Path`
|
||||||
|
pub fn ethers_core_crate() -> Path {
|
||||||
|
syn::parse_str(ETHERS_CRATES.0).expect("valid path; qed")
|
||||||
|
}
|
||||||
|
/// Convenience function to turn the `ethers_contract` name in `ETHERS_CRATE` into an `Path`
|
||||||
|
pub fn ethers_contract_crate() -> Path {
|
||||||
|
syn::parse_str(ETHERS_CRATES.1).expect("valid path; qed")
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The crates name to use when deriving macros: (`core`, `contract`)
|
||||||
|
///
|
||||||
|
/// We try to determine which crate ident to use based on the dependencies of
|
||||||
|
/// the project in which the macro is used. This is useful because the macros,
|
||||||
|
/// like `EthEvent` are provided by the `ethers-contract` crate which depends on
|
||||||
|
/// `ethers_core`. Most commonly `ethers` will be used as dependency which
|
||||||
|
/// reexports all the different crates, essentially `ethers::core` is
|
||||||
|
/// `ethers_core` So depending on the dependency used `ethers` ors `ethers_core
|
||||||
|
/// | ethers_contract`, we need to use the fitting crate ident when expand the
|
||||||
|
/// macros This will attempt to parse the current `Cargo.toml` and check the
|
||||||
|
/// ethers related dependencies.
|
||||||
|
pub fn determine_ethers_crates() -> (&'static str, &'static str) {
|
||||||
|
MetadataCommand::new()
|
||||||
|
.manifest_path(&format!(
|
||||||
|
"{}/Cargo.toml",
|
||||||
|
std::env::var("CARGO_MANIFEST_DIR").expect("No Manifest found")
|
||||||
|
))
|
||||||
|
.exec()
|
||||||
|
.ok()
|
||||||
|
.and_then(|metadata| {
|
||||||
|
metadata.root_package().and_then(|pkg| {
|
||||||
|
pkg.dependencies
|
||||||
|
.iter()
|
||||||
|
.filter(|dep| dep.kind == DependencyKind::Normal)
|
||||||
|
.find_map(|dep| {
|
||||||
|
(dep.name == "ethers").then(|| ("ethers::core", "ethers::contract"))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.unwrap_or(("ethers_core", "ethers_contract"))
|
||||||
|
}
|
||||||
|
|
||||||
/// Expands a identifier string into an token.
|
/// Expands a identifier string into an token.
|
||||||
pub fn ident(name: &str) -> Ident {
|
pub fn ident(name: &str) -> Ident {
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
//! ethereum smart contract.
|
//! ethereum smart contract.
|
||||||
#![deny(missing_docs, unsafe_code)]
|
#![deny(missing_docs, unsafe_code)]
|
||||||
|
|
||||||
use ethers_contract_abigen::Source;
|
use ethers_contract_abigen::{ethers_contract_crate, ethers_core_crate, Source};
|
||||||
use proc_macro::TokenStream;
|
use proc_macro::TokenStream;
|
||||||
use proc_macro2::{Literal, Span};
|
use proc_macro2::{Literal, Span};
|
||||||
use quote::{quote, quote_spanned};
|
use quote::{quote, quote_spanned};
|
||||||
|
@ -117,6 +117,11 @@ pub fn abigen(input: TokenStream) -> TokenStream {
|
||||||
#[proc_macro_derive(EthEvent, attributes(ethevent))]
|
#[proc_macro_derive(EthEvent, attributes(ethevent))]
|
||||||
pub fn derive_abi_event(input: TokenStream) -> TokenStream {
|
pub fn derive_abi_event(input: TokenStream) -> TokenStream {
|
||||||
let input = parse_macro_input!(input as DeriveInput);
|
let input = parse_macro_input!(input as DeriveInput);
|
||||||
|
|
||||||
|
// the ethers crates to use
|
||||||
|
let core_crate = ethers_core_crate();
|
||||||
|
let contract_crate = ethers_contract_crate();
|
||||||
|
|
||||||
let name = &input.ident;
|
let name = &input.ident;
|
||||||
let attributes = match parse_attributes(&input) {
|
let attributes = match parse_attributes(&input) {
|
||||||
Ok(attributes) => attributes,
|
Ok(attributes) => attributes,
|
||||||
|
@ -206,13 +211,13 @@ pub fn derive_abi_event(input: TokenStream) -> TokenStream {
|
||||||
let anon = attributes.anonymous.map(|(b, _)| b).unwrap_or_default();
|
let anon = attributes.anonymous.map(|(b, _)| b).unwrap_or_default();
|
||||||
|
|
||||||
let ethevent_impl = quote! {
|
let ethevent_impl = quote! {
|
||||||
impl ethers_contract::EthEvent for #name {
|
impl #contract_crate::EthEvent for #name {
|
||||||
|
|
||||||
fn name() -> ::std::borrow::Cow<'static, str> {
|
fn name() -> ::std::borrow::Cow<'static, str> {
|
||||||
#event_name.into()
|
#event_name.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn signature() -> ethers_core::types::H256 {
|
fn signature() -> #core_crate::types::H256 {
|
||||||
#signature
|
#signature
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -220,7 +225,7 @@ pub fn derive_abi_event(input: TokenStream) -> TokenStream {
|
||||||
#abi.into()
|
#abi.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn decode_log(log: ðers_core::abi::RawLog) -> Result<Self, ethers_core::abi::Error> where Self: Sized {
|
fn decode_log(log: &#core_crate::abi::RawLog) -> Result<Self, #core_crate::abi::Error> where Self: Sized {
|
||||||
#decode_log_impl
|
#decode_log_impl
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -256,55 +261,57 @@ impl EventField {
|
||||||
// these indexed param types according to
|
// these indexed param types according to
|
||||||
// https://solidity.readthedocs.io/en/develop/abi-spec.html#encoding-of-indexed-event-parameters
|
// https://solidity.readthedocs.io/en/develop/abi-spec.html#encoding-of-indexed-event-parameters
|
||||||
fn topic_param_type_quote(kind: &ParamType) -> proc_macro2::TokenStream {
|
fn topic_param_type_quote(kind: &ParamType) -> proc_macro2::TokenStream {
|
||||||
|
let core_crate = ethers_core_crate();
|
||||||
match kind {
|
match kind {
|
||||||
ParamType::String
|
ParamType::String
|
||||||
| ParamType::Bytes
|
| ParamType::Bytes
|
||||||
| ParamType::Array(_)
|
| ParamType::Array(_)
|
||||||
| ParamType::FixedArray(_, _)
|
| ParamType::FixedArray(_, _)
|
||||||
| ParamType::Tuple(_) => quote! {ethers_core::abi::ParamType::FixedBytes(32)},
|
| ParamType::Tuple(_) => quote! {#core_crate::abi::ParamType::FixedBytes(32)},
|
||||||
ty => param_type_quote(ty),
|
ty => param_type_quote(ty),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn param_type_quote(kind: &ParamType) -> proc_macro2::TokenStream {
|
fn param_type_quote(kind: &ParamType) -> proc_macro2::TokenStream {
|
||||||
|
let core_crate = ethers_core_crate();
|
||||||
match kind {
|
match kind {
|
||||||
ParamType::Address => {
|
ParamType::Address => {
|
||||||
quote! {ethers_core::abi::ParamType::Address}
|
quote! {#core_crate::abi::ParamType::Address}
|
||||||
}
|
}
|
||||||
ParamType::Bytes => {
|
ParamType::Bytes => {
|
||||||
quote! {ethers_core::abi::ParamType::Bytes}
|
quote! {#core_crate::abi::ParamType::Bytes}
|
||||||
}
|
}
|
||||||
ParamType::Int(size) => {
|
ParamType::Int(size) => {
|
||||||
let size = Literal::usize_suffixed(*size);
|
let size = Literal::usize_suffixed(*size);
|
||||||
quote! {ethers_core::abi::ParamType::Int(#size)}
|
quote! {#core_crate::abi::ParamType::Int(#size)}
|
||||||
}
|
}
|
||||||
ParamType::Uint(size) => {
|
ParamType::Uint(size) => {
|
||||||
let size = Literal::usize_suffixed(*size);
|
let size = Literal::usize_suffixed(*size);
|
||||||
quote! {ethers_core::abi::ParamType::Uint(#size)}
|
quote! {#core_crate::abi::ParamType::Uint(#size)}
|
||||||
}
|
}
|
||||||
ParamType::Bool => {
|
ParamType::Bool => {
|
||||||
quote! {ethers_core::abi::ParamType::Bool}
|
quote! {#core_crate::abi::ParamType::Bool}
|
||||||
}
|
}
|
||||||
ParamType::String => {
|
ParamType::String => {
|
||||||
quote! {ethers_core::abi::ParamType::String}
|
quote! {#core_crate::abi::ParamType::String}
|
||||||
}
|
}
|
||||||
ParamType::Array(ty) => {
|
ParamType::Array(ty) => {
|
||||||
let ty = param_type_quote(&*ty);
|
let ty = param_type_quote(&*ty);
|
||||||
quote! {ethers_core::abi::ParamType::Array(Box::new(#ty))}
|
quote! {#core_crate::abi::ParamType::Array(Box::new(#ty))}
|
||||||
}
|
}
|
||||||
ParamType::FixedBytes(size) => {
|
ParamType::FixedBytes(size) => {
|
||||||
let size = Literal::usize_suffixed(*size);
|
let size = Literal::usize_suffixed(*size);
|
||||||
quote! {ethers_core::abi::ParamType::FixedBytes(#size)}
|
quote! {#core_crate::abi::ParamType::FixedBytes(#size)}
|
||||||
}
|
}
|
||||||
ParamType::FixedArray(ty, size) => {
|
ParamType::FixedArray(ty, size) => {
|
||||||
let ty = param_type_quote(&*ty);
|
let ty = param_type_quote(&*ty);
|
||||||
let size = Literal::usize_suffixed(*size);
|
let size = Literal::usize_suffixed(*size);
|
||||||
quote! {ethers_core::abi::ParamType::FixedArray(Box::new(#ty),#size)}
|
quote! {#core_crate::abi::ParamType::FixedArray(Box::new(#ty),#size)}
|
||||||
}
|
}
|
||||||
ParamType::Tuple(tuple) => {
|
ParamType::Tuple(tuple) => {
|
||||||
let elements = tuple.iter().map(param_type_quote);
|
let elements = tuple.iter().map(param_type_quote);
|
||||||
quote! {
|
quote! {
|
||||||
ethers_core::abi::ParamType::Tuple(
|
#core_crate::abi::ParamType::Tuple(
|
||||||
::std::vec![
|
::std::vec![
|
||||||
#( #elements ),*
|
#( #elements ),*
|
||||||
]
|
]
|
||||||
|
@ -318,6 +325,8 @@ fn derive_decode_from_log_impl(
|
||||||
input: &DeriveInput,
|
input: &DeriveInput,
|
||||||
event: &Event,
|
event: &Event,
|
||||||
) -> Result<proc_macro2::TokenStream, Error> {
|
) -> Result<proc_macro2::TokenStream, Error> {
|
||||||
|
let core_crate = ethers_core_crate();
|
||||||
|
|
||||||
let fields: Vec<_> = match input.data {
|
let fields: Vec<_> = match input.data {
|
||||||
Data::Struct(ref data) => match data.fields {
|
Data::Struct(ref data) => match data.fields {
|
||||||
Fields::Named(ref fields) => {
|
Fields::Named(ref fields) => {
|
||||||
|
@ -416,16 +425,16 @@ fn derive_decode_from_log_impl(
|
||||||
},
|
},
|
||||||
quote! {
|
quote! {
|
||||||
if topic_tokens.len() != topics.len() {
|
if topic_tokens.len() != topics.len() {
|
||||||
return Err(ethers_core::abi::Error::InvalidData);
|
return Err(#core_crate::abi::Error::InvalidData);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
(
|
(
|
||||||
quote! {
|
quote! {
|
||||||
let event_signature = topics.get(0).ok_or(ethers_core::abi::Error::InvalidData)?;
|
let event_signature = topics.get(0).ok_or(#core_crate::abi::Error::InvalidData)?;
|
||||||
if event_signature != &Self::signature() {
|
if event_signature != &Self::signature() {
|
||||||
return Err(ethers_core::abi::Error::InvalidData);
|
return Err(#core_crate::abi::Error::InvalidData);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
quote! {
|
quote! {
|
||||||
|
@ -433,7 +442,7 @@ fn derive_decode_from_log_impl(
|
||||||
},
|
},
|
||||||
quote! {
|
quote! {
|
||||||
if topic_tokens.len() != topics.len() - 1 {
|
if topic_tokens.len() != topics.len() - 1 {
|
||||||
return Err(ethers_core::abi::Error::InvalidData);
|
return Err(#core_crate::abi::Error::InvalidData);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
@ -447,9 +456,9 @@ fn derive_decode_from_log_impl(
|
||||||
.all(|(idx, f)| f.index == idx)
|
.all(|(idx, f)| f.index == idx)
|
||||||
{
|
{
|
||||||
quote! {
|
quote! {
|
||||||
let topic_tokens = ethers_core::abi::decode(&topic_types, &flat_topics)?;
|
let topic_tokens = #core_crate::abi::decode(&topic_types, &flat_topics)?;
|
||||||
#topic_tokens_len_check
|
#topic_tokens_len_check
|
||||||
let data_tokens = ethers_core::abi::decode(&data_types, data)?;
|
let data_tokens = #core_crate::abi::decode(&data_types, data)?;
|
||||||
let tokens:Vec<_> = topic_tokens.into_iter().chain(data_tokens.into_iter()).collect();
|
let tokens:Vec<_> = topic_tokens.into_iter().chain(data_tokens.into_iter()).collect();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -462,9 +471,9 @@ fn derive_decode_from_log_impl(
|
||||||
});
|
});
|
||||||
|
|
||||||
quote! {
|
quote! {
|
||||||
let mut topic_tokens = ethers_core::abi::decode(&topic_types, &flat_topics)?;
|
let mut topic_tokens = #core_crate::abi::decode(&topic_types, &flat_topics)?;
|
||||||
#topic_tokens_len_check
|
#topic_tokens_len_check
|
||||||
let mut data_tokens = ethers_core::abi::decode(&data_types, &data)?;
|
let mut data_tokens = #core_crate::abi::decode(&data_types, &data)?;
|
||||||
let mut tokens = Vec::with_capacity(topics.len() + data_tokens.len());
|
let mut tokens = Vec::with_capacity(topics.len() + data_tokens.len());
|
||||||
#( tokens.push(#swap_tokens); )*
|
#( tokens.push(#swap_tokens); )*
|
||||||
}
|
}
|
||||||
|
@ -472,7 +481,7 @@ fn derive_decode_from_log_impl(
|
||||||
|
|
||||||
Ok(quote! {
|
Ok(quote! {
|
||||||
|
|
||||||
let ethers_core::abi::RawLog {data, topics} = log;
|
let #core_crate::abi::RawLog {data, topics} = log;
|
||||||
|
|
||||||
#signature_check
|
#signature_check
|
||||||
|
|
||||||
|
@ -483,7 +492,7 @@ fn derive_decode_from_log_impl(
|
||||||
|
|
||||||
#tokens_init
|
#tokens_init
|
||||||
|
|
||||||
ethers_core::abi::Detokenize::from_tokens(tokens).map_err(|_|ethers_core::abi::Error::InvalidData)
|
#core_crate::abi::Detokenize::from_tokens(tokens).map_err(|_|#core_crate::abi::Error::InvalidData)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -669,8 +678,9 @@ fn parse_int_param_type(s: &str) -> Option<ParamType> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn signature(hash: &[u8]) -> proc_macro2::TokenStream {
|
fn signature(hash: &[u8]) -> proc_macro2::TokenStream {
|
||||||
|
let core_crate = ethers_core_crate();
|
||||||
let bytes = hash.iter().copied().map(Literal::u8_unsuffixed);
|
let bytes = hash.iter().copied().map(Literal::u8_unsuffixed);
|
||||||
quote! {ethers_core::types::H256([#( #bytes ),*])}
|
quote! {#core_crate::types::H256([#( #bytes ),*])}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_event(abi: &str) -> Result<Event, String> {
|
fn parse_event(abi: &str) -> Result<Event, String> {
|
||||||
|
@ -695,6 +705,7 @@ pub fn derive_abi_type(input: TokenStream) -> TokenStream {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn derive_tokenizeable_impl(input: &DeriveInput) -> proc_macro2::TokenStream {
|
fn derive_tokenizeable_impl(input: &DeriveInput) -> proc_macro2::TokenStream {
|
||||||
|
let core_crate = ethers_core_crate();
|
||||||
let name = &input.ident;
|
let name = &input.ident;
|
||||||
let generic_params = input.generics.params.iter().map(|p| quote! { #p });
|
let generic_params = input.generics.params.iter().map(|p| quote! { #p });
|
||||||
let generic_params = quote! { #(#generic_params,)* };
|
let generic_params = quote! { #(#generic_params,)* };
|
||||||
|
@ -719,13 +730,13 @@ fn derive_tokenizeable_impl(input: &DeriveInput) -> proc_macro2::TokenStream {
|
||||||
Fields::Named(ref fields) => {
|
Fields::Named(ref fields) => {
|
||||||
let tokenize_predicates = fields.named.iter().map(|f| {
|
let tokenize_predicates = fields.named.iter().map(|f| {
|
||||||
let ty = &f.ty;
|
let ty = &f.ty;
|
||||||
quote_spanned! { f.span() => #ty: ethers_core::abi::Tokenize }
|
quote_spanned! { f.span() => #ty: #core_crate::abi::Tokenize }
|
||||||
});
|
});
|
||||||
let tokenize_predicates = quote! { #(#tokenize_predicates,)* };
|
let tokenize_predicates = quote! { #(#tokenize_predicates,)* };
|
||||||
|
|
||||||
let assignments = fields.named.iter().map(|f| {
|
let assignments = fields.named.iter().map(|f| {
|
||||||
let name = f.ident.as_ref().expect("Named fields have names");
|
let name = f.ident.as_ref().expect("Named fields have names");
|
||||||
quote_spanned! { f.span() => #name: ethers_core::abi::Tokenizable::from_token(iter.next().expect("tokens size is sufficient qed").into_token())? }
|
quote_spanned! { f.span() => #name: #core_crate::abi::Tokenizable::from_token(iter.next().expect("tokens size is sufficient qed").into_token())? }
|
||||||
});
|
});
|
||||||
let init_struct_impl = quote! { Self { #(#assignments,)* } };
|
let init_struct_impl = quote! { Self { #(#assignments,)* } };
|
||||||
|
|
||||||
|
@ -745,12 +756,12 @@ fn derive_tokenizeable_impl(input: &DeriveInput) -> proc_macro2::TokenStream {
|
||||||
Fields::Unnamed(ref fields) => {
|
Fields::Unnamed(ref fields) => {
|
||||||
let tokenize_predicates = fields.unnamed.iter().map(|f| {
|
let tokenize_predicates = fields.unnamed.iter().map(|f| {
|
||||||
let ty = &f.ty;
|
let ty = &f.ty;
|
||||||
quote_spanned! { f.span() => #ty: ethers_core::abi::Tokenize }
|
quote_spanned! { f.span() => #ty: #core_crate::abi::Tokenize }
|
||||||
});
|
});
|
||||||
let tokenize_predicates = quote! { #(#tokenize_predicates,)* };
|
let tokenize_predicates = quote! { #(#tokenize_predicates,)* };
|
||||||
|
|
||||||
let assignments = fields.unnamed.iter().map(|f| {
|
let assignments = fields.unnamed.iter().map(|f| {
|
||||||
quote_spanned! { f.span() => ethers_core::abi::Tokenizable::from_token(iter.next().expect("tokens size is sufficient qed").into_token())? }
|
quote_spanned! { f.span() => #core_crate::abi::Tokenizable::from_token(iter.next().expect("tokens size is sufficient qed").into_token())? }
|
||||||
});
|
});
|
||||||
let init_struct_impl = quote! { Self(#(#assignments,)* ) };
|
let init_struct_impl = quote! { Self(#(#assignments,)* ) };
|
||||||
|
|
||||||
|
@ -794,7 +805,7 @@ fn derive_tokenizeable_impl(input: &DeriveInput) -> proc_macro2::TokenStream {
|
||||||
// can't encode an empty struct
|
// can't encode an empty struct
|
||||||
// TODO: panic instead?
|
// TODO: panic instead?
|
||||||
quote! {
|
quote! {
|
||||||
ethers_core::abi::Token::Tuple(Vec::new())
|
#core_crate::abi::Token::Tuple(Vec::new())
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
1 => {
|
1 => {
|
||||||
|
@ -819,9 +830,9 @@ fn derive_tokenizeable_impl(input: &DeriveInput) -> proc_macro2::TokenStream {
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
let from_token = quote! {
|
let from_token = quote! {
|
||||||
if let ethers_core::abi::Token::Tuple(tokens) = token {
|
if let #core_crate::abi::Token::Tuple(tokens) = token {
|
||||||
if tokens.len() != #params_len {
|
if tokens.len() != #params_len {
|
||||||
return Err(ethers_core::abi::InvalidOutputType(::std::format!(
|
return Err(#core_crate::abi::InvalidOutputType(::std::format!(
|
||||||
"Expected {} tokens, got {}: {:?}",
|
"Expected {} tokens, got {}: {:?}",
|
||||||
#params_len,
|
#params_len,
|
||||||
tokens.len(),
|
tokens.len(),
|
||||||
|
@ -833,7 +844,7 @@ fn derive_tokenizeable_impl(input: &DeriveInput) -> proc_macro2::TokenStream {
|
||||||
|
|
||||||
Ok(#init_struct_impl)
|
Ok(#init_struct_impl)
|
||||||
} else {
|
} else {
|
||||||
Err(ethers_core::abi::InvalidOutputType(::std::format!(
|
Err(#core_crate::abi::InvalidOutputType(::std::format!(
|
||||||
"Expected Tuple, got {:?}",
|
"Expected Tuple, got {:?}",
|
||||||
token
|
token
|
||||||
)))
|
)))
|
||||||
|
@ -841,7 +852,7 @@ fn derive_tokenizeable_impl(input: &DeriveInput) -> proc_macro2::TokenStream {
|
||||||
};
|
};
|
||||||
|
|
||||||
let into_token = quote! {
|
let into_token = quote! {
|
||||||
ethers_core::abi::Token::Tuple(
|
#core_crate::abi::Token::Tuple(
|
||||||
::std::vec![
|
::std::vec![
|
||||||
#into_token_impl
|
#into_token_impl
|
||||||
]
|
]
|
||||||
|
@ -852,23 +863,23 @@ fn derive_tokenizeable_impl(input: &DeriveInput) -> proc_macro2::TokenStream {
|
||||||
};
|
};
|
||||||
|
|
||||||
quote! {
|
quote! {
|
||||||
impl<#generic_params> ethers_core::abi::Tokenizable for #name<#generic_args>
|
impl<#generic_params> #core_crate::abi::Tokenizable for #name<#generic_args>
|
||||||
where
|
where
|
||||||
#generic_predicates
|
#generic_predicates
|
||||||
#tokenize_predicates
|
#tokenize_predicates
|
||||||
{
|
{
|
||||||
|
|
||||||
fn from_token(token: ethers_core::abi::Token) -> Result<Self, ethers_core::abi::InvalidOutputType> where
|
fn from_token(token: #core_crate::abi::Token) -> Result<Self, #core_crate::abi::InvalidOutputType> where
|
||||||
Self: Sized {
|
Self: Sized {
|
||||||
#from_token_impl
|
#from_token_impl
|
||||||
}
|
}
|
||||||
|
|
||||||
fn into_token(self) -> ethers_core::abi::Token {
|
fn into_token(self) -> #core_crate::abi::Token {
|
||||||
#into_token_impl
|
#into_token_impl
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<#generic_params> ethers_core::abi::TokenizableItem for #name<#generic_args>
|
impl<#generic_params> #core_crate::abi::TokenizableItem for #name<#generic_args>
|
||||||
where
|
where
|
||||||
#generic_predicates
|
#generic_predicates
|
||||||
#tokenize_predicates
|
#tokenize_predicates
|
||||||
|
|
Loading…
Reference in New Issue