aboutsummaryrefslogtreecommitdiffstats
path: root/binapigen/vppapi/parse_json.go
diff options
context:
space:
mode:
Diffstat (limited to 'binapigen/vppapi/parse_json.go')
-rw-r--r--binapigen/vppapi/parse_json.go210
1 files changed, 73 insertions, 137 deletions
diff --git a/binapigen/vppapi/parse_json.go b/binapigen/vppapi/parse_json.go
index 45b5796..d14865c 100644
--- a/binapigen/vppapi/parse_json.go
+++ b/binapigen/vppapi/parse_json.go
@@ -18,79 +18,52 @@ import (
"encoding/json"
"errors"
"fmt"
+ "log"
"os"
"strings"
"github.com/bennyscetbun/jsongo"
- "github.com/sirupsen/logrus"
)
-var Logger *logrus.Logger
-
-func init() {
- if strings.Contains(os.Getenv("DEBUG_GOVPP"), "parser") {
- Logger = logrus.StandardLogger()
- }
-}
+var debug = strings.Contains(os.Getenv("DEBUG_GOVPP"), "parser")
func logf(f string, v ...interface{}) {
- if Logger != nil {
- Logger.Debugf(f, v...)
+ if debug {
+ log.Printf(f, v...)
}
}
const (
- // file
- objAPIVersion = "vl_api_version"
- objTypes = "types"
- objMessages = "messages"
- objUnions = "unions"
- objEnums = "enums"
- objServices = "services"
- objAliases = "aliases"
- objOptions = "options"
- objImports = "imports"
-
- // message
- messageFieldCrc = "crc"
-
- // alias
- aliasFieldLength = "length"
- aliasFieldType = "type"
-
- // service
- serviceFieldReply = "reply"
- serviceFieldStream = "stream"
- serviceFieldStreamMsg = "stream_msg"
- serviceFieldEvents = "events"
-)
-
-const (
- // file
- fileOptionVersion = "version"
-
- // field
- fieldOptionLimit = "limit"
- fieldOptionDefault = "default"
-
+ // root keys
+ fileAPIVersion = "vl_api_version"
+ fileOptions = "options"
+ fileTypes = "types"
+ fileMessages = "messages"
+ fileUnions = "unions"
+ fileEnums = "enums"
+ fileAliases = "aliases"
+ fileServices = "services"
+ fileImports = "imports"
+ // type keys
+ messageCrc = "crc"
+ enumType = "enumtype"
+ aliasLength = "length"
+ aliasType = "type"
// service
- serviceReplyNull = "null"
+ serviceReply = "reply"
+ serviceStream = "stream"
+ serviceStreamMsg = "stream_msg"
+ serviceEvents = "events"
)
func parseJSON(data []byte) (module *File, err error) {
- defer func() {
- if e := recover(); e != nil {
- err = fmt.Errorf("recovered panic: %v", e)
- }
- }()
-
- // parse JSON data into objects
+ // parse root
jsonRoot := new(jsongo.Node)
if err := json.Unmarshal(data, jsonRoot); err != nil {
return nil, fmt.Errorf("unmarshalling JSON failed: %v", err)
}
- logf("file contents:")
+ logf("file contains:")
for _, key := range jsonRoot.GetKeys() {
if jsonRoot.At(key).Len() > 0 {
logf(" - %2d %s", jsonRoot.At(key).Len(), key)
@@ -100,38 +73,35 @@ func parseJSON(data []byte) (module *File, err error) {
module = new(File)
// parse CRC
- if crc := jsonRoot.At(objAPIVersion); crc.GetType() == jsongo.TypeValue {
- module.CRC = crc.Get().(string)
+ crc := jsonRoot.At(fileAPIVersion)
+ if crc.GetType() == jsongo.TypeValue {
+ module.CRC = crc.MustGetString()
}
// parse options
- opt := jsonRoot.Map(objOptions)
+ opt := jsonRoot.Map(fileOptions)
if opt.GetType() == jsongo.TypeMap {
- module.Options = make(map[string]string, 0)
+ module.Options = make(map[string]string)
for _, key := range opt.GetKeys() {
- optionsNode := opt.At(key)
optionKey := key.(string)
- optionValue := optionsNode.Get().(string)
- module.Options[optionKey] = optionValue
+ optionVal := opt.At(key).MustGetString()
+ module.Options[optionKey] = optionVal
}
}
// parse imports
- imports := jsonRoot.Map(objImports)
- module.Imports = make([]string, 0)
- imported := make(map[string]struct{})
- for i := 0; i < imports.Len(); i++ {
- importNode := imports.At(i)
- imp, err := parseImport(importNode)
- if err != nil {
- return nil, err
- }
- if _, ok := imported[*imp]; ok {
- logf("duplicate import found: %v", *imp)
+ importsNode := jsonRoot.Map(fileImports)
+ module.Imports = make([]string, 0, importsNode.Len())
+ uniq := make(map[string]struct{})
+ for i := 0; i < importsNode.Len(); i++ {
+ importNode := importsNode.At(i)
+ imp := importNode.MustGetString()
+ if _, ok := uniq[imp]; ok {
+ logf("duplicate import found: %v", imp)
continue
}
- imported[*imp] = struct{}{}
- module.Imports = append(module.Imports, *imp)
+ uniq[imp] = struct{}{}
+ module.Imports = append(module.Imports, imp)
}
// avoid duplicate objects
@@ -146,11 +116,10 @@ func parseJSON(data []byte) (module *File, err error) {
}
// parse enum types
- enumsNode := jsonRoot.Map(objEnums)
+ enumsNode := jsonRoot.Map(fileEnums)
module.EnumTypes = make([]EnumType, 0)
for i := 0; i < enumsNode.Len(); i++ {
- enumNode := enumsNode.At(i)
- enum, err := parseEnum(enumNode)
+ enum, err := parseEnum(enumsNode.At(i))
if err != nil {
return nil, err
}
@@ -161,13 +130,12 @@ func parseJSON(data []byte) (module *File, err error) {
}
// parse alias types
- aliasesNode := jsonRoot.Map(objAliases)
+ aliasesNode := jsonRoot.Map(fileAliases)
if aliasesNode.GetType() == jsongo.TypeMap {
module.AliasTypes = make([]AliasType, 0)
for _, key := range aliasesNode.GetKeys() {
- aliasNode := aliasesNode.At(key)
aliasName := key.(string)
- alias, err := parseAlias(aliasName, aliasNode)
+ alias, err := parseAlias(aliasName, aliasesNode.At(key))
if err != nil {
return nil, err
}
@@ -179,11 +147,10 @@ func parseJSON(data []byte) (module *File, err error) {
}
// parse struct types
- typesNode := jsonRoot.Map(objTypes)
+ typesNode := jsonRoot.Map(fileTypes)
module.StructTypes = make([]StructType, 0)
for i := 0; i < typesNode.Len(); i++ {
- typNode := typesNode.At(i)
- structyp, err := parseStruct(typNode)
+ structyp, err := parseStruct(typesNode.At(i))
if err != nil {
return nil, err
}
@@ -194,11 +161,10 @@ func parseJSON(data []byte) (module *File, err error) {
}
// parse union types
- unionsNode := jsonRoot.Map(objUnions)
+ unionsNode := jsonRoot.Map(fileUnions)
module.UnionTypes = make([]UnionType, 0)
for i := 0; i < unionsNode.Len(); i++ {
- unionNode := unionsNode.At(i)
- union, err := parseUnion(unionNode)
+ union, err := parseUnion(unionsNode.At(i))
if err != nil {
return nil, err
}
@@ -209,12 +175,11 @@ func parseJSON(data []byte) (module *File, err error) {
}
// parse messages
- messagesNode := jsonRoot.Map(objMessages)
+ messagesNode := jsonRoot.Map(fileMessages)
if messagesNode.GetType() == jsongo.TypeArray {
module.Messages = make([]Message, messagesNode.Len())
for i := 0; i < messagesNode.Len(); i++ {
- msgNode := messagesNode.At(i)
- msg, err := parseMessage(msgNode)
+ msg, err := parseMessage(messagesNode.At(i))
if err != nil {
return nil, err
}
@@ -223,15 +188,14 @@ func parseJSON(data []byte) (module *File, err error) {
}
// parse services
- servicesNode := jsonRoot.Map(objServices)
+ servicesNode := jsonRoot.Map(fileServices)
if servicesNode.GetType() == jsongo.TypeMap {
module.Service = &Service{
RPCs: make([]RPC, servicesNode.Len()),
}
for i, key := range servicesNode.GetKeys() {
- rpcNode := servicesNode.At(key)
rpcName := key.(string)
- svc, err := parseServiceRPC(rpcName, rpcNode)
+ svc, err := parseServiceRPC(rpcName, servicesNode.At(key))
if err != nil {
return nil, err
}
@@ -242,20 +206,6 @@ func parseJSON(data []byte) (module *File, err error) {
return module, nil
}
-// parseImport parses VPP binary API import from JSON node
-func parseImport(importNode *jsongo.Node) (*string, error) {
- if importNode.GetType() != jsongo.TypeValue {
- return nil, errors.New("invalid JSON for import specified")
- }
-
- importName, ok := importNode.Get().(string)
- if !ok {
- return nil, fmt.Errorf("import name is %T, not a string", importNode.Get())
- }
-
- return &importName, nil
-}
-
// parseEnum parses VPP binary API enum object from JSON node
func parseEnum(enumNode *jsongo.Node) (*EnumType, error) {
if enumNode.Len() == 0 || enumNode.At(0).GetType() != jsongo.TypeValue {
@@ -266,7 +216,7 @@ func parseEnum(enumNode *jsongo.Node) (*EnumType, error) {
if !ok {
return nil, fmt.Errorf("enum name is %T, not a string", enumNode.At(0).Get())
}
- enumType, ok := enumNode.At(enumNode.Len() - 1).At("enumtype").Get().(string)
+ enumType, ok := enumNode.At(enumNode.Len() - 1).At(enumType).Get().(string)
if !ok {
return nil, fmt.Errorf("enum type invalid or missing")
}
@@ -367,7 +317,7 @@ func parseStruct(typeNode *jsongo.Node) (*StructType, error) {
// parseAlias parses VPP binary API alias object from JSON node
func parseAlias(aliasName string, aliasNode *jsongo.Node) (*AliasType, error) {
- if aliasNode.Len() == 0 || aliasNode.At(aliasFieldType).GetType() != jsongo.TypeValue {
+ if aliasNode.Len() == 0 || aliasNode.At(aliasType).GetType() != jsongo.TypeValue {
return nil, errors.New("invalid JSON for alias specified")
}
@@ -375,7 +325,7 @@ func parseAlias(aliasName string, aliasNode *jsongo.Node) (*AliasType, error) {
Name: aliasName,
}
- if typeNode := aliasNode.At(aliasFieldType); typeNode.GetType() == jsongo.TypeValue {
+ if typeNode := aliasNode.At(aliasType); typeNode.GetType() == jsongo.TypeValue {
typ, ok := typeNode.Get().(string)
if !ok {
return nil, fmt.Errorf("alias type is %T, not a string", typeNode.Get())
@@ -385,7 +335,7 @@ func parseAlias(aliasName string, aliasNode *jsongo.Node) (*AliasType, error) {
}
}
- if lengthNode := aliasNode.At(aliasFieldLength); lengthNode.GetType() == jsongo.TypeValue {
+ if lengthNode := aliasNode.At(aliasLength); lengthNode.GetType() == jsongo.TypeValue {
length, ok := lengthNode.Get().(float64)
if !ok {
return nil, fmt.Errorf("alias length is %T, not a float64", lengthNode.Get())
@@ -398,7 +348,7 @@ func parseAlias(aliasName string, aliasNode *jsongo.Node) (*AliasType, error) {
// parseMessage parses VPP binary API message object from JSON node
func parseMessage(msgNode *jsongo.Node) (*Message, error) {
- if msgNode.Len() == 0 || msgNode.At(0).GetType() != jsongo.TypeValue {
+ if msgNode.Len() < 2 || msgNode.At(0).GetType() != jsongo.TypeValue {
return nil, errors.New("invalid JSON for message specified")
}
@@ -406,9 +356,8 @@ func parseMessage(msgNode *jsongo.Node) (*Message, error) {
if !ok {
return nil, fmt.Errorf("message name is %T, not a string", msgNode.At(0).Get())
}
- msgCRC, ok := msgNode.At(msgNode.Len() - 1).At(messageFieldCrc).Get().(string)
+ msgCRC, ok := msgNode.At(msgNode.Len() - 1).At(messageCrc).Get().(string)
if !ok {
-
return nil, fmt.Errorf("message crc invalid or missing")
}
@@ -466,26 +415,16 @@ func parseField(field *jsongo.Node) (*Field, error) {
case jsongo.TypeMap:
fieldMeta := field.At(2)
-
+ if fieldMeta.Len() == 0 {
+ break
+ }
+ f.Meta = map[string]interface{}{}
for _, key := range fieldMeta.GetKeys() {
- metaNode := fieldMeta.At(key)
metaName := key.(string)
- metaValue := metaNode.Get()
-
- switch metaName {
- case fieldOptionLimit:
- metaValue = int(metaNode.Get().(float64))
- case fieldOptionDefault:
- metaValue = metaNode.Get()
- default:
- logrus.Warnf("unknown meta info (%s=%v) for field (%s)", metaName, metaValue, fieldName)
- }
-
- if f.Meta == nil {
- f.Meta = map[string]interface{}{}
- }
+ metaValue := fieldMeta.At(key).Get()
f.Meta[metaName] = metaValue
}
+
default:
return nil, errors.New("invalid JSON for field specified")
}
@@ -503,27 +442,24 @@ func parseField(field *jsongo.Node) (*Field, error) {
// parseServiceRPC parses VPP binary API service object from JSON node
func parseServiceRPC(rpcName string, rpcNode *jsongo.Node) (*RPC, error) {
- if rpcNode.Len() == 0 || rpcNode.At(serviceFieldReply).GetType() != jsongo.TypeValue {
+ if rpcNode.Len() == 0 || rpcNode.At(serviceReply).GetType() != jsongo.TypeValue {
return nil, errors.New("invalid JSON for service RPC specified")
}
rpc := RPC{
- Name: rpcName,
- RequestMsg: rpcName,
+ Request: rpcName,
}
- if replyNode := rpcNode.At(serviceFieldReply); replyNode.GetType() == jsongo.TypeValue {
+ if replyNode := rpcNode.At(serviceReply); replyNode.GetType() == jsongo.TypeValue {
reply, ok := replyNode.Get().(string)
if !ok {
return nil, fmt.Errorf("service RPC reply is %T, not a string", replyNode.Get())
}
- if reply != serviceReplyNull {
- rpc.ReplyMsg = reply
- }
+ rpc.Reply = reply
}
// is stream (dump)
- if streamNode := rpcNode.At(serviceFieldStream); streamNode.GetType() == jsongo.TypeValue {
+ if streamNode := rpcNode.At(serviceStream); streamNode.GetType() == jsongo.TypeValue {
var ok bool
rpc.Stream, ok = streamNode.Get().(bool)
if !ok {
@@ -532,7 +468,7 @@ func parseServiceRPC(rpcName string, rpcNode *jsongo.Node) (*RPC, error) {
}
// stream message
- if streamMsgNode := rpcNode.At(serviceFieldStreamMsg); streamMsgNode.GetType() == jsongo.TypeValue {
+ if streamMsgNode := rpcNode.At(serviceStreamMsg); streamMsgNode.GetType() == jsongo.TypeValue {
var ok bool
rpc.StreamMsg, ok = streamMsgNode.Get().(string)
if !ok {
@@ -541,7 +477,7 @@ func parseServiceRPC(rpcName string, rpcNode *jsongo.Node) (*RPC, error) {
}
// events service (event subscription)
- if eventsNode := rpcNode.At(serviceFieldEvents); eventsNode.GetType() == jsongo.TypeArray {
+ if eventsNode := rpcNode.At(serviceEvents); eventsNode.GetType() == jsongo.TypeArray {
for j := 0; j < eventsNode.Len(); j++ {
event := eventsNode.At(j).Get().(string)
rpc.Events = append(rpc.Events, event)