
Google's new protobuf code generator only supports protobuf serialization/deserialization and let other code generators handle RPC-related aspects. This new code generator follows the change and can be used with the new protobuf code generator. Signed-off-by: Kazuyoshi Kato <katokazu@amazon.com>
126 lines
3.8 KiB
Go
126 lines
3.8 KiB
Go
/*
|
|
Copyright The containerd Authors.
|
|
|
|
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 main
|
|
|
|
import (
|
|
"strings"
|
|
|
|
"google.golang.org/protobuf/compiler/protogen"
|
|
)
|
|
|
|
// generator is a Go code generator that uses ttrpc.Server and ttrpc.Client.
|
|
// Unlike the original gogo version, this doesn't generate serializers for message types and
|
|
// let protoc-gen-go handle them.
|
|
type generator struct {
|
|
out *protogen.GeneratedFile
|
|
|
|
ident struct {
|
|
context string
|
|
server string
|
|
client string
|
|
method string
|
|
}
|
|
}
|
|
|
|
func newGenerator(out *protogen.GeneratedFile) *generator {
|
|
gen := generator{out: out}
|
|
gen.ident.context = out.QualifiedGoIdent(protogen.GoIdent{
|
|
GoImportPath: "context",
|
|
GoName: "Context",
|
|
})
|
|
gen.ident.server = out.QualifiedGoIdent(protogen.GoIdent{
|
|
GoImportPath: "github.com/containerd/ttrpc",
|
|
GoName: "Server",
|
|
})
|
|
gen.ident.client = out.QualifiedGoIdent(protogen.GoIdent{
|
|
GoImportPath: "github.com/containerd/ttrpc",
|
|
GoName: "Client",
|
|
})
|
|
gen.ident.method = out.QualifiedGoIdent(protogen.GoIdent{
|
|
GoImportPath: "github.com/containerd/ttrpc",
|
|
GoName: "Method",
|
|
})
|
|
return &gen
|
|
}
|
|
|
|
func generate(plugin *protogen.Plugin, input *protogen.File) error {
|
|
file := plugin.NewGeneratedFile(input.GeneratedFilenamePrefix+"_ttrpc.pb.go", input.GoImportPath)
|
|
file.P("// Code generated by protoc-gen-go-ttrpc. DO NOT EDIT.")
|
|
file.P("// source: ", input.Desc.Path())
|
|
file.P("package ", input.GoPackageName)
|
|
|
|
gen := newGenerator(file)
|
|
for _, service := range input.Services {
|
|
gen.genService(service)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (gen *generator) genService(service *protogen.Service) {
|
|
fullName := service.Desc.FullName()
|
|
p := gen.out
|
|
|
|
serviceName := service.GoName + "Service"
|
|
p.P("type ", serviceName, " interface{")
|
|
for _, method := range service.Methods {
|
|
p.P(method.GoName,
|
|
"(ctx ", gen.ident.context, ",",
|
|
"req *", method.Input.GoIdent, ")",
|
|
"(*", method.Output.GoIdent, ", error)")
|
|
}
|
|
p.P("}")
|
|
|
|
// registration method
|
|
p.P("func Register", serviceName, "(srv *", gen.ident.server, ", svc ", serviceName, "){")
|
|
p.P(`srv.Register("`, fullName, `", map[string]`, gen.ident.method, "{")
|
|
for _, method := range service.Methods {
|
|
p.P(`"`, method.GoName, `": func(ctx `, gen.ident.context, ", unmarshal func(interface{}) error)(interface{}, error){")
|
|
p.P("var req ", method.Input.GoIdent)
|
|
p.P("if err := unmarshal(&req); err != nil {")
|
|
p.P("return nil, err")
|
|
p.P("}")
|
|
p.P("return svc.", method.GoName, "(ctx, &req)")
|
|
p.P("},")
|
|
}
|
|
p.P("})")
|
|
p.P("}")
|
|
|
|
clientType := service.GoName + "Client"
|
|
clientStructType := strings.ToLower(clientType[:1]) + clientType[1:]
|
|
p.P("type ", clientStructType, " struct{")
|
|
p.P("client *", gen.ident.client)
|
|
p.P("}")
|
|
p.P("func New", clientType, "(client *", gen.ident.client, ")", serviceName, "{")
|
|
p.P("return &", clientStructType, "{")
|
|
p.P("client:client,")
|
|
p.P("}")
|
|
p.P("}")
|
|
|
|
for _, method := range service.Methods {
|
|
p.P("func (c *", clientStructType, ")", method.GoName, "(",
|
|
"ctx ", gen.ident.context, ",",
|
|
"req *", method.Input.GoIdent, ")",
|
|
"(*", method.Output.GoIdent, ", error){")
|
|
p.P("var resp ", method.Output.GoIdent)
|
|
p.P(`if err := c.client.Call(ctx, "`, fullName, `", "`, method.Desc.Name(), `", req, &resp); err != nil {`)
|
|
p.P("return nil, err")
|
|
p.P("}")
|
|
p.P("return &resp, nil")
|
|
p.P("}")
|
|
}
|
|
}
|