aboutsummaryrefslogtreecommitdiffstats
path: root/cmd/binapi-generator/main.go
diff options
context:
space:
mode:
Diffstat (limited to 'cmd/binapi-generator/main.go')
-rw-r--r--cmd/binapi-generator/main.go134
1 files changed, 127 insertions, 7 deletions
diff --git a/cmd/binapi-generator/main.go b/cmd/binapi-generator/main.go
index c66fc4f..e0e2f08 100644
--- a/cmd/binapi-generator/main.go
+++ b/cmd/binapi-generator/main.go
@@ -32,9 +32,10 @@ import (
)
var (
- theInputFile = flag.String("input-file", "", "Input file with VPP API in JSON format.")
- theInputDir = flag.String("input-dir", "/usr/share/vpp/api", "Input directory with VPP API files in JSON format.")
- theOutputDir = flag.String("output-dir", ".", "Output directory where package folders will be generated.")
+ theInputFile = flag.String("input-file", "", "Input file with VPP API in JSON format.")
+ theInputTypes = flag.String("input-types", "", "Types input file with VPP API in JSON format. (split by comma)")
+ theInputDir = flag.String("input-dir", "/usr/share/vpp/api", "Input directory with VPP API files in JSON format.")
+ theOutputDir = flag.String("output-dir", ".", "Output directory where package folders will be generated.")
includeAPIVer = flag.Bool("include-apiver", true, "Include APIVersion constant for each module.")
includeServices = flag.Bool("include-services", true, "Include RPC service api and client implementation.")
@@ -84,14 +85,23 @@ func main() {
}
}
-func run(inputFile, inputDir string, outputDir string, continueErr bool) error {
+func run(inputFile, inputDir string, outputDir string, continueErr bool) (err error) {
if inputFile == "" && inputDir == "" {
return fmt.Errorf("input-file or input-dir must be specified")
}
+ var typesPkgs []*context
+ if *theInputTypes != "" {
+ types := strings.Split(*theInputTypes, ",")
+ typesPkgs, err = loadTypesPackages(types...)
+ if err != nil {
+ return fmt.Errorf("loading types input failed: %v", err)
+ }
+ }
+
if inputFile != "" {
// process one input file
- if err := generateFromFile(inputFile, outputDir); err != nil {
+ if err := generateFromFile(inputFile, outputDir, typesPkgs); err != nil {
return fmt.Errorf("code generation from %s failed: %v\n", inputFile, err)
}
} else {
@@ -107,7 +117,7 @@ func run(inputFile, inputDir string, outputDir string, continueErr bool) error {
return fmt.Errorf("no input files found in input directory: %v\n", dir)
}
for _, file := range files {
- if err := generateFromFile(file, outputDir); err != nil {
+ if err := generateFromFile(file, outputDir, typesPkgs); err != nil {
if continueErr {
logrus.Warnf("code generation from %s failed: %v (error ignored)\n", file, err)
continue
@@ -151,7 +161,7 @@ func parseInputJSON(inputData []byte) (*jsongo.Node, error) {
}
// generateFromFile generates Go package from one input JSON file
-func generateFromFile(inputFile, outputDir string) error {
+func generateFromFile(inputFile, outputDir string, typesPkgs []*context) error {
// create generator context
ctx, err := newContext(inputFile, outputDir)
if err != nil {
@@ -185,6 +195,13 @@ func generateFromFile(inputFile, outputDir string) error {
return fmt.Errorf("parsing package %s failed: %v", ctx.packageName, err)
}
+ if len(typesPkgs) > 0 {
+ err = loadTypeAliases(ctx, typesPkgs)
+ if err != nil {
+ return fmt.Errorf("loading type aliases failed: %v", err)
+ }
+ }
+
// generate Go package code
var buf bytes.Buffer
if err := generatePackage(ctx, &buf); err != nil {
@@ -210,6 +227,109 @@ func generateFromFile(inputFile, outputDir string) error {
return nil
}
+func loadTypesPackages(types ...string) ([]*context, error) {
+ var ctxs []*context
+ for _, inputFile := range types {
+ // create generator context
+ ctx, err := newContext(inputFile, "")
+ if err != nil {
+ return nil, err
+ }
+ // read API definition from input file
+ ctx.inputData, err = ioutil.ReadFile(ctx.inputFile)
+ if err != nil {
+ return nil, fmt.Errorf("reading input file %s failed: %v", ctx.inputFile, err)
+ }
+ // parse JSON data into objects
+ jsonRoot, err := parseInputJSON(ctx.inputData)
+ if err != nil {
+ return nil, fmt.Errorf("parsing JSON input failed: %v", err)
+ }
+ ctx.packageData, err = parsePackage(ctx, jsonRoot)
+ if err != nil {
+ return nil, fmt.Errorf("parsing package %s failed: %v", ctx.packageName, err)
+ }
+ ctxs = append(ctxs, ctx)
+ }
+ return ctxs, nil
+}
+
+func loadTypeAliases(ctx *context, typesCtxs []*context) error {
+ for _, t := range ctx.packageData.Types {
+ for _, c := range typesCtxs {
+ if _, ok := ctx.packageData.Imports[t.Name]; ok {
+ break
+ }
+ for _, at := range c.packageData.Types {
+ if at.Name != t.Name {
+ continue
+ }
+ if len(at.Fields) != len(t.Fields) {
+ continue
+ }
+ ctx.packageData.Imports[t.Name] = Import{
+ Package: c.packageName,
+ }
+ }
+ }
+ }
+ for _, t := range ctx.packageData.Aliases {
+ for _, c := range typesCtxs {
+ if _, ok := ctx.packageData.Imports[t.Name]; ok {
+ break
+ }
+ for _, at := range c.packageData.Aliases {
+ if at.Name != t.Name {
+ continue
+ }
+ if at.Length != t.Length {
+ continue
+ }
+ if at.Type != t.Type {
+ continue
+ }
+ ctx.packageData.Imports[t.Name] = Import{
+ Package: c.packageName,
+ }
+ }
+ }
+ }
+ for _, t := range ctx.packageData.Enums {
+ for _, c := range typesCtxs {
+ if _, ok := ctx.packageData.Imports[t.Name]; ok {
+ break
+ }
+ for _, at := range c.packageData.Enums {
+ if at.Name != t.Name {
+ continue
+ }
+ if at.Type != t.Type {
+ continue
+ }
+ ctx.packageData.Imports[t.Name] = Import{
+ Package: c.packageName,
+ }
+ }
+ }
+ }
+ for _, t := range ctx.packageData.Unions {
+ for _, c := range typesCtxs {
+ if _, ok := ctx.packageData.Imports[t.Name]; ok {
+ break
+ }
+ for _, at := range c.packageData.Unions {
+ if at.Name != t.Name {
+ continue
+ }
+ ctx.packageData.Imports[t.Name] = Import{
+ Package: c.packageName,
+ }
+ }
+ }
+ }
+ return nil
+}
+
func logf(f string, v ...interface{}) {
if *debugMode {
logrus.Debugf(f, v...)