summaryrefslogtreecommitdiffstats
path: root/cmd/binapi-generator/parse.go
diff options
context:
space:
mode:
Diffstat (limited to 'cmd/binapi-generator/parse.go')
-rw-r--r--cmd/binapi-generator/parse.go136
1 files changed, 114 insertions, 22 deletions
diff --git a/cmd/binapi-generator/parse.go b/cmd/binapi-generator/parse.go
index 2d6fdd4..5dfbe91 100644
--- a/cmd/binapi-generator/parse.go
+++ b/cmd/binapi-generator/parse.go
@@ -23,26 +23,6 @@ import (
"github.com/bennyscetbun/jsongo"
)
-func getTypeByRef(ctx *context, ref string) *Type {
- for _, typ := range ctx.packageData.Types {
- if ref == toApiType(typ.Name) {
- return &typ
- }
- }
- return nil
-}
-
-func getUnionSize(ctx *context, union *Union) (maxSize int) {
- for _, field := range union.Fields {
- if typ := getTypeByRef(ctx, field.Type); typ != nil {
- if size := getSizeOfType(typ); size > maxSize {
- maxSize = size
- }
- }
- }
- return
-}
-
// toApiType returns name that is used as type reference in VPP binary API
func toApiType(name string) string {
return fmt.Sprintf("vl_api_%s_t", name)
@@ -50,13 +30,14 @@ func toApiType(name string) string {
// parsePackage parses provided JSON data into objects prepared for code generation
func parsePackage(ctx *context, jsonRoot *jsongo.JSONNode) (*Package, error) {
- logf(" %s contains: %d services, %d messages, %d types, %d enums, %d unions (version: %s)",
+ logf(" %s contains: %d services, %d messages, %d types, %d enums, %d unions, %d aliases (version: %s)",
ctx.packageName,
jsonRoot.Map("services").Len(),
jsonRoot.Map("messages").Len(),
jsonRoot.Map("types").Len(),
jsonRoot.Map("enums").Len(),
jsonRoot.Map("unions").Len(),
+ jsonRoot.Map("aliases").Len(),
jsonRoot.Map("vl_api_version").Get(),
)
@@ -79,6 +60,22 @@ func parsePackage(ctx *context, jsonRoot *jsongo.JSONNode) (*Package, error) {
pkg.RefMap[toApiType(enum.Name)] = enum.Name
}
+ // parse aliases
+ aliases := jsonRoot.Map("aliases")
+ if aliases.GetType() == jsongo.TypeMap {
+ pkg.Aliases = make([]Alias, aliases.Len())
+ for i, key := range aliases.GetKeys() {
+ aliasNode := aliases.At(key)
+
+ alias, err := parseAlias(ctx, key.(string), aliasNode)
+ if err != nil {
+ return nil, err
+ }
+ pkg.Aliases[i] = *alias
+ pkg.RefMap[toApiType(alias.Name)] = alias.Name
+ }
+ }
+
// parse types
types := jsonRoot.Map("types")
pkg.Types = make([]Type, types.Len())
@@ -308,6 +305,42 @@ func parseType(ctx *context, typeNode *jsongo.JSONNode) (*Type, error) {
return &typ, nil
}
+const (
+ aliasesLength = "length"
+ aliasesType = "type"
+)
+
+// parseAlias parses VPP binary API alias object from JSON node
+func parseAlias(ctx *context, aliasName string, aliasNode *jsongo.JSONNode) (*Alias, error) {
+ if aliasNode.Len() == 0 || aliasNode.At(aliasesType).GetType() != jsongo.TypeValue {
+ return nil, errors.New("invalid JSON for alias specified")
+ }
+
+ alias := Alias{
+ Name: aliasName,
+ }
+
+ if typeNode := aliasNode.At(aliasesType); typeNode.GetType() == jsongo.TypeValue {
+ typ, ok := typeNode.Get().(string)
+ if !ok {
+ return nil, fmt.Errorf("alias type is %T, not a string", typeNode.Get())
+ }
+ if typ != "null" {
+ alias.Type = typ
+ }
+ }
+
+ if lengthNode := aliasNode.At(aliasesLength); lengthNode.GetType() == jsongo.TypeValue {
+ length, ok := lengthNode.Get().(float64)
+ if !ok {
+ return nil, fmt.Errorf("alias length is %T, not a float64", lengthNode.Get())
+ }
+ alias.Length = int(length)
+ }
+
+ return &alias, nil
+}
+
// parseMessage parses VPP binary API message object from JSON node
func parseMessage(ctx *context, msgNode *jsongo.JSONNode) (*Message, error) {
if msgNode.Len() == 0 || msgNode.At(0).GetType() != jsongo.TypeValue {
@@ -364,7 +397,7 @@ func parseField(ctx *context, field *jsongo.JSONNode) (*Field, error) {
if field.Len() >= 3 {
fieldLength, ok = field.At(2).Get().(float64)
if !ok {
- return nil, fmt.Errorf("field length is %T, not an int", field.At(2).Get())
+ return nil, fmt.Errorf("field length is %T, not float64", field.At(2).Get())
}
}
var fieldLengthFrom string
@@ -461,3 +494,62 @@ func convertToGoType(ctx *context, binapiType string) (typ string) {
}
return typ
}
+
+func getSizeOfType(typ *Type) (size int) {
+ for _, field := range typ.Fields {
+ size += getSizeOfBinapiTypeLength(field.Type, field.Length)
+ }
+ return size
+}
+
+func getSizeOfBinapiTypeLength(typ string, length int) (size int) {
+ if n := getBinapiTypeSize(typ); n > 0 {
+ if length > 0 {
+ return n * length
+ } else {
+ return n
+ }
+ }
+ return
+}
+
+func getTypeByRef(ctx *context, ref string) *Type {
+ for _, typ := range ctx.packageData.Types {
+ if ref == toApiType(typ.Name) {
+ return &typ
+ }
+ }
+ return nil
+}
+
+func getAliasByRef(ctx *context, ref string) *Alias {
+ for _, alias := range ctx.packageData.Aliases {
+ if ref == toApiType(alias.Name) {
+ return &alias
+ }
+ }
+ return nil
+}
+
+func getUnionSize(ctx *context, union *Union) (maxSize int) {
+ for _, field := range union.Fields {
+ typ := getTypeByRef(ctx, field.Type)
+ if typ != nil {
+ if size := getSizeOfType(typ); size > maxSize {
+ maxSize = size
+ }
+ continue
+ }
+ alias := getAliasByRef(ctx, field.Type)
+ if alias != nil {
+ if size := getSizeOfBinapiTypeLength(alias.Type, alias.Length); size > maxSize {
+ maxSize = size
+ }
+ continue
+ } else {
+ logf("no type or alias found for union %s field type %q", union.Name, field.Type)
+ continue
+ }
+ }
+ return
+}