@@ -6,6 +6,8 @@ extern crate quote;
66extern crate syn;
77
88use proc_macro:: TokenStream ;
9+ use quote:: Tokens ;
10+ use syn:: { Body , DeriveInput , VariantData } ;
911
1012#[ proc_macro_derive( NapiArgs ) ]
1113pub fn napi_args ( input : TokenStream ) -> TokenStream {
@@ -16,63 +18,18 @@ pub fn napi_args(input: TokenStream) -> TokenStream {
1618 }
1719}
1820
19- fn impl_napi_args (
20- ast : & syn:: DeriveInput ,
21- ) -> Result < quote:: Tokens , & ' static str > {
21+ fn impl_napi_args ( ast : & DeriveInput ) -> Result < Tokens , & ' static str > {
2222 let name = & ast. ident ;
2323
2424 let variant_data = match ast. body {
25- syn :: Body :: Struct ( ref data) => data,
25+ Body :: Struct ( ref data) => data,
2626 _ => return Err ( "NapiArgs can only be derived for structs" ) ,
2727 } ;
2828
29- let ( init_list, count, imports) = match * variant_data {
30- syn:: VariantData :: Struct ( ref fields) => {
31- let inner = fields
32- . iter ( )
33- . enumerate ( )
34- . map ( |( idx, field) | {
35- let ident = field. clone ( ) . ident . unwrap ( ) ;
36- quote ! {
37- #ident: <_ as NapiValue >:: from_sys_checked(
38- env,
39- argv[ #idx] ,
40- ) ?
41- }
42- } )
43- . collect :: < Vec < _ > > ( ) ;
44-
45- let outer = quote ! {
46- { #( #inner) , * }
47- } ;
48-
49- let imports = quote ! {
50- use :: napi:: NapiValue ;
51- } ;
29+ let count = args_count ( variant_data) ;
30+ let ( init_list, imports) = gen_args_code ( variant_data) ;
5231
53- ( Some ( outer) , fields. len ( ) , imports)
54- }
55-
56- syn:: VariantData :: Tuple ( ref fields) => {
57- let inner = ( 0 ..fields. len ( ) )
58- . map ( |idx| {
59- quote ! {
60- <_ as NapiValue >:: from_sys_checked( env, argv[ #idx] ) ?
61- }
62- } )
63- . collect :: < Vec < _ > > ( ) ;
64-
65- let outer = quote ! {
66- ( #( #inner) , * )
67- } ;
68-
69- ( Some ( outer) , fields. len ( ) , quote ! { } )
70- }
71-
72- syn:: VariantData :: Unit => ( None , 0 , quote ! { } ) ,
73- } ;
74-
75- let construct = if let Some ( init_list) = init_list {
32+ let initializer = if let Some ( init_list) = init_list {
7633 quote ! { #name #init_list }
7734 } else {
7835 quote ! { #name }
@@ -81,7 +38,7 @@ fn impl_napi_args(
8138 let ( gen_lifetime, ref_lifetime) = if count > 0 {
8239 ( quote ! { <' env> } , quote ! { ' env } )
8340 } else {
84- ( quote ! { } , quote ! { } )
41+ ( quote ! { } , quote ! { } )
8542 } ;
8643
8744 Ok ( quote ! {
@@ -120,8 +77,67 @@ fn impl_napi_args(
12077 return Err ( NapiError :: type_error( env, & message) ) ;
12178 }
12279
123- Ok ( #construct )
80+ Ok ( #initializer )
12481 }
12582 }
12683 } )
12784}
85+
86+ fn args_count ( variant_data : & VariantData ) -> usize {
87+ match * variant_data {
88+ VariantData :: Struct ( ref fields) | VariantData :: Tuple ( ref fields) => {
89+ fields. len ( )
90+ }
91+ VariantData :: Unit => 0 ,
92+ }
93+ }
94+
95+ fn gen_args_code (
96+ variant_data : & VariantData ,
97+ ) -> ( Option < Tokens > , Option < Tokens > ) {
98+ match * variant_data {
99+ VariantData :: Struct ( ref fields) => {
100+ let inner = fields
101+ . iter ( )
102+ . enumerate ( )
103+ . map ( |( idx, field) | {
104+ let ident = field. clone ( ) . ident . unwrap ( ) ;
105+ quote ! {
106+ #ident: <_ as NapiValue >:: from_sys_checked(
107+ env,
108+ argv[ #idx] ,
109+ ) ?
110+ }
111+ } )
112+ . collect :: < Vec < _ > > ( ) ;
113+
114+ let outer = quote ! {
115+ { #( #inner) , * }
116+ } ;
117+
118+ let imports = quote ! {
119+ use :: napi:: NapiValue ;
120+ } ;
121+
122+ ( Some ( outer) , Some ( imports) )
123+ }
124+
125+ VariantData :: Tuple ( ref fields) => {
126+ let inner = ( 0 ..fields. len ( ) )
127+ . map ( |idx| {
128+ quote ! {
129+ <_ as NapiValue >:: from_sys_checked( env, argv[ #idx] ) ?
130+ }
131+ } )
132+ . collect :: < Vec < _ > > ( ) ;
133+
134+ let outer = quote ! {
135+ ( #( #inner) , * )
136+ } ;
137+
138+ ( Some ( outer) , None )
139+ }
140+
141+ VariantData :: Unit => ( None , None ) ,
142+ }
143+ }
0 commit comments