refactor/feat(abigen,types): add bytes::Bytes static methods, refactor struct declaration (#2089)
* refactor: final struct expansion * feat(types): implement bytes::Bytes static methods * feat: use static Bytes for bytecode * chore: add rustfmt skip directive * clippy
This commit is contained in:
parent
71c6fd4928
commit
93e1850646
|
@ -1,11 +1,9 @@
|
||||||
use super::{util, Context};
|
use super::{types, util, Context};
|
||||||
|
|
||||||
use crate::contract::types;
|
|
||||||
use ethers_core::{
|
use ethers_core::{
|
||||||
abi::{Param, ParamType},
|
abi::{Param, ParamType},
|
||||||
macros::{ethers_contract_crate, ethers_core_crate, ethers_providers_crate},
|
macros::{ethers_contract_crate, ethers_core_crate, ethers_providers_crate},
|
||||||
};
|
};
|
||||||
use proc_macro2::{Ident, TokenStream};
|
use proc_macro2::{Ident, Literal, TokenStream};
|
||||||
use quote::quote;
|
use quote::quote;
|
||||||
|
|
||||||
/// Expands to the `name : type` pairs for the params
|
/// Expands to the `name : type` pairs for the params
|
||||||
|
@ -87,49 +85,56 @@ pub(crate) fn imports(name: &str) -> TokenStream {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Generates the static `Abi` constants and the contract struct
|
/// Generates the token stream for the contract's ABI, bytecode and struct declarations.
|
||||||
pub(crate) fn struct_declaration(cx: &Context) -> TokenStream {
|
pub(crate) fn struct_declaration(cx: &Context) -> TokenStream {
|
||||||
let name = &cx.contract_ident;
|
let name = &cx.contract_ident;
|
||||||
let abi = &cx.abi_str;
|
|
||||||
|
|
||||||
let abi_name = cx.inline_abi_ident();
|
|
||||||
|
|
||||||
let ethers_core = ethers_core_crate();
|
let ethers_core = ethers_core_crate();
|
||||||
let ethers_contract = ethers_contract_crate();
|
let ethers_contract = ethers_contract_crate();
|
||||||
|
|
||||||
let abi_parse = if !cx.human_readable {
|
let abi = {
|
||||||
|
let abi_name = cx.inline_abi_ident();
|
||||||
|
let abi = &cx.abi_str;
|
||||||
|
let (doc_str, parse) = if cx.human_readable {
|
||||||
|
// Human readable: use abi::parse_abi_str
|
||||||
|
let doc_str = "The parsed human-readable ABI of the contract.";
|
||||||
|
let parse = quote!(#ethers_core::abi::parse_abi_str(__ABI));
|
||||||
|
(doc_str, parse)
|
||||||
|
} else {
|
||||||
|
// JSON ABI: use serde_json::from_str
|
||||||
|
let doc_str = "The parsed JSON ABI of the contract.";
|
||||||
|
let parse = quote!(#ethers_core::utils::__serde_json::from_str(__ABI));
|
||||||
|
(doc_str, parse)
|
||||||
|
};
|
||||||
|
|
||||||
quote! {
|
quote! {
|
||||||
#[rustfmt::skip]
|
#[rustfmt::skip]
|
||||||
const __ABI: &str = #abi;
|
const __ABI: &str = #abi;
|
||||||
|
|
||||||
/// The parsed JSON-ABI of the contract.
|
// This never fails as we are parsing the ABI in this macro
|
||||||
pub static #abi_name: #ethers_contract::Lazy<#ethers_core::abi::Abi> = #ethers_contract::Lazy::new(|| #ethers_core::utils::__serde_json::from_str(__ABI)
|
#[doc = #doc_str]
|
||||||
.expect("invalid abi"));
|
pub static #abi_name: #ethers_contract::Lazy<#ethers_core::abi::Abi> =
|
||||||
}
|
#ethers_contract::Lazy::new(|| #parse.expect("ABI is always valid"));
|
||||||
} else {
|
|
||||||
quote! {
|
|
||||||
/// The parsed human readable ABI of the contract.
|
|
||||||
pub static #abi_name: #ethers_contract::Lazy<#ethers_core::abi::Abi> = #ethers_contract::Lazy::new(|| #ethers_core::abi::parse_abi_str(#abi)
|
|
||||||
.expect("invalid abi"));
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let bytecode = if let Some(ref bytecode) = cx.contract_bytecode {
|
let bytecode = cx.contract_bytecode.as_ref().map(|bytecode| {
|
||||||
|
let bytecode = bytecode.iter().copied().map(Literal::u8_unsuffixed);
|
||||||
let bytecode_name = cx.inline_bytecode_ident();
|
let bytecode_name = cx.inline_bytecode_ident();
|
||||||
let hex_bytecode = format!("{bytecode}");
|
|
||||||
quote! {
|
quote! {
|
||||||
/// Bytecode of the #name contract
|
#[rustfmt::skip]
|
||||||
pub static #bytecode_name: #ethers_contract::Lazy<#ethers_core::types::Bytes> = #ethers_contract::Lazy::new(|| #hex_bytecode.parse()
|
const __BYTECODE: &[u8] = &[ #( #bytecode ),* ];
|
||||||
.expect("invalid bytecode"));
|
|
||||||
|
#[doc = "The bytecode of the contract."]
|
||||||
|
pub static #bytecode_name: #ethers_core::types::Bytes = #ethers_core::types::Bytes::from_static(__BYTECODE);
|
||||||
}
|
}
|
||||||
} else {
|
});
|
||||||
quote! {}
|
|
||||||
};
|
|
||||||
|
|
||||||
quote! {
|
quote! {
|
||||||
// Inline ABI declaration
|
// The `Lazy` ABI
|
||||||
#abi_parse
|
#abi
|
||||||
|
|
||||||
|
// The static Bytecode, if present
|
||||||
#bytecode
|
#bytecode
|
||||||
|
|
||||||
// Struct declaration
|
// Struct declaration
|
||||||
|
|
|
@ -16,31 +16,62 @@ pub struct Bytes(
|
||||||
pub bytes::Bytes,
|
pub bytes::Bytes,
|
||||||
);
|
);
|
||||||
|
|
||||||
fn bytes_to_hex(b: &Bytes) -> String {
|
impl Bytes {
|
||||||
hex::encode(b.0.as_ref())
|
/// Creates a new empty `Bytes`.
|
||||||
|
///
|
||||||
|
/// This will not allocate and the returned `Bytes` handle will be empty.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// use ethers_core::types::Bytes;
|
||||||
|
///
|
||||||
|
/// let b = Bytes::new();
|
||||||
|
/// assert_eq!(&b[..], b"");
|
||||||
|
/// ```
|
||||||
|
#[inline]
|
||||||
|
pub const fn new() -> Self {
|
||||||
|
Self(bytes::Bytes::new())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Creates a new `Bytes` from a static slice.
|
||||||
|
///
|
||||||
|
/// The returned `Bytes` will point directly to the static slice. There is
|
||||||
|
/// no allocating or copying.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// use ethers_core::types::Bytes;
|
||||||
|
///
|
||||||
|
/// let b = Bytes::from_static(b"hello");
|
||||||
|
/// assert_eq!(&b[..], b"hello");
|
||||||
|
/// ```
|
||||||
|
#[inline]
|
||||||
|
pub const fn from_static(bytes: &'static [u8]) -> Self {
|
||||||
|
Self(bytes::Bytes::from_static(bytes))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn hex_encode(&self) -> String {
|
||||||
|
hex::encode(self.0.as_ref())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Debug for Bytes {
|
impl Debug for Bytes {
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
|
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
|
||||||
write!(f, "Bytes(0x{})", bytes_to_hex(self))
|
write!(f, "Bytes(0x{})", self.hex_encode())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for Bytes {
|
impl Display for Bytes {
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
|
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
|
||||||
write!(f, "0x{}", bytes_to_hex(self))
|
write!(f, "0x{}", self.hex_encode())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LowerHex for Bytes {
|
impl LowerHex for Bytes {
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
|
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
|
||||||
write!(f, "0x{}", bytes_to_hex(self))
|
write!(f, "0x{}", self.hex_encode())
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Bytes {
|
|
||||||
pub fn to_vec(&self) -> Vec<u8> {
|
|
||||||
self.as_ref().to_vec()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue