Skip to content

Commit d3a745a

Browse files
committed
Add basic writing of interfaces
1 parent 846785a commit d3a745a

File tree

2 files changed

+167
-40
lines changed

2 files changed

+167
-40
lines changed

Source/buildimplementationrust.go

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,18 @@ func buildRustGlobalStubFile(component ComponentDefinition, w LanguageWriter, Cl
129129
}
130130

131131
func buildRustInterfaces(component ComponentDefinition, w LanguageWriter, ClassIdentifier string) error {
132+
NameSpace := component.NameSpace
133+
w.Writeln("/*************************************************************************************************************************")
134+
w.Writeln(" Traits defined for %s", NameSpace)
135+
w.Writeln("**************************************************************************************************************************/")
136+
w.Writeln("")
137+
for i := 0; i < len(component.Classes); i++ {
138+
classinfo := component.Classes[i]
139+
err := writeRustTrait(component, classinfo, w)
140+
if err != nil {
141+
return err
142+
}
143+
}
132144
return nil
133145
}
134146

@@ -142,3 +154,67 @@ func buildCargoForRustImplementation(component ComponentDefinition, w LanguageWr
142154
w.Writeln(" crate-type = [\"cdylib\"]")
143155
return nil
144156
}
157+
158+
func writeRustTrait(component ComponentDefinition, class ComponentDefinitionClass, w LanguageWriter) error {
159+
w.Writeln("// Trait for interface %s", class.ClassName)
160+
w.Writeln("//")
161+
if class.ClassDescription != "" {
162+
w.Writeln("// %s", class.ClassDescription)
163+
w.Writeln("//")
164+
}
165+
parentClassString := ""
166+
if !component.isBaseClass(class) {
167+
if class.ParentClass == "" {
168+
parentClassString = fmt.Sprintf(": %s ", component.Global.BaseClassName)
169+
} else {
170+
parentClassString = fmt.Sprintf(": %s ", class.ParentClass)
171+
}
172+
}
173+
w.Writeln("trait %s %s {", class.ClassName, parentClassString)
174+
w.AddIndentationLevel(1)
175+
// TODO add the base class methods!
176+
177+
for j := 0; j < len(class.Methods); j++ {
178+
method := class.Methods[j]
179+
w.Writeln("")
180+
err := writeRustTraitFn(method, w)
181+
if err != nil {
182+
return err
183+
}
184+
}
185+
w.ResetIndentationLevel()
186+
w.Writeln("}")
187+
w.Writeln("")
188+
w.Writeln("")
189+
return nil
190+
}
191+
192+
func writeRustTraitFn(method ComponentDefinitionMethod, w LanguageWriter) error {
193+
methodName := toSnakeCase(method.MethodName)
194+
w.Writeln("// %s", methodName)
195+
w.Writeln("//")
196+
w.Writeln("// %s", method.MethodDescription)
197+
parameterString := "&mut self"
198+
returnType := ""
199+
for k := 0; k < len(method.Params); k++ {
200+
param := method.Params[k]
201+
RustParams, err := generateRustParameters(param, false)
202+
if err != nil {
203+
return err
204+
}
205+
RustParam := RustParams[0]
206+
if param.ParamPass != "return" {
207+
parameterString += fmt.Sprintf(", %s : %s", RustParam.ParamName, RustParam.ParamType)
208+
} else {
209+
returnType = RustParam.ParamType
210+
}
211+
w.Writeln("// %s", RustParam.ParamComment)
212+
}
213+
w.Writeln("//")
214+
if returnType == "" {
215+
w.Writeln("fn %s(%s);", methodName, parameterString)
216+
} else {
217+
w.Writeln("fn %s(%s) -> %s;", methodName, parameterString, returnType)
218+
}
219+
return nil
220+
}

Source/languagerust.go

Lines changed: 91 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,16 @@ package main
3535

3636
import (
3737
"fmt"
38+
"regexp"
3839
"strings"
3940
)
4041

