Skip to content

Commit 0ac7f75

Browse files
committed
Create the stub impls
1 parent e1e97fc commit 0ac7f75

File tree

2 files changed

+232
-19
lines changed

2 files changed

+232
-19
lines changed

Source/buildimplementationrust.go

Lines changed: 231 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -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\ndevelopment 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\ndevelopment 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\ndevelopment 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

246323
func 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
}

Source/languagerust.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ func writeRustBaseTypeDefinitions(componentdefinition ComponentDefinition, w Lan
140140
}
141141
w.Writeln("//")
142142
funcName := funcinfo.FunctionName
143-
w.Writeln("type %s = unsafe extern \"C\" fn(%s);", funcName, parameterString)
143+
w.Writeln("pub type %s = unsafe extern \"C\" fn(%s);", funcName, parameterString)
144144
}
145145
}
146146

0 commit comments

Comments
 (0)