@@ -119,7 +119,7 @@ fn generate_eng_wasm_aux_functions(
119
119
0 => String :: new( ) ,
120
120
length => {
121
121
let mut data = Vec :: with_capacity( length as usize ) ;
122
- for _ in 0 ..length{
122
+ for _ in 0 ..length {
123
123
data. push( 0 ) ;
124
124
}
125
125
@@ -146,7 +146,7 @@ fn generate_eng_wasm_aux_functions(
146
146
0 => Vec :: new( ) ,
147
147
length => {
148
148
let mut data = Vec :: with_capacity( length as usize ) ;
149
- for _ in 0 ..length{
149
+ for _ in 0 ..length {
150
150
data. push( 0 ) ;
151
151
}
152
152
@@ -174,15 +174,15 @@ fn generate_deploy_function(
174
174
let input_pats_and_types = get_signature_input_pats_and_types ( & constructor_signature) ;
175
175
let expectations = get_contract_input_parsing_error_messages ( & input_pats_and_types) ;
176
176
let input_types = input_pats_and_types. iter ( ) . map ( |( _pat, type_) | type_) ;
177
+ let variables = generate_enumerated_idents ( "var_" , input_pats_and_types. len ( ) ) ;
177
178
178
179
return quote ! {
179
180
#[ no_mangle]
180
181
pub fn #deploy_func_name( ) {
181
182
let args_ = args( ) ;
182
183
let mut stream = eng_wasm:: eng_pwasm_abi:: eth:: Stream :: new( & args_) ;
183
- <#implementor>:: #constructor_name( #(
184
- stream. pop:: <#input_types>( ) . expect( #expectations) ,
185
- ) * ) ;
184
+ #( let #variables = stream. pop:: <#input_types>( ) . expect( #expectations) ; ) *
185
+ <#implementor>:: #constructor_name( #( #variables) , * ) ;
186
186
}
187
187
} ;
188
188
} else {
@@ -242,6 +242,7 @@ fn generate_dispatch_function(
242
242
let input_pats_and_types = get_signature_input_pats_and_types ( & signature) ;
243
243
let expectations = get_contract_input_parsing_error_messages ( & input_pats_and_types) ;
244
244
let input_types = input_pats_and_types. iter ( ) . map ( |( _pat, type_) | type_) ;
245
+ let variables = generate_enumerated_idents ( "var_" , input_pats_and_types. len ( ) ) ;
245
246
246
247
let return_value_count = match output_type {
247
248
syn:: ReturnType :: Default => 0 ,
@@ -260,17 +261,26 @@ fn generate_dispatch_function(
260
261
}
261
262
} ;
262
263
264
+ // Make sure we only generate code for initializing the stream of inputs,
265
+ // if we expect inputs at all
266
+ let stream_initialization_snippet = match input_pats_and_types. len ( ) {
267
+ 0 => quote ! ( ) ,
268
+ _ => quote ! ( let mut stream = eng_wasm:: eng_pwasm_abi:: eth:: Stream :: new( args) ; ) ,
269
+ } ;
270
+
263
271
match return_value_count {
264
272
0 => Some ( quote ! {
265
273
#method_name_as_string => {
266
- let mut stream = eng_wasm:: eng_pwasm_abi:: eth:: Stream :: new( args) ;
267
- <#implementor>:: #method_name( #( stream. pop:: <#input_types>( ) . expect( #expectations) , ) * ) ;
274
+ #stream_initialization_snippet
275
+ #( let #variables = stream. pop:: <#input_types>( ) . expect( #expectations) ; ) *
276
+ <#implementor>:: #method_name( #( #variables) , * ) ;
268
277
}
269
278
} ) ,
270
279
_ => Some ( quote ! {
271
280
#method_name_as_string => {
272
- let mut stream = eng_wasm:: eng_pwasm_abi:: eth:: Stream :: new( args) ;
273
- let result = <#implementor>:: #method_name( #( stream. pop:: <#input_types>( ) . expect( #expectations) , ) * ) ;
281
+ #stream_initialization_snippet
282
+ #( let #variables = stream. pop:: <#input_types>( ) . expect( #expectations) ; ) *
283
+ let result = <#implementor>:: #method_name( #( #variables) , * ) ;
274
284
// 32 is the size of each argument in the serialised form
275
285
// The Sink.drain_to() method might resize this array if any
276
286
// dynamically sized elements are returned, but if not, then only one
@@ -297,10 +307,62 @@ fn generate_dispatch_function(
297
307
}
298
308
}
299
309
310
+ /// Generate `count` identifiers with the specified prefix, and a decimal suffix in ascending order.
311
+ ///
312
+ /// for example, calling `generate_enumerated_idents("var_", 5)` will generate a vector with the
313
+ /// identifiers `var_0`, `var_1`, `var_2`, `var_3`, `var_4`.
314
+ fn generate_enumerated_idents ( prefix : & str , count : usize ) -> Vec < syn:: Ident > {
315
+ ( 0 ..count)
316
+ . map ( |index| quote:: format_ident!( "{}{}" , prefix, index) )
317
+ . collect ( )
318
+ }
319
+
300
320
#[ cfg( test) ]
301
321
mod tests {
302
322
use super :: * ;
303
323
324
+ /// This is here to use as a sanity check on the full generated code.
325
+ ///
326
+ /// To see what code is generated, comment out the `#[ignore]` line, and run
327
+ /// ```sh
328
+ /// cargo test show_output -- --nocapture
329
+ /// ```
330
+ /// Then, take the output from the console (between the two dotted lines, drop it into
331
+ /// https://play.rust-lang.org/ , and under the tools menu, choose "Rustfmt".
332
+ #[ test]
333
+ #[ ignore]
334
+ fn show_output ( ) {
335
+ let input = quote ! (
336
+ pub trait Erc20Interface {
337
+ fn construct( contract_owner: H256 , total_supply: U256 ) ;
338
+ /// creates new tokens and sends to the specified address
339
+ fn mint( owner: H256 , addr: H256 , tokens: U256 , sig: Vec <u8 >) ;
340
+ /// get the total_supply
341
+ fn total_supply( ) -> U256 ;
342
+ /// get the balance of the specified address
343
+ fn balance_of( token_owner: H256 ) -> U256 ;
344
+ /// get the allowed amount of the owner tokens to be spent by the spender address
345
+ fn allowance( owner: H256 , spender: H256 ) -> U256 ;
346
+ /// transfer tokens from 'from' address to the 'to' address.
347
+ /// the function panics if the 'from' address does not have enough tokens.
348
+ fn transfer( from: H256 , to: H256 , tokens: U256 , sig: Vec <u8 >) ;
349
+ /// approve the 'spender' address to spend 'tokens' from the 'owner's address balance.
350
+ /// the function panics if the 'owner' address does not have enough tokens.
351
+ fn approve( token_owner: H256 , spender: H256 , tokens: U256 , sig: Vec <u8 >) ;
352
+ /// 'spender' address transfers tokens on behalf of the owner address to the 'to' address.
353
+ /// the function panics if the 'owner' address does not have enough tokens or the 'spender'
354
+ /// address does not have enough tokens as well.
355
+ fn transfer_from( owner: H256 , spender: H256 , to: H256 , tokens: U256 , sig: Vec <u8 >) ;
356
+ }
357
+ ) ;
358
+
359
+ let output = impl_pub_interface ( quote ! ( ) , input) ;
360
+
361
+ eprintln ! ( "{:-<80}" , "" ) ;
362
+ eprintln ! ( "{}" , output) ;
363
+ eprintln ! ( "{:-<80}" , "" ) ;
364
+ }
365
+
304
366
#[ test]
305
367
fn apply_macro_attr_works_on_trait ( ) {
306
368
let attr_tokens = quote ! ( Bar ) ;
@@ -433,14 +495,13 @@ mod tests {
433
495
pub fn deploy( ) {
434
496
let args_ = args( ) ;
435
497
let mut stream = eng_wasm:: eng_pwasm_abi:: eth:: Stream :: new( & args_) ;
436
- <Contract >:: construct(
437
- stream
438
- . pop:: <H256 >( )
439
- . expect( "could not decode argument `contract_owner` as `H256`" ) ,
440
- stream
441
- . pop:: <U256 >( )
442
- . expect( "could not decode argument `total_supply` as `U256`" ) ,
443
- ) ;
498
+ let var_0 = stream
499
+ . pop:: <H256 >( )
500
+ . expect( "could not decode argument `contract_owner` as `H256`" ) ;
501
+ let var_1 = stream
502
+ . pop:: <U256 >( )
503
+ . expect( "could not decode argument `total_supply` as `U256`" ) ;
504
+ <Contract >:: construct( var_0, var_1) ;
444
505
}
445
506
) ;
446
507
@@ -486,23 +547,21 @@ mod tests {
486
547
match name {
487
548
"mint" => {
488
549
let mut stream = eng_wasm:: eng_pwasm_abi:: eth:: Stream :: new( args) ;
489
- <Contract >:: mint(
490
- stream
491
- . pop:: <H256 >( )
492
- . expect( "could not decode argument `owner` as `H256`" ) ,
493
- stream
494
- . pop:: <H256 >( )
495
- . expect( "could not decode argument `addr` as `H256`" ) ,
496
- stream
497
- . pop:: <U256 >( )
498
- . expect( "could not decode argument `tokens` as `U256`" ) ,
499
- stream
500
- . pop:: <Vec <u8 >>( )
501
- . expect( "could not decode argument `sig` as `Vec < u8 >`" ) ,
502
- ) ;
550
+ let var_0 = stream
551
+ . pop:: <H256 >( )
552
+ . expect( "could not decode argument `owner` as `H256`" ) ;
553
+ let var_1 = stream
554
+ . pop:: <H256 >( )
555
+ . expect( "could not decode argument `addr` as `H256`" ) ;
556
+ let var_2 = stream
557
+ . pop:: <U256 >( )
558
+ . expect( "could not decode argument `tokens` as `U256`" ) ;
559
+ let var_3 = stream
560
+ . pop:: <Vec <u8 >>( )
561
+ . expect( "could not decode argument `sig` as `Vec < u8 >`" ) ;
562
+ <Contract >:: mint( var_0, var_1, var_2, var_3) ;
503
563
}
504
564
"total_supply" => {
505
- let mut stream = eng_wasm:: eng_pwasm_abi:: eth:: Stream :: new( args) ;
506
565
let result = <Contract >:: total_supply( ) ;
507
566
let mut result_bytes = eng_wasm:: Vec :: with_capacity( 1usize * 32 ) ;
508
567
let mut sink = eng_wasm:: eng_pwasm_abi:: eth:: Sink :: new( 1usize ) ;
@@ -517,11 +576,10 @@ mod tests {
517
576
}
518
577
"balance_of" => {
519
578
let mut stream = eng_wasm:: eng_pwasm_abi:: eth:: Stream :: new( args) ;
520
- let result = <Contract >:: balance_of(
521
- stream
522
- . pop:: <H256 >( )
523
- . expect( "could not decode argument `token_owner` as `H256`" ) ,
524
- ) ;
579
+ let var_0 = stream
580
+ . pop:: <H256 >( )
581
+ . expect( "could not decode argument `token_owner` as `H256`" ) ;
582
+ let result = <Contract >:: balance_of( var_0) ;
525
583
let mut result_bytes = eng_wasm:: Vec :: with_capacity( 1usize * 32 ) ;
526
584
let mut sink = eng_wasm:: eng_pwasm_abi:: eth:: Sink :: new( 1usize ) ;
527
585
sink. push( result) ;
@@ -535,14 +593,13 @@ mod tests {
535
593
}
536
594
"allowance" => {
537
595
let mut stream = eng_wasm:: eng_pwasm_abi:: eth:: Stream :: new( args) ;
538
- let result = <Contract >:: allowance(
539
- stream
540
- . pop:: <H256 >( )
541
- . expect( "could not decode argument `owner` as `H256`" ) ,
542
- stream
543
- . pop:: <H256 >( )
544
- . expect( "could not decode argument `spender` as `H256`" ) ,
545
- ) ;
596
+ let var_0 = stream
597
+ . pop:: <H256 >( )
598
+ . expect( "could not decode argument `owner` as `H256`" ) ;
599
+ let var_1 = stream
600
+ . pop:: <H256 >( )
601
+ . expect( "could not decode argument `spender` as `H256`" ) ;
602
+ let result = <Contract >:: allowance( var_0, var_1) ;
546
603
let mut result_bytes = eng_wasm:: Vec :: with_capacity( 1usize * 32 ) ;
547
604
let mut sink = eng_wasm:: eng_pwasm_abi:: eth:: Sink :: new( 1usize ) ;
548
605
sink. push( result) ;
@@ -556,57 +613,54 @@ mod tests {
556
613
}
557
614
"transfer" => {
558
615
let mut stream = eng_wasm:: eng_pwasm_abi:: eth:: Stream :: new( args) ;
559
- <Contract >:: transfer(
560
- stream
561
- . pop:: <H256 >( )
562
- . expect( "could not decode argument `from` as `H256`" ) ,
563
- stream
564
- . pop:: <H256 >( )
565
- . expect( "could not decode argument `to` as `H256`" ) ,
566
- stream
567
- . pop:: <U256 >( )
568
- . expect( "could not decode argument `tokens` as `U256`" ) ,
569
- stream
570
- . pop:: <Vec <u8 >>( )
571
- . expect( "could not decode argument `sig` as `Vec < u8 >`" ) ,
572
- ) ;
616
+ let var_0 = stream
617
+ . pop:: <H256 >( )
618
+ . expect( "could not decode argument `from` as `H256`" ) ;
619
+ let var_1 = stream
620
+ . pop:: <H256 >( )
621
+ . expect( "could not decode argument `to` as `H256`" ) ;
622
+ let var_2 = stream
623
+ . pop:: <U256 >( )
624
+ . expect( "could not decode argument `tokens` as `U256`" ) ;
625
+ let var_3 = stream
626
+ . pop:: <Vec <u8 >>( )
627
+ . expect( "could not decode argument `sig` as `Vec < u8 >`" ) ;
628
+ <Contract >:: transfer( var_0, var_1, var_2, var_3) ;
573
629
}
574
630
"approve" => {
575
631
let mut stream = eng_wasm:: eng_pwasm_abi:: eth:: Stream :: new( args) ;
576
- <Contract >:: approve(
577
- stream
578
- . pop:: <H256 >( )
579
- . expect( "could not decode argument `token_owner` as `H256`" ) ,
580
- stream
581
- . pop:: <H256 >( )
582
- . expect( "could not decode argument `spender` as `H256`" ) ,
583
- stream
584
- . pop:: <U256 >( )
585
- . expect( "could not decode argument `tokens` as `U256`" ) ,
586
- stream
587
- . pop:: <Vec <u8 >>( )
588
- . expect( "could not decode argument `sig` as `Vec < u8 >`" ) ,
589
- ) ;
632
+ let var_0 = stream
633
+ . pop:: <H256 >( )
634
+ . expect( "could not decode argument `token_owner` as `H256`" ) ;
635
+ let var_1 = stream
636
+ . pop:: <H256 >( )
637
+ . expect( "could not decode argument `spender` as `H256`" ) ;
638
+ let var_2 = stream
639
+ . pop:: <U256 >( )
640
+ . expect( "could not decode argument `tokens` as `U256`" ) ;
641
+ let var_3 = stream
642
+ . pop:: <Vec <u8 >>( )
643
+ . expect( "could not decode argument `sig` as `Vec < u8 >`" ) ;
644
+ <Contract >:: approve( var_0, var_1, var_2, var_3) ;
590
645
}
591
646
"transfer_from" => {
592
647
let mut stream = eng_wasm:: eng_pwasm_abi:: eth:: Stream :: new( args) ;
593
- <Contract >:: transfer_from(
594
- stream
595
- . pop:: <H256 >( )
596
- . expect( "could not decode argument `owner` as `H256`" ) ,
597
- stream
598
- . pop:: <H256 >( )
599
- . expect( "could not decode argument `spender` as `H256`" ) ,
600
- stream
601
- . pop:: <H256 >( )
602
- . expect( "could not decode argument `to` as `H256`" ) ,
603
- stream
604
- . pop:: <U256 >( )
605
- . expect( "could not decode argument `tokens` as `U256`" ) ,
606
- stream
607
- . pop:: <Vec <u8 >>( )
608
- . expect( "could not decode argument `sig` as `Vec < u8 >`" ) ,
609
- ) ;
648
+ let var_0 = stream
649
+ . pop:: <H256 >( )
650
+ . expect( "could not decode argument `owner` as `H256`" ) ;
651
+ let var_1 = stream
652
+ . pop:: <H256 >( )
653
+ . expect( "could not decode argument `spender` as `H256`" ) ;
654
+ let var_2 = stream
655
+ . pop:: <H256 >( )
656
+ . expect( "could not decode argument `to` as `H256`" ) ;
657
+ let var_3 = stream
658
+ . pop:: <U256 >( )
659
+ . expect( "could not decode argument `tokens` as `U256`" ) ;
660
+ let var_4 = stream
661
+ . pop:: <Vec <u8 >>( )
662
+ . expect( "could not decode argument `sig` as `Vec < u8 >`" ) ;
663
+ <Contract >:: transfer_from( var_0, var_1, var_2, var_3, var_4) ;
610
664
}
611
665
_ => panic!( "Unknown method called:\" {}\" " , name) ,
612
666
}
0 commit comments