difftreelog
feat support complex types in solidity defs
in: master
5 files changed
crates/evm-coder-macros/src/solidity_interface.rsdiffbeforeafterboth1#![allow(dead_code)]1#![allow(dead_code)]223use quote::quote;3use quote::quote;4use darling::FromMeta;4use darling::{FromMeta, ToTokens};5use inflector::cases;5use inflector::cases;6use std::fmt::Write;6use std::fmt::Write;7use syn::{7use syn::{8 FnArg, Generics, Ident, ImplItem, ImplItemMethod, ItemImpl, Meta, NestedMeta, PatType, Path,8 Expr, FnArg, GenericArgument, Generics, Ident, ImplItem, ImplItemMethod, ItemImpl, Lit, Meta,9 ReturnType, Type, spanned::Spanned,9 NestedMeta, PatType, Path, PathArguments, ReturnType, Type, spanned::Spanned,10};10};111112use crate::{12use crate::{13 fn_selector_str, parse_ident_from_pat, parse_ident_from_path, parse_ident_from_type,13 fn_selector_str, parse_ident_from_pat, parse_ident_from_path, parse_path, parse_path_segment,14 parse_result_ok, pascal_ident_to_call, pascal_ident_to_snake_call, snake_ident_to_pascal,14 parse_result_ok, pascal_ident_to_call, pascal_ident_to_snake_call, snake_ident_to_pascal,15 snake_ident_to_screaming,15 snake_ident_to_screaming,16};16};77 fn expand_generator(&self) -> proc_macro2::TokenStream {77 fn expand_generator(&self) -> proc_macro2::TokenStream {78 let pascal_call_name = &self.pascal_call_name;78 let pascal_call_name = &self.pascal_call_name;79 quote! {79 quote! {80 #pascal_call_name::generate_solidity_interface(out_set, is_impl);80 #pascal_call_name::generate_solidity_interface(tc, is_impl);81 }81 }82 }82 }838384 fn expand_event_generator(&self) -> proc_macro2::TokenStream {84 fn expand_event_generator(&self) -> proc_macro2::TokenStream {85 let name = &self.name;85 let name = &self.name;86 quote! {86 quote! {87 #name::generate_solidity_interface(out_set, is_impl);87 #name::generate_solidity_interface(tc, is_impl);88 }88 }89 }89 }90}90}121 rename_selector: Option<String>,121 rename_selector: Option<String>,122}122}123124enum AbiType {125 // type126 Plain(Ident),127 // (type1,type2)128 Tuple(Vec<AbiType>),129 // type[]130 Vec(Box<AbiType>),131 // type[20]132 Array(Box<AbiType>, usize),133}134impl AbiType {135 fn try_from(value: &Type) -> syn::Result<Self> {136 let value = Self::try_maybe_special_from(value)?;137 if value.is_special() {138 return Err(syn::Error::new(value.span(), "unexpected special type"));139 }140 Ok(value)141 }142 fn try_maybe_special_from(value: &Type) -> syn::Result<Self> {143 match value {144 Type::Array(arr) => {145 let wrapped = AbiType::try_from(&arr.elem)?;146 match &arr.len {147 Expr::Lit(l) => match &l.lit {148 Lit::Int(i) => {149 let num = i.base10_parse::<usize>()?;150 Ok(AbiType::Array(Box::new(wrapped), num as usize))151 }152 _ => Err(syn::Error::new(arr.len.span(), "should be int literal")),153 },154 _ => Err(syn::Error::new(arr.len.span(), "should be literal")),155 }156 }157 Type::Path(_) => {158 let path = parse_path(value)?;159 let segment = parse_path_segment(path)?;160 if segment.ident == "Vec" {161 let args = match &segment.arguments {162 PathArguments::AngleBracketed(e) => e,163 _ => {164 return Err(syn::Error::new(165 segment.arguments.span(),166 "missing Vec generic",167 ))168 }169 };170 let args = &args.args;171 if args.len() != 1 {172 return Err(syn::Error::new(173 args.span(),174 "expected only one generic for vec",175 ));176 }177 let arg = args.first().unwrap();178179 let ty = match arg {180 GenericArgument::Type(ty) => ty,181 _ => {182 return Err(syn::Error::new(183 arg.span(),184 "expected first generic to be type",185 ))186 }187 };188189 let wrapped = AbiType::try_from(ty)?;190 Ok(Self::Vec(Box::new(wrapped)))191 } else {192 if !segment.arguments.is_empty() {193 return Err(syn::Error::new(194 segment.arguments.span(),195 "unexpected generic arguments for non-vec type",196 ));197 }198 Ok(Self::Plain(segment.ident.clone()))199 }200 }201 Type::Tuple(t) => {202 let mut out = Vec::with_capacity(t.elems.len());203 for el in t.elems.iter() {204 out.push(AbiType::try_from(el)?)205 }206 Ok(Self::Tuple(out))207 }208 _ => Err(syn::Error::new(209 value.span(),210 "unexpected type, only arrays, plain types and tuples are supported",211 )),212 }213 }214 fn is_value(&self) -> bool {215 match self {216 Self::Plain(v) if v == "value" => true,217 _ => false,218 }219 }220 fn is_caller(&self) -> bool {221 match self {222 Self::Plain(v) if v == "caller" => true,223 _ => false,224 }225 }226 fn is_special(&self) -> bool {227 self.is_caller() || self.is_value()228 }229 fn selector_ty_buf(&self, buf: &mut String) -> std::fmt::Result {230 match self {231 AbiType::Plain(t) => {232 write!(buf, "{}", t)233 }234 AbiType::Tuple(t) => {235 write!(buf, "(")?;236 for (i, t) in t.iter().enumerate() {237 if i != 0 {238 write!(buf, ",")?;239 }240 t.selector_ty_buf(buf)?;241 }242 write!(buf, ")")243 }244 AbiType::Vec(v) => {245 v.selector_ty_buf(buf)?;246 write!(buf, "[]")247 }248 AbiType::Array(v, len) => {249 v.selector_ty_buf(buf)?;250 write!(buf, "[{}]", len)251 }252 }253 }254 fn selector_ty(&self) -> String {255 let mut out = String::new();256 self.selector_ty_buf(&mut out).expect("no fmt error");257 out258 }259}260impl ToTokens for AbiType {261 fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {262 match self {263 AbiType::Plain(t) => tokens.extend(quote! {#t}),264 AbiType::Tuple(t) => {265 tokens.extend(quote! {(266 #(#t),*267 )});268 }269 AbiType::Vec(v) => tokens.extend(quote! {Vec<#v>}),270 AbiType::Array(v, l) => tokens.extend(quote! {[#v; #l]}),271 }272 }273}123274124struct MethodArg {275struct MethodArg {125 name: Ident,276 name: Ident,126 camel_name: String,277 camel_name: String,127 ty: Ident,278 ty: AbiType,128}279}129impl MethodArg {280impl MethodArg {130 fn try_from(value: &PatType) -> syn::Result<Self> {281 fn try_from(value: &PatType) -> syn::Result<Self> {131 let name = parse_ident_from_pat(&value.pat)?.clone();282 let name = parse_ident_from_pat(&value.pat)?.clone();132 Ok(Self {283 Ok(Self {133 camel_name: cases::camelcase::to_camel_case(&name.to_string()),284 camel_name: cases::camelcase::to_camel_case(&name.to_string()),134 name,285 name,135 ty: parse_ident_from_type(&value.ty, false)?.clone(),286 ty: AbiType::try_maybe_special_from(&value.ty)?,136 })287 })137 }288 }138 fn is_value(&self) -> bool {289 fn is_value(&self) -> bool {139 self.ty == "value"290 self.ty.is_value()140 }291 }141 fn is_caller(&self) -> bool {292 fn is_caller(&self) -> bool {142 self.ty == "caller"293 self.ty.is_caller()143 }294 }144 fn is_special(&self) -> bool {295 fn is_special(&self) -> bool {145 self.is_value() || self.is_caller()296 self.ty.is_special()146 }297 }147 fn selector_ty(&self) -> &Ident {298 fn selector_ty(&self) -> String {148 assert!(!self.is_special());299 assert!(!self.is_special());149 &self.ty300 self.ty.selector_ty()150 }301 }151302152 fn expand_call_def(&self) -> proc_macro2::TokenStream {303 fn expand_call_def(&self) -> proc_macro2::TokenStream {544 )*695 )*545 )696 )546 }697 }547 pub fn generate_solidity_interface(out_set: &mut sp_std::collections::btree_set::BTreeSet<string>, is_impl: bool) {698 pub fn generate_solidity_interface(tc: &evm_coder::solidity::TypeCollector, is_impl: bool) {548 use evm_coder::solidity::*;699 use evm_coder::solidity::*;549 use core::fmt::Write;700 use core::fmt::Write;550 let interface = SolidityInterface {701 let interface = SolidityInterface {559 )*),710 )*),560 };711 };561 if is_impl {712 if is_impl {562 out_set.insert("// Common stubs holder\ncontract Dummy {\n\tuint8 dummy;\n\tstring stub_error = \"this contract is implemented in native\";\n}\n".into());713 tc.collect("// Common stubs holder\ncontract Dummy {\n\tuint8 dummy;\n\tstring stub_error = \"this contract is implemented in native\";\n}\n".into());563 } else {714 } else {564 out_set.insert("// Common stubs holder\ninterface Dummy {\n}\n".into());715 tc.collect("// Common stubs holder\ninterface Dummy {\n}\n".into());565 }716 }566 #(717 #(567 #solidity_generators718 #solidity_generators576 if #solidity_name.starts_with("Inline") {727 if #solidity_name.starts_with("Inline") {577 out.push_str("// Inline\n");728 out.push_str("// Inline\n");578 }729 }579 let _ = interface.format(is_impl, &mut out);730 let _ = interface.format(is_impl, &mut out, tc);580 out_set.insert(out);731 tc.collect(out);581 }732 }582 }733 }583 impl ::evm_coder::Call for #call_name {734 impl ::evm_coder::Call for #call_name {crates/evm-coder-macros/src/to_log.rsdiffbeforeafterboth--- a/crates/evm-coder-macros/src/to_log.rs
+++ b/crates/evm-coder-macros/src/to_log.rs
@@ -179,7 +179,7 @@
#consts
)*
- pub fn generate_solidity_interface(out_set: &mut sp_std::collections::btree_set::BTreeSet<string>, is_impl: bool) {
+ pub fn generate_solidity_interface(tc: &evm_coder::solidity::TypeCollector, is_impl: bool) {
use evm_coder::solidity::*;
use core::fmt::Write;
let interface = SolidityInterface {
@@ -191,8 +191,8 @@
};
let mut out = string::new();
out.push_str("// Inline\n");
- let _ = interface.format(is_impl, &mut out);
- out_set.insert(out);
+ let _ = interface.format(is_impl, &mut out, tc);
+ tc.collect(out);
}
}
crates/evm-coder/src/abi.rsdiffbeforeafterboth--- a/crates/evm-coder/src/abi.rs
+++ b/crates/evm-coder/src/abi.rs
@@ -247,6 +247,51 @@
impl_abi_readable!(bool, bool);
impl_abi_readable!(string, string);
+mod sealed {
+ /// Not all types can be placed in vec, i.e `Vec<u8>` is restricted, `bytes` should be used instead
+ pub trait CanBePlacedInVec {}
+}
+
+impl sealed::CanBePlacedInVec for U256 {}
+impl sealed::CanBePlacedInVec for string {}
+impl sealed::CanBePlacedInVec for H160 {}
+
+impl<R: sealed::CanBePlacedInVec> AbiRead<Vec<R>> for AbiReader<'_>
+where
+ Self: AbiRead<R>,
+{
+ fn abi_read(&mut self) -> Result<Vec<R>> {
+ todo!()
+ }
+}
+
+macro_rules! impl_tuples {
+ ($($ident:ident)+) => {
+ impl<$($ident),+> sealed::CanBePlacedInVec for ($($ident,)+) {}
+ impl<$($ident),+> AbiRead<($($ident,)+)> for AbiReader<'_>
+ where
+ $(Self: AbiRead<$ident>),+
+ {
+ fn abi_read(&mut self) -> Result<($($ident,)+)> {
+ Ok((
+ $(<Self as AbiRead<$ident>>::abi_read(self)?,)+
+ ))
+ }
+ }
+ };
+}
+
+impl_tuples! {A}
+impl_tuples! {A B}
+impl_tuples! {A B C}
+impl_tuples! {A B C D}
+impl_tuples! {A B C D E}
+impl_tuples! {A B C D E F}
+impl_tuples! {A B C D E F G}
+impl_tuples! {A B C D E F G H}
+impl_tuples! {A B C D E F G H I}
+impl_tuples! {A B C D E F G H I J}
+
pub trait AbiWrite {
fn abi_write(&self, writer: &mut AbiWriter);
}
crates/evm-coder/src/lib.rsdiffbeforeafterboth--- a/crates/evm-coder/src/lib.rs
+++ b/crates/evm-coder/src/lib.rs
@@ -67,8 +67,8 @@
#[test]
#[ignore]
fn $name() {
- use sp_std::collections::btree_set::BTreeSet;
- let mut out = BTreeSet::new();
+ use evm_coder::solidity::TypeCollector;
+ let mut out = TypeCollector::new();
$decl::generate_solidity_interface(&mut out, $is_impl);
println!("=== SNIP START ===");
println!("// SPDX-License-Identifier: OTHER");
@@ -76,7 +76,7 @@
println!();
println!("pragma solidity >=0.8.0 <0.9.0;");
println!();
- for b in out {
+ for b in out.finish() {
println!("{}", b);
}
println!("=== SNIP END ===");
crates/evm-coder/src/solidity.rsdiffbeforeafterboth--- a/crates/evm-coder/src/solidity.rs
+++ b/crates/evm-coder/src/solidity.rs
@@ -1,25 +1,79 @@
#[cfg(not(feature = "std"))]
-use alloc::{string::String};
-use core::{fmt, marker::PhantomData};
+use alloc::{
+ string::String,
+ vec::Vec,
+ collections::{BTreeSet, BTreeMap},
+ format,
+};
+#[cfg(feature = "std")]
+use std::collections::{BTreeSet, BTreeMap};
+use core::{
+ fmt::{self, Write},
+ marker::PhantomData,
+ cell::{Cell, RefCell},
+};
use impl_trait_for_tuples::impl_for_tuples;
use crate::types::*;
+#[derive(Default)]
+pub struct TypeCollector {
+ structs: RefCell<BTreeSet<string>>,
+ anonymous: RefCell<BTreeMap<Vec<string>, usize>>,
+ id: Cell<usize>,
+}
+impl TypeCollector {
+ pub fn new() -> Self {
+ Self::default()
+ }
+ pub fn collect(&self, item: string) {
+ self.structs.borrow_mut().insert(item);
+ }
+ pub fn next_id(&self) -> usize {
+ let v = self.id.get();
+ self.id.set(v + 1);
+ v
+ }
+ pub fn collect_tuple<T: SolidityTupleType>(&self) -> String {
+ let names = T::names(self);
+ if let Some(id) = self.anonymous.borrow().get(&names).cloned() {
+ return format!("Tuple{}", id);
+ }
+ let id = self.next_id();
+ let mut str = String::new();
+ writeln!(str, "// Anonymous struct").unwrap();
+ writeln!(str, "struct Tuple{} {{", id).unwrap();
+ for (i, name) in names.iter().enumerate() {
+ writeln!(str, "\t{} field_{};", name, i).unwrap();
+ }
+ writeln!(str, "}}").unwrap();
+ self.collect(str);
+ self.anonymous.borrow_mut().insert(names, id);
+ format!("Tuple{}", id)
+ }
+ pub fn finish(self) -> BTreeSet<string> {
+ self.structs.into_inner()
+ }
+}
+
pub trait SolidityTypeName: 'static {
- fn solidity_name(writer: &mut impl fmt::Write) -> fmt::Result;
- fn solidity_default(writer: &mut impl fmt::Write) -> fmt::Result;
+ fn solidity_name(writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result;
+ fn is_simple() -> bool;
+ fn solidity_default(writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result;
fn is_void() -> bool {
false
}
}
-
macro_rules! solidity_type_name {
- ($($ty:ident => $name:literal = $default:literal),* $(,)?) => {
+ ($($ty:ty => $name:literal $simple:literal = $default:literal),* $(,)?) => {
$(
impl SolidityTypeName for $ty {
- fn solidity_name(writer: &mut impl core::fmt::Write) -> core::fmt::Result {
+ fn solidity_name(writer: &mut impl core::fmt::Write, _tc: &TypeCollector) -> core::fmt::Result {
write!(writer, $name)
}
- fn solidity_default(writer: &mut impl core::fmt::Write) -> core::fmt::Result {
+ fn is_simple() -> bool {
+ $simple
+ }
+ fn solidity_default(writer: &mut impl core::fmt::Write, _tc: &TypeCollector) -> core::fmt::Result {
write!(writer, $default)
}
}
@@ -28,20 +82,23 @@
}
solidity_type_name! {
- uint8 => "uint8" = "0",
- uint32 => "uint32" = "0",
- uint128 => "uint128" = "0",
- uint256 => "uint256" = "0",
- address => "address" = "0x0000000000000000000000000000000000000000",
- string => "string memory" = "\"\"",
- bytes => "bytes memory" = "hex\"\"",
- bool => "bool" = "false",
+ uint8 => "uint8" true = "0",
+ uint32 => "uint32" true = "0",
+ uint128 => "uint128" true = "0",
+ uint256 => "uint256" true = "0",
+ address => "address" true = "0x0000000000000000000000000000000000000000",
+ string => "string" false = "\"\"",
+ bytes => "bytes" false = "hex\"\"",
+ bool => "bool" true = "false",
}
impl SolidityTypeName for void {
- fn solidity_name(_writer: &mut impl fmt::Write) -> fmt::Result {
+ fn solidity_name(_writer: &mut impl fmt::Write, _tc: &TypeCollector) -> fmt::Result {
Ok(())
}
- fn solidity_default(_writer: &mut impl fmt::Write) -> fmt::Result {
+ fn is_simple() -> bool {
+ true
+ }
+ fn solidity_default(_writer: &mut impl fmt::Write, _tc: &TypeCollector) -> fmt::Result {
Ok(())
}
fn is_void() -> bool {
@@ -49,10 +106,88 @@
}
}
+mod sealed {
+ pub trait CanBePlacedInVec {}
+}
+
+impl sealed::CanBePlacedInVec for uint256 {}
+impl sealed::CanBePlacedInVec for string {}
+impl sealed::CanBePlacedInVec for address {}
+
+impl<T: SolidityTypeName + sealed::CanBePlacedInVec> SolidityTypeName for Vec<T> {
+ fn solidity_name(writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result {
+ T::solidity_name(writer, tc)?;
+ write!(writer, "[]")
+ }
+ fn is_simple() -> bool {
+ false
+ }
+ fn solidity_default(writer: &mut impl fmt::Write, _tc: &TypeCollector) -> fmt::Result {
+ write!(writer, "[]")
+ }
+}
+
+pub trait SolidityTupleType {
+ fn names(tc: &TypeCollector) -> Vec<String>;
+ fn len() -> usize;
+}
+
+macro_rules! count {
+ () => (0usize);
+ ( $x:tt $($xs:tt)* ) => (1usize + count!($($xs)*));
+}
+
+macro_rules! impl_tuples {
+ ($($ident:ident)+) => {
+ impl<$($ident),+> sealed::CanBePlacedInVec for ($($ident,)+) {}
+ impl<$($ident: SolidityTypeName + 'static),+> SolidityTupleType for ($($ident,)+) {
+ fn names(tc: &TypeCollector) -> Vec<string> {
+ let mut collected = Vec::with_capacity(Self::len());
+ $({
+ let mut out = string::new();
+ $ident::solidity_name(&mut out, tc).expect("no fmt error");
+ collected.push(out);
+ })*;
+ collected
+ }
+
+ fn len() -> usize {
+ count!($($ident)*)
+ }
+ }
+ impl<$($ident: SolidityTypeName + 'static),+> SolidityTypeName for ($($ident,)+) {
+ fn solidity_name(writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result {
+ write!(writer, "{}", tc.collect_tuple::<Self>())
+ }
+ fn is_simple() -> bool {
+ false
+ }
+ fn solidity_default(writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result {
+ write!(writer, "{}(", tc.collect_tuple::<Self>())?;
+ $(
+ <$ident>::solidity_default(writer, tc)?;
+ )*
+ write!(writer, ")")
+ }
+ }
+ };
+}
+
+impl_tuples! {A}
+impl_tuples! {A B}
+impl_tuples! {A B C}
+impl_tuples! {A B C D}
+impl_tuples! {A B C D E}
+impl_tuples! {A B C D E F}
+impl_tuples! {A B C D E F G}
+impl_tuples! {A B C D E F G H}
+impl_tuples! {A B C D E F G H I}
+impl_tuples! {A B C D E F G H I J}
+
pub trait SolidityArguments {
- fn solidity_name(&self, writer: &mut impl fmt::Write) -> fmt::Result;
+ fn solidity_name(&self, writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result;
fn solidity_get(&self, writer: &mut impl fmt::Write) -> fmt::Result;
- fn solidity_default(&self, writer: &mut impl fmt::Write) -> fmt::Result;
+ fn solidity_default(&self, writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result;
fn is_empty(&self) -> bool {
self.len() == 0
}
@@ -63,9 +198,13 @@
pub struct UnnamedArgument<T>(PhantomData<*const T>);
impl<T: SolidityTypeName> SolidityArguments for UnnamedArgument<T> {
- fn solidity_name(&self, writer: &mut impl fmt::Write) -> fmt::Result {
+ fn solidity_name(&self, writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result {
if !T::is_void() {
- T::solidity_name(writer)
+ T::solidity_name(writer, tc)?;
+ if !T::is_simple() {
+ write!(writer, " memory")?;
+ }
+ Ok(())
} else {
Ok(())
}
@@ -73,8 +212,8 @@
fn solidity_get(&self, _writer: &mut impl fmt::Write) -> fmt::Result {
Ok(())
}
- fn solidity_default(&self, writer: &mut impl fmt::Write) -> fmt::Result {
- T::solidity_default(writer)
+ fn solidity_default(&self, writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result {
+ T::solidity_default(writer, tc)
}
fn len(&self) -> usize {
if T::is_void() {
@@ -94,9 +233,12 @@
}
impl<T: SolidityTypeName> SolidityArguments for NamedArgument<T> {
- fn solidity_name(&self, writer: &mut impl fmt::Write) -> fmt::Result {
+ fn solidity_name(&self, writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result {
if !T::is_void() {
- T::solidity_name(writer)?;
+ T::solidity_name(writer, tc)?;
+ if !T::is_simple() {
+ write!(writer, " memory")?;
+ }
write!(writer, " {}", self.0)
} else {
Ok(())
@@ -105,8 +247,8 @@
fn solidity_get(&self, writer: &mut impl fmt::Write) -> fmt::Result {
writeln!(writer, "\t\t{};", self.0)
}
- fn solidity_default(&self, writer: &mut impl fmt::Write) -> fmt::Result {
- T::solidity_default(writer)
+ fn solidity_default(&self, writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result {
+ T::solidity_default(writer, tc)
}
fn len(&self) -> usize {
if T::is_void() {
@@ -126,9 +268,9 @@
}
impl<T: SolidityTypeName> SolidityArguments for SolidityEventArgument<T> {
- fn solidity_name(&self, writer: &mut impl fmt::Write) -> fmt::Result {
+ fn solidity_name(&self, writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result {
if !T::is_void() {
- T::solidity_name(writer)?;
+ T::solidity_name(writer, tc)?;
if self.0 {
write!(writer, " indexed")?;
}
@@ -140,8 +282,8 @@
fn solidity_get(&self, writer: &mut impl fmt::Write) -> fmt::Result {
writeln!(writer, "\t\t{};", self.1)
}
- fn solidity_default(&self, writer: &mut impl fmt::Write) -> fmt::Result {
- T::solidity_default(writer)
+ fn solidity_default(&self, writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result {
+ T::solidity_default(writer, tc)
}
fn len(&self) -> usize {
if T::is_void() {
@@ -153,13 +295,13 @@
}
impl SolidityArguments for () {
- fn solidity_name(&self, _writer: &mut impl fmt::Write) -> fmt::Result {
+ fn solidity_name(&self, _writer: &mut impl fmt::Write, _tc: &TypeCollector) -> fmt::Result {
Ok(())
}
fn solidity_get(&self, _writer: &mut impl fmt::Write) -> fmt::Result {
Ok(())
}
- fn solidity_default(&self, _writer: &mut impl fmt::Write) -> fmt::Result {
+ fn solidity_default(&self, _writer: &mut impl fmt::Write, _tc: &TypeCollector) -> fmt::Result {
Ok(())
}
fn len(&self) -> usize {
@@ -171,7 +313,7 @@
impl SolidityArguments for Tuple {
for_tuples!( where #( Tuple: SolidityArguments ),* );
- fn solidity_name(&self, writer: &mut impl fmt::Write) -> fmt::Result {
+ fn solidity_name(&self, writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result {
let mut first = true;
for_tuples!( #(
if !Tuple.is_empty() {
@@ -179,7 +321,7 @@
write!(writer, ", ")?;
}
first = false;
- Tuple.solidity_name(writer)?;
+ Tuple.solidity_name(writer, tc)?;
}
)* );
Ok(())
@@ -190,12 +332,12 @@
)* );
Ok(())
}
- fn solidity_default(&self, writer: &mut impl fmt::Write) -> fmt::Result {
+ fn solidity_default(&self, writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result {
if self.is_empty() {
Ok(())
} else if self.len() == 1 {
for_tuples!( #(
- Tuple.solidity_default(writer)?;
+ Tuple.solidity_default(writer, tc)?;
)* );
Ok(())
} else {
@@ -207,7 +349,7 @@
write!(writer, ", ")?;
}
first = false;
- Tuple.solidity_name(writer)?;
+ Tuple.solidity_default(writer, tc)?;
}
)* );
write!(writer, ")")?;
@@ -220,7 +362,12 @@
}
pub trait SolidityFunctions {
- fn solidity_name(&self, is_impl: bool, writer: &mut impl fmt::Write) -> fmt::Result;
+ fn solidity_name(
+ &self,
+ is_impl: bool,
+ writer: &mut impl fmt::Write,
+ tc: &TypeCollector,
+ ) -> fmt::Result;
}
pub enum SolidityMutability {
@@ -235,9 +382,14 @@
pub mutability: SolidityMutability,
}
impl<A: SolidityArguments, R: SolidityArguments> SolidityFunctions for SolidityFunction<A, R> {
- fn solidity_name(&self, is_impl: bool, writer: &mut impl fmt::Write) -> fmt::Result {
+ fn solidity_name(
+ &self,
+ is_impl: bool,
+ writer: &mut impl fmt::Write,
+ tc: &TypeCollector,
+ ) -> fmt::Result {
write!(writer, "\tfunction {}(", self.name)?;
- self.args.solidity_name(writer)?;
+ self.args.solidity_name(writer, tc)?;
write!(writer, ")")?;
if is_impl {
write!(writer, " public")?;
@@ -251,7 +403,7 @@
}
if !self.result.is_empty() {
write!(writer, " returns (")?;
- self.result.solidity_name(writer)?;
+ self.result.solidity_name(writer, tc)?;
write!(writer, ")")?;
}
if is_impl {
@@ -265,7 +417,7 @@
}
if !self.result.is_empty() {
write!(writer, "\t\treturn ")?;
- self.result.solidity_default(writer)?;
+ self.result.solidity_default(writer, tc)?;
writeln!(writer, ";")?;
}
writeln!(writer, "\t}}")?;
@@ -280,10 +432,15 @@
impl SolidityFunctions for Tuple {
for_tuples!( where #( Tuple: SolidityFunctions ),* );
- fn solidity_name(&self, is_impl: bool, writer: &mut impl fmt::Write) -> fmt::Result {
+ fn solidity_name(
+ &self,
+ is_impl: bool,
+ writer: &mut impl fmt::Write,
+ tc: &TypeCollector,
+ ) -> fmt::Result {
let mut first = false;
for_tuples!( #(
- Tuple.solidity_name(is_impl, writer)?;
+ Tuple.solidity_name(is_impl, writer, tc)?;
)* );
Ok(())
}
@@ -296,7 +453,12 @@
}
impl<F: SolidityFunctions> SolidityInterface<F> {
- pub fn format(&self, is_impl: bool, out: &mut impl fmt::Write) -> fmt::Result {
+ pub fn format(
+ &self,
+ is_impl: bool,
+ out: &mut impl fmt::Write,
+ tc: &TypeCollector,
+ ) -> fmt::Result {
if is_impl {
write!(out, "contract ")?;
} else {
@@ -313,7 +475,7 @@
}
}
writeln!(out, " {{")?;
- self.functions.solidity_name(is_impl, out)?;
+ self.functions.solidity_name(is_impl, out, tc)?;
writeln!(out, "}}")?;
Ok(())
}
@@ -325,9 +487,14 @@
}
impl<A: SolidityArguments> SolidityFunctions for SolidityEvent<A> {
- fn solidity_name(&self, _is_impl: bool, writer: &mut impl fmt::Write) -> fmt::Result {
+ fn solidity_name(
+ &self,
+ _is_impl: bool,
+ writer: &mut impl fmt::Write,
+ tc: &TypeCollector,
+ ) -> fmt::Result {
write!(writer, "\tevent {}(", self.name)?;
- self.args.solidity_name(writer)?;
+ self.args.solidity_name(writer, tc)?;
writeln!(writer, ");")
}
}