git.delta.rocks / unique-network / refs/commits / 4aadc003b1ed

difftreelog

feat support complex types in solidity defs

Yaroslav Bolyukin2021-09-01parent: #07de194.patch.diff
in: master

5 files changed

modifiedcrates/evm-coder-macros/src/solidity_interface.rsdiffbeforeafterboth
1#![allow(dead_code)]1#![allow(dead_code)]
22
3use 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};
1111
12use 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 }
8383
84 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}
123
124enum AbiType {
125 // type
126 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();
178
179 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 };
188
189 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 out
258 }
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}
123274
124struct 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 }
151302
152 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_generators
576 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 {
modifiedcrates/evm-coder-macros/src/to_log.rsdiffbeforeafterboth
179 #consts179 #consts
180 )*180 )*
181181
182 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 }
198198
modifiedcrates/evm-coder/src/abi.rsdiffbeforeafterboth
247impl_abi_readable!(bool, bool);247impl_abi_readable!(bool, bool);
248impl_abi_readable!(string, string);248impl_abi_readable!(string, string);
249
250mod sealed {
251 /// Not all types can be placed in vec, i.e `Vec<u8>` is restricted, `bytes` should be used instead
252 pub trait CanBePlacedInVec {}
253}
254
255impl sealed::CanBePlacedInVec for U256 {}
256impl sealed::CanBePlacedInVec for string {}
257impl sealed::CanBePlacedInVec for H160 {}
258
259impl<R: sealed::CanBePlacedInVec> AbiRead<Vec<R>> for AbiReader<'_>
260where
261 Self: AbiRead<R>,
262{
263 fn abi_read(&mut self) -> Result<Vec<R>> {
264 todo!()
265 }
266}
267
268macro_rules! impl_tuples {
269 ($($ident:ident)+) => {
270 impl<$($ident),+> sealed::CanBePlacedInVec for ($($ident,)+) {}
271 impl<$($ident),+> AbiRead<($($ident,)+)> for AbiReader<'_>
272 where
273 $(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}
283
284impl_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}
249294
250pub trait AbiWrite {295pub trait AbiWrite {
251 fn abi_write(&self, writer: &mut AbiWriter);296 fn abi_write(&self, writer: &mut AbiWriter);
modifiedcrates/evm-coder/src/lib.rsdiffbeforeafterboth
67 #[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 ===");
modifiedcrates/evm-coder/src/solidity.rsdiffbeforeafterboth
1#[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::*;
17
18#[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 v
35 }
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}
657
7pub 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 false
12 }64 }
13}65}
14
15macro_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 $simple
75 }
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}
2983
30solidity_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 true
100 }
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 true
49 }106 }
50}107}
108
109mod sealed {
110 pub trait CanBePlacedInVec {}
111}
112
113impl sealed::CanBePlacedInVec for uint256 {}
114impl sealed::CanBePlacedInVec for string {}
115impl sealed::CanBePlacedInVec for address {}
116
117impl<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 false
124 }
125 fn solidity_default(writer: &mut impl fmt::Write, _tc: &TypeCollector) -> fmt::Result {
126 write!(writer, "[]")
127 }
128}
129
130pub trait SolidityTupleType {
131 fn names(tc: &TypeCollector) -> Vec<String>;
132 fn len() -> usize;
133}
134
135macro_rules! count {
136 () => (0usize);
137 ( $x:tt $($xs:tt)* ) => (1usize + count!($($xs)*));
138}
139
140macro_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 collected
152 }
153
154 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 false
164 }
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}
175
176impl_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}
51186
52pub 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() == 0
58 }193 }
63pub struct UnnamedArgument<T>(PhantomData<*const T>);198pub struct UnnamedArgument<T>(PhantomData<*const T>);
64199
65impl<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}
95234
96impl<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}
127269
128impl<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}
154296
155impl 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 ),* );
173315
174 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}
225372
238 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}