42+
func toSnakeCase(BaseType string) string {
43+
var matchCapital = regexp.MustCompile("(.)([A-Z])")
44+
underscored := matchCapital.ReplaceAllString(BaseType, "${1}_${2}")
45+
return strings.ToLower(underscored)
46+
}
47+
4148
func writeRustBaseTypeDefinitions(componentdefinition ComponentDefinition, w LanguageWriter, NameSpace string, BaseName string) error {
4249
w.Writeln("#[allow(unused_imports)]")
4350
w.Writeln("use std::ffi;")
@@ -59,7 +66,7 @@ func writeRustBaseTypeDefinitions(componentdefinition ComponentDefinition, w Lan
5966
w.Writeln(" Basic pointers definition for %s", NameSpace)
6067
w.Writeln("**************************************************************************************************************************/")
6168
w.Writeln("")
62-
w.Writeln("type Handle = std::ffi::c_void")
69+
w.Writeln("type Handle = std::ffi::c_void;")
6370

6471
if len(componentdefinition.Enums) > 0 {
6572
w.Writeln("/*************************************************************************************************************************")
@@ -69,15 +76,16 @@ func writeRustBaseTypeDefinitions(componentdefinition ComponentDefinition, w Lan
6976
for i := 0; i < len(componentdefinition.Enums); i++ {
7077
enuminfo := componentdefinition.Enums[i]
7178
w.Writeln("#[repr(C, u16)]")
72-
w.Writeln("#[allow(non_snake_case)]")
73-
w.Writeln("pub enum %s {", enuminfo.Name)
79+
enumName := enuminfo.Name
80+
w.Writeln("pub enum %s {", enumName)
7481
for j := 0; j < len(enuminfo.Options); j++ {
7582
option := enuminfo.Options[j]
7683
sep := ","
7784
if j == len(enuminfo.Options)-1 {
7885
sep = ""
7986
}
80-
w.Writeln(" pub %s = %d%s", option.Name, option.Value, sep)
87+
optionName := option.Name
88+
w.Writeln(" pub %s = %d%s", optionName, option.Value, sep)
8189
}
8290
w.Writeln("}")
8391
w.Writeln("")
@@ -91,9 +99,9 @@ func writeRustBaseTypeDefinitions(componentdefinition ComponentDefinition, w Lan
9199
w.Writeln("")
92100
for i := 0; i < len(componentdefinition.Structs); i++ {
93101
structinfo := componentdefinition.Structs[i]
102+
structName := structinfo.Name
94103
w.Writeln("#[repr(C)]")
95-
w.Writeln("#[allow(non_snake_case)]")
96-
w.Writeln("pub struct %s {", structinfo.Name)
104+
w.Writeln("pub struct %s {", structName)
97105
for j := 0; j < len(structinfo.Members); j++ {
98106
member := structinfo.Members[j]
99107
last := j == len(structinfo.Members)-1
@@ -118,7 +126,7 @@ func writeRustBaseTypeDefinitions(componentdefinition ComponentDefinition, w Lan
118126
w.Writeln("//")
119127
parameterString := ""
120128
for j := 0; j < len(funcinfo.Params); j++ {
121-
RustParameters, err := generatePlainRustParameters(funcinfo.Params[j])
129+
RustParameters, err := generateRustParameters(funcinfo.Params[j], true)
122130
RustParameter := RustParameters[0]
123131
if err != nil {
124132
return err
@@ -130,7 +138,9 @@ func writeRustBaseTypeDefinitions(componentdefinition ComponentDefinition, w Lan
130138
parameterString += fmt.Sprintf(", %s : %s", RustParameter.ParamName, RustParameter.ParamType)
131139
}
132140
}
133-
w.Writeln("type %s = unsafe extern \"C\" fn(%s);", funcinfo.FunctionName, parameterString)
141+
w.Writeln("//")
142+
funcName := funcinfo.FunctionName
143+
w.Writeln("type %s = unsafe extern \"C\" fn(%s);", funcName, parameterString)
134144
}
135145
}
136146

@@ -150,37 +160,38 @@ func writeRustMemberLine(member ComponentDefinitionMember, w LanguageWriter, Str
150160
arraysuffix = fmt.Sprintf("[%d]%s", member.Rows, suffix)
151161
}
152162
}
163+
memberName := toSnakeCase(member.Name)
153164
switch member.Type {
154165
case "uint8":
155-
w.Writeln(" pub %s: u8%s", member.Name, arraysuffix)
166+
w.Writeln(" pub %s: u8%s", memberName, arraysuffix)
156167
case "uint16":
157-
w.Writeln(" pub %s: u16%s", member.Name, arraysuffix)
168+
w.Writeln(" pub %s: u16%s", memberName, arraysuffix)
158169
case "uint32":
159-
w.Writeln(" pub %s: u32%s", member.Name, arraysuffix)
170+
w.Writeln(" pub %s: u32%s", memberName, arraysuffix)
160171
case "uint64":
161-
w.Writeln(" pub %s: u64%s", member.Name, arraysuffix)
172+
w.Writeln(" pub %s: u64%s", memberName, arraysuffix)
162173
case "int8":
163-
w.Writeln(" pub %s: i8%s", member.Name, arraysuffix)
174+
w.Writeln(" pub %s: i8%s", memberName, arraysuffix)
164175
case "int16":
165-
w.Writeln(" pub %s: i16%s", member.Name, arraysuffix)
176+
w.Writeln(" pub %s: i16%s", memberName, arraysuffix)
166177
case "int32":
167-
w.Writeln(" pub %s: i32%s", member.Name, arraysuffix)
178+
w.Writeln(" pub %s: i32%s", memberName, arraysuffix)
168179
case "int64":
169-
w.Writeln(" pub %s: i64%s", member.Name, arraysuffix)
180+
w.Writeln(" pub %s: i64%s", memberName, arraysuffix)
170181
case "bool":
171-
w.Writeln(" pub %s: bool%s", member.Name, arraysuffix)
182+
w.Writeln(" pub %s: bool%s", memberName, arraysuffix)
172183
case "single":
173-
w.Writeln(" pub %s: f32%s", member.Name, arraysuffix)
184+
w.Writeln(" pub %s: f32%s", memberName, arraysuffix)
174185
case "double":
175-
w.Writeln(" pub %s: f64%s", member.Name, arraysuffix)
186+
w.Writeln(" pub %s: f64%s", memberName, arraysuffix)
176187
case "pointer":
177-
w.Writeln(" pub %s: c_void%s", member.Name, arraysuffix)
188+
w.Writeln(" pub %s: c_void%s", memberName, arraysuffix)
178189
case "string":
179190
return fmt.Errorf("it is not possible for struct %s to contain a string value", StructName)
180191
case "class", "optionalclass":
181192
return fmt.Errorf("it is not possible for struct %s to contain a handle value", StructName)
182193
case "enum":
183-
w.Writeln(" pub %s: u16%s", member.Name, arraysuffix)
194+
w.Writeln(" pub %s: u16%s", memberName, arraysuffix)
184195
}
185196
return nil
186197
}
@@ -192,8 +203,28 @@ type RustParameter struct {
192203
ParamComment string
193204
}
194205

195-
func generatePlainRustParameters(param ComponentDefinitionParam) ([]RustParameter, error) {
206+
func generateRustParameters(param ComponentDefinitionParam, isPlain bool) ([]RustParameter, error) {
207+
Params := make([]RustParameter, 1)
208+
ParamTypeName, err := generateRustParameterType(param, isPlain)
209+
if err != nil {
210+
return nil, err
211+
}
212+
213+
if isPlain {
214+
if param.ParamType == "basicarray" {
215+
return nil, fmt.Errorf("Not yet handled")
216+
}
196217

218+
if param.ParamType == "structarray" {
219+
return nil, fmt.Errorf("Not yet handled")
220+
}
221+
}
222+
223+
Params[0].ParamType = ParamTypeName
224+
Params[0].ParamName = toSnakeCase(param.ParamName)
225+
Params[0].ParamComment = fmt.Sprintf("* @param[%s] %s - %s", param.ParamPass, Params[0].ParamName, param.ParamDescription)
226+
227+
return Params, nil
197228
}
198229

199230
func generateRustParameterType(param ComponentDefinitionParam, isPlain bool) (string, error) {
@@ -246,64 +277,84 @@ func generateRustParameterType(param ComponentDefinitionParam, isPlain bool) (st
246277
RustParamTypeName = "*mut char"
247278
} else {
248279
// TODO
249-
return "", fmt.Errorf("Not yet handled")
280+
return "", fmt.Errorf("%s Not yet handled", param.ParamType)
250281
}
251282

252283
case "enum":
253284
if isPlain {
254285
RustParamTypeName = fmt.Sprintf("u16")
255286
} else {
256-
// TODO
257-
return "", fmt.Errorf("Not yet handled")
287+
switch param.ParamPass {
288+
case "out":
289+
RustParamTypeName = fmt.Sprintf("&mut %s", ParamClass)
290+
case "in", "return":
291+
RustParamTypeName = fmt.Sprintf("%s", ParamClass)
292+
}
258293
}
259294

260295
case "functiontype":
261-
if isPlain {
262-
RustParamTypeName = fmt.Sprintf("%s", ParamClass)
263-
} else {
264-
// TODO
265-
return "", fmt.Errorf("Not yet handled")
266-
}
296+
RustParamTypeName = fmt.Sprintf("%s", ParamClass)
267297

268298
case "struct":
269299
if isPlain {
270300
RustParamTypeName = fmt.Sprintf("*mut %s", ParamClass)
271301
} else {
272-
// TODO
273-
return "", fmt.Errorf("Not yet handled")
302+
switch param.ParamPass {
303+
case "out":
304+
RustParamTypeName = fmt.Sprintf("&mut %s", ParamClass)
305+
case "in":
306+
RustParamTypeName = fmt.Sprintf("& %s", ParamClass)
307+
case "return":
308+
RustParamTypeName = fmt.Sprintf("%s", ParamClass)
309+
}
274310
}
275311

276312
case "basicarray":
277-
basicTypeName, err := generateRustParameterType(param, isPlain)
313+
basicParam := param
314+
basicParam.ParamType = param.ParamClass
315+
basicParam.ParamPass = "return"
316+
basicTypeName, err := generateRustParameterType(basicParam, isPlain)
278317
if err != nil {
279318
return "", err
280319
}
281320

282321
if isPlain {
283322
RustParamTypeName = fmt.Sprintf("*mut %s", basicTypeName)
284323
} else {
285-
// TODO
286-
return "", fmt.Errorf("Not yet handled")
324+
switch param.ParamPass {
325+
case "out":
326+
RustParamTypeName = fmt.Sprintf("&mut Vec<%s>", basicTypeName)
327+
case "in":
328+
RustParamTypeName = fmt.Sprintf("&[%s]", basicTypeName)
329+
case "return":
330+
RustParamTypeName = fmt.Sprintf("Vec<%s>", basicTypeName)
331+
}
287332
}
288333

289334
case "structarray":
290335
if isPlain {
291336
RustParamTypeName = fmt.Sprintf("*mut %s", ParamClass)
292337
} else {
293-
// TODO
294-
return "", fmt.Errorf("Not yet handled")
338+
switch param.ParamPass {
339+
case "out":
340+
RustParamTypeName = fmt.Sprintf("&mut Vec<%s>", ParamClass)
341+
case "in":
342+
RustParamTypeName = fmt.Sprintf("&[%s]", ParamClass)
343+
case "return":
344+
RustParamTypeName = fmt.Sprintf("Vec<%s>", ParamClass)
345+
}
295346
}
296347

297348
case "class", "optionalclass":
298349
if isPlain {
299350
RustParamTypeName = fmt.Sprintf("Handle")
300351
} else {
301352
// TODO
302-
return "", fmt.Errorf("Not yet handled")
353+
return "", fmt.Errorf("%s Not yet handled", param.ParamType)
303354
}
304355

305356
default:
306-
return "", fmt.Errorf("invalid parameter type \"%s\" for Pascal parameter", ParamTypeName)
357+
return "", fmt.Errorf("invalid parameter type \"%s\" for Rust parameter", ParamTypeName)
307358
}
308359

309360
return RustParamTypeName, nil

0 commit comments

Comments
 (0)