1
1
use syn:: { spanned:: Spanned , FnArg , ImplItem , ItemImpl , Pat , PatIdent , Signature , Type } ;
2
2
3
3
use proc_macro:: TokenStream ;
4
+ use quote:: { quote, ToTokens } ;
4
5
use std:: boxed:: Box ;
5
6
7
+ #[ derive( Clone , Eq , PartialEq , Ord , PartialOrd , Hash , Debug ) ]
8
+ pub enum RpcMode {
9
+ Disabled ,
10
+ Remote ,
11
+ RemoteSync ,
12
+ Master ,
13
+ Puppet ,
14
+ MasterSync ,
15
+ PuppetSync ,
16
+ }
17
+
18
+ impl RpcMode {
19
+ fn parse ( s : & str ) -> Option < Self > {
20
+ match s {
21
+ "remote" => Some ( RpcMode :: Remote ) ,
22
+ "remote_sync" => Some ( RpcMode :: RemoteSync ) ,
23
+ "master" => Some ( RpcMode :: Master ) ,
24
+ "puppet" => Some ( RpcMode :: Puppet ) ,
25
+ "disabled" => Some ( RpcMode :: Disabled ) ,
26
+ "master_sync" => Some ( RpcMode :: MasterSync ) ,
27
+ "puppet_sync" => Some ( RpcMode :: PuppetSync ) ,
28
+ _ => None ,
29
+ }
30
+ }
31
+ }
32
+
33
+ impl Default for RpcMode {
34
+ fn default ( ) -> Self {
35
+ RpcMode :: Disabled
36
+ }
37
+ }
38
+
39
+ impl ToTokens for RpcMode {
40
+ fn to_tokens ( & self , tokens : & mut proc_macro2:: TokenStream ) {
41
+ match self {
42
+ RpcMode :: Disabled => tokens. extend ( quote ! ( RpcMode :: Disabled ) ) ,
43
+ RpcMode :: Remote => tokens. extend ( quote ! ( RpcMode :: Remote ) ) ,
44
+ RpcMode :: RemoteSync => tokens. extend ( quote ! ( RpcMode :: RemoteSync ) ) ,
45
+ RpcMode :: Master => tokens. extend ( quote ! ( RpcMode :: Master ) ) ,
46
+ RpcMode :: Puppet => tokens. extend ( quote ! ( RpcMode :: Puppet ) ) ,
47
+ RpcMode :: MasterSync => tokens. extend ( quote ! ( RpcMode :: MasterSync ) ) ,
48
+ RpcMode :: PuppetSync => tokens. extend ( quote ! ( RpcMode :: PuppetSync ) ) ,
49
+ }
50
+ }
51
+ }
52
+
6
53
pub ( crate ) struct ClassMethodExport {
7
54
pub ( crate ) class_ty : Box < Type > ,
8
55
pub ( crate ) methods : Vec < ExportMethod > ,
@@ -17,6 +64,7 @@ pub(crate) struct ExportMethod {
17
64
#[ derive( Clone , Eq , PartialEq , Ord , PartialOrd , Hash , Debug , Default ) ]
18
65
pub ( crate ) struct ExportArgs {
19
66
pub ( crate ) optional_args : Option < usize > ,
67
+ pub ( crate ) rpc_mode : RpcMode ,
20
68
}
21
69
22
70
pub ( crate ) fn derive_methods ( meta : TokenStream , input : TokenStream ) -> TokenStream {
@@ -69,6 +117,8 @@ pub(crate) fn derive_methods(meta: TokenStream, input: TokenStream) -> TokenStre
69
117
None => 0 ,
70
118
} ;
71
119
120
+ let rpc = args. rpc_mode ;
121
+
72
122
let args = sig. inputs . iter ( ) . enumerate ( ) . map ( |( n, arg) | {
73
123
let span = arg. span ( ) ;
74
124
if n < arg_count - optional_args {
@@ -85,7 +135,7 @@ pub(crate) fn derive_methods(meta: TokenStream, input: TokenStream) -> TokenStre
85
135
fn #name ( #( #args ) * ) -> #ret_ty
86
136
) ;
87
137
88
- #builder. add_method ( #name_string, method) ;
138
+ #builder. add_method_with_rpc_mode ( #name_string, method, #rpc ) ;
89
139
}
90
140
)
91
141
} )
@@ -153,6 +203,7 @@ fn impl_gdnative_expose(ast: ItemImpl) -> (ItemImpl, ClassMethodExport) {
153
203
let items = match func {
154
204
ImplItem :: Method ( mut method) => {
155
205
let mut export_args = None ;
206
+ let mut rpc = None ;
156
207
157
208
let mut errors = vec ! [ ] ;
158
209
@@ -174,7 +225,6 @@ fn impl_gdnative_expose(ast: ItemImpl) -> (ItemImpl, ClassMethodExport) {
174
225
if let Some ( "export" ) = last_seg. as_deref ( ) {
175
226
let _export_args = export_args. get_or_insert_with ( ExportArgs :: default) ;
176
227
if !attr. tokens . is_empty ( ) {
177
- use quote:: ToTokens ;
178
228
use syn:: { Meta , MetaNameValue , NestedMeta } ;
179
229
180
230
let meta = match attr. parse_meta ( ) {
@@ -218,7 +268,7 @@ fn impl_gdnative_expose(ast: ItemImpl) -> (ItemImpl, ClassMethodExport) {
218
268
}
219
269
} ;
220
270
221
- for MetaNameValue { path, .. } in pairs {
271
+ for MetaNameValue { path, lit , .. } in pairs {
222
272
let last = match path. segments . last ( ) {
223
273
Some ( val) => val,
224
274
None => {
@@ -229,9 +279,43 @@ fn impl_gdnative_expose(ast: ItemImpl) -> (ItemImpl, ClassMethodExport) {
229
279
return false ;
230
280
}
231
281
} ;
232
- let unexpected = last. ident . to_string ( ) ;
233
- let msg =
234
- format ! ( "unknown option for export: `{}`" , unexpected) ;
282
+ let path = last. ident . to_string ( ) ;
283
+
284
+ // Match rpc mode
285
+ match path. as_str ( ) {
286
+ "rpc" => {
287
+ let value = if let syn:: Lit :: Str ( lit_str) = lit {
288
+ lit_str. value ( )
289
+ } else {
290
+ errors. push ( syn:: Error :: new (
291
+ last. span ( ) ,
292
+ "unexpected type for rpc value, expected Str" ,
293
+ ) ) ;
294
+ return false ;
295
+ } ;
296
+
297
+ if let Some ( mode) = RpcMode :: parse ( value. as_str ( ) ) {
298
+ if rpc. replace ( mode) . is_some ( ) {
299
+ errors. push ( syn:: Error :: new (
300
+ last. span ( ) ,
301
+ "rpc mode was set more than once" ,
302
+ ) ) ;
303
+ return false ;
304
+ }
305
+ } else {
306
+ errors. push ( syn:: Error :: new (
307
+ last. span ( ) ,
308
+ format ! ( "unexpected value for rpc: {}" , value) ,
309
+ ) ) ;
310
+ return false ;
311
+ }
312
+
313
+ return false ;
314
+ }
315
+ _ => ( ) ,
316
+ }
317
+
318
+ let msg = format ! ( "unknown option for export: `{}`" , path) ;
235
319
errors. push ( syn:: Error :: new ( last. span ( ) , msg) ) ;
236
320
}
237
321
}
@@ -283,6 +367,7 @@ fn impl_gdnative_expose(ast: ItemImpl) -> (ItemImpl, ClassMethodExport) {
283
367
}
284
368
285
369
export_args. optional_args = optional_args;
370
+ export_args. rpc_mode = rpc. unwrap_or ( RpcMode :: Disabled ) ;
286
371
287
372
methods_to_export. push ( ExportMethod {
288
373
sig : method. sig . clone ( ) ,
0 commit comments