From c6de66854cd06a02dc681497c32bbaa55427e299 Mon Sep 17 00:00:00 2001 From: DaniPopes <57450786+DaniPopes@users.noreply.github.com> Date: Thu, 7 Mar 2024 23:48:15 +0100 Subject: [PATCH] feat(json-abi): add configuration for `JsonAbi::to_sol` --- crates/json-abi/src/abi.rs | 15 ++++++----- crates/json-abi/src/lib.rs | 1 + crates/json-abi/src/to_sol.rs | 49 ++++++++++++++++++++++++++++++++--- crates/json-abi/tests/abi.rs | 2 +- crates/sol-macro/src/json.rs | 4 +-- 5 files changed, 59 insertions(+), 12 deletions(-) diff --git a/crates/json-abi/src/abi.rs b/crates/json-abi/src/abi.rs index d98777238c..55d24c627d 100644 --- a/crates/json-abi/src/abi.rs +++ b/crates/json-abi/src/abi.rs @@ -1,4 +1,7 @@ -use crate::{AbiItem, Constructor, Error, Event, Fallback, Function, Receive}; +use crate::{ + to_sol::{SolPrinter, ToSolConfig}, + AbiItem, Constructor, Error, Event, Fallback, Function, Receive, +}; use alloc::{collections::btree_map, string::String, vec::Vec}; use alloy_primitives::Bytes; use btree_map::BTreeMap; @@ -195,18 +198,18 @@ impl JsonAbi { /// Note that enums are going to be identical to `uint8` UDVTs, since no /// other information about enums is present in the ABI. #[inline] - pub fn to_sol(&self, name: &str) -> String { + pub fn to_sol(&self, name: &str, config: Option) -> String { let mut out = String::new(); - self.to_sol_raw(name, &mut out); + self.to_sol_raw(name, &mut out, config); out } /// Formats this JSON ABI as a Solidity interface into the given string. /// /// See [`to_sol`](JsonAbi::to_sol) for more information. - pub fn to_sol_raw(&self, name: &str, out: &mut String) { + pub fn to_sol_raw(&self, name: &str, out: &mut String, config: Option) { let len = self.len(); - out.reserve((len + 1) * 128); + out.reserve(len * 128); out.push_str("interface "); if !name.is_empty() { @@ -216,7 +219,7 @@ impl JsonAbi { out.push('{'); if len > 0 { out.push('\n'); - crate::to_sol::ToSol::to_sol(self, &mut crate::to_sol::SolPrinter::new(out)); + SolPrinter::new(out, config.unwrap_or_default()).print(self); } out.push('}'); } diff --git a/crates/json-abi/src/lib.rs b/crates/json-abi/src/lib.rs index c5c7ddc1c4..a8a40df392 100644 --- a/crates/json-abi/src/lib.rs +++ b/crates/json-abi/src/lib.rs @@ -47,6 +47,7 @@ mod internal_type; pub use internal_type::InternalType; mod to_sol; +pub use to_sol::ToSolConfig; pub(crate) mod utils; diff --git a/crates/json-abi/src/to_sol.rs b/crates/json-abi/src/to_sol.rs index 098176e09f..4f2babacad 100644 --- a/crates/json-abi/src/to_sol.rs +++ b/crates/json-abi/src/to_sol.rs @@ -8,13 +8,49 @@ use core::{ ops::{Deref, DerefMut}, }; +/// Configuration for [`JsonAbi::to_sol`]. +#[derive(Clone, Debug)] +#[allow(missing_copy_implementations)] // Future-proofing +pub struct ToSolConfig { + print_constructors: bool, +} + +impl Default for ToSolConfig { + #[inline] + fn default() -> Self { + Self::new() + } +} + +impl ToSolConfig { + /// Creates a new configuration with default settings. + #[inline] + pub const fn new() -> Self { + Self { print_constructors: false } + } + + /// Sets whether to print constructors. Default: `false`. + #[inline] + pub const fn print_constructors(mut self, yes: bool) -> Self { + self.print_constructors = yes; + self + } +} + pub(crate) trait ToSol { fn to_sol(&self, out: &mut SolPrinter<'_>); } pub(crate) struct SolPrinter<'a> { + /// The buffer to write to. s: &'a mut String, + + /// Whether to emit `memory` when printing parameters. + /// This is set to `true` when printing functions so that we emit valid Solidity. emit_param_location: bool, + + /// Configuration. + config: ToSolConfig, } impl Deref for SolPrinter<'_> { @@ -35,8 +71,13 @@ impl DerefMut for SolPrinter<'_> { impl<'a> SolPrinter<'a> { #[inline] - pub(crate) fn new(s: &'a mut String) -> Self { - Self { s, emit_param_location: false } + pub(crate) fn new(s: &'a mut String, config: ToSolConfig) -> Self { + Self { s, emit_param_location: false, config } + } + + #[inline] + pub(crate) fn print(&mut self, value: &T) { + value.to_sol(self); } #[inline] @@ -69,7 +110,9 @@ impl ToSol for JsonAbi { fmt!(its.0); fmt!(self.errors()); fmt!(self.events()); - fmt!(self.constructor()); + if out.config.print_constructors { + fmt!(self.constructor()); + } fmt!(self.fallback); fmt!(self.receive); fmt!(self.functions()); diff --git a/crates/json-abi/tests/abi.rs b/crates/json-abi/tests/abi.rs index 88ab38ce02..a39e43a7d5 100644 --- a/crates/json-abi/tests/abi.rs +++ b/crates/json-abi/tests/abi.rs @@ -83,7 +83,7 @@ fn to_sol_test(path: &str, abi: &JsonAbi, run_solc: bool) { // Ignore constructors for Solc tests. abi.constructor = None; abi.dedup(); - let actual = abi.to_sol(name); + let actual = abi.to_sol(name, None); ensure_file_contents(&sol_path, &actual); diff --git a/crates/sol-macro/src/json.rs b/crates/sol-macro/src/json.rs index e8ed3a0d86..f5f348ce55 100644 --- a/crates/sol-macro/src/json.rs +++ b/crates/sol-macro/src/json.rs @@ -1,4 +1,4 @@ -use alloy_json_abi::{ContractObject, JsonAbi}; +use alloy_json_abi::{ContractObject, JsonAbi, ToSolConfig}; use proc_macro2::{Ident, TokenStream}; use quote::{quote, TokenStreamExt}; use syn::{Attribute, Result}; @@ -51,7 +51,7 @@ Generated by the following Solidity interface... fn abi_to_sol(name: &Ident, abi: &mut JsonAbi) -> String { abi.dedup(); - abi.to_sol(&name.to_string()) + abi.to_sol(&name.to_string(), Some(ToSolConfig::new().print_constructors(true))) } /// Returns `sol!` tokens.