X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=cmd%2Fbinapi-generator%2Fmain.go;h=e0e2f0815cf5a44ce4f81d60d2bebdca052e8f5d;hb=2df59463fcbb1a5aec2173712b32fb9740157a9d;hp=c66fc4fa28736bd39b9997fdb9ea175d773610e3;hpb=8c64ee581e9cda9030c79c3d85a5ac76d8fd1bca;p=govpp.git 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...)