From d1f24d37bd447b64e402298bb8eb2479681facf9 Mon Sep 17 00:00:00 2001 From: Ondrej Fabry Date: Fri, 17 Jul 2020 10:36:28 +0200 Subject: Improve binapi generator - simplified Size/Marshal/Unmarshal methods - replace struc in unions with custom marshal/unmarshal - fix imports in generated files - fix mock adapter - generate rpc service using low-level stream API (dumps generate control ping or stream msg..) - move examples/binapi to binapi and generate all API for latest release - add binapigen.Plugin for developing custom generator plugins - optionally generate HTTP handlers (REST API) for RPC services - add govpp program for browsing VPP API Change-Id: I092e9ed2b0c17972b3476463c3d4b14dd76ed42b Signed-off-by: Ondrej Fabry --- binapigen/generate_rpc.go | 203 ---------------------------------------------- 1 file changed, 203 deletions(-) delete mode 100644 binapigen/generate_rpc.go (limited to 'binapigen/generate_rpc.go') diff --git a/binapigen/generate_rpc.go b/binapigen/generate_rpc.go deleted file mode 100644 index 4beec04..0000000 --- a/binapigen/generate_rpc.go +++ /dev/null @@ -1,203 +0,0 @@ -// Copyright (c) 2020 Cisco and/or its affiliates. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at: -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package binapigen - -import ( - "fmt" - "io" - "strings" -) - -// generated service names -const ( - serviceApiName = "RPCService" // name for the RPC service interface - serviceImplName = "serviceClient" // name for the RPC service implementation - serviceClientName = "ServiceClient" // name for the RPC service client - - // TODO: register service descriptor - //serviceDescType = "ServiceDesc" // name for service descriptor type - //serviceDescName = "_ServiceRPC_serviceDesc" // name for service descriptor var -) - -func generateFileRPC(ctx *GenFile, w io.Writer) { - logf("----------------------------") - logf("generating RPC file package: %q", ctx.file.PackageName) - logf("----------------------------") - - // generate file header - fmt.Fprintln(w, "// Code generated by GoVPP's binapi-generator. DO NOT EDIT.") - fmt.Fprintln(w) - - // generate package header - fmt.Fprintf(w, "package %s\n", ctx.file.PackageName) - fmt.Fprintln(w) - - // generate imports - fmt.Fprintln(w, "import (") - fmt.Fprintln(w, ` "context"`) - fmt.Fprintln(w, ` "io"`) - fmt.Fprintln(w) - fmt.Fprintf(w, "\tapi \"%s\"\n", "git.fd.io/govpp.git/api") - fmt.Fprintln(w, ")") - fmt.Fprintln(w) - - // generate RPC service - if ctx.file.Service != nil && len(ctx.file.Service.RPCs) > 0 { - generateService(ctx, w, ctx.file.Service) - } - - // generate message registrations - /*fmt.Fprintln(w, "var _RPCService_desc = api.RPCDesc{") - - fmt.Fprintln(w, "}") - fmt.Fprintln(w)*/ - - // generate import refs - fmt.Fprintf(w, "// Reference imports to suppress errors if they are not otherwise used.\n") - fmt.Fprintf(w, "var _ = api.RegisterMessage\n") - fmt.Fprintf(w, "var _ = context.Background\n") - fmt.Fprintf(w, "var _ = io.Copy\n") - -} - -func generateService(ctx *GenFile, w io.Writer, svc *Service) { - // generate services comment - generateComment(ctx, w, serviceApiName, "services", "service") - - // generate service api - fmt.Fprintf(w, "type %s interface {\n", serviceApiName) - for _, rpc := range svc.RPCs { - generateRPCMethod(ctx, w, &rpc) - fmt.Fprintln(w) - } - fmt.Fprintln(w, "}") - fmt.Fprintln(w) - - // generate client implementation - fmt.Fprintf(w, "type %s struct {\n", serviceImplName) - fmt.Fprintf(w, "\tch api.Channel\n") - fmt.Fprintln(w, "}") - fmt.Fprintln(w) - - // generate client constructor - fmt.Fprintf(w, "func New%s(ch api.Channel) %s {\n", serviceClientName, serviceApiName) - fmt.Fprintf(w, "\treturn &%s{ch}\n", serviceImplName) - fmt.Fprintln(w, "}") - fmt.Fprintln(w) - - for _, rpc := range svc.RPCs { - method := camelCaseName(rpc.RequestMsg) - if m := strings.TrimSuffix(method, "Dump"); method != m { - method = "Dump" + m - } - - fmt.Fprintf(w, "func (c *%s) ", serviceImplName) - generateRPCMethod(ctx, w, &rpc) - fmt.Fprintln(w, " {") - if rpc.Stream { - streamImpl := fmt.Sprintf("%s_%sClient", serviceImplName, method) - fmt.Fprintf(w, "\tstream := c.ch.SendMultiRequest(in)\n") - fmt.Fprintf(w, "\tx := &%s{stream}\n", streamImpl) - fmt.Fprintf(w, "\treturn x, nil\n") - } else if replyTyp := camelCaseName(rpc.ReplyMsg); replyTyp != "" { - fmt.Fprintf(w, "\tout := new(%s)\n", replyTyp) - fmt.Fprintf(w, "\terr:= c.ch.SendRequest(in).ReceiveReply(out)\n") - fmt.Fprintf(w, "\tif err != nil { return nil, err }\n") - fmt.Fprintf(w, "\treturn out, nil\n") - } else { - fmt.Fprintf(w, "\tc.ch.SendRequest(in)\n") - fmt.Fprintf(w, "\treturn nil\n") - } - fmt.Fprintln(w, "}") - fmt.Fprintln(w) - - if rpc.Stream { - replyTyp := camelCaseName(rpc.ReplyMsg) - method := camelCaseName(rpc.RequestMsg) - if m := strings.TrimSuffix(method, "Dump"); method != m { - method = "Dump" + m - } - streamApi := fmt.Sprintf("%s_%sClient", serviceApiName, method) - - fmt.Fprintf(w, "type %s interface {\n", streamApi) - fmt.Fprintf(w, "\tRecv() (*%s, error)\n", replyTyp) - fmt.Fprintln(w, "}") - fmt.Fprintln(w) - - streamImpl := fmt.Sprintf("%s_%sClient", serviceImplName, method) - fmt.Fprintf(w, "type %s struct {\n", streamImpl) - fmt.Fprintf(w, "\tapi.MultiRequestCtx\n") - fmt.Fprintln(w, "}") - fmt.Fprintln(w) - - fmt.Fprintf(w, "func (c *%s) Recv() (*%s, error) {\n", streamImpl, replyTyp) - fmt.Fprintf(w, "\tm := new(%s)\n", replyTyp) - fmt.Fprintf(w, "\tstop, err := c.MultiRequestCtx.ReceiveReply(m)\n") - fmt.Fprintf(w, "\tif err != nil { return nil, err }\n") - fmt.Fprintf(w, "\tif stop { return nil, io.EOF }\n") - fmt.Fprintf(w, "\treturn m, nil\n") - fmt.Fprintln(w, "}") - fmt.Fprintln(w) - } - } - - // TODO: generate service descriptor - /*fmt.Fprintf(w, "var %s = api.%s{\n", serviceDescName, serviceDescType) - fmt.Fprintf(w, "\tServiceName: \"%s\",\n", ctx.moduleName) - fmt.Fprintf(w, "\tHandlerType: (*%s)(nil),\n", serviceApiName) - fmt.Fprintf(w, "\tMethods: []api.MethodDesc{\n") - for _, method := range rpcs { - fmt.Fprintf(w, "\t {\n") - fmt.Fprintf(w, "\t MethodName: \"%s\",\n", method.Name) - fmt.Fprintf(w, "\t },\n") - } - fmt.Fprintf(w, "\t},\n") - //fmt.Fprintf(w, "\tCompatibility: %s,\n", messageCrcName) - //fmt.Fprintf(w, "\tMetadata: reflect.TypeOf((*%s)(nil)).Elem().PkgPath(),\n", serviceApiName) - fmt.Fprintf(w, "\tMetadata: \"%s\",\n", ctx.inputFile) - fmt.Fprintln(w, "}")*/ - - fmt.Fprintln(w) -} - -func generateRPCMethod(ctx *GenFile, w io.Writer, rpc *RPC) { - reqTyp := camelCaseName(rpc.RequestMsg) - - logf(" writing RPC: %+v", reqTyp) - - // method name is same as parameter type name by default - method := reqTyp - if rpc.Stream { - // use Dump as prefix instead of suffix for stream services - if m := strings.TrimSuffix(method, "Dump"); method != m { - method = "Dump" + m - } - } - - params := fmt.Sprintf("in *%s", reqTyp) - returns := "error" - - if replyType := camelCaseName(rpc.ReplyMsg); replyType != "" { - var replyTyp string - if rpc.Stream { - replyTyp = fmt.Sprintf("%s_%sClient", serviceApiName, method) - } else { - replyTyp = fmt.Sprintf("*%s", replyType) - } - returns = fmt.Sprintf("(%s, error)", replyTyp) - } - - fmt.Fprintf(w, "\t%s(ctx context.Context, %s) %s", method, params, returns) -} -- cgit 1.2.3-korg