@@ -47,15 +47,18 @@ func BuildImplementationRust(component ComponentDefinition, outputFolder string,
47
47
forceRebuild := true
48
48
LibraryName := component .LibraryName
49
49
BaseName := component .BaseName
50
+ modfiles := make ([]string , 0 )
50
51
indentString := getIndentationString (implementation .Indentation )
51
52
52
53
stubIdentifier := ""
53
54
if len (implementation .StubIdentifier ) > 0 {
54
55
stubIdentifier = "_" + strings .ToLower (implementation .StubIdentifier )
55
56
}
56
57
57
- IntfFileName := BaseName + "_interfaces.rs"
58
+ InterfaceMod := BaseName + "_interfaces"
59
+ IntfFileName := InterfaceMod + ".rs"
58
60
IntfFilePath := path .Join (outputFolder , IntfFileName )
61
+ modfiles = append (modfiles , IntfFilePath )
59
62
log .Printf ("Creating \" %s\" " , IntfFilePath )
60
63
IntfRSFile , err := CreateLanguageFile (IntfFilePath , indentString )
61
64
if err != nil {
@@ -68,12 +71,13 @@ func BuildImplementationRust(component ComponentDefinition, outputFolder string,
68
71
if err != nil {
69
72
return err
70
73
}
71
- err = buildRustInterfaces (component , IntfRSFile , implementation . ClassIdentifier )
74
+ err = buildRustInterfaces (component , IntfRSFile )
72
75
if err != nil {
73
76
return err
74
77
}
75
78
76
79
IntfWrapperStubName := path .Join (stubOutputFolder , BaseName + stubIdentifier + ".rs" )
80
+ modfiles = append (modfiles , IntfWrapperStubName )
77
81
if forceRebuild || ! FileExists (IntfWrapperStubName ) {
78
82
log .Printf ("Creating \" %s\" " , IntfWrapperStubName )
79
83
stubfile , err := CreateLanguageFile (IntfWrapperStubName , indentString )
@@ -83,19 +87,62 @@ func BuildImplementationRust(component ComponentDefinition, outputFolder string,
83
87
stubfile .WriteCLicenseHeader (component ,
84
88
fmt .Sprintf ("This is an autogenerated Rust implementation file in order to allow easy\n development of %s. It needs to be generated only once." , LibraryName ),
85
89
true )
86
- RelInterfaceFile , err := filepath .Rel (stubOutputFolder , IntfFilePath )
87
90
if err != nil {
88
91
return err
89
92
}
90
- err = buildRustGlobalStubFile (component , stubfile , implementation . ClassIdentifier , RelInterfaceFile )
93
+ err = buildRustGlobalStubFile (component , stubfile , InterfaceMod )
91
94
if err != nil {
92
95
return err
93
96
}
94
97
} else {
95
98
log .Printf ("Omitting recreation of implementation stub \" %s\" " , IntfWrapperStubName )
96
99
}
97
100
101
+ for i := 0 ; i < len (component .Classes ); i ++ {
102
+ class := component .Classes [i ]
103
+ StubBase := BaseName + stubIdentifier
104
+ StubClassName := path .Join (stubOutputFolder , StubBase + "_" + toSnakeCase (class .ClassName )+ ".rs" )
105
+ modfiles = append (modfiles , StubClassName )
106
+ if forceRebuild || ! FileExists (StubClassName ) {
107
+ log .Printf ("Creating \" %s\" " , StubClassName )
108
+ stubfile , err := CreateLanguageFile (StubClassName , indentString )
109
+ if err != nil {
110
+ return err
111
+ }
112
+ stubfile .WriteCLicenseHeader (component ,
113
+ fmt .Sprintf ("This is an autogenerated Rust implementation file in order to allow easy\n development of %s. It needs to be generated only once." , LibraryName ),
114
+ true )
115
+ if err != nil {
116
+ return err
117
+ }
118
+ err = buildRustStubFile (component , class , stubfile , InterfaceMod , StubBase )
119
+ if err != nil {
120
+ return err
121
+ }
122
+ } else {
123
+ log .Printf ("Omitting recreation of implementation stub \" %s\" " , StubClassName )
124
+ }
125
+ }
126
+
98
127
if len (projectOutputFolder ) > 0 {
128
+ IntfWrapperLibName := path .Join (projectOutputFolder , "lib.rs" )
129
+ if forceRebuild || ! FileExists (IntfWrapperLibName ) {
130
+ log .Printf ("Creating \" %s\" " , IntfWrapperLibName )
131
+ libfile , err := CreateLanguageFile (IntfWrapperLibName , indentString )
132
+ if err != nil {
133
+ return err
134
+ }
135
+ libfile .WriteCLicenseHeader (component ,
136
+ fmt .Sprintf ("This is an autogenerated Rust implementation file in order to allow easy\n development of %s. It needs to be generated only once." , LibraryName ),
137
+ true )
138
+ err = buildRustGlobalLibFile (component , libfile , projectOutputFolder , modfiles )
139
+ if err != nil {
140
+ return err
141
+ }
142
+ } else {
143
+ log .Printf ("Omitting recreation of lib \" %s\" " , IntfWrapperLibName )
144
+ }
145
+
99
146
CargoFileName := path .Join (projectOutputFolder , "Cargo.toml" )
100
147
if forceRebuild || ! FileExists (CargoFileName ) {
101
148
log .Printf ("Creating Cargo file \" %s\" for Rust Implementation" , CargoFileName )
@@ -106,7 +153,7 @@ func BuildImplementationRust(component ComponentDefinition, outputFolder string,
106
153
CargoFile .WriteTomlLicenseHeader (component ,
107
154
fmt .Sprintf ("This is an autogenerated Cargo file for the development of %s." , LibraryName ),
108
155
true )
109
- LibPath , err := filepath .Rel (projectOutputFolder , IntfWrapperStubName )
156
+ LibPath , err := filepath .Rel (projectOutputFolder , IntfWrapperLibName )
110
157
if err != nil {
111
158
return err
112
159
}
@@ -119,16 +166,24 @@ func BuildImplementationRust(component ComponentDefinition, outputFolder string,
119
166
return nil
120
167
}
121
168
122
- func buildRustGlobalStubFile (component ComponentDefinition , w LanguageWriter , ClassIdentifier string , RelInterfaceFile string ) error {
169
+ func buildRustGlobalLibFile (component ComponentDefinition , w LanguageWriter , basedir string , modfiles [] string ) error {
123
170
w .Writeln ("" )
124
171
// Get all modules
125
- w .Writeln ("#[path = \" %s\" ]" , strings .ReplaceAll (RelInterfaceFile , "\\ " , "/" ))
126
- IntfName := strings .TrimSuffix (filepath .Base (RelInterfaceFile ), ".rs" )
127
- w .Writeln ("mod %s;" , IntfName )
172
+ for i := 0 ; i < len (modfiles ); i ++ {
173
+ modfile := modfiles [i ]
174
+ relfile , err := filepath .Rel (basedir , modfile )
175
+ if err != nil {
176
+ return err
177
+ }
178
+ w .Writeln ("#[path = \" %s\" ]" , strings .ReplaceAll (relfile , "\\ " , "/" ))
179
+ IntfName := strings .TrimSuffix (filepath .Base (relfile ), ".rs" )
180
+ w .Writeln ("mod %s;" , IntfName )
181
+ w .Writeln ("" )
182
+ }
128
183
return nil
129
184
}
130
185
131
- func buildRustInterfaces (component ComponentDefinition , w LanguageWriter , ClassIdentifier string ) error {
186
+ func buildRustInterfaces (component ComponentDefinition , w LanguageWriter ) error {
132
187
NameSpace := component .NameSpace
133
188
w .Writeln ("/*************************************************************************************************************************" )
134
189
w .Writeln (" Traits defined for %s" , NameSpace )
@@ -178,7 +233,7 @@ func writeRustTrait(component ComponentDefinition, class ComponentDefinitionClas
178
233
parentClassString = fmt .Sprintf (": %s " , class .ParentClass )
179
234
}
180
235
}
181
- w .Writeln ("trait %s %s {" , class .ClassName , parentClassString )
236
+ w .Writeln ("pub trait %s %s {" , class .ClassName , parentClassString )
182
237
w .AddIndentationLevel (1 )
183
238
methods := class .Methods
184
239
if component .isBaseClass (class ) {
@@ -194,7 +249,7 @@ func writeRustTrait(component ComponentDefinition, class ComponentDefinitionClas
194
249
for j := 0 ; j < len (methods ); j ++ {
195
250
method := methods [j ]
196
251
w .Writeln ("" )
197
- err := writeRustTraitFn (method , w , true )
252
+ err := writeRustTraitFn (method , w , true , false , false )
198
253
if err != nil {
199
254
return err
200
255
}
@@ -206,12 +261,13 @@ func writeRustTrait(component ComponentDefinition, class ComponentDefinitionClas
206
261
return nil
207
262
}
208
263
209
- func writeRustTraitFn (method ComponentDefinitionMethod , w LanguageWriter , hasSelf bool ) error {
264
+ func writeRustTraitFn (method ComponentDefinitionMethod , w LanguageWriter , hasSelf bool , hasImpl bool , hasImplParent bool ) error {
210
265
methodName := toSnakeCase (method .MethodName )
211
266
w .Writeln ("// %s" , methodName )
212
267
w .Writeln ("//" )
213
268
w .Writeln ("// %s" , method .MethodDescription )
214
269
parameterString := ""
270
+ parameterNames := ""
215
271
if hasSelf {
216
272
parameterString += "&mut self"
217
273
}
@@ -229,35 +285,192 @@ func writeRustTraitFn(method ComponentDefinitionMethod, w LanguageWriter, hasSel
229
285
} else {
230
286
parameterString += fmt .Sprintf (", %s : %s" , RustParam .ParamName , RustParam .ParamType )
231
287
}
288
+ if parameterNames == "" {
289
+ parameterNames += RustParam .ParamName
290
+ } else {
291
+ parameterNames += fmt .Sprintf (", %s" , RustParam .ParamName )
292
+ }
232
293
} else {
233
294
returnType = RustParam .ParamType
234
295
}
235
296
w .Writeln ("// %s" , RustParam .ParamComment )
236
297
}
237
298
w .Writeln ("//" )
238
- if returnType == "" {
239
- w .Writeln ("fn %s(%s);" , methodName , parameterString )
299
+ if ! hasImpl {
300
+ if returnType == "" {
301
+ w .Writeln ("fn %s(%s);" , methodName , parameterString )
302
+ } else {
303
+ w .Writeln ("fn %s(%s) -> %s;" , methodName , parameterString , returnType )
304
+ }
240
305
} else {
241
- w .Writeln ("fn %s(%s) -> %s;" , methodName , parameterString , returnType )
306
+ if returnType == "" {
307
+ w .Writeln ("fn %s(%s) {" , methodName , parameterString )
308
+ } else {
309
+ w .Writeln ("fn %s(%s) -> %s {" , methodName , parameterString , returnType )
310
+ }
311
+ w .AddIndentationLevel (1 )
312
+ if ! hasImplParent {
313
+ w .Writeln ("unimplemented!();" )
314
+ } else {
315
+ w .Writeln ("self.parent.%s(%s)" , methodName , parameterNames )
316
+ }
317
+ w .AddIndentationLevel (- 1 )
318
+ w .Writeln ("}" )
242
319
}
243
320
return nil
244
321
}
245
322
246
323
func writeRustGlobalTrait (component ComponentDefinition , w LanguageWriter ) error {
247
324
w .Writeln ("// Wrapper trait for global methods" )
248
325
w .Writeln ("//" )
249
- w .Writeln ("trait Wrapper {" )
326
+ w .Writeln ("pub trait Wrapper {" )
327
+ w .AddIndentationLevel (1 )
328
+ methods := component .Global .Methods
329
+ for j := 0 ; j < len (methods ); j ++ {
330
+ method := methods [j ]
331
+ w .Writeln ("" )
332
+ err := writeRustTraitFn (method , w , false , false , false )
333
+ if err != nil {
334
+ return err
335
+ }
336
+ }
337
+ w .ResetIndentationLevel ()
338
+ w .Writeln ("}" )
339
+ return nil
340
+ }
341
+
342
+ func buildRustGlobalStubFile (component ComponentDefinition , w LanguageWriter , InterfaceMod string ) error {
343
+ w .Writeln ("" )
344
+ w .Writeln ("use %s::*;" , InterfaceMod )
345
+ w .Writeln ("" )
346
+ w .Writeln ("// Wrapper struct to implement the wrapper trait for global methods" )
347
+ w .Writeln ("struct CWrapper;" )
348
+ w .Writeln ("" )
349
+ w .Writeln ("impl Wrapper for CWrapper {" )
350
+ w .Writeln ("" )
250
351
w .AddIndentationLevel (1 )
251
352
methods := component .Global .Methods
252
353
for j := 0 ; j < len (methods ); j ++ {
253
354
method := methods [j ]
254
355
w .Writeln ("" )
255
- err := writeRustTraitFn (method , w , false )
356
+ err := writeRustTraitFn (method , w , false , true , false )
256
357
if err != nil {
257
358
return err
258
359
}
259
360
}
260
361
w .ResetIndentationLevel ()
261
362
w .Writeln ("}" )
363
+ w .Writeln ("" )
364
+ return nil
365
+ }
366
+
367
+ func getParentList (component ComponentDefinition , class ComponentDefinitionClass ) ([]string , error ) {
368
+ parents := make ([]string , 0 )
369
+ currClass := class
370
+ for ! component .isBaseClass (currClass ) {
371
+ parent := currClass .ParentClass
372
+ if parent == "" {
373
+ parent = component .baseClass ().ClassName
374
+ }
375
+ parents = append (parents , parent )
376
+ parClass , err := getClass (component , parent )
377
+ if err != nil {
378
+ return parents , err
379
+ }
380
+ currClass = parClass
381
+ }
382
+ return parents , nil
383
+ }
384
+
385
+ func getClass (component ComponentDefinition , name string ) (ComponentDefinitionClass , error ) {
386
+ for i := 0 ; i < len (component .Classes ); i ++ {
387
+ class := component .Classes [i ]
388
+ if class .ClassName == name {
389
+ return class , nil
390
+ }
391
+ }
392
+ return component .baseClass (), fmt .Errorf ("Cannot find class %s" , name )
393
+ }
394
+
395
+ func buildRustStubFile (component ComponentDefinition , class ComponentDefinitionClass , w LanguageWriter , InterfaceMod string , StubBase string ) error {
396
+ Name := class .ClassName
397
+ parents , err := getParentList (component , class )
398
+ if err != nil {
399
+ return err
400
+ }
401
+ w .Writeln ("" )
402
+ w .Writeln ("use %s::*;" , InterfaceMod )
403
+ if len (parents ) > 0 {
404
+ parentName := parents [0 ]
405
+ w .Writeln ("use %s_%s::C%s;" , StubBase , toSnakeCase (parentName ), parentName )
406
+ }
407
+ w .Writeln ("" )
408
+ w .Writeln ("// Stub struct to implement the %s trait" , Name )
409
+ if len (parents ) == 0 {
410
+ w .Writeln ("pub struct C%s;" , Name )
411
+ } else {
412
+ w .Writeln ("pub struct C%s {" , Name )
413
+ w .AddIndentationLevel (1 )
414
+ w .Writeln ("parent : C%s" , parents [0 ])
415
+ w .ResetIndentationLevel ()
416
+ w .Writeln ("}" )
417
+ w .Writeln ("" )
418
+ w .Writeln ("// Implementation of parent traits via parent" )
419
+ w .Writeln ("" )
420
+ for i := 0 ; i < len (parents ); i ++ {
421
+ parent := parents [i ]
422
+ parentClass , err := getClass (component , parent )
423
+ if err != nil {
424
+ return err
425
+ }
426
+ w .Writeln ("impl %s for C%s {" , parent , Name )
427
+ w .AddIndentationLevel (1 )
428
+ methods := parentClass .Methods
429
+ if component .isBaseClass (parentClass ) {
430
+ methods = append (
431
+ methods ,
432
+ GetLastErrorMessageMethod (),
433
+ ClearErrorMessageMethod (),
434
+ RegisterErrorMessageMethod (),
435
+ IncRefCountMethod (),
436
+ DecRefCountMethod ())
437
+ }
438
+ for j := 0 ; j < len (methods ); j ++ {
439
+ method := methods [j ]
440
+ w .Writeln ("" )
441
+ err := writeRustTraitFn (method , w , true , true , true )
442
+ if err != nil {
443
+ return err
444
+ }
445
+ }
446
+ w .ResetIndentationLevel ()
447
+ w .Writeln ("}" )
448
+ }
449
+ }
450
+ w .Writeln ("" )
451
+ w .Writeln ("impl %s for C%s {" , Name , Name )
452
+ w .Writeln ("" )
453
+ w .AddIndentationLevel (1 )
454
+ methods := class .Methods
455
+ if component .isBaseClass (class ) {
456
+ methods = append (
457
+ methods ,
458
+ GetLastErrorMessageMethod (),
459
+ ClearErrorMessageMethod (),
460
+ RegisterErrorMessageMethod (),
461
+ IncRefCountMethod (),
462
+ DecRefCountMethod ())
463
+ }
464
+ for j := 0 ; j < len (methods ); j ++ {
465
+ method := methods [j ]
466
+ w .Writeln ("" )
467
+ err := writeRustTraitFn (method , w , true , true , false )
468
+ if err != nil {
469
+ return err
470
+ }
471
+ }
472
+ w .ResetIndentationLevel ()
473
+ w .Writeln ("}" )
474
+ w .Writeln ("" )
262
475
return nil
263
476
}
0 commit comments