@@ -47,15 +47,18 @@ func BuildImplementationRust(component ComponentDefinition, outputFolder string,
4747 forceRebuild := true
4848 LibraryName := component .LibraryName
4949 BaseName := component .BaseName
50+ modfiles := make ([]string , 0 )
5051 indentString := getIndentationString (implementation .Indentation )
5152
5253 stubIdentifier := ""
5354 if len (implementation .StubIdentifier ) > 0 {
5455 stubIdentifier = "_" + strings .ToLower (implementation .StubIdentifier )
5556 }
5657
57- IntfFileName := BaseName + "_interfaces.rs"
58+ InterfaceMod := BaseName + "_interfaces"
59+ IntfFileName := InterfaceMod + ".rs"
5860 IntfFilePath := path .Join (outputFolder , IntfFileName )
61+ modfiles = append (modfiles , IntfFilePath )
5962 log .Printf ("Creating \" %s\" " , IntfFilePath )
6063 IntfRSFile , err := CreateLanguageFile (IntfFilePath , indentString )
6164 if err != nil {
@@ -68,12 +71,13 @@ func BuildImplementationRust(component ComponentDefinition, outputFolder string,
6871 if err != nil {
6972 return err
7073 }
71- err = buildRustInterfaces (component , IntfRSFile , implementation . ClassIdentifier )
74+ err = buildRustInterfaces (component , IntfRSFile )
7275 if err != nil {
7376 return err
7477 }
7578
7679 IntfWrapperStubName := path .Join (stubOutputFolder , BaseName + stubIdentifier + ".rs" )
80+ modfiles = append (modfiles , IntfWrapperStubName )
7781 if forceRebuild || ! FileExists (IntfWrapperStubName ) {
7882 log .Printf ("Creating \" %s\" " , IntfWrapperStubName )
7983 stubfile , err := CreateLanguageFile (IntfWrapperStubName , indentString )
@@ -83,19 +87,62 @@ func BuildImplementationRust(component ComponentDefinition, outputFolder string,
8387 stubfile .WriteCLicenseHeader (component ,
8488 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 ),
8589 true )
86- RelInterfaceFile , err := filepath .Rel (stubOutputFolder , IntfFilePath )
8790 if err != nil {
8891 return err
8992 }
90- err = buildRustGlobalStubFile (component , stubfile , implementation . ClassIdentifier , RelInterfaceFile )
93+ err = buildRustGlobalStubFile (component , stubfile , InterfaceMod )
9194 if err != nil {
9295 return err
9396 }
9497 } else {
9598 log .Printf ("Omitting recreation of implementation stub \" %s\" " , IntfWrapperStubName )
9699 }
97100
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+
98127 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+
99146 CargoFileName := path .Join (projectOutputFolder , "Cargo.toml" )
100147 if forceRebuild || ! FileExists (CargoFileName ) {
101148 log .Printf ("Creating Cargo file \" %s\" for Rust Implementation" , CargoFileName )
@@ -106,7 +153,7 @@ func BuildImplementationRust(component ComponentDefinition, outputFolder string,
106153 CargoFile .WriteTomlLicenseHeader (component ,
107154 fmt .Sprintf ("This is an autogenerated Cargo file for the development of %s." , LibraryName ),
108155 true )
109- LibPath , err := filepath .Rel (projectOutputFolder , IntfWrapperStubName )
156+ LibPath , err := filepath .Rel (projectOutputFolder , IntfWrapperLibName )
110157 if err != nil {
111158 return err
112159 }
@@ -119,16 +166,24 @@ func BuildImplementationRust(component ComponentDefinition, outputFolder string,
119166 return nil
120167}
121168
122- func buildRustGlobalStubFile (component ComponentDefinition , w LanguageWriter , ClassIdentifier string , RelInterfaceFile string ) error {
169+ func buildRustGlobalLibFile (component ComponentDefinition , w LanguageWriter , basedir string , modfiles [] string ) error {
123170 w .Writeln ("" )
124171 // 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+ }
128183 return nil
129184}
130185
131- func buildRustInterfaces (component ComponentDefinition , w LanguageWriter , ClassIdentifier string ) error {
186+ func buildRustInterfaces (component ComponentDefinition , w LanguageWriter ) error {
132187 NameSpace := component .NameSpace
133188 w .Writeln ("/*************************************************************************************************************************" )
134189 w .Writeln (" Traits defined for %s" , NameSpace )
@@ -178,7 +233,7 @@ func writeRustTrait(component ComponentDefinition, class ComponentDefinitionClas
178233 parentClassString = fmt .Sprintf (": %s " , class .ParentClass )
179234 }
180235 }
181- w .Writeln ("trait %s %s {" , class .ClassName , parentClassString )
236+ w .Writeln ("pub trait %s %s {" , class .ClassName , parentClassString )
182237 w .AddIndentationLevel (1 )
183238 methods := class .Methods
184239 if component .isBaseClass (class ) {
@@ -194,7 +249,7 @@ func writeRustTrait(component ComponentDefinition, class ComponentDefinitionClas
194249 for j := 0 ; j < len (methods ); j ++ {
195250 method := methods [j ]
196251 w .Writeln ("" )
197- err := writeRustTraitFn (method , w , true )
252+ err := writeRustTraitFn (method , w , true , false , false )
198253 if err != nil {
199254 return err
200255 }
@@ -206,12 +261,13 @@ func writeRustTrait(component ComponentDefinition, class ComponentDefinitionClas
206261 return nil
207262}
208263
209- func writeRustTraitFn (method ComponentDefinitionMethod , w LanguageWriter , hasSelf bool ) error {
264+ func writeRustTraitFn (method ComponentDefinitionMethod , w LanguageWriter , hasSelf bool , hasImpl bool , hasImplParent bool ) error {
210265 methodName := toSnakeCase (method .MethodName )
211266 w .Writeln ("// %s" , methodName )
212267 w .Writeln ("//" )
213268 w .Writeln ("// %s" , method .MethodDescription )
214269 parameterString := ""
270+ parameterNames := ""
215271 if hasSelf {
216272 parameterString += "&mut self"
217273 }
@@ -229,35 +285,192 @@ func writeRustTraitFn(method ComponentDefinitionMethod, w LanguageWriter, hasSel
229285 } else {
230286 parameterString += fmt .Sprintf (", %s : %s" , RustParam .ParamName , RustParam .ParamType )
231287 }
288+ if parameterNames == "" {
289+ parameterNames += RustParam .ParamName
290+ } else {
291+ parameterNames += fmt .Sprintf (", %s" , RustParam .ParamName )
292+ }
232293 } else {
233294 returnType = RustParam .ParamType
234295 }
235296 w .Writeln ("// %s" , RustParam .ParamComment )
236297 }
237298 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+ }
240305 } 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 ("}" )
242319 }
243320 return nil
244321}
245322
246323func writeRustGlobalTrait (component ComponentDefinition , w LanguageWriter ) error {
247324 w .Writeln ("// Wrapper trait for global methods" )
248325 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 ("" )
250351 w .AddIndentationLevel (1 )
251352 methods := component .Global .Methods
252353 for j := 0 ; j < len (methods ); j ++ {
253354 method := methods [j ]
254355 w .Writeln ("" )
255- err := writeRustTraitFn (method , w , false )
356+ err := writeRustTraitFn (method , w , false , true , false )
256357 if err != nil {
257358 return err
258359 }
259360 }
260361 w .ResetIndentationLevel ()
261362 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 ("" )
262475 return nil
263476}
0 commit comments