1 // Copyright (c) 2020 Cisco and/or its affiliates.
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at:
7 // http://www.apache.org/licenses/LICENSE-2.0
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
23 func generatePackageRPC(ctx *GenFile, w io.Writer) {
24 logf("----------------------------")
25 logf("generating RPC package: %q", ctx.file.PackageName)
26 logf("----------------------------")
28 fmt.Fprintln(w, "// Code generated by GoVPP's binapi-generator. DO NOT EDIT.")
31 fmt.Fprintf(w, "package %s\n", ctx.file.PackageName)
34 fmt.Fprintln(w, "import (")
35 fmt.Fprintln(w, ` "context"`)
36 fmt.Fprintln(w, ` "io"`)
38 fmt.Fprintf(w, "\tapi \"%s\"\n", "git.fd.io/govpp.git/api")
43 if ctx.file.Service != nil && len(ctx.file.Service.RPCs) > 0 {
44 generateServiceMethods(ctx, w, ctx.file.Service.RPCs)
47 // generate message registrations
48 /*fmt.Fprintln(w, "var _RPCService_desc = api.RPCDesc{")
53 fmt.Fprintf(w, "// Reference imports to suppress errors if they are not otherwise used.\n")
54 fmt.Fprintf(w, "var _ = api.RegisterMessage\n")
55 fmt.Fprintf(w, "var _ = context.Background\n")
56 fmt.Fprintf(w, "var _ = io.Copy\n")
60 func generateServiceMethods(ctx *GenFile, w io.Writer, methods []RPC) {
61 // generate services comment
62 generateComment(ctx, w, serviceApiName, "services", "service")
64 // generate service api
65 fmt.Fprintf(w, "type %s interface {\n", serviceApiName)
66 for _, svc := range methods {
67 generateServiceMethod(ctx, w, &svc)
73 // generate client implementation
74 fmt.Fprintf(w, "type %s struct {\n", serviceImplName)
75 fmt.Fprintf(w, "\tch api.Channel\n")
79 // generate client constructor
80 fmt.Fprintf(w, "func New%s(ch api.Channel) %s {\n", serviceClientName, serviceApiName)
81 fmt.Fprintf(w, "\treturn &%s{ch}\n", serviceImplName)
85 for _, met := range methods {
86 method := camelCaseName(met.RequestMsg)
87 if m := strings.TrimSuffix(method, "Dump"); method != m {
91 fmt.Fprintf(w, "func (c *%s) ", serviceImplName)
92 generateServiceMethod(ctx, w, &met)
95 streamImpl := fmt.Sprintf("%s_%sClient", serviceImplName, method)
96 fmt.Fprintf(w, "\tstream := c.ch.SendMultiRequest(in)\n")
97 fmt.Fprintf(w, "\tx := &%s{stream}\n", streamImpl)
98 fmt.Fprintf(w, "\treturn x, nil\n")
99 } else if replyTyp := camelCaseName(met.ReplyMsg); replyTyp != "" {
100 fmt.Fprintf(w, "\tout := new(%s)\n", replyTyp)
101 fmt.Fprintf(w, "\terr:= c.ch.SendRequest(in).ReceiveReply(out)\n")
102 fmt.Fprintf(w, "\tif err != nil { return nil, err }\n")
103 fmt.Fprintf(w, "\treturn out, nil\n")
105 fmt.Fprintf(w, "\tc.ch.SendRequest(in)\n")
106 fmt.Fprintf(w, "\treturn nil\n")
112 replyTyp := camelCaseName(met.ReplyMsg)
113 method := camelCaseName(met.RequestMsg)
114 if m := strings.TrimSuffix(method, "Dump"); method != m {
117 streamApi := fmt.Sprintf("%s_%sClient", serviceApiName, method)
119 fmt.Fprintf(w, "type %s interface {\n", streamApi)
120 fmt.Fprintf(w, "\tRecv() (*%s, error)\n", replyTyp)
124 streamImpl := fmt.Sprintf("%s_%sClient", serviceImplName, method)
125 fmt.Fprintf(w, "type %s struct {\n", streamImpl)
126 fmt.Fprintf(w, "\tapi.MultiRequestCtx\n")
130 fmt.Fprintf(w, "func (c *%s) Recv() (*%s, error) {\n", streamImpl, replyTyp)
131 fmt.Fprintf(w, "\tm := new(%s)\n", replyTyp)
132 fmt.Fprintf(w, "\tstop, err := c.MultiRequestCtx.ReceiveReply(m)\n")
133 fmt.Fprintf(w, "\tif err != nil { return nil, err }\n")
134 fmt.Fprintf(w, "\tif stop { return nil, io.EOF }\n")
135 fmt.Fprintf(w, "\treturn m, nil\n")
141 // TODO: generate service descriptor
142 /*fmt.Fprintf(w, "var %s = api.%s{\n", serviceDescName, serviceDescType)
143 fmt.Fprintf(w, "\tServiceName: \"%s\",\n", ctx.moduleName)
144 fmt.Fprintf(w, "\tHandlerType: (*%s)(nil),\n", serviceApiName)
145 fmt.Fprintf(w, "\tMethods: []api.MethodDesc{\n")
146 for _, method := range methods {
147 fmt.Fprintf(w, "\t {\n")
148 fmt.Fprintf(w, "\t MethodName: \"%s\",\n", method.Name)
149 fmt.Fprintf(w, "\t },\n")
151 fmt.Fprintf(w, "\t},\n")
152 //fmt.Fprintf(w, "\tCompatibility: %s,\n", messageCrcName)
153 //fmt.Fprintf(w, "\tMetadata: reflect.TypeOf((*%s)(nil)).Elem().PkgPath(),\n", serviceApiName)
154 fmt.Fprintf(w, "\tMetadata: \"%s\",\n", ctx.inputFile)
155 fmt.Fprintln(w, "}")*/
160 func generateServiceMethod(ctx *GenFile, w io.Writer, rpc *RPC) {
161 reqTyp := camelCaseName(rpc.RequestMsg)
163 logf(" writing RPC: %+v", reqTyp)
165 // method name is same as parameter type name by default
168 // use Dump as prefix instead of suffix for stream services
169 if m := strings.TrimSuffix(method, "Dump"); method != m {
174 params := fmt.Sprintf("in *%s", reqTyp)
177 if replyType := camelCaseName(rpc.ReplyMsg); replyType != "" {
180 replyTyp = fmt.Sprintf("%s_%sClient", serviceApiName, method)
182 replyTyp = fmt.Sprintf("*%s", replyType)
184 returns = fmt.Sprintf("(%s, error)", replyTyp)
187 fmt.Fprintf(w, "\t%s(ctx context.Context, %s) %s", method, params, returns)