git.delta.rocks / unique-network / refs/commits / fedf21492c5a

difftreelog

feat generate solidity and abi traits for enums

Trubnikov Sergey2022-11-29parent: #a1ef1e7.patch.diff
in: master

3 files changed

modifiedcrates/evm-coder/procedural/src/abi_derive.rsdiffbeforeafterboth
44 let struct_from_tuple = struct_from_tuple(name, is_named_fields, field_names.clone());44 let struct_from_tuple = struct_from_tuple(name, is_named_fields, field_names.clone());
4545
46 let can_be_plcaed_in_vec = impl_can_be_placed_in_vec(name);46 let can_be_plcaed_in_vec = impl_can_be_placed_in_vec(name);
47 let abi_type = impl_abi_type(name, tuple_type.clone());47 let abi_type = impl_struct_abi_type(name, tuple_type.clone());
48 let abi_read = impl_abi_read(name, tuple_type, tuple_names, struct_from_tuple);48 let abi_read = impl_struct_abi_read(name, tuple_type, tuple_names, struct_from_tuple);
49 let abi_write = impl_abi_write(name, is_named_fields, tuple_ref_type, tuple_data);49 let abi_write = impl_struct_abi_write(name, is_named_fields, tuple_ref_type, tuple_data);
50 let solidity_type = impl_solidity_type(name, field_types.clone(), params_count);50 let solidity_type = impl_struct_solidity_type(name, field_types.clone(), params_count);
51 let solidity_type_name = impl_solidity_type_name(name, field_types.clone(), params_count);51 let solidity_type_name =
52 impl_struct_solidity_type_name(name, field_types.clone(), params_count);
52 let solidity_struct_collect =53 let solidity_struct_collect =
53 impl_solidity_struct_collect(name, field_names, field_types, field_docs, &docs)?;54 impl_struct_solidity_struct_collect(name, field_names, field_types, field_docs, &docs)?;
5455
55 Ok(quote! {56 Ok(quote! {
56 #can_be_plcaed_in_vec57 #can_be_plcaed_in_vec
69) -> syn::Result<proc_macro2::TokenStream> {70) -> syn::Result<proc_macro2::TokenStream> {
70 let name = &ast.ident;71 let name = &ast.ident;
71 check_repr_u8(name, &ast.attrs)?;72 check_repr_u8(name, &ast.attrs)?;
72 check_option_validity(de)?;73 let option_count = check_and_count_option(de)?;
73
74 dbg!(&de);74 let enum_options = de.variants.iter().map(|v| &v.ident);
75
76 let from = impl_enum_from_u8(name, enum_options.clone());
77 let solidity_option = impl_solidity_option(name, enum_options.clone());
78 let can_be_plcaed_in_vec = impl_can_be_placed_in_vec(name);
79 let abi_type = impl_enum_abi_type(name);
80 let abi_read = impl_enum_abi_read(name);
81 let abi_write = impl_enum_abi_write(name);
82 let solidity_type_name = impl_enum_solidity_type_name(name, enum_options.clone());
83 let solidity_struct_collect =
84 impl_enum_solidity_struct_collect(name, enum_options, option_count);
7585
76 Ok(quote!())86 Ok(quote! {
87 #from
88 #solidity_option
89 #can_be_plcaed_in_vec
90 #abi_type
91 #abi_read
92 #abi_write
93 #solidity_type_name
94 #solidity_struct_collect
95 })
77}96}
97
98fn impl_solidity_option<'a>(
99 name: &proc_macro2::Ident,
100 enum_options: impl Iterator<Item = &'a syn::Ident>,
101) -> proc_macro2::TokenStream {
102 let enum_options = enum_options.map(|opt| {
103 let s = name.to_string() + "." + opt.to_string().as_str();
104 let as_string = proc_macro2::Literal::string(s.as_str());
105 quote!(#name::#opt => #as_string,)
106 });
107 quote!(
108 impl ::evm_coder::solidity::SolidityEnum for #name {
109 fn solidity_option(&self) -> &str {
110 match <#name>::default() {
111 #(#enum_options)*
112 }
113 }
114 }
115 )
116}
117
118fn impl_enum_from_u8<'a>(
119 name: &proc_macro2::Ident,
120 enum_options: impl Iterator<Item = &'a syn::Ident>,
121) -> proc_macro2::TokenStream {
122 let enum_options = enum_options.enumerate().map(|(i, opt)| {
123 let n = proc_macro2::Literal::u8_suffixed(i as u8);
124 quote! {#n => Ok(#name::#opt),}
125 });
126 quote!(
127 impl TryFrom<u8> for #name {
128 type Error = &'static str;
129
130 fn try_from(value: u8) -> ::std::result::Result<Self, Self::Error> {
131 const err: &'static str = "Not convertible";
132 match value {
133 #(#enum_options)*
134 _ => Err(err)
135 }
136 }
137 }
138 )
139}
140
141fn impl_enum_abi_type(name: &syn::Ident) -> proc_macro2::TokenStream {
142 quote! {
143 impl ::evm_coder::abi::AbiType for #name {
144 const SIGNATURE: ::evm_coder::custom_signature::SignatureUnit = <u8 as ::evm_coder::abi::AbiType>::SIGNATURE;
145
146 fn is_dynamic() -> bool {
147 <u8 as ::evm_coder::abi::AbiType>::is_dynamic()
148 }
149 fn size() -> usize {
150 <u8 as ::evm_coder::abi::AbiType>::size()
151 }
152 }
153 }
154}
155
156fn impl_enum_abi_read(name: &syn::Ident) -> proc_macro2::TokenStream {
157 quote!(
158 impl ::evm_coder::abi::AbiRead for #name {
159 fn abi_read(reader: &mut ::evm_coder::abi::AbiReader) -> ::evm_coder::execution::Result<Self> {
160 Ok(
161 <u8 as ::evm_coder::abi::AbiRead>::abi_read(reader)?
162 .try_into()?
163 )
164 }
165 }
166 )
167}
168
169fn impl_enum_abi_write(name: &syn::Ident) -> proc_macro2::TokenStream {
170 quote!(
171 impl ::evm_coder::abi::AbiWrite for #name {
172 fn abi_write(&self, writer: &mut ::evm_coder::abi::AbiWriter) {
173 ::evm_coder::abi::AbiWrite::abi_write(&(*self as u8), writer);
174 }
175 }
176 )
177}
178
179fn impl_enum_solidity_type_name<'a>(
180 name: &syn::Ident,
181 enum_options: impl Iterator<Item = &'a syn::Ident>,
182) -> proc_macro2::TokenStream {
183 let enum_options = enum_options.map(|opt| quote!(,));
184 quote!(
185 #[cfg(feature = "stubgen")]
186 impl ::evm_coder::solidity::SolidityTypeName for #name {
187 fn solidity_name(
188 writer: &mut impl ::core::fmt::Write,
189 tc: &::evm_coder::solidity::TypeCollector,
190 ) -> ::core::fmt::Result {
191 write!(writer, "{}", tc.collect_struct::<Self>())
192 }
193
194 fn is_simple() -> bool {
195 true
196 }
197
198 fn solidity_default(
199 writer: &mut impl ::core::fmt::Write,
200 tc: &::evm_coder::solidity::TypeCollector,
201 ) -> ::core::fmt::Result {
202 write!(writer, "{}", <#name as ::evm_coder::solidity::SolidityEnum>::solidity_option(&<#name>::default()))
203 }
204 }
205 )
206}
207
208fn impl_enum_solidity_struct_collect<'a>(
209 name: &syn::Ident,
210 enum_options: impl Iterator<Item = &'a syn::Ident>,
211 option_count: usize,
212) -> proc_macro2::TokenStream {
213 let string_name = name.to_string();
214 let enum_options = enum_options.enumerate().map(|(i, opt)| {
215 let opt = proc_macro2::Literal::string(opt.to_string().as_str());
216 let comma = if i != option_count - 1 { "," } else { "" };
217 quote! {
218 writeln!(str, "\t{}{}", #opt, #comma).expect("Enum format option");
219 }
220 });
221 quote!(
222 #[cfg(feature = "stubgen")]
223 impl ::evm_coder::solidity::StructCollect for #name {
224 fn name() -> String {
225 #string_name.into()
226 }
227
228 fn declaration() -> String {
229 use std::fmt::Write;
230
231 let mut str = String::new();
232 // #(#docs)*
233 writeln!(str, "enum {} {{", <Self as ::evm_coder::solidity::StructCollect>::name()).unwrap();
234 #(#enum_options)*
235 writeln!(str, "}}").unwrap();
236 str
237 }
238 }
239 )
240}
78241
79fn check_option_validity(de: &syn::DataEnum) -> syn::Result<()> {242fn check_and_count_option(de: &syn::DataEnum) -> syn::Result<usize> {
243 let mut count = 0;
80 for error in de.variants.iter().filter_map(|v| {244 for error in de.variants.iter().filter_map(|v| {
81 if !v.fields.is_empty() {245 if !v.fields.is_empty() {
82 Some(Err(syn::Error::new(246 Some(Err(syn::Error::new(
89 "Enumeration options should not have an explicit specified value",253 "Enumeration options should not have an explicit specified value",
90 )))254 )))
91 } else {255 } else {
256 count += 1;
92 None257 None
93 }258 }
94 }) {259 }) {
95 return error;260 return error;
96 }261 }
97262
98 Ok(())263 Ok(count)
99}264}
100265
101fn check_repr_u8(name: &syn::Ident, attrs: &Vec<syn::Attribute>) -> syn::Result<()> {266fn check_repr_u8(name: &syn::Ident, attrs: &Vec<syn::Attribute>) -> syn::Result<()> {
271 }436 }
272}437}
273438
274fn impl_abi_type(439fn impl_struct_abi_type(
275 name: &syn::Ident,440 name: &syn::Ident,
276 tuple_type: proc_macro2::TokenStream,441 tuple_type: proc_macro2::TokenStream,
277) -> proc_macro2::TokenStream {442) -> proc_macro2::TokenStream {
288 }453 }
289}454}
290455
291fn impl_abi_read(456fn impl_struct_abi_read(
292 name: &syn::Ident,457 name: &syn::Ident,
293 tuple_type: proc_macro2::TokenStream,458 tuple_type: proc_macro2::TokenStream,
294 tuple_names: proc_macro2::TokenStream,459 tuple_names: proc_macro2::TokenStream,
304 )469 )
305}470}
306471
307fn impl_abi_write(472fn impl_struct_abi_write(
308 name: &syn::Ident,473 name: &syn::Ident,
309 _is_named_fields: bool,474 _is_named_fields: bool,
310 tuple_type: proc_macro2::TokenStream,475 tuple_type: proc_macro2::TokenStream,
319 )484 )
320}485}
321486
322fn impl_solidity_type<'a>(487fn impl_struct_solidity_type<'a>(
323 name: &syn::Ident,488 name: &syn::Ident,
324 field_types: impl Iterator<Item = &'a syn::Type> + Clone,489 field_types: impl Iterator<Item = &'a syn::Type> + Clone,
325 params_count: usize,490 params_count: usize,
347 }512 }
348}513}
349514
350fn impl_solidity_type_name<'a>(515fn impl_struct_solidity_type_name<'a>(
351 name: &syn::Ident,516 name: &syn::Ident,
352 field_types: impl Iterator<Item = &'a syn::Type> + Clone,517 field_types: impl Iterator<Item = &'a syn::Type> + Clone,
353 params_count: usize,518 params_count: usize,
390 }555 }
391}556}
392557
393fn impl_solidity_struct_collect<'a>(558fn impl_struct_solidity_struct_collect<'a>(
394 name: &syn::Ident,559 name: &syn::Ident,
395 field_names: impl Iterator<Item = proc_macro2::Ident> + Clone,560 field_names: impl Iterator<Item = proc_macro2::Ident> + Clone,
396 field_types: impl Iterator<Item = &'a syn::Type> + Clone,561 field_types: impl Iterator<Item = &'a syn::Type> + Clone,
modifiedcrates/evm-coder/src/solidity/traits.rsdiffbeforeafterboth
8 fn declaration() -> String;8 fn declaration() -> String;
9}9}
10
11pub trait SolidityEnum: 'static {
12 fn solidity_option(&self) -> &str;
13}
1014
11pub trait SolidityTypeName: 'static {15pub trait SolidityTypeName: 'static {
12 fn solidity_name(writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result;16 fn solidity_name(writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result;
modifiedcrates/evm-coder/tests/abi_derive_generation.rsdiffbeforeafterboth
7575
76 #[test]76 #[test]
77 #[cfg(feature = "stubgen")]77 #[cfg(feature = "stubgen")]
78 fn struct_collect_TypeStruct3DerivedMixedParam() {78 fn struct_collect_type_struct3_derived_mixed_param() {
79 assert_eq!(79 assert_eq!(
80 <TypeStruct3DerivedMixedParam as ::evm_coder::solidity::StructCollect>::name(),80 <TypeStruct3DerivedMixedParam as ::evm_coder::solidity::StructCollect>::name(),
81 "TypeStruct3DerivedMixedParam"81 "TypeStruct3DerivedMixedParam"
296296
297 #[test]297 #[test]
298 #[cfg(feature = "stubgen")]298 #[cfg(feature = "stubgen")]
299 fn struct_collect_TupleStruct3DerivedMixedParam() {299 fn struct_collect_tuple_struct3_derived_mixed_param() {
300 assert_eq!(300 assert_eq!(
301 <TupleStruct3DerivedMixedParam as ::evm_coder::solidity::StructCollect>::name(),301 <TupleStruct3DerivedMixedParam as ::evm_coder::solidity::StructCollect>::name(),
302 "TupleStruct3DerivedMixedParam"302 "TupleStruct3DerivedMixedParam"
739mod test_enum {739mod test_enum {
740 use evm_coder::AbiCoder;740 use evm_coder::AbiCoder;
741741
742 #[derive(AbiCoder)]742 #[derive(AbiCoder, Default)]
743 #[repr(u8)]743 #[repr(u8)]
744 enum Color {744 enum Color {
745 Red,745 Red,
746 Green,746 Green,
747 #[default]
747 Blue,748 Blue,
748 }749 }
749750