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.rsdiffbeforeafterboth179 #consts179 #consts180 )*180 )*181181182 pub fn generate_solidity_interface(out_set: &mut sp_std::collections::btree_set::BTreeSet<string>, is_impl: bool) {182 pub fn generate_solidity_interface(tc: &evm_coder::solidity::TypeCollector, is_impl: bool) {183 use evm_coder::solidity::*;183 use evm_coder::solidity::*;184 use core::fmt::Write;184 use core::fmt::Write;185 let interface = SolidityInterface {185 let interface = SolidityInterface {191 };191 };192 let mut out = string::new();192 let mut out = string::new();193 out.push_str("// Inline\n");193 out.push_str("// Inline\n");194 let _ = interface.format(is_impl, &mut out);194 let _ = interface.format(is_impl, &mut out, tc);195 out_set.insert(out);195 tc.collect(out);196 }196 }197 }197 }198198crates/evm-coder/src/abi.rsdiffbeforeafterboth247impl_abi_readable!(bool, bool);247impl_abi_readable!(bool, bool);248impl_abi_readable!(string, string);248impl_abi_readable!(string, string);249250mod sealed {251 /// Not all types can be placed in vec, i.e `Vec<u8>` is restricted, `bytes` should be used instead252 pub trait CanBePlacedInVec {}253}254255impl sealed::CanBePlacedInVec for U256 {}256impl sealed::CanBePlacedInVec for string {}257impl sealed::CanBePlacedInVec for H160 {}258259impl<R: sealed::CanBePlacedInVec> AbiRead<Vec<R>> for AbiReader<'_>260where261 Self: AbiRead<R>,262{263 fn abi_read(&mut self) -> Result<Vec<R>> {264 todo!()265 }266}267268macro_rules! impl_tuples {269 ($($ident:ident)+) => {270 impl<$($ident),+> sealed::CanBePlacedInVec for ($($ident,)+) {}271 impl<$($ident),+> AbiRead<($($ident,)+)> for AbiReader<'_>272 where273 $(Self: AbiRead<$ident>),+274 {275 fn abi_read(&mut self) -> Result<($($ident,)+)> {276 Ok((277 $(<Self as AbiRead<$ident>>::abi_read(self)?,)+278 ))279 }280 }281 };282}283284impl_tuples! {A}285impl_tuples! {A B}286impl_tuples! {A B C}287impl_tuples! {A B C D}288impl_tuples! {A B C D E}289impl_tuples! {A B C D E F}290impl_tuples! {A B C D E F G}291impl_tuples! {A B C D E F G H}292impl_tuples! {A B C D E F G H I}293impl_tuples! {A B C D E F G H I J}249294250pub trait AbiWrite {295pub trait AbiWrite {251 fn abi_write(&self, writer: &mut AbiWriter);296 fn abi_write(&self, writer: &mut AbiWriter);crates/evm-coder/src/lib.rsdiffbeforeafterboth67 #[test]67 #[test]68 #[ignore]68 #[ignore]69 fn $name() {69 fn $name() {70 use sp_std::collections::btree_set::BTreeSet;70 use evm_coder::solidity::TypeCollector;71 let mut out = BTreeSet::new();71 let mut out = TypeCollector::new();72 $decl::generate_solidity_interface(&mut out, $is_impl);72 $decl::generate_solidity_interface(&mut out, $is_impl);73 println!("=== SNIP START ===");73 println!("=== SNIP START ===");74 println!("// SPDX-License-Identifier: OTHER");74 println!("// SPDX-License-Identifier: OTHER");75 println!("// This code is automatically generated");75 println!("// This code is automatically generated");76 println!();76 println!();77 println!("pragma solidity >=0.8.0 <0.9.0;");77 println!("pragma solidity >=0.8.0 <0.9.0;");78 println!();78 println!();79 for b in out {79 for b in out.finish() {80 println!("{}", b);80 println!("{}", b);81 }81 }82 println!("=== SNIP END ===");82 println!("=== SNIP END ===");crates/evm-coder/src/solidity.rsdiffbeforeafterboth1#[cfg(not(feature = "std"))]1#[cfg(not(feature = "std"))]2use alloc::{string::String};2use alloc::{3 string::String,4 vec::Vec,5 collections::{BTreeSet, BTreeMap},6 format,7};8#[cfg(feature = "std")]9use std::collections::{BTreeSet, BTreeMap};3use core::{fmt, marker::PhantomData};10use core::{11 fmt::{self, Write},12 marker::PhantomData,13 cell::{Cell, RefCell},14};4use impl_trait_for_tuples::impl_for_tuples;15use impl_trait_for_tuples::impl_for_tuples;5use crate::types::*;16use crate::types::*;1718#[derive(Default)]19pub struct TypeCollector {20 structs: RefCell<BTreeSet<string>>,21 anonymous: RefCell<BTreeMap<Vec<string>, usize>>,22 id: Cell<usize>,23}24impl TypeCollector {25 pub fn new() -> Self {26 Self::default()27 }28 pub fn collect(&self, item: string) {29 self.structs.borrow_mut().insert(item);30 }31 pub fn next_id(&self) -> usize {32 let v = self.id.get();33 self.id.set(v + 1);34 v35 }36 pub fn collect_tuple<T: SolidityTupleType>(&self) -> String {37 let names = T::names(self);38 if let Some(id) = self.anonymous.borrow().get(&names).cloned() {39 return format!("Tuple{}", id);40 }41 let id = self.next_id();42 let mut str = String::new();43 writeln!(str, "// Anonymous struct").unwrap();44 writeln!(str, "struct Tuple{} {{", id).unwrap();45 for (i, name) in names.iter().enumerate() {46 writeln!(str, "\t{} field_{};", name, i).unwrap();47 }48 writeln!(str, "}}").unwrap();49 self.collect(str);50 self.anonymous.borrow_mut().insert(names, id);51 format!("Tuple{}", id)52 }53 pub fn finish(self) -> BTreeSet<string> {54 self.structs.into_inner()55 }56}6577pub trait SolidityTypeName: 'static {58pub trait SolidityTypeName: 'static {8 fn solidity_name(writer: &mut impl fmt::Write) -> fmt::Result;59 fn solidity_name(writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result;60 fn is_simple() -> bool;9 fn solidity_default(writer: &mut impl fmt::Write) -> fmt::Result;61 fn solidity_default(writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result;10 fn is_void() -> bool {62 fn is_void() -> bool {11 false63 false12 }64 }13}65}1415macro_rules! solidity_type_name {66macro_rules! solidity_type_name {16 ($($ty:ident => $name:literal = $default:literal),* $(,)?) => {67 ($($ty:ty => $name:literal $simple:literal = $default:literal),* $(,)?) => {17 $(68 $(18 impl SolidityTypeName for $ty {69 impl SolidityTypeName for $ty {19 fn solidity_name(writer: &mut impl core::fmt::Write) -> core::fmt::Result {70 fn solidity_name(writer: &mut impl core::fmt::Write, _tc: &TypeCollector) -> core::fmt::Result {20 write!(writer, $name)71 write!(writer, $name)21 }72 }73 fn is_simple() -> bool {74 $simple75 }22 fn solidity_default(writer: &mut impl core::fmt::Write) -> core::fmt::Result {76 fn solidity_default(writer: &mut impl core::fmt::Write, _tc: &TypeCollector) -> core::fmt::Result {23 write!(writer, $default)77 write!(writer, $default)24 }78 }25 }79 }28}82}298330solidity_type_name! {84solidity_type_name! {31 uint8 => "uint8" = "0",85 uint8 => "uint8" true = "0",32 uint32 => "uint32" = "0",86 uint32 => "uint32" true = "0",33 uint128 => "uint128" = "0",87 uint128 => "uint128" true = "0",34 uint256 => "uint256" = "0",88 uint256 => "uint256" true = "0",35 address => "address" = "0x0000000000000000000000000000000000000000",89 address => "address" true = "0x0000000000000000000000000000000000000000",36 string => "string memory" = "\"\"",90 string => "string" false = "\"\"",37 bytes => "bytes memory" = "hex\"\"",91 bytes => "bytes" false = "hex\"\"",38 bool => "bool" = "false",92 bool => "bool" true = "false",39}93}40impl SolidityTypeName for void {94impl SolidityTypeName for void {41 fn solidity_name(_writer: &mut impl fmt::Write) -> fmt::Result {95 fn solidity_name(_writer: &mut impl fmt::Write, _tc: &TypeCollector) -> fmt::Result {42 Ok(())96 Ok(())43 }97 }98 fn is_simple() -> bool {99 true100 }44 fn solidity_default(_writer: &mut impl fmt::Write) -> fmt::Result {101 fn solidity_default(_writer: &mut impl fmt::Write, _tc: &TypeCollector) -> fmt::Result {45 Ok(())102 Ok(())46 }103 }47 fn is_void() -> bool {104 fn is_void() -> bool {48 true105 true49 }106 }50}107}108109mod sealed {110 pub trait CanBePlacedInVec {}111}112113impl sealed::CanBePlacedInVec for uint256 {}114impl sealed::CanBePlacedInVec for string {}115impl sealed::CanBePlacedInVec for address {}116117impl<T: SolidityTypeName + sealed::CanBePlacedInVec> SolidityTypeName for Vec<T> {118 fn solidity_name(writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result {119 T::solidity_name(writer, tc)?;120 write!(writer, "[]")121 }122 fn is_simple() -> bool {123 false124 }125 fn solidity_default(writer: &mut impl fmt::Write, _tc: &TypeCollector) -> fmt::Result {126 write!(writer, "[]")127 }128}129130pub trait SolidityTupleType {131 fn names(tc: &TypeCollector) -> Vec<String>;132 fn len() -> usize;133}134135macro_rules! count {136 () => (0usize);137 ( $x:tt $($xs:tt)* ) => (1usize + count!($($xs)*));138}139140macro_rules! impl_tuples {141 ($($ident:ident)+) => {142 impl<$($ident),+> sealed::CanBePlacedInVec for ($($ident,)+) {}143 impl<$($ident: SolidityTypeName + 'static),+> SolidityTupleType for ($($ident,)+) {144 fn names(tc: &TypeCollector) -> Vec<string> {145 let mut collected = Vec::with_capacity(Self::len());146 $({147 let mut out = string::new();148 $ident::solidity_name(&mut out, tc).expect("no fmt error");149 collected.push(out);150 })*;151 collected152 }153154 fn len() -> usize {155 count!($($ident)*)156 }157 }158 impl<$($ident: SolidityTypeName + 'static),+> SolidityTypeName for ($($ident,)+) {159 fn solidity_name(writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result {160 write!(writer, "{}", tc.collect_tuple::<Self>())161 }162 fn is_simple() -> bool {163 false164 }165 fn solidity_default(writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result {166 write!(writer, "{}(", tc.collect_tuple::<Self>())?;167 $(168 <$ident>::solidity_default(writer, tc)?;169 )*170 write!(writer, ")")171 }172 }173 };174}175176impl_tuples! {A}177impl_tuples! {A B}178impl_tuples! {A B C}179impl_tuples! {A B C D}180impl_tuples! {A B C D E}181impl_tuples! {A B C D E F}182impl_tuples! {A B C D E F G}183impl_tuples! {A B C D E F G H}184impl_tuples! {A B C D E F G H I}185impl_tuples! {A B C D E F G H I J}5118652pub trait SolidityArguments {187pub trait SolidityArguments {53 fn solidity_name(&self, writer: &mut impl fmt::Write) -> fmt::Result;188 fn solidity_name(&self, writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result;54 fn solidity_get(&self, writer: &mut impl fmt::Write) -> fmt::Result;189 fn solidity_get(&self, writer: &mut impl fmt::Write) -> fmt::Result;55 fn solidity_default(&self, writer: &mut impl fmt::Write) -> fmt::Result;190 fn solidity_default(&self, writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result;56 fn is_empty(&self) -> bool {191 fn is_empty(&self) -> bool {57 self.len() == 0192 self.len() == 058 }193 }63pub struct UnnamedArgument<T>(PhantomData<*const T>);198pub struct UnnamedArgument<T>(PhantomData<*const T>);6419965impl<T: SolidityTypeName> SolidityArguments for UnnamedArgument<T> {200impl<T: SolidityTypeName> SolidityArguments for UnnamedArgument<T> {66 fn solidity_name(&self, writer: &mut impl fmt::Write) -> fmt::Result {201 fn solidity_name(&self, writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result {67 if !T::is_void() {202 if !T::is_void() {68 T::solidity_name(writer)203 T::solidity_name(writer, tc)?;204 if !T::is_simple() {205 write!(writer, " memory")?;206 }207 Ok(())69 } else {208 } else {70 Ok(())209 Ok(())71 }210 }72 }211 }73 fn solidity_get(&self, _writer: &mut impl fmt::Write) -> fmt::Result {212 fn solidity_get(&self, _writer: &mut impl fmt::Write) -> fmt::Result {74 Ok(())213 Ok(())75 }214 }76 fn solidity_default(&self, writer: &mut impl fmt::Write) -> fmt::Result {215 fn solidity_default(&self, writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result {77 T::solidity_default(writer)216 T::solidity_default(writer, tc)78 }217 }79 fn len(&self) -> usize {218 fn len(&self) -> usize {80 if T::is_void() {219 if T::is_void() {94}233}9523496impl<T: SolidityTypeName> SolidityArguments for NamedArgument<T> {235impl<T: SolidityTypeName> SolidityArguments for NamedArgument<T> {97 fn solidity_name(&self, writer: &mut impl fmt::Write) -> fmt::Result {236 fn solidity_name(&self, writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result {98 if !T::is_void() {237 if !T::is_void() {99 T::solidity_name(writer)?;238 T::solidity_name(writer, tc)?;239 if !T::is_simple() {240 write!(writer, " memory")?;241 }100 write!(writer, " {}", self.0)242 write!(writer, " {}", self.0)101 } else {243 } else {102 Ok(())244 Ok(())105 fn solidity_get(&self, writer: &mut impl fmt::Write) -> fmt::Result {247 fn solidity_get(&self, writer: &mut impl fmt::Write) -> fmt::Result {106 writeln!(writer, "\t\t{};", self.0)248 writeln!(writer, "\t\t{};", self.0)107 }249 }108 fn solidity_default(&self, writer: &mut impl fmt::Write) -> fmt::Result {250 fn solidity_default(&self, writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result {109 T::solidity_default(writer)251 T::solidity_default(writer, tc)110 }252 }111 fn len(&self) -> usize {253 fn len(&self) -> usize {112 if T::is_void() {254 if T::is_void() {126}268}127269128impl<T: SolidityTypeName> SolidityArguments for SolidityEventArgument<T> {270impl<T: SolidityTypeName> SolidityArguments for SolidityEventArgument<T> {129 fn solidity_name(&self, writer: &mut impl fmt::Write) -> fmt::Result {271 fn solidity_name(&self, writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result {130 if !T::is_void() {272 if !T::is_void() {131 T::solidity_name(writer)?;273 T::solidity_name(writer, tc)?;132 if self.0 {274 if self.0 {133 write!(writer, " indexed")?;275 write!(writer, " indexed")?;134 }276 }140 fn solidity_get(&self, writer: &mut impl fmt::Write) -> fmt::Result {282 fn solidity_get(&self, writer: &mut impl fmt::Write) -> fmt::Result {141 writeln!(writer, "\t\t{};", self.1)283 writeln!(writer, "\t\t{};", self.1)142 }284 }143 fn solidity_default(&self, writer: &mut impl fmt::Write) -> fmt::Result {285 fn solidity_default(&self, writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result {144 T::solidity_default(writer)286 T::solidity_default(writer, tc)145 }287 }146 fn len(&self) -> usize {288 fn len(&self) -> usize {147 if T::is_void() {289 if T::is_void() {153}295}154296155impl SolidityArguments for () {297impl SolidityArguments for () {156 fn solidity_name(&self, _writer: &mut impl fmt::Write) -> fmt::Result {298 fn solidity_name(&self, _writer: &mut impl fmt::Write, _tc: &TypeCollector) -> fmt::Result {157 Ok(())299 Ok(())158 }300 }159 fn solidity_get(&self, _writer: &mut impl fmt::Write) -> fmt::Result {301 fn solidity_get(&self, _writer: &mut impl fmt::Write) -> fmt::Result {160 Ok(())302 Ok(())161 }303 }162 fn solidity_default(&self, _writer: &mut impl fmt::Write) -> fmt::Result {304 fn solidity_default(&self, _writer: &mut impl fmt::Write, _tc: &TypeCollector) -> fmt::Result {163 Ok(())305 Ok(())164 }306 }165 fn len(&self) -> usize {307 fn len(&self) -> usize {171impl SolidityArguments for Tuple {313impl SolidityArguments for Tuple {172 for_tuples!( where #( Tuple: SolidityArguments ),* );314 for_tuples!( where #( Tuple: SolidityArguments ),* );173315174 fn solidity_name(&self, writer: &mut impl fmt::Write) -> fmt::Result {316 fn solidity_name(&self, writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result {175 let mut first = true;317 let mut first = true;176 for_tuples!( #(318 for_tuples!( #(177 if !Tuple.is_empty() {319 if !Tuple.is_empty() {178 if !first {320 if !first {179 write!(writer, ", ")?;321 write!(writer, ", ")?;180 }322 }181 first = false;323 first = false;182 Tuple.solidity_name(writer)?;324 Tuple.solidity_name(writer, tc)?;183 }325 }184 )* );326 )* );185 Ok(())327 Ok(())190 )* );332 )* );191 Ok(())333 Ok(())192 }334 }193 fn solidity_default(&self, writer: &mut impl fmt::Write) -> fmt::Result {335 fn solidity_default(&self, writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result {194 if self.is_empty() {336 if self.is_empty() {195 Ok(())337 Ok(())196 } else if self.len() == 1 {338 } else if self.len() == 1 {197 for_tuples!( #(339 for_tuples!( #(198 Tuple.solidity_default(writer)?;340 Tuple.solidity_default(writer, tc)?;199 )* );341 )* );200 Ok(())342 Ok(())201 } else {343 } else {207 write!(writer, ", ")?;349 write!(writer, ", ")?;208 }350 }209 first = false;351 first = false;210 Tuple.solidity_name(writer)?;352 Tuple.solidity_default(writer, tc)?;211 }353 }212 )* );354 )* );213 write!(writer, ")")?;355 write!(writer, ")")?;223 fn solidity_name(&self, is_impl: bool, writer: &mut impl fmt::Write) -> fmt::Result;365 fn solidity_name(366 &self,367 is_impl: bool,368 writer: &mut impl fmt::Write,369 tc: &TypeCollector,370 ) -> fmt::Result;224}371}225372238 fn solidity_name(&self, is_impl: bool, writer: &mut impl fmt::Write) -> fmt::Result {385 fn solidity_name(386 &self,387 is_impl: bool,388 writer: &mut impl fmt::Write,389 tc: &TypeCollector,390 ) -> fmt::Result {239 write!(writer, "\tfunction {}(", self.name)?;391 write!(writer, "\tfunction {}(", self.name)?;240 self.args.solidity_name(writer)?;392 self.args.solidity_name(writer, tc)?;241 write!(writer, ")")?;393 write!(writer, ")")?;242 if is_impl {394 if is_impl {243 write!(writer, " public")?;395 write!(writer, " public")?;251 }403 }252 if !self.result.is_empty() {404 if !self.result.is_empty() {253 write!(writer, " returns (")?;405 write!(writer, " returns (")?;254 self.result.solidity_name(writer)?;406 self.result.solidity_name(writer, tc)?;255 write!(writer, ")")?;407 write!(writer, ")")?;256 }408 }257 if is_impl {409 if is_impl {265 }417 }266 if !self.result.is_empty() {418 if !self.result.is_empty() {267 write!(writer, "\t\treturn ")?;419 write!(writer, "\t\treturn ")?;268 self.result.solidity_default(writer)?;420 self.result.solidity_default(writer, tc)?;269 writeln!(writer, ";")?;421 writeln!(writer, ";")?;270 }422 }271 writeln!(writer, "\t}}")?;423 writeln!(writer, "\t}}")?;283 fn solidity_name(&self, is_impl: bool, writer: &mut impl fmt::Write) -> fmt::Result {435 fn solidity_name(436 &self,437 is_impl: bool,438 writer: &mut impl fmt::Write,439 tc: &TypeCollector,440 ) -> fmt::Result {284 let mut first = false;441 let mut first = false;285 for_tuples!( #(442 for_tuples!( #(286 Tuple.solidity_name(is_impl, writer)?;443 Tuple.solidity_name(is_impl, writer, tc)?;287 )* );444 )* );288 Ok(())445 Ok(())289 }446 }299 pub fn format(&self, is_impl: bool, out: &mut impl fmt::Write) -> fmt::Result {456 pub fn format(457 &self,458 is_impl: bool,459 out: &mut impl fmt::Write,460 tc: &TypeCollector,461 ) -> fmt::Result {300 if is_impl {462 if is_impl {301 write!(out, "contract ")?;463 write!(out, "contract ")?;313 }475 }314 }476 }315 writeln!(out, " {{")?;477 writeln!(out, " {{")?;316 self.functions.solidity_name(is_impl, out)?;478 self.functions.solidity_name(is_impl, out, tc)?;317 writeln!(out, "}}")?;479 writeln!(out, "}}")?;318 Ok(())480 Ok(())319 }481 }328 fn solidity_name(&self, _is_impl: bool, writer: &mut impl fmt::Write) -> fmt::Result {490 fn solidity_name(491 &self,492 _is_impl: bool,493 writer: &mut impl fmt::Write,494 tc: &TypeCollector,495 ) -> fmt::Result {329 write!(writer, "\tevent {}(", self.name)?;496 write!(writer, "\tevent {}(", self.name)?;330 self.args.solidity_name(writer)?;497 self.args.solidity_name(writer, tc)?;331 writeln!(writer, ");")498 writeln!(writer, ");")332 }499 }333}500}