use tools build constraint for proto dependencies

Signed-off-by: CrazyMax <crazy-max@users.noreply.github.com>
This commit is contained in:
CrazyMax 2022-12-26 09:47:51 +01:00
parent 2ebd97dec1
commit f1ca793980
No known key found for this signature in database
GPG key ID: 3248E46B6BB8C7F7
52 changed files with 19808 additions and 1 deletions

15
internal/tools/tools.go Normal file
View file

@ -0,0 +1,15 @@
//go:build tools
// +build tools
// Package tools tracks dependencies on binaries not referenced in this codebase.
// https://github.com/golang/go/wiki/Modules#how-can-i-track-tool-dependencies-for-a-module
// Disclaimer: Avoid adding tools that don't need to be inferred from go.mod
// like golangci-lint and check they don't import too many dependencies.
package tools
import (
_ "github.com/gogo/protobuf/protoc-gen-gogo"
_ "github.com/gogo/protobuf/protoc-gen-gogofast"
_ "github.com/gogo/protobuf/protoc-gen-gogoslick"
_ "github.com/golang/protobuf/protoc-gen-go"
)

View file

@ -44,6 +44,7 @@ require (
github.com/godbus/dbus/v5 v5.1.0
github.com/gogo/protobuf v1.3.2
github.com/golang/gddo v0.0.0-20190904175337-72a348e765d2
github.com/golang/protobuf v1.5.2
github.com/google/go-cmp v0.5.9
github.com/google/uuid v1.3.0
github.com/gorilla/mux v1.8.0
@ -138,7 +139,6 @@ require (
github.com/gogo/googleapis v1.4.1 // indirect
github.com/golang-jwt/jwt/v4 v4.4.2 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/protobuf v1.5.2 // indirect
github.com/google/btree v1.1.2 // indirect
github.com/google/certificate-transparency-go v1.1.4 // indirect
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect

View file

@ -0,0 +1,580 @@
// Protocol Buffers for Go with Gadgets
//
// Copyright (c) 2013, The GoGo Authors. All rights reserved.
// http://github.com/gogo/protobuf
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package compare
import (
"github.com/gogo/protobuf/gogoproto"
"github.com/gogo/protobuf/proto"
descriptor "github.com/gogo/protobuf/protoc-gen-gogo/descriptor"
"github.com/gogo/protobuf/protoc-gen-gogo/generator"
"github.com/gogo/protobuf/vanity"
)
type plugin struct {
*generator.Generator
generator.PluginImports
fmtPkg generator.Single
bytesPkg generator.Single
sortkeysPkg generator.Single
protoPkg generator.Single
}
func NewPlugin() *plugin {
return &plugin{}
}
func (p *plugin) Name() string {
return "compare"
}
func (p *plugin) Init(g *generator.Generator) {
p.Generator = g
}
func (p *plugin) Generate(file *generator.FileDescriptor) {
p.PluginImports = generator.NewPluginImports(p.Generator)
p.fmtPkg = p.NewImport("fmt")
p.bytesPkg = p.NewImport("bytes")
p.sortkeysPkg = p.NewImport("github.com/gogo/protobuf/sortkeys")
p.protoPkg = p.NewImport("github.com/gogo/protobuf/proto")
for _, msg := range file.Messages() {
if msg.DescriptorProto.GetOptions().GetMapEntry() {
continue
}
if gogoproto.HasCompare(file.FileDescriptorProto, msg.DescriptorProto) {
p.generateMessage(file, msg)
}
}
}
func (p *plugin) generateNullableField(fieldname string) {
p.P(`if this.`, fieldname, ` != nil && that1.`, fieldname, ` != nil {`)
p.In()
p.P(`if *this.`, fieldname, ` != *that1.`, fieldname, `{`)
p.In()
p.P(`if *this.`, fieldname, ` < *that1.`, fieldname, `{`)
p.In()
p.P(`return -1`)
p.Out()
p.P(`}`)
p.P(`return 1`)
p.Out()
p.P(`}`)
p.Out()
p.P(`} else if this.`, fieldname, ` != nil {`)
p.In()
p.P(`return 1`)
p.Out()
p.P(`} else if that1.`, fieldname, ` != nil {`)
p.In()
p.P(`return -1`)
p.Out()
p.P(`}`)
}
func (p *plugin) generateMsgNullAndTypeCheck(ccTypeName string) {
p.P(`if that == nil {`)
p.In()
p.P(`if this == nil {`)
p.In()
p.P(`return 0`)
p.Out()
p.P(`}`)
p.P(`return 1`)
p.Out()
p.P(`}`)
p.P(``)
p.P(`that1, ok := that.(*`, ccTypeName, `)`)
p.P(`if !ok {`)
p.In()
p.P(`that2, ok := that.(`, ccTypeName, `)`)
p.P(`if ok {`)
p.In()
p.P(`that1 = &that2`)
p.Out()
p.P(`} else {`)
p.In()
p.P(`return 1`)
p.Out()
p.P(`}`)
p.Out()
p.P(`}`)
p.P(`if that1 == nil {`)
p.In()
p.P(`if this == nil {`)
p.In()
p.P(`return 0`)
p.Out()
p.P(`}`)
p.P(`return 1`)
p.Out()
p.P(`} else if this == nil {`)
p.In()
p.P(`return -1`)
p.Out()
p.P(`}`)
}
func (p *plugin) generateField(file *generator.FileDescriptor, message *generator.Descriptor, field *descriptor.FieldDescriptorProto) {
proto3 := gogoproto.IsProto3(file.FileDescriptorProto)
fieldname := p.GetOneOfFieldName(message, field)
repeated := field.IsRepeated()
ctype := gogoproto.IsCustomType(field)
nullable := gogoproto.IsNullable(field)
// oneof := field.OneofIndex != nil
if !repeated {
if ctype {
if nullable {
p.P(`if that1.`, fieldname, ` == nil {`)
p.In()
p.P(`if this.`, fieldname, ` != nil {`)
p.In()
p.P(`return 1`)
p.Out()
p.P(`}`)
p.Out()
p.P(`} else if this.`, fieldname, ` == nil {`)
p.In()
p.P(`return -1`)
p.Out()
p.P(`} else if c := this.`, fieldname, `.Compare(*that1.`, fieldname, `); c != 0 {`)
} else {
p.P(`if c := this.`, fieldname, `.Compare(that1.`, fieldname, `); c != 0 {`)
}
p.In()
p.P(`return c`)
p.Out()
p.P(`}`)
} else {
if field.IsMessage() || p.IsGroup(field) {
if nullable {
p.P(`if c := this.`, fieldname, `.Compare(that1.`, fieldname, `); c != 0 {`)
} else {
p.P(`if c := this.`, fieldname, `.Compare(&that1.`, fieldname, `); c != 0 {`)
}
p.In()
p.P(`return c`)
p.Out()
p.P(`}`)
} else if field.IsBytes() {
p.P(`if c := `, p.bytesPkg.Use(), `.Compare(this.`, fieldname, `, that1.`, fieldname, `); c != 0 {`)
p.In()
p.P(`return c`)
p.Out()
p.P(`}`)
} else if field.IsString() {
if nullable && !proto3 {
p.generateNullableField(fieldname)
} else {
p.P(`if this.`, fieldname, ` != that1.`, fieldname, `{`)
p.In()
p.P(`if this.`, fieldname, ` < that1.`, fieldname, `{`)
p.In()
p.P(`return -1`)
p.Out()
p.P(`}`)
p.P(`return 1`)
p.Out()
p.P(`}`)
}
} else if field.IsBool() {
if nullable && !proto3 {
p.P(`if this.`, fieldname, ` != nil && that1.`, fieldname, ` != nil {`)
p.In()
p.P(`if *this.`, fieldname, ` != *that1.`, fieldname, `{`)
p.In()
p.P(`if !*this.`, fieldname, ` {`)
p.In()
p.P(`return -1`)
p.Out()
p.P(`}`)
p.P(`return 1`)
p.Out()
p.P(`}`)
p.Out()
p.P(`} else if this.`, fieldname, ` != nil {`)
p.In()
p.P(`return 1`)
p.Out()
p.P(`} else if that1.`, fieldname, ` != nil {`)
p.In()
p.P(`return -1`)
p.Out()
p.P(`}`)
} else {
p.P(`if this.`, fieldname, ` != that1.`, fieldname, `{`)
p.In()
p.P(`if !this.`, fieldname, ` {`)
p.In()
p.P(`return -1`)
p.Out()
p.P(`}`)
p.P(`return 1`)
p.Out()
p.P(`}`)
}
} else {
if nullable && !proto3 {
p.generateNullableField(fieldname)
} else {
p.P(`if this.`, fieldname, ` != that1.`, fieldname, `{`)
p.In()
p.P(`if this.`, fieldname, ` < that1.`, fieldname, `{`)
p.In()
p.P(`return -1`)
p.Out()
p.P(`}`)
p.P(`return 1`)
p.Out()
p.P(`}`)
}
}
}
} else {
p.P(`if len(this.`, fieldname, `) != len(that1.`, fieldname, `) {`)
p.In()
p.P(`if len(this.`, fieldname, `) < len(that1.`, fieldname, `) {`)
p.In()
p.P(`return -1`)
p.Out()
p.P(`}`)
p.P(`return 1`)
p.Out()
p.P(`}`)
p.P(`for i := range this.`, fieldname, ` {`)
p.In()
if ctype {
p.P(`if c := this.`, fieldname, `[i].Compare(that1.`, fieldname, `[i]); c != 0 {`)
p.In()
p.P(`return c`)
p.Out()
p.P(`}`)
} else {
if p.IsMap(field) {
m := p.GoMapType(nil, field)
valuegoTyp, _ := p.GoType(nil, m.ValueField)
valuegoAliasTyp, _ := p.GoType(nil, m.ValueAliasField)
nullable, valuegoTyp, valuegoAliasTyp = generator.GoMapValueTypes(field, m.ValueField, valuegoTyp, valuegoAliasTyp)
mapValue := m.ValueAliasField
if mapValue.IsMessage() || p.IsGroup(mapValue) {
if nullable && valuegoTyp == valuegoAliasTyp {
p.P(`if c := this.`, fieldname, `[i].Compare(that1.`, fieldname, `[i]); c != 0 {`)
} else {
// Compare() has a pointer receiver, but map value is a value type
a := `this.` + fieldname + `[i]`
b := `that1.` + fieldname + `[i]`
if valuegoTyp != valuegoAliasTyp {
// cast back to the type that has the generated methods on it
a = `(` + valuegoTyp + `)(` + a + `)`
b = `(` + valuegoTyp + `)(` + b + `)`
}
p.P(`a := `, a)
p.P(`b := `, b)
if nullable {
p.P(`if c := a.Compare(b); c != 0 {`)
} else {
p.P(`if c := (&a).Compare(&b); c != 0 {`)
}
}
p.In()
p.P(`return c`)
p.Out()
p.P(`}`)
} else if mapValue.IsBytes() {
p.P(`if c := `, p.bytesPkg.Use(), `.Compare(this.`, fieldname, `[i], that1.`, fieldname, `[i]); c != 0 {`)
p.In()
p.P(`return c`)
p.Out()
p.P(`}`)
} else if mapValue.IsString() {
p.P(`if this.`, fieldname, `[i] != that1.`, fieldname, `[i] {`)
p.In()
p.P(`if this.`, fieldname, `[i] < that1.`, fieldname, `[i] {`)
p.In()
p.P(`return -1`)
p.Out()
p.P(`}`)
p.P(`return 1`)
p.Out()
p.P(`}`)
} else {
p.P(`if this.`, fieldname, `[i] != that1.`, fieldname, `[i] {`)
p.In()
p.P(`if this.`, fieldname, `[i] < that1.`, fieldname, `[i] {`)
p.In()
p.P(`return -1`)
p.Out()
p.P(`}`)
p.P(`return 1`)
p.Out()
p.P(`}`)
}
} else if field.IsMessage() || p.IsGroup(field) {
if nullable {
p.P(`if c := this.`, fieldname, `[i].Compare(that1.`, fieldname, `[i]); c != 0 {`)
p.In()
p.P(`return c`)
p.Out()
p.P(`}`)
} else {
p.P(`if c := this.`, fieldname, `[i].Compare(&that1.`, fieldname, `[i]); c != 0 {`)
p.In()
p.P(`return c`)
p.Out()
p.P(`}`)
}
} else if field.IsBytes() {
p.P(`if c := `, p.bytesPkg.Use(), `.Compare(this.`, fieldname, `[i], that1.`, fieldname, `[i]); c != 0 {`)
p.In()
p.P(`return c`)
p.Out()
p.P(`}`)
} else if field.IsString() {
p.P(`if this.`, fieldname, `[i] != that1.`, fieldname, `[i] {`)
p.In()
p.P(`if this.`, fieldname, `[i] < that1.`, fieldname, `[i] {`)
p.In()
p.P(`return -1`)
p.Out()
p.P(`}`)
p.P(`return 1`)
p.Out()
p.P(`}`)
} else if field.IsBool() {
p.P(`if this.`, fieldname, `[i] != that1.`, fieldname, `[i] {`)
p.In()
p.P(`if !this.`, fieldname, `[i] {`)
p.In()
p.P(`return -1`)
p.Out()
p.P(`}`)
p.P(`return 1`)
p.Out()
p.P(`}`)
} else {
p.P(`if this.`, fieldname, `[i] != that1.`, fieldname, `[i] {`)
p.In()
p.P(`if this.`, fieldname, `[i] < that1.`, fieldname, `[i] {`)
p.In()
p.P(`return -1`)
p.Out()
p.P(`}`)
p.P(`return 1`)
p.Out()
p.P(`}`)
}
}
p.Out()
p.P(`}`)
}
}
func (p *plugin) generateMessage(file *generator.FileDescriptor, message *generator.Descriptor) {
ccTypeName := generator.CamelCaseSlice(message.TypeName())
p.P(`func (this *`, ccTypeName, `) Compare(that interface{}) int {`)
p.In()
p.generateMsgNullAndTypeCheck(ccTypeName)
oneofs := make(map[string]struct{})
for _, field := range message.Field {
oneof := field.OneofIndex != nil
if oneof {
fieldname := p.GetFieldName(message, field)
if _, ok := oneofs[fieldname]; ok {
continue
} else {
oneofs[fieldname] = struct{}{}
}
p.P(`if that1.`, fieldname, ` == nil {`)
p.In()
p.P(`if this.`, fieldname, ` != nil {`)
p.In()
p.P(`return 1`)
p.Out()
p.P(`}`)
p.Out()
p.P(`} else if this.`, fieldname, ` == nil {`)
p.In()
p.P(`return -1`)
p.Out()
p.P(`} else {`)
p.In()
// Generate two type switches in order to compare the
// types of the oneofs. If they are of the same type
// call Compare, otherwise return 1 or -1.
p.P(`thisType := -1`)
p.P(`switch this.`, fieldname, `.(type) {`)
for i, subfield := range message.Field {
if *subfield.OneofIndex == *field.OneofIndex {
ccTypeName := p.OneOfTypeName(message, subfield)
p.P(`case *`, ccTypeName, `:`)
p.In()
p.P(`thisType = `, i)
p.Out()
}
}
p.P(`default:`)
p.In()
p.P(`panic(fmt.Sprintf("compare: unexpected type %T in oneof", this.`, fieldname, `))`)
p.Out()
p.P(`}`)
p.P(`that1Type := -1`)
p.P(`switch that1.`, fieldname, `.(type) {`)
for i, subfield := range message.Field {
if *subfield.OneofIndex == *field.OneofIndex {
ccTypeName := p.OneOfTypeName(message, subfield)
p.P(`case *`, ccTypeName, `:`)
p.In()
p.P(`that1Type = `, i)
p.Out()
}
}
p.P(`default:`)
p.In()
p.P(`panic(fmt.Sprintf("compare: unexpected type %T in oneof", that1.`, fieldname, `))`)
p.Out()
p.P(`}`)
p.P(`if thisType == that1Type {`)
p.In()
p.P(`if c := this.`, fieldname, `.Compare(that1.`, fieldname, `); c != 0 {`)
p.In()
p.P(`return c`)
p.Out()
p.P(`}`)
p.Out()
p.P(`} else if thisType < that1Type {`)
p.In()
p.P(`return -1`)
p.Out()
p.P(`} else if thisType > that1Type {`)
p.In()
p.P(`return 1`)
p.Out()
p.P(`}`)
p.Out()
p.P(`}`)
} else {
p.generateField(file, message, field)
}
}
if message.DescriptorProto.HasExtension() {
if gogoproto.HasExtensionsMap(file.FileDescriptorProto, message.DescriptorProto) {
p.P(`thismap := `, p.protoPkg.Use(), `.GetUnsafeExtensionsMap(this)`)
p.P(`thatmap := `, p.protoPkg.Use(), `.GetUnsafeExtensionsMap(that1)`)
p.P(`extkeys := make([]int32, 0, len(thismap)+len(thatmap))`)
p.P(`for k, _ := range thismap {`)
p.In()
p.P(`extkeys = append(extkeys, k)`)
p.Out()
p.P(`}`)
p.P(`for k, _ := range thatmap {`)
p.In()
p.P(`if _, ok := thismap[k]; !ok {`)
p.In()
p.P(`extkeys = append(extkeys, k)`)
p.Out()
p.P(`}`)
p.Out()
p.P(`}`)
p.P(p.sortkeysPkg.Use(), `.Int32s(extkeys)`)
p.P(`for _, k := range extkeys {`)
p.In()
p.P(`if v, ok := thismap[k]; ok {`)
p.In()
p.P(`if v2, ok := thatmap[k]; ok {`)
p.In()
p.P(`if c := v.Compare(&v2); c != 0 {`)
p.In()
p.P(`return c`)
p.Out()
p.P(`}`)
p.Out()
p.P(`} else {`)
p.In()
p.P(`return 1`)
p.Out()
p.P(`}`)
p.Out()
p.P(`} else {`)
p.In()
p.P(`return -1`)
p.Out()
p.P(`}`)
p.Out()
p.P(`}`)
} else {
fieldname := "XXX_extensions"
p.P(`if c := `, p.bytesPkg.Use(), `.Compare(this.`, fieldname, `, that1.`, fieldname, `); c != 0 {`)
p.In()
p.P(`return c`)
p.Out()
p.P(`}`)
}
}
if gogoproto.HasUnrecognized(file.FileDescriptorProto, message.DescriptorProto) {
fieldname := "XXX_unrecognized"
p.P(`if c := `, p.bytesPkg.Use(), `.Compare(this.`, fieldname, `, that1.`, fieldname, `); c != 0 {`)
p.In()
p.P(`return c`)
p.Out()
p.P(`}`)
}
p.P(`return 0`)
p.Out()
p.P(`}`)
//Generate Compare methods for oneof fields
m := proto.Clone(message.DescriptorProto).(*descriptor.DescriptorProto)
for _, field := range m.Field {
oneof := field.OneofIndex != nil
if !oneof {
continue
}
ccTypeName := p.OneOfTypeName(message, field)
p.P(`func (this *`, ccTypeName, `) Compare(that interface{}) int {`)
p.In()
p.generateMsgNullAndTypeCheck(ccTypeName)
vanity.TurnOffNullableForNativeTypes(field)
p.generateField(file, message, field)
p.P(`return 0`)
p.Out()
p.P(`}`)
}
}
func init() {
generator.RegisterPlugin(NewPlugin())
}

View file

@ -0,0 +1,118 @@
// Protocol Buffers for Go with Gadgets
//
// Copyright (c) 2013, The GoGo Authors. All rights reserved.
// http://github.com/gogo/protobuf
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package compare
import (
"github.com/gogo/protobuf/gogoproto"
"github.com/gogo/protobuf/plugin/testgen"
"github.com/gogo/protobuf/protoc-gen-gogo/generator"
)
type test struct {
*generator.Generator
}
func NewTest(g *generator.Generator) testgen.TestPlugin {
return &test{g}
}
func (p *test) Generate(imports generator.PluginImports, file *generator.FileDescriptor) bool {
used := false
randPkg := imports.NewImport("math/rand")
timePkg := imports.NewImport("time")
testingPkg := imports.NewImport("testing")
protoPkg := imports.NewImport("github.com/gogo/protobuf/proto")
unsafePkg := imports.NewImport("unsafe")
if !gogoproto.ImportsGoGoProto(file.FileDescriptorProto) {
protoPkg = imports.NewImport("github.com/golang/protobuf/proto")
}
for _, message := range file.Messages() {
ccTypeName := generator.CamelCaseSlice(message.TypeName())
if !gogoproto.HasCompare(file.FileDescriptorProto, message.DescriptorProto) {
continue
}
if message.DescriptorProto.GetOptions().GetMapEntry() {
continue
}
if gogoproto.HasTestGen(file.FileDescriptorProto, message.DescriptorProto) {
used = true
hasUnsafe := gogoproto.IsUnsafeMarshaler(file.FileDescriptorProto, message.DescriptorProto) ||
gogoproto.IsUnsafeUnmarshaler(file.FileDescriptorProto, message.DescriptorProto)
p.P(`func Test`, ccTypeName, `Compare(t *`, testingPkg.Use(), `.T) {`)
p.In()
if hasUnsafe {
p.P(`var bigendian uint32 = 0x01020304`)
p.P(`if *(*byte)(`, unsafePkg.Use(), `.Pointer(&bigendian)) == 1 {`)
p.In()
p.P(`t.Skip("unsafe does not work on big endian architectures")`)
p.Out()
p.P(`}`)
}
p.P(`popr := `, randPkg.Use(), `.New(`, randPkg.Use(), `.NewSource(`, timePkg.Use(), `.Now().UnixNano()))`)
p.P(`p := NewPopulated`, ccTypeName, `(popr, false)`)
p.P(`dAtA, err := `, protoPkg.Use(), `.Marshal(p)`)
p.P(`if err != nil {`)
p.In()
p.P(`panic(err)`)
p.Out()
p.P(`}`)
p.P(`msg := &`, ccTypeName, `{}`)
p.P(`if err := `, protoPkg.Use(), `.Unmarshal(dAtA, msg); err != nil {`)
p.In()
p.P(`panic(err)`)
p.Out()
p.P(`}`)
p.P(`if c := p.Compare(msg); c != 0 {`)
p.In()
p.P(`t.Fatalf("%#v !Compare %#v, since %d", msg, p, c)`)
p.Out()
p.P(`}`)
p.P(`p2 := NewPopulated`, ccTypeName, `(popr, false)`)
p.P(`c := p.Compare(p2)`)
p.P(`c2 := p2.Compare(p)`)
p.P(`if c != (-1 * c2) {`)
p.In()
p.P(`t.Errorf("p.Compare(p2) = %d", c)`)
p.P(`t.Errorf("p2.Compare(p) = %d", c2)`)
p.P(`t.Errorf("p = %#v", p)`)
p.P(`t.Errorf("p2 = %#v", p2)`)
p.Out()
p.P(`}`)
p.Out()
p.P(`}`)
}
}
return used
}
func init() {
testgen.RegisterTestPlugin(NewTest)
}

View file

@ -0,0 +1,133 @@
// Protocol Buffers for Go with Gadgets
//
// Copyright (c) 2013, The GoGo Authors. All rights reserved.
// http://github.com/gogo/protobuf
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/*
The defaultcheck plugin is used to check whether nullable is not used incorrectly.
For instance:
An error is caused if a nullable field:
- has a default value,
- is an enum which does not start at zero,
- is used for an extension,
- is used for a native proto3 type,
- is used for a repeated native type.
An error is also caused if a field with a default value is used in a message:
- which is a face.
- without getters.
It is enabled by the following extensions:
- nullable
For incorrect usage of nullable with tests see:
github.com/gogo/protobuf/test/nullableconflict
*/
package defaultcheck
import (
"fmt"
"github.com/gogo/protobuf/gogoproto"
"github.com/gogo/protobuf/protoc-gen-gogo/generator"
"os"
)
type plugin struct {
*generator.Generator
}
func NewPlugin() *plugin {
return &plugin{}
}
func (p *plugin) Name() string {
return "defaultcheck"
}
func (p *plugin) Init(g *generator.Generator) {
p.Generator = g
}
func (p *plugin) Generate(file *generator.FileDescriptor) {
proto3 := gogoproto.IsProto3(file.FileDescriptorProto)
for _, msg := range file.Messages() {
getters := gogoproto.HasGoGetters(file.FileDescriptorProto, msg.DescriptorProto)
face := gogoproto.IsFace(file.FileDescriptorProto, msg.DescriptorProto)
for _, field := range msg.GetField() {
if len(field.GetDefaultValue()) > 0 {
if !getters {
fmt.Fprintf(os.Stderr, "ERROR: field %v.%v cannot have a default value and not have a getter method", generator.CamelCase(*msg.Name), generator.CamelCase(*field.Name))
os.Exit(1)
}
if face {
fmt.Fprintf(os.Stderr, "ERROR: field %v.%v cannot have a default value be in a face", generator.CamelCase(*msg.Name), generator.CamelCase(*field.Name))
os.Exit(1)
}
}
if gogoproto.IsNullable(field) {
continue
}
if len(field.GetDefaultValue()) > 0 {
fmt.Fprintf(os.Stderr, "ERROR: field %v.%v cannot be non-nullable and have a default value", generator.CamelCase(*msg.Name), generator.CamelCase(*field.Name))
os.Exit(1)
}
if !field.IsMessage() && !gogoproto.IsCustomType(field) {
if field.IsRepeated() {
fmt.Fprintf(os.Stderr, "WARNING: field %v.%v is a repeated non-nullable native type, nullable=false has no effect\n", generator.CamelCase(*msg.Name), generator.CamelCase(*field.Name))
} else if proto3 {
fmt.Fprintf(os.Stderr, "ERROR: field %v.%v is a native type and in proto3 syntax with nullable=false there exists conflicting implementations when encoding zero values", generator.CamelCase(*msg.Name), generator.CamelCase(*field.Name))
os.Exit(1)
}
if field.IsBytes() {
fmt.Fprintf(os.Stderr, "WARNING: field %v.%v is a non-nullable bytes type, nullable=false has no effect\n", generator.CamelCase(*msg.Name), generator.CamelCase(*field.Name))
}
}
if !field.IsEnum() {
continue
}
enum := p.ObjectNamed(field.GetTypeName()).(*generator.EnumDescriptor)
if len(enum.Value) == 0 || enum.Value[0].GetNumber() != 0 {
fmt.Fprintf(os.Stderr, "ERROR: field %v.%v cannot be non-nullable and be an enum type %v which does not start with zero", generator.CamelCase(*msg.Name), generator.CamelCase(*field.Name), enum.GetName())
os.Exit(1)
}
}
}
for _, e := range file.GetExtension() {
if !gogoproto.IsNullable(e) {
fmt.Fprintf(os.Stderr, "ERROR: extended field %v cannot be nullable %v", generator.CamelCase(e.GetName()), generator.CamelCase(*e.Name))
os.Exit(1)
}
}
}
func (p *plugin) GenerateImports(*generator.FileDescriptor) {}
func init() {
generator.RegisterPlugin(NewPlugin())
}

View file

@ -0,0 +1,201 @@
// Protocol Buffers for Go with Gadgets
//
// Copyright (c) 2013, The GoGo Authors. All rights reserved.
// http://github.com/gogo/protobuf
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/*
The description (experimental) plugin generates a Description method for each message.
The Description method returns a populated google_protobuf.FileDescriptorSet struct.
This contains the description of the files used to generate this message.
It is enabled by the following extensions:
- description
- description_all
The description plugin also generates a test given it is enabled using one of the following extensions:
- testgen
- testgen_all
Let us look at:
github.com/gogo/protobuf/test/example/example.proto
Btw all the output can be seen at:
github.com/gogo/protobuf/test/example/*
The following message:
message B {
option (gogoproto.description) = true;
optional A A = 1 [(gogoproto.nullable) = false, (gogoproto.embed) = true];
repeated bytes G = 2 [(gogoproto.customtype) = "github.com/gogo/protobuf/test/custom.Uint128", (gogoproto.nullable) = false];
}
given to the description plugin, will generate the following code:
func (this *B) Description() (desc *google_protobuf.FileDescriptorSet) {
return ExampleDescription()
}
and the following test code:
func TestDescription(t *testing9.T) {
ExampleDescription()
}
The hope is to use this struct in some way instead of reflect.
This package is subject to change, since a use has not been figured out yet.
*/
package description
import (
"bytes"
"compress/gzip"
"fmt"
"github.com/gogo/protobuf/gogoproto"
"github.com/gogo/protobuf/proto"
descriptor "github.com/gogo/protobuf/protoc-gen-gogo/descriptor"
"github.com/gogo/protobuf/protoc-gen-gogo/generator"
)
type plugin struct {
*generator.Generator
generator.PluginImports
}
func NewPlugin() *plugin {
return &plugin{}
}
func (p *plugin) Name() string {
return "description"
}
func (p *plugin) Init(g *generator.Generator) {
p.Generator = g
}
func (p *plugin) Generate(file *generator.FileDescriptor) {
used := false
localName := generator.FileName(file)
p.PluginImports = generator.NewPluginImports(p.Generator)
descriptorPkg := p.NewImport("github.com/gogo/protobuf/protoc-gen-gogo/descriptor")
protoPkg := p.NewImport("github.com/gogo/protobuf/proto")
gzipPkg := p.NewImport("compress/gzip")
bytesPkg := p.NewImport("bytes")
ioutilPkg := p.NewImport("io/ioutil")
for _, message := range file.Messages() {
if !gogoproto.HasDescription(file.FileDescriptorProto, message.DescriptorProto) {
continue
}
if message.DescriptorProto.GetOptions().GetMapEntry() {
continue
}
used = true
ccTypeName := generator.CamelCaseSlice(message.TypeName())
p.P(`func (this *`, ccTypeName, `) Description() (desc *`, descriptorPkg.Use(), `.FileDescriptorSet) {`)
p.In()
p.P(`return `, localName, `Description()`)
p.Out()
p.P(`}`)
}
if used {
p.P(`func `, localName, `Description() (desc *`, descriptorPkg.Use(), `.FileDescriptorSet) {`)
p.In()
//Don't generate SourceCodeInfo, since it will create too much code.
ss := make([]*descriptor.SourceCodeInfo, 0)
for _, f := range p.Generator.AllFiles().GetFile() {
ss = append(ss, f.SourceCodeInfo)
f.SourceCodeInfo = nil
}
b, err := proto.Marshal(p.Generator.AllFiles())
if err != nil {
panic(err)
}
for i, f := range p.Generator.AllFiles().GetFile() {
f.SourceCodeInfo = ss[i]
}
p.P(`d := &`, descriptorPkg.Use(), `.FileDescriptorSet{}`)
var buf bytes.Buffer
w, _ := gzip.NewWriterLevel(&buf, gzip.BestCompression)
w.Write(b)
w.Close()
b = buf.Bytes()
p.P("var gzipped = []byte{")
p.In()
p.P("// ", len(b), " bytes of a gzipped FileDescriptorSet")
for len(b) > 0 {
n := 16
if n > len(b) {
n = len(b)
}
s := ""
for _, c := range b[:n] {
s += fmt.Sprintf("0x%02x,", c)
}
p.P(s)
b = b[n:]
}
p.Out()
p.P("}")
p.P(`r := `, bytesPkg.Use(), `.NewReader(gzipped)`)
p.P(`gzipr, err := `, gzipPkg.Use(), `.NewReader(r)`)
p.P(`if err != nil {`)
p.In()
p.P(`panic(err)`)
p.Out()
p.P(`}`)
p.P(`ungzipped, err := `, ioutilPkg.Use(), `.ReadAll(gzipr)`)
p.P(`if err != nil {`)
p.In()
p.P(`panic(err)`)
p.Out()
p.P(`}`)
p.P(`if err := `, protoPkg.Use(), `.Unmarshal(ungzipped, d); err != nil {`)
p.In()
p.P(`panic(err)`)
p.Out()
p.P(`}`)
p.P(`return d`)
p.Out()
p.P(`}`)
}
}
func init() {
generator.RegisterPlugin(NewPlugin())
}

View file

@ -0,0 +1,73 @@
// Protocol Buffers for Go with Gadgets
//
// Copyright (c) 2013, The GoGo Authors. All rights reserved.
// http://github.com/gogo/protobuf
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package description
import (
"github.com/gogo/protobuf/gogoproto"
"github.com/gogo/protobuf/plugin/testgen"
"github.com/gogo/protobuf/protoc-gen-gogo/generator"
)
type test struct {
*generator.Generator
}
func NewTest(g *generator.Generator) testgen.TestPlugin {
return &test{g}
}
func (p *test) Generate(imports generator.PluginImports, file *generator.FileDescriptor) bool {
used := false
testingPkg := imports.NewImport("testing")
for _, message := range file.Messages() {
if !gogoproto.HasDescription(file.FileDescriptorProto, message.DescriptorProto) ||
!gogoproto.HasTestGen(file.FileDescriptorProto, message.DescriptorProto) {
continue
}
if message.DescriptorProto.GetOptions().GetMapEntry() {
continue
}
used = true
}
if used {
localName := generator.FileName(file)
p.P(`func Test`, localName, `Description(t *`, testingPkg.Use(), `.T) {`)
p.In()
p.P(localName, `Description()`)
p.Out()
p.P(`}`)
}
return used
}
func init() {
testgen.RegisterTestPlugin(NewTest)
}

View file

@ -0,0 +1,200 @@
// Protocol Buffers for Go with Gadgets
//
// Copyright (c) 2013, The GoGo Authors. All rights reserved.
// http://github.com/gogo/protobuf
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/*
The embedcheck plugin is used to check whether embed is not used incorrectly.
For instance:
An embedded message has a generated string method, but the is a member of a message which does not.
This causes a warning.
An error is caused by a namespace conflict.
It is enabled by the following extensions:
- embed
- embed_all
For incorrect usage of embed with tests see:
github.com/gogo/protobuf/test/embedconflict
*/
package embedcheck
import (
"fmt"
"os"
"github.com/gogo/protobuf/gogoproto"
"github.com/gogo/protobuf/protoc-gen-gogo/generator"
)
type plugin struct {
*generator.Generator
}
func NewPlugin() *plugin {
return &plugin{}
}
func (p *plugin) Name() string {
return "embedcheck"
}
func (p *plugin) Init(g *generator.Generator) {
p.Generator = g
}
var overwriters []map[string]gogoproto.EnableFunc = []map[string]gogoproto.EnableFunc{
{
"stringer": gogoproto.IsStringer,
},
{
"gostring": gogoproto.HasGoString,
},
{
"equal": gogoproto.HasEqual,
},
{
"verboseequal": gogoproto.HasVerboseEqual,
},
{
"size": gogoproto.IsSizer,
"protosizer": gogoproto.IsProtoSizer,
},
{
"unmarshaler": gogoproto.IsUnmarshaler,
"unsafe_unmarshaler": gogoproto.IsUnsafeUnmarshaler,
},
{
"marshaler": gogoproto.IsMarshaler,
"unsafe_marshaler": gogoproto.IsUnsafeMarshaler,
},
}
func (p *plugin) Generate(file *generator.FileDescriptor) {
for _, msg := range file.Messages() {
for _, os := range overwriters {
possible := true
for _, overwriter := range os {
if overwriter(file.FileDescriptorProto, msg.DescriptorProto) {
possible = false
}
}
if possible {
p.checkOverwrite(msg, os)
}
}
p.checkNameSpace(msg)
for _, field := range msg.GetField() {
if gogoproto.IsEmbed(field) && gogoproto.IsCustomName(field) {
fmt.Fprintf(os.Stderr, "ERROR: field %v with custom name %v cannot be embedded", *field.Name, gogoproto.GetCustomName(field))
os.Exit(1)
}
}
p.checkRepeated(msg)
}
for _, e := range file.GetExtension() {
if gogoproto.IsEmbed(e) {
fmt.Fprintf(os.Stderr, "ERROR: extended field %v cannot be embedded", generator.CamelCase(*e.Name))
os.Exit(1)
}
}
}
func (p *plugin) checkNameSpace(message *generator.Descriptor) map[string]bool {
ccTypeName := generator.CamelCaseSlice(message.TypeName())
names := make(map[string]bool)
for _, field := range message.Field {
fieldname := generator.CamelCase(*field.Name)
if field.IsMessage() && gogoproto.IsEmbed(field) {
desc := p.ObjectNamed(field.GetTypeName())
moreNames := p.checkNameSpace(desc.(*generator.Descriptor))
for another := range moreNames {
if names[another] {
fmt.Fprintf(os.Stderr, "ERROR: duplicate embedded fieldname %v in type %v\n", fieldname, ccTypeName)
os.Exit(1)
}
names[another] = true
}
} else {
if names[fieldname] {
fmt.Fprintf(os.Stderr, "ERROR: duplicate embedded fieldname %v in type %v\n", fieldname, ccTypeName)
os.Exit(1)
}
names[fieldname] = true
}
}
return names
}
func (p *plugin) checkOverwrite(message *generator.Descriptor, enablers map[string]gogoproto.EnableFunc) {
ccTypeName := generator.CamelCaseSlice(message.TypeName())
names := []string{}
for name := range enablers {
names = append(names, name)
}
for _, field := range message.Field {
if field.IsMessage() && gogoproto.IsEmbed(field) {
fieldname := generator.CamelCase(*field.Name)
desc := p.ObjectNamed(field.GetTypeName())
msg := desc.(*generator.Descriptor)
for errStr, enabled := range enablers {
if enabled(msg.File().FileDescriptorProto, msg.DescriptorProto) {
fmt.Fprintf(os.Stderr, "WARNING: found non-%v %v with embedded %v %v\n", names, ccTypeName, errStr, fieldname)
}
}
p.checkOverwrite(msg, enablers)
}
}
}
func (p *plugin) checkRepeated(message *generator.Descriptor) {
ccTypeName := generator.CamelCaseSlice(message.TypeName())
for _, field := range message.Field {
if !gogoproto.IsEmbed(field) {
continue
}
if field.IsBytes() {
fieldname := generator.CamelCase(*field.Name)
fmt.Fprintf(os.Stderr, "ERROR: found embedded bytes field %s in message %s\n", fieldname, ccTypeName)
os.Exit(1)
}
if !field.IsRepeated() {
continue
}
fieldname := generator.CamelCase(*field.Name)
fmt.Fprintf(os.Stderr, "ERROR: found repeated embedded field %s in message %s\n", fieldname, ccTypeName)
os.Exit(1)
}
}
func (p *plugin) GenerateImports(*generator.FileDescriptor) {}
func init() {
generator.RegisterPlugin(NewPlugin())
}

View file

@ -0,0 +1,104 @@
// Protocol Buffers for Go with Gadgets
//
// Copyright (c) 2013, The GoGo Authors. All rights reserved.
// http://github.com/gogo/protobuf
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/*
The enumstringer (experimental) plugin generates a String method for each enum.
It is enabled by the following extensions:
- enum_stringer
- enum_stringer_all
This package is subject to change.
*/
package enumstringer
import (
"github.com/gogo/protobuf/gogoproto"
"github.com/gogo/protobuf/protoc-gen-gogo/generator"
)
type enumstringer struct {
*generator.Generator
generator.PluginImports
atleastOne bool
localName string
}
func NewEnumStringer() *enumstringer {
return &enumstringer{}
}
func (p *enumstringer) Name() string {
return "enumstringer"
}
func (p *enumstringer) Init(g *generator.Generator) {
p.Generator = g
}
func (p *enumstringer) Generate(file *generator.FileDescriptor) {
p.PluginImports = generator.NewPluginImports(p.Generator)
p.atleastOne = false
p.localName = generator.FileName(file)
strconvPkg := p.NewImport("strconv")
for _, enum := range file.Enums() {
if !gogoproto.IsEnumStringer(file.FileDescriptorProto, enum.EnumDescriptorProto) {
continue
}
if gogoproto.IsGoEnumStringer(file.FileDescriptorProto, enum.EnumDescriptorProto) {
panic("Go enum stringer conflicts with new enumstringer plugin: please use gogoproto.goproto_enum_stringer or gogoproto.goproto_enum_string_all and set it to false")
}
p.atleastOne = true
ccTypeName := generator.CamelCaseSlice(enum.TypeName())
p.P("func (x ", ccTypeName, ") String() string {")
p.In()
p.P(`s, ok := `, ccTypeName, `_name[int32(x)]`)
p.P(`if ok {`)
p.In()
p.P(`return s`)
p.Out()
p.P(`}`)
p.P(`return `, strconvPkg.Use(), `.Itoa(int(x))`)
p.Out()
p.P(`}`)
}
if !p.atleastOne {
return
}
}
func init() {
generator.RegisterPlugin(NewEnumStringer())
}

694
vendor/github.com/gogo/protobuf/plugin/equal/equal.go generated vendored Normal file
View file

@ -0,0 +1,694 @@
// Protocol Buffers for Go with Gadgets
//
// Copyright (c) 2013, The GoGo Authors. All rights reserved.
// http://github.com/gogo/protobuf
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/*
The equal plugin generates an Equal and a VerboseEqual method for each message.
These equal methods are quite obvious.
The only difference is that VerboseEqual returns a non nil error if it is not equal.
This error contains more detail on exactly which part of the message was not equal to the other message.
The idea is that this is useful for debugging.
Equal is enabled using the following extensions:
- equal
- equal_all
While VerboseEqual is enable dusing the following extensions:
- verbose_equal
- verbose_equal_all
The equal plugin also generates a test given it is enabled using one of the following extensions:
- testgen
- testgen_all
Let us look at:
github.com/gogo/protobuf/test/example/example.proto
Btw all the output can be seen at:
github.com/gogo/protobuf/test/example/*
The following message:
option (gogoproto.equal_all) = true;
option (gogoproto.verbose_equal_all) = true;
message B {
optional A A = 1 [(gogoproto.nullable) = false, (gogoproto.embed) = true];
repeated bytes G = 2 [(gogoproto.customtype) = "github.com/gogo/protobuf/test/custom.Uint128", (gogoproto.nullable) = false];
}
given to the equal plugin, will generate the following code:
func (this *B) VerboseEqual(that interface{}) error {
if that == nil {
if this == nil {
return nil
}
return fmt2.Errorf("that == nil && this != nil")
}
that1, ok := that.(*B)
if !ok {
return fmt2.Errorf("that is not of type *B")
}
if that1 == nil {
if this == nil {
return nil
}
return fmt2.Errorf("that is type *B but is nil && this != nil")
} else if this == nil {
return fmt2.Errorf("that is type *B but is not nil && this == nil")
}
if !this.A.Equal(&that1.A) {
return fmt2.Errorf("A this(%v) Not Equal that(%v)", this.A, that1.A)
}
if len(this.G) != len(that1.G) {
return fmt2.Errorf("G this(%v) Not Equal that(%v)", len(this.G), len(that1.G))
}
for i := range this.G {
if !this.G[i].Equal(that1.G[i]) {
return fmt2.Errorf("G this[%v](%v) Not Equal that[%v](%v)", i, this.G[i], i, that1.G[i])
}
}
if !bytes.Equal(this.XXX_unrecognized, that1.XXX_unrecognized) {
return fmt2.Errorf("XXX_unrecognized this(%v) Not Equal that(%v)", this.XXX_unrecognized, that1.XXX_unrecognized)
}
return nil
}
func (this *B) Equal(that interface{}) bool {
if that == nil {
return this == nil
}
that1, ok := that.(*B)
if !ok {
return false
}
if that1 == nil {
return this == nil
} else if this == nil {
return false
}
if !this.A.Equal(&that1.A) {
return false
}
if len(this.G) != len(that1.G) {
return false
}
for i := range this.G {
if !this.G[i].Equal(that1.G[i]) {
return false
}
}
if !bytes.Equal(this.XXX_unrecognized, that1.XXX_unrecognized) {
return false
}
return true
}
and the following test code:
func TestBVerboseEqual(t *testing8.T) {
popr := math_rand8.New(math_rand8.NewSource(time8.Now().UnixNano()))
p := NewPopulatedB(popr, false)
dAtA, err := github_com_gogo_protobuf_proto2.Marshal(p)
if err != nil {
panic(err)
}
msg := &B{}
if err := github_com_gogo_protobuf_proto2.Unmarshal(dAtA, msg); err != nil {
panic(err)
}
if err := p.VerboseEqual(msg); err != nil {
t.Fatalf("%#v !VerboseEqual %#v, since %v", msg, p, err)
}
*/
package equal
import (
"github.com/gogo/protobuf/gogoproto"
"github.com/gogo/protobuf/proto"
descriptor "github.com/gogo/protobuf/protoc-gen-gogo/descriptor"
"github.com/gogo/protobuf/protoc-gen-gogo/generator"
"github.com/gogo/protobuf/vanity"
)
type plugin struct {
*generator.Generator
generator.PluginImports
fmtPkg generator.Single
bytesPkg generator.Single
protoPkg generator.Single
}
func NewPlugin() *plugin {
return &plugin{}
}
func (p *plugin) Name() string {
return "equal"
}
func (p *plugin) Init(g *generator.Generator) {
p.Generator = g
}
func (p *plugin) Generate(file *generator.FileDescriptor) {
p.PluginImports = generator.NewPluginImports(p.Generator)
p.fmtPkg = p.NewImport("fmt")
p.bytesPkg = p.NewImport("bytes")
p.protoPkg = p.NewImport("github.com/gogo/protobuf/proto")
for _, msg := range file.Messages() {
if msg.DescriptorProto.GetOptions().GetMapEntry() {
continue
}
if gogoproto.HasVerboseEqual(file.FileDescriptorProto, msg.DescriptorProto) {
p.generateMessage(file, msg, true)
}
if gogoproto.HasEqual(file.FileDescriptorProto, msg.DescriptorProto) {
p.generateMessage(file, msg, false)
}
}
}
func (p *plugin) generateNullableField(fieldname string, verbose bool) {
p.P(`if this.`, fieldname, ` != nil && that1.`, fieldname, ` != nil {`)
p.In()
p.P(`if *this.`, fieldname, ` != *that1.`, fieldname, `{`)
p.In()
if verbose {
p.P(`return `, p.fmtPkg.Use(), `.Errorf("`, fieldname, ` this(%v) Not Equal that(%v)", *this.`, fieldname, `, *that1.`, fieldname, `)`)
} else {
p.P(`return false`)
}
p.Out()
p.P(`}`)
p.Out()
p.P(`} else if this.`, fieldname, ` != nil {`)
p.In()
if verbose {
p.P(`return `, p.fmtPkg.Use(), `.Errorf("this.`, fieldname, ` == nil && that.`, fieldname, ` != nil")`)
} else {
p.P(`return false`)
}
p.Out()
p.P(`} else if that1.`, fieldname, ` != nil {`)
}
func (p *plugin) generateMsgNullAndTypeCheck(ccTypeName string, verbose bool) {
p.P(`if that == nil {`)
p.In()
if verbose {
p.P(`if this == nil {`)
p.In()
p.P(`return nil`)
p.Out()
p.P(`}`)
p.P(`return `, p.fmtPkg.Use(), `.Errorf("that == nil && this != nil")`)
} else {
p.P(`return this == nil`)
}
p.Out()
p.P(`}`)
p.P(``)
p.P(`that1, ok := that.(*`, ccTypeName, `)`)
p.P(`if !ok {`)
p.In()
p.P(`that2, ok := that.(`, ccTypeName, `)`)
p.P(`if ok {`)
p.In()
p.P(`that1 = &that2`)
p.Out()
p.P(`} else {`)
p.In()
if verbose {
p.P(`return `, p.fmtPkg.Use(), `.Errorf("that is not of type *`, ccTypeName, `")`)
} else {
p.P(`return false`)
}
p.Out()
p.P(`}`)
p.Out()
p.P(`}`)
p.P(`if that1 == nil {`)
p.In()
if verbose {
p.P(`if this == nil {`)
p.In()
p.P(`return nil`)
p.Out()
p.P(`}`)
p.P(`return `, p.fmtPkg.Use(), `.Errorf("that is type *`, ccTypeName, ` but is nil && this != nil")`)
} else {
p.P(`return this == nil`)
}
p.Out()
p.P(`} else if this == nil {`)
p.In()
if verbose {
p.P(`return `, p.fmtPkg.Use(), `.Errorf("that is type *`, ccTypeName, ` but is not nil && this == nil")`)
} else {
p.P(`return false`)
}
p.Out()
p.P(`}`)
}
func (p *plugin) generateField(file *generator.FileDescriptor, message *generator.Descriptor, field *descriptor.FieldDescriptorProto, verbose bool) {
proto3 := gogoproto.IsProto3(file.FileDescriptorProto)
fieldname := p.GetOneOfFieldName(message, field)
repeated := field.IsRepeated()
ctype := gogoproto.IsCustomType(field)
nullable := gogoproto.IsNullable(field)
isNormal := (gogoproto.IsStdDuration(field) ||
gogoproto.IsStdDouble(field) ||
gogoproto.IsStdFloat(field) ||
gogoproto.IsStdInt64(field) ||
gogoproto.IsStdUInt64(field) ||
gogoproto.IsStdInt32(field) ||
gogoproto.IsStdUInt32(field) ||
gogoproto.IsStdBool(field) ||
gogoproto.IsStdString(field))
isBytes := gogoproto.IsStdBytes(field)
isTimestamp := gogoproto.IsStdTime(field)
// oneof := field.OneofIndex != nil
if !repeated {
if ctype || isTimestamp {
if nullable {
p.P(`if that1.`, fieldname, ` == nil {`)
p.In()
p.P(`if this.`, fieldname, ` != nil {`)
p.In()
if verbose {
p.P(`return `, p.fmtPkg.Use(), `.Errorf("this.`, fieldname, ` != nil && that1.`, fieldname, ` == nil")`)
} else {
p.P(`return false`)
}
p.Out()
p.P(`}`)
p.Out()
p.P(`} else if !this.`, fieldname, `.Equal(*that1.`, fieldname, `) {`)
} else {
p.P(`if !this.`, fieldname, `.Equal(that1.`, fieldname, `) {`)
}
p.In()
if verbose {
p.P(`return `, p.fmtPkg.Use(), `.Errorf("`, fieldname, ` this(%v) Not Equal that(%v)", this.`, fieldname, `, that1.`, fieldname, `)`)
} else {
p.P(`return false`)
}
p.Out()
p.P(`}`)
} else if isNormal {
if nullable {
p.generateNullableField(fieldname, verbose)
} else {
p.P(`if this.`, fieldname, ` != that1.`, fieldname, `{`)
}
p.In()
if verbose {
p.P(`return `, p.fmtPkg.Use(), `.Errorf("`, fieldname, ` this(%v) Not Equal that(%v)", this.`, fieldname, `, that1.`, fieldname, `)`)
} else {
p.P(`return false`)
}
p.Out()
p.P(`}`)
} else if isBytes {
if nullable {
p.P(`if that1.`, fieldname, ` == nil {`)
p.In()
p.P(`if this.`, fieldname, ` != nil {`)
p.In()
if verbose {
p.P(`return `, p.fmtPkg.Use(), `.Errorf("this.`, fieldname, ` != nil && that1.`, fieldname, ` == nil")`)
} else {
p.P(`return false`)
}
p.Out()
p.P(`}`)
p.Out()
p.P(`} else if !`, p.bytesPkg.Use(), `.Equal(*this.`, fieldname, `, *that1.`, fieldname, `) {`)
} else {
p.P(`if !`, p.bytesPkg.Use(), `.Equal(this.`, fieldname, `, that1.`, fieldname, `) {`)
}
p.In()
if verbose {
p.P(`return `, p.fmtPkg.Use(), `.Errorf("`, fieldname, ` this(%v) Not Equal that(%v)", this.`, fieldname, `, that1.`, fieldname, `)`)
} else {
p.P(`return false`)
}
p.Out()
p.P(`}`)
} else {
if field.IsMessage() || p.IsGroup(field) {
if nullable {
p.P(`if !this.`, fieldname, `.Equal(that1.`, fieldname, `) {`)
} else {
p.P(`if !this.`, fieldname, `.Equal(&that1.`, fieldname, `) {`)
}
} else if field.IsBytes() {
p.P(`if !`, p.bytesPkg.Use(), `.Equal(this.`, fieldname, `, that1.`, fieldname, `) {`)
} else if field.IsString() {
if nullable && !proto3 {
p.generateNullableField(fieldname, verbose)
} else {
p.P(`if this.`, fieldname, ` != that1.`, fieldname, `{`)
}
} else {
if nullable && !proto3 {
p.generateNullableField(fieldname, verbose)
} else {
p.P(`if this.`, fieldname, ` != that1.`, fieldname, `{`)
}
}
p.In()
if verbose {
p.P(`return `, p.fmtPkg.Use(), `.Errorf("`, fieldname, ` this(%v) Not Equal that(%v)", this.`, fieldname, `, that1.`, fieldname, `)`)
} else {
p.P(`return false`)
}
p.Out()
p.P(`}`)
}
} else {
p.P(`if len(this.`, fieldname, `) != len(that1.`, fieldname, `) {`)
p.In()
if verbose {
p.P(`return `, p.fmtPkg.Use(), `.Errorf("`, fieldname, ` this(%v) Not Equal that(%v)", len(this.`, fieldname, `), len(that1.`, fieldname, `))`)
} else {
p.P(`return false`)
}
p.Out()
p.P(`}`)
p.P(`for i := range this.`, fieldname, ` {`)
p.In()
if ctype && !p.IsMap(field) {
p.P(`if !this.`, fieldname, `[i].Equal(that1.`, fieldname, `[i]) {`)
} else if isTimestamp {
if nullable {
p.P(`if !this.`, fieldname, `[i].Equal(*that1.`, fieldname, `[i]) {`)
} else {
p.P(`if !this.`, fieldname, `[i].Equal(that1.`, fieldname, `[i]) {`)
}
} else if isNormal {
if nullable {
p.P(`if dthis, dthat := this.`, fieldname, `[i], that1.`, fieldname, `[i]; (dthis != nil && dthat != nil && *dthis != *dthat) || (dthis != nil && dthat == nil) || (dthis == nil && dthat != nil) {`)
} else {
p.P(`if this.`, fieldname, `[i] != that1.`, fieldname, `[i] {`)
}
} else if isBytes {
if nullable {
p.P(`if !`, p.bytesPkg.Use(), `.Equal(*this.`, fieldname, `[i], *that1.`, fieldname, `[i]) {`)
} else {
p.P(`if !`, p.bytesPkg.Use(), `.Equal(this.`, fieldname, `[i], that1.`, fieldname, `[i]) {`)
}
} else {
if p.IsMap(field) {
m := p.GoMapType(nil, field)
valuegoTyp, _ := p.GoType(nil, m.ValueField)
valuegoAliasTyp, _ := p.GoType(nil, m.ValueAliasField)
nullable, valuegoTyp, valuegoAliasTyp = generator.GoMapValueTypes(field, m.ValueField, valuegoTyp, valuegoAliasTyp)
mapValue := m.ValueAliasField
mapValueNormal := (gogoproto.IsStdDuration(mapValue) ||
gogoproto.IsStdDouble(mapValue) ||
gogoproto.IsStdFloat(mapValue) ||
gogoproto.IsStdInt64(mapValue) ||
gogoproto.IsStdUInt64(mapValue) ||
gogoproto.IsStdInt32(mapValue) ||
gogoproto.IsStdUInt32(mapValue) ||
gogoproto.IsStdBool(mapValue) ||
gogoproto.IsStdString(mapValue))
mapValueBytes := gogoproto.IsStdBytes(mapValue)
if mapValue.IsMessage() || p.IsGroup(mapValue) {
if nullable && valuegoTyp == valuegoAliasTyp {
p.P(`if !this.`, fieldname, `[i].Equal(that1.`, fieldname, `[i]) {`)
} else {
// Equal() has a pointer receiver, but map value is a value type
a := `this.` + fieldname + `[i]`
b := `that1.` + fieldname + `[i]`
if !mapValueNormal && !mapValueBytes && valuegoTyp != valuegoAliasTyp {
// cast back to the type that has the generated methods on it
a = `(` + valuegoTyp + `)(` + a + `)`
b = `(` + valuegoTyp + `)(` + b + `)`
}
p.P(`a := `, a)
p.P(`b := `, b)
if mapValueNormal {
if nullable {
p.P(`if *a != *b {`)
} else {
p.P(`if a != b {`)
}
} else if mapValueBytes {
if nullable {
p.P(`if !`, p.bytesPkg.Use(), `.Equal(*a, *b) {`)
} else {
p.P(`if !`, p.bytesPkg.Use(), `.Equal(a, b) {`)
}
} else if nullable {
p.P(`if !a.Equal(b) {`)
} else {
p.P(`if !(&a).Equal(&b) {`)
}
}
} else if mapValue.IsBytes() {
if ctype {
if nullable {
p.P(`if !this.`, fieldname, `[i].Equal(*that1.`, fieldname, `[i]) { //nullable`)
} else {
p.P(`if !this.`, fieldname, `[i].Equal(that1.`, fieldname, `[i]) { //not nullable`)
}
} else {
p.P(`if !`, p.bytesPkg.Use(), `.Equal(this.`, fieldname, `[i], that1.`, fieldname, `[i]) {`)
}
} else if mapValue.IsString() {
p.P(`if this.`, fieldname, `[i] != that1.`, fieldname, `[i] {`)
} else {
p.P(`if this.`, fieldname, `[i] != that1.`, fieldname, `[i] {`)
}
} else if field.IsMessage() || p.IsGroup(field) {
if nullable {
p.P(`if !this.`, fieldname, `[i].Equal(that1.`, fieldname, `[i]) {`)
} else {
p.P(`if !this.`, fieldname, `[i].Equal(&that1.`, fieldname, `[i]) {`)
}
} else if field.IsBytes() {
p.P(`if !`, p.bytesPkg.Use(), `.Equal(this.`, fieldname, `[i], that1.`, fieldname, `[i]) {`)
} else if field.IsString() {
p.P(`if this.`, fieldname, `[i] != that1.`, fieldname, `[i] {`)
} else {
p.P(`if this.`, fieldname, `[i] != that1.`, fieldname, `[i] {`)
}
}
p.In()
if verbose {
p.P(`return `, p.fmtPkg.Use(), `.Errorf("`, fieldname, ` this[%v](%v) Not Equal that[%v](%v)", i, this.`, fieldname, `[i], i, that1.`, fieldname, `[i])`)
} else {
p.P(`return false`)
}
p.Out()
p.P(`}`)
p.Out()
p.P(`}`)
}
}
func (p *plugin) generateMessage(file *generator.FileDescriptor, message *generator.Descriptor, verbose bool) {
ccTypeName := generator.CamelCaseSlice(message.TypeName())
if verbose {
p.P(`func (this *`, ccTypeName, `) VerboseEqual(that interface{}) error {`)
} else {
p.P(`func (this *`, ccTypeName, `) Equal(that interface{}) bool {`)
}
p.In()
p.generateMsgNullAndTypeCheck(ccTypeName, verbose)
oneofs := make(map[string]struct{})
for _, field := range message.Field {
oneof := field.OneofIndex != nil
if oneof {
fieldname := p.GetFieldName(message, field)
if _, ok := oneofs[fieldname]; ok {
continue
} else {
oneofs[fieldname] = struct{}{}
}
p.P(`if that1.`, fieldname, ` == nil {`)
p.In()
p.P(`if this.`, fieldname, ` != nil {`)
p.In()
if verbose {
p.P(`return `, p.fmtPkg.Use(), `.Errorf("this.`, fieldname, ` != nil && that1.`, fieldname, ` == nil")`)
} else {
p.P(`return false`)
}
p.Out()
p.P(`}`)
p.Out()
p.P(`} else if this.`, fieldname, ` == nil {`)
p.In()
if verbose {
p.P(`return `, p.fmtPkg.Use(), `.Errorf("this.`, fieldname, ` == nil && that1.`, fieldname, ` != nil")`)
} else {
p.P(`return false`)
}
p.Out()
if verbose {
p.P(`} else if err := this.`, fieldname, `.VerboseEqual(that1.`, fieldname, `); err != nil {`)
} else {
p.P(`} else if !this.`, fieldname, `.Equal(that1.`, fieldname, `) {`)
}
p.In()
if verbose {
p.P(`return err`)
} else {
p.P(`return false`)
}
p.Out()
p.P(`}`)
} else {
p.generateField(file, message, field, verbose)
}
}
if message.DescriptorProto.HasExtension() {
if gogoproto.HasExtensionsMap(file.FileDescriptorProto, message.DescriptorProto) {
fieldname := "XXX_InternalExtensions"
p.P(`thismap := `, p.protoPkg.Use(), `.GetUnsafeExtensionsMap(this)`)
p.P(`thatmap := `, p.protoPkg.Use(), `.GetUnsafeExtensionsMap(that1)`)
p.P(`for k, v := range thismap {`)
p.In()
p.P(`if v2, ok := thatmap[k]; ok {`)
p.In()
p.P(`if !v.Equal(&v2) {`)
p.In()
if verbose {
p.P(`return `, p.fmtPkg.Use(), `.Errorf("`, fieldname, ` this[%v](%v) Not Equal that[%v](%v)", k, thismap[k], k, thatmap[k])`)
} else {
p.P(`return false`)
}
p.Out()
p.P(`}`)
p.Out()
p.P(`} else {`)
p.In()
if verbose {
p.P(`return `, p.fmtPkg.Use(), `.Errorf("`, fieldname, `[%v] Not In that", k)`)
} else {
p.P(`return false`)
}
p.Out()
p.P(`}`)
p.Out()
p.P(`}`)
p.P(`for k, _ := range thatmap {`)
p.In()
p.P(`if _, ok := thismap[k]; !ok {`)
p.In()
if verbose {
p.P(`return `, p.fmtPkg.Use(), `.Errorf("`, fieldname, `[%v] Not In this", k)`)
} else {
p.P(`return false`)
}
p.Out()
p.P(`}`)
p.Out()
p.P(`}`)
} else {
fieldname := "XXX_extensions"
p.P(`if !`, p.bytesPkg.Use(), `.Equal(this.`, fieldname, `, that1.`, fieldname, `) {`)
p.In()
if verbose {
p.P(`return `, p.fmtPkg.Use(), `.Errorf("`, fieldname, ` this(%v) Not Equal that(%v)", this.`, fieldname, `, that1.`, fieldname, `)`)
} else {
p.P(`return false`)
}
p.Out()
p.P(`}`)
}
}
if gogoproto.HasUnrecognized(file.FileDescriptorProto, message.DescriptorProto) {
fieldname := "XXX_unrecognized"
p.P(`if !`, p.bytesPkg.Use(), `.Equal(this.`, fieldname, `, that1.`, fieldname, `) {`)
p.In()
if verbose {
p.P(`return `, p.fmtPkg.Use(), `.Errorf("`, fieldname, ` this(%v) Not Equal that(%v)", this.`, fieldname, `, that1.`, fieldname, `)`)
} else {
p.P(`return false`)
}
p.Out()
p.P(`}`)
}
if verbose {
p.P(`return nil`)
} else {
p.P(`return true`)
}
p.Out()
p.P(`}`)
//Generate Equal methods for oneof fields
m := proto.Clone(message.DescriptorProto).(*descriptor.DescriptorProto)
for _, field := range m.Field {
oneof := field.OneofIndex != nil
if !oneof {
continue
}
ccTypeName := p.OneOfTypeName(message, field)
if verbose {
p.P(`func (this *`, ccTypeName, `) VerboseEqual(that interface{}) error {`)
} else {
p.P(`func (this *`, ccTypeName, `) Equal(that interface{}) bool {`)
}
p.In()
p.generateMsgNullAndTypeCheck(ccTypeName, verbose)
vanity.TurnOffNullableForNativeTypes(field)
p.generateField(file, message, field, verbose)
if verbose {
p.P(`return nil`)
} else {
p.P(`return true`)
}
p.Out()
p.P(`}`)
}
}
func init() {
generator.RegisterPlugin(NewPlugin())
}

View file

@ -0,0 +1,109 @@
// Protocol Buffers for Go with Gadgets
//
// Copyright (c) 2013, The GoGo Authors. All rights reserved.
// http://github.com/gogo/protobuf
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package equal
import (
"github.com/gogo/protobuf/gogoproto"
"github.com/gogo/protobuf/plugin/testgen"
"github.com/gogo/protobuf/protoc-gen-gogo/generator"
)
type test struct {
*generator.Generator
}
func NewTest(g *generator.Generator) testgen.TestPlugin {
return &test{g}
}
func (p *test) Generate(imports generator.PluginImports, file *generator.FileDescriptor) bool {
used := false
randPkg := imports.NewImport("math/rand")
timePkg := imports.NewImport("time")
testingPkg := imports.NewImport("testing")
protoPkg := imports.NewImport("github.com/gogo/protobuf/proto")
unsafePkg := imports.NewImport("unsafe")
if !gogoproto.ImportsGoGoProto(file.FileDescriptorProto) {
protoPkg = imports.NewImport("github.com/golang/protobuf/proto")
}
for _, message := range file.Messages() {
ccTypeName := generator.CamelCaseSlice(message.TypeName())
if !gogoproto.HasVerboseEqual(file.FileDescriptorProto, message.DescriptorProto) {
continue
}
if message.DescriptorProto.GetOptions().GetMapEntry() {
continue
}
if gogoproto.HasTestGen(file.FileDescriptorProto, message.DescriptorProto) {
used = true
hasUnsafe := gogoproto.IsUnsafeMarshaler(file.FileDescriptorProto, message.DescriptorProto) ||
gogoproto.IsUnsafeUnmarshaler(file.FileDescriptorProto, message.DescriptorProto)
p.P(`func Test`, ccTypeName, `VerboseEqual(t *`, testingPkg.Use(), `.T) {`)
p.In()
if hasUnsafe {
if hasUnsafe {
p.P(`var bigendian uint32 = 0x01020304`)
p.P(`if *(*byte)(`, unsafePkg.Use(), `.Pointer(&bigendian)) == 1 {`)
p.In()
p.P(`t.Skip("unsafe does not work on big endian architectures")`)
p.Out()
p.P(`}`)
}
}
p.P(`popr := `, randPkg.Use(), `.New(`, randPkg.Use(), `.NewSource(`, timePkg.Use(), `.Now().UnixNano()))`)
p.P(`p := NewPopulated`, ccTypeName, `(popr, false)`)
p.P(`dAtA, err := `, protoPkg.Use(), `.Marshal(p)`)
p.P(`if err != nil {`)
p.In()
p.P(`panic(err)`)
p.Out()
p.P(`}`)
p.P(`msg := &`, ccTypeName, `{}`)
p.P(`if err := `, protoPkg.Use(), `.Unmarshal(dAtA, msg); err != nil {`)
p.In()
p.P(`panic(err)`)
p.Out()
p.P(`}`)
p.P(`if err := p.VerboseEqual(msg); err != nil {`)
p.In()
p.P(`t.Fatalf("%#v !VerboseEqual %#v, since %v", msg, p, err)`)
p.Out()
p.P(`}`)
p.Out()
p.P(`}`)
}
}
return used
}
func init() {
testgen.RegisterTestPlugin(NewTest)
}

233
vendor/github.com/gogo/protobuf/plugin/face/face.go generated vendored Normal file
View file

@ -0,0 +1,233 @@
// Protocol Buffers for Go with Gadgets
//
// Copyright (c) 2013, The GoGo Authors. All rights reserved.
// http://github.com/gogo/protobuf
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/*
The face plugin generates a function will be generated which can convert a structure which satisfies an interface (face) to the specified structure.
This interface contains getters for each of the fields in the struct.
The specified struct is also generated with the getters.
This means that getters should be turned off so as not to conflict with face getters.
This allows it to satisfy its own face.
It is enabled by the following extensions:
- face
- face_all
Turn off getters by using the following extensions:
- getters
- getters_all
The face plugin also generates a test given it is enabled using one of the following extensions:
- testgen
- testgen_all
Let us look at:
github.com/gogo/protobuf/test/example/example.proto
Btw all the output can be seen at:
github.com/gogo/protobuf/test/example/*
The following message:
message A {
option (gogoproto.face) = true;
option (gogoproto.goproto_getters) = false;
optional string Description = 1 [(gogoproto.nullable) = false];
optional int64 Number = 2 [(gogoproto.nullable) = false];
optional bytes Id = 3 [(gogoproto.customtype) = "github.com/gogo/protobuf/test/custom.Uuid", (gogoproto.nullable) = false];
}
given to the face plugin, will generate the following code:
type AFace interface {
Proto() github_com_gogo_protobuf_proto.Message
GetDescription() string
GetNumber() int64
GetId() github_com_gogo_protobuf_test_custom.Uuid
}
func (this *A) Proto() github_com_gogo_protobuf_proto.Message {
return this
}
func (this *A) TestProto() github_com_gogo_protobuf_proto.Message {
return NewAFromFace(this)
}
func (this *A) GetDescription() string {
return this.Description
}
func (this *A) GetNumber() int64 {
return this.Number
}
func (this *A) GetId() github_com_gogo_protobuf_test_custom.Uuid {
return this.Id
}
func NewAFromFace(that AFace) *A {
this := &A{}
this.Description = that.GetDescription()
this.Number = that.GetNumber()
this.Id = that.GetId()
return this
}
and the following test code:
func TestAFace(t *testing7.T) {
popr := math_rand7.New(math_rand7.NewSource(time7.Now().UnixNano()))
p := NewPopulatedA(popr, true)
msg := p.TestProto()
if !p.Equal(msg) {
t.Fatalf("%#v !Face Equal %#v", msg, p)
}
}
The struct A, representing the message, will also be generated just like always.
As you can see A satisfies its own Face, AFace.
Creating another struct which satisfies AFace is very easy.
Simply create all these methods specified in AFace.
Implementing The Proto method is done with the helper function NewAFromFace:
func (this *MyStruct) Proto() proto.Message {
return NewAFromFace(this)
}
just the like TestProto method which is used to test the NewAFromFace function.
*/
package face
import (
"github.com/gogo/protobuf/gogoproto"
"github.com/gogo/protobuf/protoc-gen-gogo/generator"
)
type plugin struct {
*generator.Generator
generator.PluginImports
}
func NewPlugin() *plugin {
return &plugin{}
}
func (p *plugin) Name() string {
return "face"
}
func (p *plugin) Init(g *generator.Generator) {
p.Generator = g
}
func (p *plugin) Generate(file *generator.FileDescriptor) {
p.PluginImports = generator.NewPluginImports(p.Generator)
protoPkg := p.NewImport("github.com/gogo/protobuf/proto")
if !gogoproto.ImportsGoGoProto(file.FileDescriptorProto) {
protoPkg = p.NewImport("github.com/golang/protobuf/proto")
}
for _, message := range file.Messages() {
if !gogoproto.IsFace(file.FileDescriptorProto, message.DescriptorProto) {
continue
}
if message.DescriptorProto.GetOptions().GetMapEntry() {
continue
}
if message.DescriptorProto.HasExtension() {
panic("face does not support message with extensions")
}
if gogoproto.HasGoGetters(file.FileDescriptorProto, message.DescriptorProto) {
panic("face requires getters to be disabled please use gogoproto.getters or gogoproto.getters_all and set it to false")
}
ccTypeName := generator.CamelCaseSlice(message.TypeName())
p.P(`type `, ccTypeName, `Face interface{`)
p.In()
p.P(`Proto() `, protoPkg.Use(), `.Message`)
for _, field := range message.Field {
fieldname := p.GetFieldName(message, field)
goTyp, _ := p.GoType(message, field)
if p.IsMap(field) {
m := p.GoMapType(nil, field)
goTyp = m.GoType
}
p.P(`Get`, fieldname, `() `, goTyp)
}
p.Out()
p.P(`}`)
p.P(``)
p.P(`func (this *`, ccTypeName, `) Proto() `, protoPkg.Use(), `.Message {`)
p.In()
p.P(`return this`)
p.Out()
p.P(`}`)
p.P(``)
p.P(`func (this *`, ccTypeName, `) TestProto() `, protoPkg.Use(), `.Message {`)
p.In()
p.P(`return New`, ccTypeName, `FromFace(this)`)
p.Out()
p.P(`}`)
p.P(``)
for _, field := range message.Field {
fieldname := p.GetFieldName(message, field)
goTyp, _ := p.GoType(message, field)
if p.IsMap(field) {
m := p.GoMapType(nil, field)
goTyp = m.GoType
}
p.P(`func (this *`, ccTypeName, `) Get`, fieldname, `() `, goTyp, `{`)
p.In()
p.P(` return this.`, fieldname)
p.Out()
p.P(`}`)
p.P(``)
}
p.P(``)
p.P(`func New`, ccTypeName, `FromFace(that `, ccTypeName, `Face) *`, ccTypeName, ` {`)
p.In()
p.P(`this := &`, ccTypeName, `{}`)
for _, field := range message.Field {
fieldname := p.GetFieldName(message, field)
p.P(`this.`, fieldname, ` = that.Get`, fieldname, `()`)
}
p.P(`return this`)
p.Out()
p.P(`}`)
p.P(``)
}
}
func init() {
generator.RegisterPlugin(NewPlugin())
}

View file

@ -0,0 +1,82 @@
// Protocol Buffers for Go with Gadgets
//
// Copyright (c) 2013, The GoGo Authors. All rights reserved.
// http://github.com/gogo/protobuf
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package face
import (
"github.com/gogo/protobuf/gogoproto"
"github.com/gogo/protobuf/plugin/testgen"
"github.com/gogo/protobuf/protoc-gen-gogo/generator"
)
type test struct {
*generator.Generator
}
func NewTest(g *generator.Generator) testgen.TestPlugin {
return &test{g}
}
func (p *test) Generate(imports generator.PluginImports, file *generator.FileDescriptor) bool {
used := false
randPkg := imports.NewImport("math/rand")
timePkg := imports.NewImport("time")
testingPkg := imports.NewImport("testing")
for _, message := range file.Messages() {
ccTypeName := generator.CamelCaseSlice(message.TypeName())
if !gogoproto.IsFace(file.FileDescriptorProto, message.DescriptorProto) {
continue
}
if message.DescriptorProto.GetOptions().GetMapEntry() {
continue
}
if gogoproto.HasTestGen(file.FileDescriptorProto, message.DescriptorProto) {
used = true
p.P(`func Test`, ccTypeName, `Face(t *`, testingPkg.Use(), `.T) {`)
p.In()
p.P(`popr := `, randPkg.Use(), `.New(`, randPkg.Use(), `.NewSource(`, timePkg.Use(), `.Now().UnixNano()))`)
p.P(`p := NewPopulated`, ccTypeName, `(popr, true)`)
p.P(`msg := p.TestProto()`)
p.P(`if !p.Equal(msg) {`)
p.In()
p.P(`t.Fatalf("%#v !Face Equal %#v", msg, p)`)
p.Out()
p.P(`}`)
p.Out()
p.P(`}`)
}
}
return used
}
func init() {
testgen.RegisterTestPlugin(NewTest)
}

View file

@ -0,0 +1,386 @@
// Protocol Buffers for Go with Gadgets
//
// Copyright (c) 2013, The GoGo Authors. All rights reserved.
// http://github.com/gogo/protobuf
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/*
The gostring plugin generates a GoString method for each message.
The GoString method is called whenever you use a fmt.Printf as such:
fmt.Printf("%#v", mymessage)
or whenever you actually call GoString()
The output produced by the GoString method can be copied from the output into code and used to set a variable.
It is totally valid Go Code and is populated exactly as the struct that was printed out.
It is enabled by the following extensions:
- gostring
- gostring_all
The gostring plugin also generates a test given it is enabled using one of the following extensions:
- testgen
- testgen_all
Let us look at:
github.com/gogo/protobuf/test/example/example.proto
Btw all the output can be seen at:
github.com/gogo/protobuf/test/example/*
The following message:
option (gogoproto.gostring_all) = true;
message A {
optional string Description = 1 [(gogoproto.nullable) = false];
optional int64 Number = 2 [(gogoproto.nullable) = false];
optional bytes Id = 3 [(gogoproto.customtype) = "github.com/gogo/protobuf/test/custom.Uuid", (gogoproto.nullable) = false];
}
given to the gostring plugin, will generate the following code:
func (this *A) GoString() string {
if this == nil {
return "nil"
}
s := strings1.Join([]string{`&test.A{` + `Description:` + fmt1.Sprintf("%#v", this.Description), `Number:` + fmt1.Sprintf("%#v", this.Number), `Id:` + fmt1.Sprintf("%#v", this.Id), `XXX_unrecognized:` + fmt1.Sprintf("%#v", this.XXX_unrecognized) + `}`}, ", ")
return s
}
and the following test code:
func TestAGoString(t *testing6.T) {
popr := math_rand6.New(math_rand6.NewSource(time6.Now().UnixNano()))
p := NewPopulatedA(popr, false)
s1 := p.GoString()
s2 := fmt2.Sprintf("%#v", p)
if s1 != s2 {
t.Fatalf("GoString want %v got %v", s1, s2)
}
_, err := go_parser.ParseExpr(s1)
if err != nil {
panic(err)
}
}
Typically fmt.Printf("%#v") will stop to print when it reaches a pointer and
not print their values, while the generated GoString method will always print all values, recursively.
*/
package gostring
import (
"fmt"
"os"
"strconv"
"strings"
"github.com/gogo/protobuf/gogoproto"
"github.com/gogo/protobuf/protoc-gen-gogo/generator"
)
type gostring struct {
*generator.Generator
generator.PluginImports
atleastOne bool
localName string
overwrite bool
}
func NewGoString() *gostring {
return &gostring{}
}
func (p *gostring) Name() string {
return "gostring"
}
func (p *gostring) Overwrite() {
p.overwrite = true
}
func (p *gostring) Init(g *generator.Generator) {
p.Generator = g
}
func (p *gostring) Generate(file *generator.FileDescriptor) {
proto3 := gogoproto.IsProto3(file.FileDescriptorProto)
p.PluginImports = generator.NewPluginImports(p.Generator)
p.atleastOne = false
p.localName = generator.FileName(file)
fmtPkg := p.NewImport("fmt")
stringsPkg := p.NewImport("strings")
protoPkg := p.NewImport("github.com/gogo/protobuf/proto")
if !gogoproto.ImportsGoGoProto(file.FileDescriptorProto) {
protoPkg = p.NewImport("github.com/golang/protobuf/proto")
}
sortPkg := p.NewImport("sort")
strconvPkg := p.NewImport("strconv")
reflectPkg := p.NewImport("reflect")
sortKeysPkg := p.NewImport("github.com/gogo/protobuf/sortkeys")
extensionToGoStringUsed := false
for _, message := range file.Messages() {
if !p.overwrite && !gogoproto.HasGoString(file.FileDescriptorProto, message.DescriptorProto) {
continue
}
if message.DescriptorProto.GetOptions().GetMapEntry() {
continue
}
p.atleastOne = true
packageName := file.GoPackageName()
ccTypeName := generator.CamelCaseSlice(message.TypeName())
p.P(`func (this *`, ccTypeName, `) GoString() string {`)
p.In()
p.P(`if this == nil {`)
p.In()
p.P(`return "nil"`)
p.Out()
p.P(`}`)
p.P(`s := make([]string, 0, `, strconv.Itoa(len(message.Field)+4), `)`)
p.P(`s = append(s, "&`, packageName, ".", ccTypeName, `{")`)
oneofs := make(map[string]struct{})
for _, field := range message.Field {
nullable := gogoproto.IsNullable(field)
repeated := field.IsRepeated()
fieldname := p.GetFieldName(message, field)
oneof := field.OneofIndex != nil
if oneof {
if _, ok := oneofs[fieldname]; ok {
continue
} else {
oneofs[fieldname] = struct{}{}
}
p.P(`if this.`, fieldname, ` != nil {`)
p.In()
p.P(`s = append(s, "`, fieldname, `: " + `, fmtPkg.Use(), `.Sprintf("%#v", this.`, fieldname, `) + ",\n")`)
p.Out()
p.P(`}`)
} else if p.IsMap(field) {
m := p.GoMapType(nil, field)
mapgoTyp, keyField, keyAliasField := m.GoType, m.KeyField, m.KeyAliasField
keysName := `keysFor` + fieldname
keygoTyp, _ := p.GoType(nil, keyField)
keygoTyp = strings.Replace(keygoTyp, "*", "", 1)
keygoAliasTyp, _ := p.GoType(nil, keyAliasField)
keygoAliasTyp = strings.Replace(keygoAliasTyp, "*", "", 1)
keyCapTyp := generator.CamelCase(keygoTyp)
p.P(keysName, ` := make([]`, keygoTyp, `, 0, len(this.`, fieldname, `))`)
p.P(`for k, _ := range this.`, fieldname, ` {`)
p.In()
if keygoAliasTyp == keygoTyp {
p.P(keysName, ` = append(`, keysName, `, k)`)
} else {
p.P(keysName, ` = append(`, keysName, `, `, keygoTyp, `(k))`)
}
p.Out()
p.P(`}`)
p.P(sortKeysPkg.Use(), `.`, keyCapTyp, `s(`, keysName, `)`)
mapName := `mapStringFor` + fieldname
p.P(mapName, ` := "`, mapgoTyp, `{"`)
p.P(`for _, k := range `, keysName, ` {`)
p.In()
if keygoAliasTyp == keygoTyp {
p.P(mapName, ` += fmt.Sprintf("%#v: %#v,", k, this.`, fieldname, `[k])`)
} else {
p.P(mapName, ` += fmt.Sprintf("%#v: %#v,", k, this.`, fieldname, `[`, keygoAliasTyp, `(k)])`)
}
p.Out()
p.P(`}`)
p.P(mapName, ` += "}"`)
p.P(`if this.`, fieldname, ` != nil {`)
p.In()
p.P(`s = append(s, "`, fieldname, `: " + `, mapName, `+ ",\n")`)
p.Out()
p.P(`}`)
} else if (field.IsMessage() && !gogoproto.IsCustomType(field) && !gogoproto.IsStdType(field)) || p.IsGroup(field) {
if nullable || repeated {
p.P(`if this.`, fieldname, ` != nil {`)
p.In()
}
if nullable {
p.P(`s = append(s, "`, fieldname, `: " + `, fmtPkg.Use(), `.Sprintf("%#v", this.`, fieldname, `) + ",\n")`)
} else if repeated {
if nullable {
p.P(`s = append(s, "`, fieldname, `: " + `, fmtPkg.Use(), `.Sprintf("%#v", this.`, fieldname, `) + ",\n")`)
} else {
goTyp, _ := p.GoType(message, field)
goTyp = strings.Replace(goTyp, "[]", "", 1)
p.P("vs := make([]", goTyp, ", len(this.", fieldname, "))")
p.P("for i := range vs {")
p.In()
p.P("vs[i] = this.", fieldname, "[i]")
p.Out()
p.P("}")
p.P(`s = append(s, "`, fieldname, `: " + `, fmtPkg.Use(), `.Sprintf("%#v", vs) + ",\n")`)
}
} else {
p.P(`s = append(s, "`, fieldname, `: " + `, stringsPkg.Use(), `.Replace(this.`, fieldname, `.GoString()`, ",`&`,``,1)", ` + ",\n")`)
}
if nullable || repeated {
p.Out()
p.P(`}`)
}
} else {
if !proto3 && (nullable || repeated) {
p.P(`if this.`, fieldname, ` != nil {`)
p.In()
}
if field.IsEnum() {
if nullable && !repeated && !proto3 {
goTyp, _ := p.GoType(message, field)
p.P(`s = append(s, "`, fieldname, `: " + valueToGoString`, p.localName, `(this.`, fieldname, `,"`, generator.GoTypeToName(goTyp), `"`, `) + ",\n")`)
} else {
p.P(`s = append(s, "`, fieldname, `: " + `, fmtPkg.Use(), `.Sprintf("%#v", this.`, fieldname, `) + ",\n")`)
}
} else {
if nullable && !repeated && !proto3 {
goTyp, _ := p.GoType(message, field)
p.P(`s = append(s, "`, fieldname, `: " + valueToGoString`, p.localName, `(this.`, fieldname, `,"`, generator.GoTypeToName(goTyp), `"`, `) + ",\n")`)
} else {
p.P(`s = append(s, "`, fieldname, `: " + `, fmtPkg.Use(), `.Sprintf("%#v", this.`, fieldname, `) + ",\n")`)
}
}
if !proto3 && (nullable || repeated) {
p.Out()
p.P(`}`)
}
}
}
if message.DescriptorProto.HasExtension() {
if gogoproto.HasExtensionsMap(file.FileDescriptorProto, message.DescriptorProto) {
p.P(`s = append(s, "XXX_InternalExtensions: " + extensionToGoString`, p.localName, `(this) + ",\n")`)
extensionToGoStringUsed = true
} else {
p.P(`if this.XXX_extensions != nil {`)
p.In()
p.P(`s = append(s, "XXX_extensions: " + `, fmtPkg.Use(), `.Sprintf("%#v", this.XXX_extensions) + ",\n")`)
p.Out()
p.P(`}`)
}
}
if gogoproto.HasUnrecognized(file.FileDescriptorProto, message.DescriptorProto) {
p.P(`if this.XXX_unrecognized != nil {`)
p.In()
p.P(`s = append(s, "XXX_unrecognized:" + `, fmtPkg.Use(), `.Sprintf("%#v", this.XXX_unrecognized) + ",\n")`)
p.Out()
p.P(`}`)
}
p.P(`s = append(s, "}")`)
p.P(`return `, stringsPkg.Use(), `.Join(s, "")`)
p.Out()
p.P(`}`)
//Generate GoString methods for oneof fields
for _, field := range message.Field {
oneof := field.OneofIndex != nil
if !oneof {
continue
}
ccTypeName := p.OneOfTypeName(message, field)
p.P(`func (this *`, ccTypeName, `) GoString() string {`)
p.In()
p.P(`if this == nil {`)
p.In()
p.P(`return "nil"`)
p.Out()
p.P(`}`)
fieldname := p.GetOneOfFieldName(message, field)
outStr := strings.Join([]string{
"s := ",
stringsPkg.Use(), ".Join([]string{`&", packageName, ".", ccTypeName, "{` + \n",
"`", fieldname, ":` + ", fmtPkg.Use(), `.Sprintf("%#v", this.`, fieldname, `)`,
" + `}`",
`}`,
`,", "`,
`)`}, "")
p.P(outStr)
p.P(`return s`)
p.Out()
p.P(`}`)
}
}
if !p.atleastOne {
return
}
p.P(`func valueToGoString`, p.localName, `(v interface{}, typ string) string {`)
p.In()
p.P(`rv := `, reflectPkg.Use(), `.ValueOf(v)`)
p.P(`if rv.IsNil() {`)
p.In()
p.P(`return "nil"`)
p.Out()
p.P(`}`)
p.P(`pv := `, reflectPkg.Use(), `.Indirect(rv).Interface()`)
p.P(`return `, fmtPkg.Use(), `.Sprintf("func(v %v) *%v { return &v } ( %#v )", typ, typ, pv)`)
p.Out()
p.P(`}`)
if extensionToGoStringUsed {
if !gogoproto.ImportsGoGoProto(file.FileDescriptorProto) {
fmt.Fprintf(os.Stderr, "The GoString plugin for messages with extensions requires importing gogoprotobuf. Please see file %s", file.GetName())
os.Exit(1)
}
p.P(`func extensionToGoString`, p.localName, `(m `, protoPkg.Use(), `.Message) string {`)
p.In()
p.P(`e := `, protoPkg.Use(), `.GetUnsafeExtensionsMap(m)`)
p.P(`if e == nil { return "nil" }`)
p.P(`s := "proto.NewUnsafeXXX_InternalExtensions(map[int32]proto.Extension{"`)
p.P(`keys := make([]int, 0, len(e))`)
p.P(`for k := range e {`)
p.In()
p.P(`keys = append(keys, int(k))`)
p.Out()
p.P(`}`)
p.P(sortPkg.Use(), `.Ints(keys)`)
p.P(`ss := []string{}`)
p.P(`for _, k := range keys {`)
p.In()
p.P(`ss = append(ss, `, strconvPkg.Use(), `.Itoa(k) + ": " + e[int32(k)].GoString())`)
p.Out()
p.P(`}`)
p.P(`s+=`, stringsPkg.Use(), `.Join(ss, ",") + "})"`)
p.P(`return s`)
p.Out()
p.P(`}`)
}
}
func init() {
generator.RegisterPlugin(NewGoString())
}

View file

@ -0,0 +1,90 @@
// Protocol Buffers for Go with Gadgets
//
// Copyright (c) 2013, The GoGo Authors. All rights reserved.
// http://github.com/gogo/protobuf
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package gostring
import (
"github.com/gogo/protobuf/gogoproto"
"github.com/gogo/protobuf/plugin/testgen"
"github.com/gogo/protobuf/protoc-gen-gogo/generator"
)
type test struct {
*generator.Generator
}
func NewTest(g *generator.Generator) testgen.TestPlugin {
return &test{g}
}
func (p *test) Generate(imports generator.PluginImports, file *generator.FileDescriptor) bool {
used := false
randPkg := imports.NewImport("math/rand")
timePkg := imports.NewImport("time")
testingPkg := imports.NewImport("testing")
fmtPkg := imports.NewImport("fmt")
parserPkg := imports.NewImport("go/parser")
for _, message := range file.Messages() {
ccTypeName := generator.CamelCaseSlice(message.TypeName())
if !gogoproto.HasGoString(file.FileDescriptorProto, message.DescriptorProto) {
continue
}
if message.DescriptorProto.GetOptions().GetMapEntry() {
continue
}
if gogoproto.HasTestGen(file.FileDescriptorProto, message.DescriptorProto) {
used = true
p.P(`func Test`, ccTypeName, `GoString(t *`, testingPkg.Use(), `.T) {`)
p.In()
p.P(`popr := `, randPkg.Use(), `.New(`, randPkg.Use(), `.NewSource(`, timePkg.Use(), `.Now().UnixNano()))`)
p.P(`p := NewPopulated`, ccTypeName, `(popr, false)`)
p.P(`s1 := p.GoString()`)
p.P(`s2 := `, fmtPkg.Use(), `.Sprintf("%#v", p)`)
p.P(`if s1 != s2 {`)
p.In()
p.P(`t.Fatalf("GoString want %v got %v", s1, s2)`)
p.Out()
p.P(`}`)
p.P(`_, err := `, parserPkg.Use(), `.ParseExpr(s1)`)
p.P(`if err != nil {`)
p.In()
p.P(`t.Fatal(err)`)
p.Out()
p.P(`}`)
p.Out()
p.P(`}`)
}
}
return used
}
func init() {
testgen.RegisterTestPlugin(NewTest)
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,93 @@
// Protocol Buffers for Go with Gadgets
//
// Copyright (c) 2013, The GoGo Authors. All rights reserved.
// http://github.com/gogo/protobuf
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/*
The oneofcheck plugin is used to check whether oneof is not used incorrectly.
For instance:
An error is caused if a oneof field:
- is used in a face
- is an embedded field
*/
package oneofcheck
import (
"fmt"
"github.com/gogo/protobuf/gogoproto"
"github.com/gogo/protobuf/protoc-gen-gogo/generator"
"os"
)
type plugin struct {
*generator.Generator
}
func NewPlugin() *plugin {
return &plugin{}
}
func (p *plugin) Name() string {
return "oneofcheck"
}
func (p *plugin) Init(g *generator.Generator) {
p.Generator = g
}
func (p *plugin) Generate(file *generator.FileDescriptor) {
for _, msg := range file.Messages() {
face := gogoproto.IsFace(file.FileDescriptorProto, msg.DescriptorProto)
for _, field := range msg.GetField() {
if field.OneofIndex == nil {
continue
}
if face {
fmt.Fprintf(os.Stderr, "ERROR: field %v.%v cannot be in a face and oneof\n", generator.CamelCase(*msg.Name), generator.CamelCase(*field.Name))
os.Exit(1)
}
if gogoproto.IsEmbed(field) {
fmt.Fprintf(os.Stderr, "ERROR: field %v.%v cannot be in an oneof and an embedded field\n", generator.CamelCase(*msg.Name), generator.CamelCase(*field.Name))
os.Exit(1)
}
if !gogoproto.IsNullable(field) {
fmt.Fprintf(os.Stderr, "ERROR: field %v.%v cannot be in an oneof and a non-nullable field\n", generator.CamelCase(*msg.Name), generator.CamelCase(*field.Name))
os.Exit(1)
}
if gogoproto.IsUnion(file.FileDescriptorProto, msg.DescriptorProto) {
fmt.Fprintf(os.Stderr, "ERROR: field %v.%v cannot be in an oneof and in an union (deprecated)\n", generator.CamelCase(*msg.Name), generator.CamelCase(*field.Name))
os.Exit(1)
}
}
}
}
func (p *plugin) GenerateImports(*generator.FileDescriptor) {}
func init() {
generator.RegisterPlugin(NewPlugin())
}

View file

@ -0,0 +1,815 @@
// Protocol Buffers for Go with Gadgets
//
// Copyright (c) 2013, The GoGo Authors. All rights reserved.
// http://github.com/gogo/protobuf
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/*
The populate plugin generates a NewPopulated function.
This function returns a newly populated structure.
It is enabled by the following extensions:
- populate
- populate_all
Let us look at:
github.com/gogo/protobuf/test/example/example.proto
Btw all the output can be seen at:
github.com/gogo/protobuf/test/example/*
The following message:
option (gogoproto.populate_all) = true;
message B {
optional A A = 1 [(gogoproto.nullable) = false, (gogoproto.embed) = true];
repeated bytes G = 2 [(gogoproto.customtype) = "github.com/gogo/protobuf/test/custom.Uint128", (gogoproto.nullable) = false];
}
given to the populate plugin, will generate code the following code:
func NewPopulatedB(r randyExample, easy bool) *B {
this := &B{}
v2 := NewPopulatedA(r, easy)
this.A = *v2
if r.Intn(10) != 0 {
v3 := r.Intn(10)
this.G = make([]github_com_gogo_protobuf_test_custom.Uint128, v3)
for i := 0; i < v3; i++ {
v4 := github_com_gogo_protobuf_test_custom.NewPopulatedUint128(r)
this.G[i] = *v4
}
}
if !easy && r.Intn(10) != 0 {
this.XXX_unrecognized = randUnrecognizedExample(r, 3)
}
return this
}
The idea that is useful for testing.
Most of the other plugins' generated test code uses it.
You will still be able to use the generated test code of other packages
if you turn off the popluate plugin and write your own custom NewPopulated function.
If the easy flag is not set the XXX_unrecognized and XXX_extensions fields are also populated.
These have caused problems with JSON marshalling and unmarshalling tests.
*/
package populate
import (
"fmt"
"math"
"strconv"
"strings"
"github.com/gogo/protobuf/gogoproto"
"github.com/gogo/protobuf/proto"
descriptor "github.com/gogo/protobuf/protoc-gen-gogo/descriptor"
"github.com/gogo/protobuf/protoc-gen-gogo/generator"
"github.com/gogo/protobuf/vanity"
)
type VarGen interface {
Next() string
Current() string
}
type varGen struct {
index int64
}
func NewVarGen() VarGen {
return &varGen{0}
}
func (this *varGen) Next() string {
this.index++
return fmt.Sprintf("v%d", this.index)
}
func (this *varGen) Current() string {
return fmt.Sprintf("v%d", this.index)
}
type plugin struct {
*generator.Generator
generator.PluginImports
varGen VarGen
atleastOne bool
localName string
typesPkg generator.Single
}
func NewPlugin() *plugin {
return &plugin{}
}
func (p *plugin) Name() string {
return "populate"
}
func (p *plugin) Init(g *generator.Generator) {
p.Generator = g
}
func value(typeName string, fieldType descriptor.FieldDescriptorProto_Type) string {
switch fieldType {
case descriptor.FieldDescriptorProto_TYPE_DOUBLE:
return typeName + "(r.Float64())"
case descriptor.FieldDescriptorProto_TYPE_FLOAT:
return typeName + "(r.Float32())"
case descriptor.FieldDescriptorProto_TYPE_INT64,
descriptor.FieldDescriptorProto_TYPE_SFIXED64,
descriptor.FieldDescriptorProto_TYPE_SINT64:
return typeName + "(r.Int63())"
case descriptor.FieldDescriptorProto_TYPE_UINT64,
descriptor.FieldDescriptorProto_TYPE_FIXED64:
return typeName + "(uint64(r.Uint32()))"
case descriptor.FieldDescriptorProto_TYPE_INT32,
descriptor.FieldDescriptorProto_TYPE_SINT32,
descriptor.FieldDescriptorProto_TYPE_SFIXED32,
descriptor.FieldDescriptorProto_TYPE_ENUM:
return typeName + "(r.Int31())"
case descriptor.FieldDescriptorProto_TYPE_UINT32,
descriptor.FieldDescriptorProto_TYPE_FIXED32:
return typeName + "(r.Uint32())"
case descriptor.FieldDescriptorProto_TYPE_BOOL:
return typeName + `(bool(r.Intn(2) == 0))`
case descriptor.FieldDescriptorProto_TYPE_STRING,
descriptor.FieldDescriptorProto_TYPE_GROUP,
descriptor.FieldDescriptorProto_TYPE_MESSAGE,
descriptor.FieldDescriptorProto_TYPE_BYTES:
}
panic(fmt.Errorf("unexpected type %v", typeName))
}
func negative(fieldType descriptor.FieldDescriptorProto_Type) bool {
switch fieldType {
case descriptor.FieldDescriptorProto_TYPE_UINT64,
descriptor.FieldDescriptorProto_TYPE_FIXED64,
descriptor.FieldDescriptorProto_TYPE_UINT32,
descriptor.FieldDescriptorProto_TYPE_FIXED32,
descriptor.FieldDescriptorProto_TYPE_BOOL:
return false
}
return true
}
func (p *plugin) getFuncName(goTypName string, field *descriptor.FieldDescriptorProto) string {
funcName := "NewPopulated" + goTypName
goTypNames := strings.Split(goTypName, ".")
if len(goTypNames) == 2 {
funcName = goTypNames[0] + ".NewPopulated" + goTypNames[1]
} else if len(goTypNames) != 1 {
panic(fmt.Errorf("unreachable: too many dots in %v", goTypName))
}
if field != nil {
switch {
case gogoproto.IsStdTime(field):
funcName = p.typesPkg.Use() + ".NewPopulatedStdTime"
case gogoproto.IsStdDuration(field):
funcName = p.typesPkg.Use() + ".NewPopulatedStdDuration"
case gogoproto.IsStdDouble(field):
funcName = p.typesPkg.Use() + ".NewPopulatedStdDouble"
case gogoproto.IsStdFloat(field):
funcName = p.typesPkg.Use() + ".NewPopulatedStdFloat"
case gogoproto.IsStdInt64(field):
funcName = p.typesPkg.Use() + ".NewPopulatedStdInt64"
case gogoproto.IsStdUInt64(field):
funcName = p.typesPkg.Use() + ".NewPopulatedStdUInt64"
case gogoproto.IsStdInt32(field):
funcName = p.typesPkg.Use() + ".NewPopulatedStdInt32"
case gogoproto.IsStdUInt32(field):
funcName = p.typesPkg.Use() + ".NewPopulatedStdUInt32"
case gogoproto.IsStdBool(field):
funcName = p.typesPkg.Use() + ".NewPopulatedStdBool"
case gogoproto.IsStdString(field):
funcName = p.typesPkg.Use() + ".NewPopulatedStdString"
case gogoproto.IsStdBytes(field):
funcName = p.typesPkg.Use() + ".NewPopulatedStdBytes"
}
}
return funcName
}
func (p *plugin) getFuncCall(goTypName string, field *descriptor.FieldDescriptorProto) string {
funcName := p.getFuncName(goTypName, field)
funcCall := funcName + "(r, easy)"
return funcCall
}
func (p *plugin) getCustomFuncCall(goTypName string) string {
funcName := p.getFuncName(goTypName, nil)
funcCall := funcName + "(r)"
return funcCall
}
func (p *plugin) getEnumVal(field *descriptor.FieldDescriptorProto, goTyp string) string {
enum := p.ObjectNamed(field.GetTypeName()).(*generator.EnumDescriptor)
l := len(enum.Value)
values := make([]string, l)
for i := range enum.Value {
values[i] = strconv.Itoa(int(*enum.Value[i].Number))
}
arr := "[]int32{" + strings.Join(values, ",") + "}"
val := strings.Join([]string{generator.GoTypeToName(goTyp), `(`, arr, `[r.Intn(`, fmt.Sprintf("%d", l), `)])`}, "")
return val
}
func (p *plugin) GenerateField(file *generator.FileDescriptor, message *generator.Descriptor, field *descriptor.FieldDescriptorProto) {
proto3 := gogoproto.IsProto3(file.FileDescriptorProto)
goTyp, _ := p.GoType(message, field)
fieldname := p.GetOneOfFieldName(message, field)
goTypName := generator.GoTypeToName(goTyp)
if p.IsMap(field) {
m := p.GoMapType(nil, field)
keygoTyp, _ := p.GoType(nil, m.KeyField)
keygoTyp = strings.Replace(keygoTyp, "*", "", 1)
keygoAliasTyp, _ := p.GoType(nil, m.KeyAliasField)
keygoAliasTyp = strings.Replace(keygoAliasTyp, "*", "", 1)
valuegoTyp, _ := p.GoType(nil, m.ValueField)
valuegoAliasTyp, _ := p.GoType(nil, m.ValueAliasField)
keytypName := generator.GoTypeToName(keygoTyp)
keygoAliasTyp = generator.GoTypeToName(keygoAliasTyp)
valuetypAliasName := generator.GoTypeToName(valuegoAliasTyp)
nullable, valuegoTyp, valuegoAliasTyp := generator.GoMapValueTypes(field, m.ValueField, valuegoTyp, valuegoAliasTyp)
p.P(p.varGen.Next(), ` := r.Intn(10)`)
p.P(`this.`, fieldname, ` = make(`, m.GoType, `)`)
p.P(`for i := 0; i < `, p.varGen.Current(), `; i++ {`)
p.In()
keyval := ""
if m.KeyField.IsString() {
keyval = fmt.Sprintf("randString%v(r)", p.localName)
} else {
keyval = value(keytypName, m.KeyField.GetType())
}
if keygoAliasTyp != keygoTyp {
keyval = keygoAliasTyp + `(` + keyval + `)`
}
if m.ValueField.IsMessage() || p.IsGroup(field) ||
(m.ValueField.IsBytes() && gogoproto.IsCustomType(field)) {
s := `this.` + fieldname + `[` + keyval + `] = `
if gogoproto.IsStdType(field) {
valuegoTyp = valuegoAliasTyp
}
funcCall := p.getCustomFuncCall(goTypName)
if !gogoproto.IsCustomType(field) {
goTypName = generator.GoTypeToName(valuegoTyp)
funcCall = p.getFuncCall(goTypName, m.ValueAliasField)
}
if !nullable {
funcCall = `*` + funcCall
}
if valuegoTyp != valuegoAliasTyp {
funcCall = `(` + valuegoAliasTyp + `)(` + funcCall + `)`
}
s += funcCall
p.P(s)
} else if m.ValueField.IsEnum() {
s := `this.` + fieldname + `[` + keyval + `]` + ` = ` + p.getEnumVal(m.ValueField, valuegoTyp)
p.P(s)
} else if m.ValueField.IsBytes() {
count := p.varGen.Next()
p.P(count, ` := r.Intn(100)`)
p.P(p.varGen.Next(), ` := `, keyval)
p.P(`this.`, fieldname, `[`, p.varGen.Current(), `] = make(`, valuegoTyp, `, `, count, `)`)
p.P(`for i := 0; i < `, count, `; i++ {`)
p.In()
p.P(`this.`, fieldname, `[`, p.varGen.Current(), `][i] = byte(r.Intn(256))`)
p.Out()
p.P(`}`)
} else if m.ValueField.IsString() {
s := `this.` + fieldname + `[` + keyval + `]` + ` = ` + fmt.Sprintf("randString%v(r)", p.localName)
p.P(s)
} else {
p.P(p.varGen.Next(), ` := `, keyval)
p.P(`this.`, fieldname, `[`, p.varGen.Current(), `] = `, value(valuetypAliasName, m.ValueField.GetType()))
if negative(m.ValueField.GetType()) {
p.P(`if r.Intn(2) == 0 {`)
p.In()
p.P(`this.`, fieldname, `[`, p.varGen.Current(), `] *= -1`)
p.Out()
p.P(`}`)
}
}
p.Out()
p.P(`}`)
} else if gogoproto.IsCustomType(field) {
funcCall := p.getCustomFuncCall(goTypName)
if field.IsRepeated() {
p.P(p.varGen.Next(), ` := r.Intn(10)`)
p.P(`this.`, fieldname, ` = make(`, goTyp, `, `, p.varGen.Current(), `)`)
p.P(`for i := 0; i < `, p.varGen.Current(), `; i++ {`)
p.In()
p.P(p.varGen.Next(), `:= `, funcCall)
p.P(`this.`, fieldname, `[i] = *`, p.varGen.Current())
p.Out()
p.P(`}`)
} else if gogoproto.IsNullable(field) {
p.P(`this.`, fieldname, ` = `, funcCall)
} else {
p.P(p.varGen.Next(), `:= `, funcCall)
p.P(`this.`, fieldname, ` = *`, p.varGen.Current())
}
} else if field.IsMessage() || p.IsGroup(field) {
funcCall := p.getFuncCall(goTypName, field)
if field.IsRepeated() {
p.P(p.varGen.Next(), ` := r.Intn(5)`)
p.P(`this.`, fieldname, ` = make(`, goTyp, `, `, p.varGen.Current(), `)`)
p.P(`for i := 0; i < `, p.varGen.Current(), `; i++ {`)
p.In()
if gogoproto.IsNullable(field) {
p.P(`this.`, fieldname, `[i] = `, funcCall)
} else {
p.P(p.varGen.Next(), `:= `, funcCall)
p.P(`this.`, fieldname, `[i] = *`, p.varGen.Current())
}
p.Out()
p.P(`}`)
} else {
if gogoproto.IsNullable(field) {
p.P(`this.`, fieldname, ` = `, funcCall)
} else {
p.P(p.varGen.Next(), `:= `, funcCall)
p.P(`this.`, fieldname, ` = *`, p.varGen.Current())
}
}
} else {
if field.IsEnum() {
val := p.getEnumVal(field, goTyp)
if field.IsRepeated() {
p.P(p.varGen.Next(), ` := r.Intn(10)`)
p.P(`this.`, fieldname, ` = make(`, goTyp, `, `, p.varGen.Current(), `)`)
p.P(`for i := 0; i < `, p.varGen.Current(), `; i++ {`)
p.In()
p.P(`this.`, fieldname, `[i] = `, val)
p.Out()
p.P(`}`)
} else if !gogoproto.IsNullable(field) || proto3 {
p.P(`this.`, fieldname, ` = `, val)
} else {
p.P(p.varGen.Next(), ` := `, val)
p.P(`this.`, fieldname, ` = &`, p.varGen.Current())
}
} else if field.IsBytes() {
if field.IsRepeated() {
p.P(p.varGen.Next(), ` := r.Intn(10)`)
p.P(`this.`, fieldname, ` = make(`, goTyp, `, `, p.varGen.Current(), `)`)
p.P(`for i := 0; i < `, p.varGen.Current(), `; i++ {`)
p.In()
p.P(p.varGen.Next(), ` := r.Intn(100)`)
p.P(`this.`, fieldname, `[i] = make([]byte,`, p.varGen.Current(), `)`)
p.P(`for j := 0; j < `, p.varGen.Current(), `; j++ {`)
p.In()
p.P(`this.`, fieldname, `[i][j] = byte(r.Intn(256))`)
p.Out()
p.P(`}`)
p.Out()
p.P(`}`)
} else {
p.P(p.varGen.Next(), ` := r.Intn(100)`)
p.P(`this.`, fieldname, ` = make(`, goTyp, `, `, p.varGen.Current(), `)`)
p.P(`for i := 0; i < `, p.varGen.Current(), `; i++ {`)
p.In()
p.P(`this.`, fieldname, `[i] = byte(r.Intn(256))`)
p.Out()
p.P(`}`)
}
} else if field.IsString() {
typName := generator.GoTypeToName(goTyp)
val := fmt.Sprintf("%s(randString%v(r))", typName, p.localName)
if field.IsRepeated() {
p.P(p.varGen.Next(), ` := r.Intn(10)`)
p.P(`this.`, fieldname, ` = make(`, goTyp, `, `, p.varGen.Current(), `)`)
p.P(`for i := 0; i < `, p.varGen.Current(), `; i++ {`)
p.In()
p.P(`this.`, fieldname, `[i] = `, val)
p.Out()
p.P(`}`)
} else if !gogoproto.IsNullable(field) || proto3 {
p.P(`this.`, fieldname, ` = `, val)
} else {
p.P(p.varGen.Next(), `:= `, val)
p.P(`this.`, fieldname, ` = &`, p.varGen.Current())
}
} else {
typName := generator.GoTypeToName(goTyp)
if field.IsRepeated() {
p.P(p.varGen.Next(), ` := r.Intn(10)`)
p.P(`this.`, fieldname, ` = make(`, goTyp, `, `, p.varGen.Current(), `)`)
p.P(`for i := 0; i < `, p.varGen.Current(), `; i++ {`)
p.In()
p.P(`this.`, fieldname, `[i] = `, value(typName, field.GetType()))
if negative(field.GetType()) {
p.P(`if r.Intn(2) == 0 {`)
p.In()
p.P(`this.`, fieldname, `[i] *= -1`)
p.Out()
p.P(`}`)
}
p.Out()
p.P(`}`)
} else if !gogoproto.IsNullable(field) || proto3 {
p.P(`this.`, fieldname, ` = `, value(typName, field.GetType()))
if negative(field.GetType()) {
p.P(`if r.Intn(2) == 0 {`)
p.In()
p.P(`this.`, fieldname, ` *= -1`)
p.Out()
p.P(`}`)
}
} else {
p.P(p.varGen.Next(), ` := `, value(typName, field.GetType()))
if negative(field.GetType()) {
p.P(`if r.Intn(2) == 0 {`)
p.In()
p.P(p.varGen.Current(), ` *= -1`)
p.Out()
p.P(`}`)
}
p.P(`this.`, fieldname, ` = &`, p.varGen.Current())
}
}
}
}
func (p *plugin) hasLoop(pkg string, field *descriptor.FieldDescriptorProto, visited []*generator.Descriptor, excludes []*generator.Descriptor) *generator.Descriptor {
if field.IsMessage() || p.IsGroup(field) || p.IsMap(field) {
var fieldMessage *generator.Descriptor
if p.IsMap(field) {
m := p.GoMapType(nil, field)
if !m.ValueField.IsMessage() {
return nil
}
fieldMessage = p.ObjectNamed(m.ValueField.GetTypeName()).(*generator.Descriptor)
} else {
fieldMessage = p.ObjectNamed(field.GetTypeName()).(*generator.Descriptor)
}
fieldTypeName := generator.CamelCaseSlice(fieldMessage.TypeName())
for _, message := range visited {
messageTypeName := generator.CamelCaseSlice(message.TypeName())
if fieldTypeName == messageTypeName {
for _, e := range excludes {
if fieldTypeName == generator.CamelCaseSlice(e.TypeName()) {
return nil
}
}
return fieldMessage
}
}
for _, f := range fieldMessage.Field {
if strings.HasPrefix(f.GetTypeName(), "."+pkg) {
visited = append(visited, fieldMessage)
loopTo := p.hasLoop(pkg, f, visited, excludes)
if loopTo != nil {
return loopTo
}
}
}
}
return nil
}
func (p *plugin) loops(pkg string, field *descriptor.FieldDescriptorProto, message *generator.Descriptor) int {
//fmt.Fprintf(os.Stderr, "loops %v %v\n", field.GetTypeName(), generator.CamelCaseSlice(message.TypeName()))
excludes := []*generator.Descriptor{}
loops := 0
for {
visited := []*generator.Descriptor{}
loopTo := p.hasLoop(pkg, field, visited, excludes)
if loopTo == nil {
break
}
//fmt.Fprintf(os.Stderr, "loopTo %v\n", generator.CamelCaseSlice(loopTo.TypeName()))
excludes = append(excludes, loopTo)
loops++
}
return loops
}
func (p *plugin) Generate(file *generator.FileDescriptor) {
p.atleastOne = false
p.PluginImports = generator.NewPluginImports(p.Generator)
p.varGen = NewVarGen()
proto3 := gogoproto.IsProto3(file.FileDescriptorProto)
p.typesPkg = p.NewImport("github.com/gogo/protobuf/types")
p.localName = generator.FileName(file)
protoPkg := p.NewImport("github.com/gogo/protobuf/proto")
if !gogoproto.ImportsGoGoProto(file.FileDescriptorProto) {
protoPkg = p.NewImport("github.com/golang/protobuf/proto")
}
for _, message := range file.Messages() {
if !gogoproto.HasPopulate(file.FileDescriptorProto, message.DescriptorProto) {
continue
}
if message.DescriptorProto.GetOptions().GetMapEntry() {
continue
}
p.atleastOne = true
ccTypeName := generator.CamelCaseSlice(message.TypeName())
loopLevels := make([]int, len(message.Field))
maxLoopLevel := 0
for i, field := range message.Field {
loopLevels[i] = p.loops(file.GetPackage(), field, message)
if loopLevels[i] > maxLoopLevel {
maxLoopLevel = loopLevels[i]
}
}
ranTotal := 0
for i := range loopLevels {
ranTotal += int(math.Pow10(maxLoopLevel - loopLevels[i]))
}
p.P(`func NewPopulated`, ccTypeName, `(r randy`, p.localName, `, easy bool) *`, ccTypeName, ` {`)
p.In()
p.P(`this := &`, ccTypeName, `{}`)
if gogoproto.IsUnion(message.File().FileDescriptorProto, message.DescriptorProto) && len(message.Field) > 0 {
p.P(`fieldNum := r.Intn(`, fmt.Sprintf("%d", ranTotal), `)`)
p.P(`switch fieldNum {`)
k := 0
for i, field := range message.Field {
is := []string{}
ran := int(math.Pow10(maxLoopLevel - loopLevels[i]))
for j := 0; j < ran; j++ {
is = append(is, fmt.Sprintf("%d", j+k))
}
k += ran
p.P(`case `, strings.Join(is, ","), `:`)
p.In()
p.GenerateField(file, message, field)
p.Out()
}
p.P(`}`)
} else {
var maxFieldNumber int32
oneofs := make(map[string]struct{})
for fieldIndex, field := range message.Field {
if field.GetNumber() > maxFieldNumber {
maxFieldNumber = field.GetNumber()
}
oneof := field.OneofIndex != nil
if !oneof {
if field.IsRequired() || (!gogoproto.IsNullable(field) && !field.IsRepeated()) || (proto3 && !field.IsMessage()) {
p.GenerateField(file, message, field)
} else {
if loopLevels[fieldIndex] > 0 {
p.P(`if r.Intn(5) == 0 {`)
} else {
p.P(`if r.Intn(5) != 0 {`)
}
p.In()
p.GenerateField(file, message, field)
p.Out()
p.P(`}`)
}
} else {
fieldname := p.GetFieldName(message, field)
if _, ok := oneofs[fieldname]; ok {
continue
} else {
oneofs[fieldname] = struct{}{}
}
fieldNumbers := []int32{}
for _, f := range message.Field {
fname := p.GetFieldName(message, f)
if fname == fieldname {
fieldNumbers = append(fieldNumbers, f.GetNumber())
}
}
p.P(`oneofNumber_`, fieldname, ` := `, fmt.Sprintf("%#v", fieldNumbers), `[r.Intn(`, strconv.Itoa(len(fieldNumbers)), `)]`)
p.P(`switch oneofNumber_`, fieldname, ` {`)
for _, f := range message.Field {
fname := p.GetFieldName(message, f)
if fname != fieldname {
continue
}
p.P(`case `, strconv.Itoa(int(f.GetNumber())), `:`)
p.In()
ccTypeName := p.OneOfTypeName(message, f)
p.P(`this.`, fname, ` = NewPopulated`, ccTypeName, `(r, easy)`)
p.Out()
}
p.P(`}`)
}
}
if message.DescriptorProto.HasExtension() {
p.P(`if !easy && r.Intn(10) != 0 {`)
p.In()
p.P(`l := r.Intn(5)`)
p.P(`for i := 0; i < l; i++ {`)
p.In()
if len(message.DescriptorProto.GetExtensionRange()) > 1 {
p.P(`eIndex := r.Intn(`, strconv.Itoa(len(message.DescriptorProto.GetExtensionRange())), `)`)
p.P(`fieldNumber := 0`)
p.P(`switch eIndex {`)
for i, e := range message.DescriptorProto.GetExtensionRange() {
p.P(`case `, strconv.Itoa(i), `:`)
p.In()
p.P(`fieldNumber = r.Intn(`, strconv.Itoa(int(e.GetEnd()-e.GetStart())), `) + `, strconv.Itoa(int(e.GetStart())))
p.Out()
if e.GetEnd() > maxFieldNumber {
maxFieldNumber = e.GetEnd()
}
}
p.P(`}`)
} else {
e := message.DescriptorProto.GetExtensionRange()[0]
p.P(`fieldNumber := r.Intn(`, strconv.Itoa(int(e.GetEnd()-e.GetStart())), `) + `, strconv.Itoa(int(e.GetStart())))
if e.GetEnd() > maxFieldNumber {
maxFieldNumber = e.GetEnd()
}
}
p.P(`wire := r.Intn(4)`)
p.P(`if wire == 3 { wire = 5 }`)
p.P(`dAtA := randField`, p.localName, `(nil, r, fieldNumber, wire)`)
p.P(protoPkg.Use(), `.SetRawExtension(this, int32(fieldNumber), dAtA)`)
p.Out()
p.P(`}`)
p.Out()
p.P(`}`)
}
if maxFieldNumber < (1 << 10) {
p.P(`if !easy && r.Intn(10) != 0 {`)
p.In()
if gogoproto.HasUnrecognized(file.FileDescriptorProto, message.DescriptorProto) {
p.P(`this.XXX_unrecognized = randUnrecognized`, p.localName, `(r, `, strconv.Itoa(int(maxFieldNumber+1)), `)`)
}
p.Out()
p.P(`}`)
}
}
p.P(`return this`)
p.Out()
p.P(`}`)
p.P(``)
//Generate NewPopulated functions for oneof fields
m := proto.Clone(message.DescriptorProto).(*descriptor.DescriptorProto)
for _, f := range m.Field {
oneof := f.OneofIndex != nil
if !oneof {
continue
}
ccTypeName := p.OneOfTypeName(message, f)
p.P(`func NewPopulated`, ccTypeName, `(r randy`, p.localName, `, easy bool) *`, ccTypeName, ` {`)
p.In()
p.P(`this := &`, ccTypeName, `{}`)
vanity.TurnOffNullableForNativeTypes(f)
p.GenerateField(file, message, f)
p.P(`return this`)
p.Out()
p.P(`}`)
}
}
if !p.atleastOne {
return
}
p.P(`type randy`, p.localName, ` interface {`)
p.In()
p.P(`Float32() float32`)
p.P(`Float64() float64`)
p.P(`Int63() int64`)
p.P(`Int31() int32`)
p.P(`Uint32() uint32`)
p.P(`Intn(n int) int`)
p.Out()
p.P(`}`)
p.P(`func randUTF8Rune`, p.localName, `(r randy`, p.localName, `) rune {`)
p.In()
p.P(`ru := r.Intn(62)`)
p.P(`if ru < 10 {`)
p.In()
p.P(`return rune(ru+48)`)
p.Out()
p.P(`} else if ru < 36 {`)
p.In()
p.P(`return rune(ru+55)`)
p.Out()
p.P(`}`)
p.P(`return rune(ru+61)`)
p.Out()
p.P(`}`)
p.P(`func randString`, p.localName, `(r randy`, p.localName, `) string {`)
p.In()
p.P(p.varGen.Next(), ` := r.Intn(100)`)
p.P(`tmps := make([]rune, `, p.varGen.Current(), `)`)
p.P(`for i := 0; i < `, p.varGen.Current(), `; i++ {`)
p.In()
p.P(`tmps[i] = randUTF8Rune`, p.localName, `(r)`)
p.Out()
p.P(`}`)
p.P(`return string(tmps)`)
p.Out()
p.P(`}`)
p.P(`func randUnrecognized`, p.localName, `(r randy`, p.localName, `, maxFieldNumber int) (dAtA []byte) {`)
p.In()
p.P(`l := r.Intn(5)`)
p.P(`for i := 0; i < l; i++ {`)
p.In()
p.P(`wire := r.Intn(4)`)
p.P(`if wire == 3 { wire = 5 }`)
p.P(`fieldNumber := maxFieldNumber + r.Intn(100)`)
p.P(`dAtA = randField`, p.localName, `(dAtA, r, fieldNumber, wire)`)
p.Out()
p.P(`}`)
p.P(`return dAtA`)
p.Out()
p.P(`}`)
p.P(`func randField`, p.localName, `(dAtA []byte, r randy`, p.localName, `, fieldNumber int, wire int) []byte {`)
p.In()
p.P(`key := uint32(fieldNumber)<<3 | uint32(wire)`)
p.P(`switch wire {`)
p.P(`case 0:`)
p.In()
p.P(`dAtA = encodeVarintPopulate`, p.localName, `(dAtA, uint64(key))`)
p.P(p.varGen.Next(), ` := r.Int63()`)
p.P(`if r.Intn(2) == 0 {`)
p.In()
p.P(p.varGen.Current(), ` *= -1`)
p.Out()
p.P(`}`)
p.P(`dAtA = encodeVarintPopulate`, p.localName, `(dAtA, uint64(`, p.varGen.Current(), `))`)
p.Out()
p.P(`case 1:`)
p.In()
p.P(`dAtA = encodeVarintPopulate`, p.localName, `(dAtA, uint64(key))`)
p.P(`dAtA = append(dAtA, byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)))`)
p.Out()
p.P(`case 2:`)
p.In()
p.P(`dAtA = encodeVarintPopulate`, p.localName, `(dAtA, uint64(key))`)
p.P(`ll := r.Intn(100)`)
p.P(`dAtA = encodeVarintPopulate`, p.localName, `(dAtA, uint64(ll))`)
p.P(`for j := 0; j < ll; j++ {`)
p.In()
p.P(`dAtA = append(dAtA, byte(r.Intn(256)))`)
p.Out()
p.P(`}`)
p.Out()
p.P(`default:`)
p.In()
p.P(`dAtA = encodeVarintPopulate`, p.localName, `(dAtA, uint64(key))`)
p.P(`dAtA = append(dAtA, byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)))`)
p.Out()
p.P(`}`)
p.P(`return dAtA`)
p.Out()
p.P(`}`)
p.P(`func encodeVarintPopulate`, p.localName, `(dAtA []byte, v uint64) []byte {`)
p.In()
p.P(`for v >= 1<<7 {`)
p.In()
p.P(`dAtA = append(dAtA, uint8(uint64(v)&0x7f|0x80))`)
p.P(`v >>= 7`)
p.Out()
p.P(`}`)
p.P(`dAtA = append(dAtA, uint8(v))`)
p.P(`return dAtA`)
p.Out()
p.P(`}`)
}
func init() {
generator.RegisterPlugin(NewPlugin())
}

696
vendor/github.com/gogo/protobuf/plugin/size/size.go generated vendored Normal file
View file

@ -0,0 +1,696 @@
// Protocol Buffers for Go with Gadgets
//
// Copyright (c) 2013, The GoGo Authors. All rights reserved.
// http://github.com/gogo/protobuf
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/*
The size plugin generates a Size or ProtoSize method for each message.
This is useful with the MarshalTo method generated by the marshalto plugin and the
gogoproto.marshaler and gogoproto.marshaler_all extensions.
It is enabled by the following extensions:
- sizer
- sizer_all
- protosizer
- protosizer_all
The size plugin also generates a test given it is enabled using one of the following extensions:
- testgen
- testgen_all
And a benchmark given it is enabled using one of the following extensions:
- benchgen
- benchgen_all
Let us look at:
github.com/gogo/protobuf/test/example/example.proto
Btw all the output can be seen at:
github.com/gogo/protobuf/test/example/*
The following message:
option (gogoproto.sizer_all) = true;
message B {
option (gogoproto.description) = true;
optional A A = 1 [(gogoproto.nullable) = false, (gogoproto.embed) = true];
repeated bytes G = 2 [(gogoproto.customtype) = "github.com/gogo/protobuf/test/custom.Uint128", (gogoproto.nullable) = false];
}
given to the size plugin, will generate the following code:
func (m *B) Size() (n int) {
if m == nil {
return 0
}
var l int
_ = l
l = m.A.Size()
n += 1 + l + sovExample(uint64(l))
if len(m.G) > 0 {
for _, e := range m.G {
l = e.Size()
n += 1 + l + sovExample(uint64(l))
}
}
if m.XXX_unrecognized != nil {
n += len(m.XXX_unrecognized)
}
return n
}
and the following test code:
func TestBSize(t *testing5.T) {
popr := math_rand5.New(math_rand5.NewSource(time5.Now().UnixNano()))
p := NewPopulatedB(popr, true)
dAtA, err := github_com_gogo_protobuf_proto2.Marshal(p)
if err != nil {
panic(err)
}
size := p.Size()
if len(dAtA) != size {
t.Fatalf("size %v != marshalled size %v", size, len(dAtA))
}
}
func BenchmarkBSize(b *testing5.B) {
popr := math_rand5.New(math_rand5.NewSource(616))
total := 0
pops := make([]*B, 1000)
for i := 0; i < 1000; i++ {
pops[i] = NewPopulatedB(popr, false)
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
total += pops[i%1000].Size()
}
b.SetBytes(int64(total / b.N))
}
The sovExample function is a size of varint function for the example.pb.go file.
*/
package size
import (
"fmt"
"os"
"strconv"
"strings"
"github.com/gogo/protobuf/gogoproto"
"github.com/gogo/protobuf/proto"
descriptor "github.com/gogo/protobuf/protoc-gen-gogo/descriptor"
"github.com/gogo/protobuf/protoc-gen-gogo/generator"
"github.com/gogo/protobuf/vanity"
)
type size struct {
*generator.Generator
generator.PluginImports
atleastOne bool
localName string
typesPkg generator.Single
bitsPkg generator.Single
}
func NewSize() *size {
return &size{}
}
func (p *size) Name() string {
return "size"
}
func (p *size) Init(g *generator.Generator) {
p.Generator = g
}
func wireToType(wire string) int {
switch wire {
case "fixed64":
return proto.WireFixed64
case "fixed32":
return proto.WireFixed32
case "varint":
return proto.WireVarint
case "bytes":
return proto.WireBytes
case "group":
return proto.WireBytes
case "zigzag32":
return proto.WireVarint
case "zigzag64":
return proto.WireVarint
}
panic("unreachable")
}
func keySize(fieldNumber int32, wireType int) int {
x := uint32(fieldNumber)<<3 | uint32(wireType)
size := 0
for size = 0; x > 127; size++ {
x >>= 7
}
size++
return size
}
func (p *size) sizeVarint() {
p.P(`
func sov`, p.localName, `(x uint64) (n int) {
return (`, p.bitsPkg.Use(), `.Len64(x | 1) + 6)/ 7
}`)
}
func (p *size) sizeZigZag() {
p.P(`func soz`, p.localName, `(x uint64) (n int) {
return sov`, p.localName, `(uint64((x << 1) ^ uint64((int64(x) >> 63))))
}`)
}
func (p *size) std(field *descriptor.FieldDescriptorProto, name string) (string, bool) {
ptr := ""
if gogoproto.IsNullable(field) {
ptr = "*"
}
if gogoproto.IsStdTime(field) {
return p.typesPkg.Use() + `.SizeOfStdTime(` + ptr + name + `)`, true
} else if gogoproto.IsStdDuration(field) {
return p.typesPkg.Use() + `.SizeOfStdDuration(` + ptr + name + `)`, true
} else if gogoproto.IsStdDouble(field) {
return p.typesPkg.Use() + `.SizeOfStdDouble(` + ptr + name + `)`, true
} else if gogoproto.IsStdFloat(field) {
return p.typesPkg.Use() + `.SizeOfStdFloat(` + ptr + name + `)`, true
} else if gogoproto.IsStdInt64(field) {
return p.typesPkg.Use() + `.SizeOfStdInt64(` + ptr + name + `)`, true
} else if gogoproto.IsStdUInt64(field) {
return p.typesPkg.Use() + `.SizeOfStdUInt64(` + ptr + name + `)`, true
} else if gogoproto.IsStdInt32(field) {
return p.typesPkg.Use() + `.SizeOfStdInt32(` + ptr + name + `)`, true
} else if gogoproto.IsStdUInt32(field) {
return p.typesPkg.Use() + `.SizeOfStdUInt32(` + ptr + name + `)`, true
} else if gogoproto.IsStdBool(field) {
return p.typesPkg.Use() + `.SizeOfStdBool(` + ptr + name + `)`, true
} else if gogoproto.IsStdString(field) {
return p.typesPkg.Use() + `.SizeOfStdString(` + ptr + name + `)`, true
} else if gogoproto.IsStdBytes(field) {
return p.typesPkg.Use() + `.SizeOfStdBytes(` + ptr + name + `)`, true
}
return "", false
}
func (p *size) generateField(proto3 bool, file *generator.FileDescriptor, message *generator.Descriptor, field *descriptor.FieldDescriptorProto, sizeName string) {
fieldname := p.GetOneOfFieldName(message, field)
nullable := gogoproto.IsNullable(field)
repeated := field.IsRepeated()
doNilCheck := gogoproto.NeedsNilCheck(proto3, field)
if repeated {
p.P(`if len(m.`, fieldname, `) > 0 {`)
p.In()
} else if doNilCheck {
p.P(`if m.`, fieldname, ` != nil {`)
p.In()
}
packed := field.IsPacked() || (proto3 && field.IsPacked3())
_, wire := p.GoType(message, field)
wireType := wireToType(wire)
fieldNumber := field.GetNumber()
if packed {
wireType = proto.WireBytes
}
key := keySize(fieldNumber, wireType)
switch *field.Type {
case descriptor.FieldDescriptorProto_TYPE_DOUBLE,
descriptor.FieldDescriptorProto_TYPE_FIXED64,
descriptor.FieldDescriptorProto_TYPE_SFIXED64:
if packed {
p.P(`n+=`, strconv.Itoa(key), `+sov`, p.localName, `(uint64(len(m.`, fieldname, `)*8))`, `+len(m.`, fieldname, `)*8`)
} else if repeated {
p.P(`n+=`, strconv.Itoa(key+8), `*len(m.`, fieldname, `)`)
} else if proto3 {
p.P(`if m.`, fieldname, ` != 0 {`)
p.In()
p.P(`n+=`, strconv.Itoa(key+8))
p.Out()
p.P(`}`)
} else if nullable {
p.P(`n+=`, strconv.Itoa(key+8))
} else {
p.P(`n+=`, strconv.Itoa(key+8))
}
case descriptor.FieldDescriptorProto_TYPE_FLOAT,
descriptor.FieldDescriptorProto_TYPE_FIXED32,
descriptor.FieldDescriptorProto_TYPE_SFIXED32:
if packed {
p.P(`n+=`, strconv.Itoa(key), `+sov`, p.localName, `(uint64(len(m.`, fieldname, `)*4))`, `+len(m.`, fieldname, `)*4`)
} else if repeated {
p.P(`n+=`, strconv.Itoa(key+4), `*len(m.`, fieldname, `)`)
} else if proto3 {
p.P(`if m.`, fieldname, ` != 0 {`)
p.In()
p.P(`n+=`, strconv.Itoa(key+4))
p.Out()
p.P(`}`)
} else if nullable {
p.P(`n+=`, strconv.Itoa(key+4))
} else {
p.P(`n+=`, strconv.Itoa(key+4))
}
case descriptor.FieldDescriptorProto_TYPE_INT64,
descriptor.FieldDescriptorProto_TYPE_UINT64,
descriptor.FieldDescriptorProto_TYPE_UINT32,
descriptor.FieldDescriptorProto_TYPE_ENUM,
descriptor.FieldDescriptorProto_TYPE_INT32:
if packed {
p.P(`l = 0`)
p.P(`for _, e := range m.`, fieldname, ` {`)
p.In()
p.P(`l+=sov`, p.localName, `(uint64(e))`)
p.Out()
p.P(`}`)
p.P(`n+=`, strconv.Itoa(key), `+sov`, p.localName, `(uint64(l))+l`)
} else if repeated {
p.P(`for _, e := range m.`, fieldname, ` {`)
p.In()
p.P(`n+=`, strconv.Itoa(key), `+sov`, p.localName, `(uint64(e))`)
p.Out()
p.P(`}`)
} else if proto3 {
p.P(`if m.`, fieldname, ` != 0 {`)
p.In()
p.P(`n+=`, strconv.Itoa(key), `+sov`, p.localName, `(uint64(m.`, fieldname, `))`)
p.Out()
p.P(`}`)
} else if nullable {
p.P(`n+=`, strconv.Itoa(key), `+sov`, p.localName, `(uint64(*m.`, fieldname, `))`)
} else {
p.P(`n+=`, strconv.Itoa(key), `+sov`, p.localName, `(uint64(m.`, fieldname, `))`)
}
case descriptor.FieldDescriptorProto_TYPE_BOOL:
if packed {
p.P(`n+=`, strconv.Itoa(key), `+sov`, p.localName, `(uint64(len(m.`, fieldname, `)))`, `+len(m.`, fieldname, `)*1`)
} else if repeated {
p.P(`n+=`, strconv.Itoa(key+1), `*len(m.`, fieldname, `)`)
} else if proto3 {
p.P(`if m.`, fieldname, ` {`)
p.In()
p.P(`n+=`, strconv.Itoa(key+1))
p.Out()
p.P(`}`)
} else if nullable {
p.P(`n+=`, strconv.Itoa(key+1))
} else {
p.P(`n+=`, strconv.Itoa(key+1))
}
case descriptor.FieldDescriptorProto_TYPE_STRING:
if repeated {
p.P(`for _, s := range m.`, fieldname, ` { `)
p.In()
p.P(`l = len(s)`)
p.P(`n+=`, strconv.Itoa(key), `+l+sov`, p.localName, `(uint64(l))`)
p.Out()
p.P(`}`)
} else if proto3 {
p.P(`l=len(m.`, fieldname, `)`)
p.P(`if l > 0 {`)
p.In()
p.P(`n+=`, strconv.Itoa(key), `+l+sov`, p.localName, `(uint64(l))`)
p.Out()
p.P(`}`)
} else if nullable {
p.P(`l=len(*m.`, fieldname, `)`)
p.P(`n+=`, strconv.Itoa(key), `+l+sov`, p.localName, `(uint64(l))`)
} else {
p.P(`l=len(m.`, fieldname, `)`)
p.P(`n+=`, strconv.Itoa(key), `+l+sov`, p.localName, `(uint64(l))`)
}
case descriptor.FieldDescriptorProto_TYPE_GROUP:
panic(fmt.Errorf("size does not support group %v", fieldname))
case descriptor.FieldDescriptorProto_TYPE_MESSAGE:
if p.IsMap(field) {
m := p.GoMapType(nil, field)
_, keywire := p.GoType(nil, m.KeyAliasField)
valuegoTyp, _ := p.GoType(nil, m.ValueField)
valuegoAliasTyp, valuewire := p.GoType(nil, m.ValueAliasField)
_, fieldwire := p.GoType(nil, field)
nullable, valuegoTyp, valuegoAliasTyp = generator.GoMapValueTypes(field, m.ValueField, valuegoTyp, valuegoAliasTyp)
fieldKeySize := keySize(field.GetNumber(), wireToType(fieldwire))
keyKeySize := keySize(1, wireToType(keywire))
valueKeySize := keySize(2, wireToType(valuewire))
p.P(`for k, v := range m.`, fieldname, ` { `)
p.In()
p.P(`_ = k`)
p.P(`_ = v`)
sum := []string{strconv.Itoa(keyKeySize)}
switch m.KeyField.GetType() {
case descriptor.FieldDescriptorProto_TYPE_DOUBLE,
descriptor.FieldDescriptorProto_TYPE_FIXED64,
descriptor.FieldDescriptorProto_TYPE_SFIXED64:
sum = append(sum, `8`)
case descriptor.FieldDescriptorProto_TYPE_FLOAT,
descriptor.FieldDescriptorProto_TYPE_FIXED32,
descriptor.FieldDescriptorProto_TYPE_SFIXED32:
sum = append(sum, `4`)
case descriptor.FieldDescriptorProto_TYPE_INT64,
descriptor.FieldDescriptorProto_TYPE_UINT64,
descriptor.FieldDescriptorProto_TYPE_UINT32,
descriptor.FieldDescriptorProto_TYPE_ENUM,
descriptor.FieldDescriptorProto_TYPE_INT32:
sum = append(sum, `sov`+p.localName+`(uint64(k))`)
case descriptor.FieldDescriptorProto_TYPE_BOOL:
sum = append(sum, `1`)
case descriptor.FieldDescriptorProto_TYPE_STRING,
descriptor.FieldDescriptorProto_TYPE_BYTES:
sum = append(sum, `len(k)+sov`+p.localName+`(uint64(len(k)))`)
case descriptor.FieldDescriptorProto_TYPE_SINT32,
descriptor.FieldDescriptorProto_TYPE_SINT64:
sum = append(sum, `soz`+p.localName+`(uint64(k))`)
}
switch m.ValueField.GetType() {
case descriptor.FieldDescriptorProto_TYPE_DOUBLE,
descriptor.FieldDescriptorProto_TYPE_FIXED64,
descriptor.FieldDescriptorProto_TYPE_SFIXED64:
sum = append(sum, strconv.Itoa(valueKeySize))
sum = append(sum, strconv.Itoa(8))
case descriptor.FieldDescriptorProto_TYPE_FLOAT,
descriptor.FieldDescriptorProto_TYPE_FIXED32,
descriptor.FieldDescriptorProto_TYPE_SFIXED32:
sum = append(sum, strconv.Itoa(valueKeySize))
sum = append(sum, strconv.Itoa(4))
case descriptor.FieldDescriptorProto_TYPE_INT64,
descriptor.FieldDescriptorProto_TYPE_UINT64,
descriptor.FieldDescriptorProto_TYPE_UINT32,
descriptor.FieldDescriptorProto_TYPE_ENUM,
descriptor.FieldDescriptorProto_TYPE_INT32:
sum = append(sum, strconv.Itoa(valueKeySize))
sum = append(sum, `sov`+p.localName+`(uint64(v))`)
case descriptor.FieldDescriptorProto_TYPE_BOOL:
sum = append(sum, strconv.Itoa(valueKeySize))
sum = append(sum, `1`)
case descriptor.FieldDescriptorProto_TYPE_STRING:
sum = append(sum, strconv.Itoa(valueKeySize))
sum = append(sum, `len(v)+sov`+p.localName+`(uint64(len(v)))`)
case descriptor.FieldDescriptorProto_TYPE_BYTES:
if gogoproto.IsCustomType(field) {
p.P(`l = 0`)
if nullable {
p.P(`if v != nil {`)
p.In()
}
p.P(`l = v.`, sizeName, `()`)
p.P(`l += `, strconv.Itoa(valueKeySize), ` + sov`+p.localName+`(uint64(l))`)
if nullable {
p.Out()
p.P(`}`)
}
sum = append(sum, `l`)
} else {
p.P(`l = 0`)
if proto3 {
p.P(`if len(v) > 0 {`)
} else {
p.P(`if v != nil {`)
}
p.In()
p.P(`l = `, strconv.Itoa(valueKeySize), ` + len(v)+sov`+p.localName+`(uint64(len(v)))`)
p.Out()
p.P(`}`)
sum = append(sum, `l`)
}
case descriptor.FieldDescriptorProto_TYPE_SINT32,
descriptor.FieldDescriptorProto_TYPE_SINT64:
sum = append(sum, strconv.Itoa(valueKeySize))
sum = append(sum, `soz`+p.localName+`(uint64(v))`)
case descriptor.FieldDescriptorProto_TYPE_MESSAGE:
stdSizeCall, stdOk := p.std(m.ValueAliasField, "v")
if nullable {
p.P(`l = 0`)
p.P(`if v != nil {`)
p.In()
if stdOk {
p.P(`l = `, stdSizeCall)
} else if valuegoTyp != valuegoAliasTyp {
p.P(`l = ((`, valuegoTyp, `)(v)).`, sizeName, `()`)
} else {
p.P(`l = v.`, sizeName, `()`)
}
p.P(`l += `, strconv.Itoa(valueKeySize), ` + sov`+p.localName+`(uint64(l))`)
p.Out()
p.P(`}`)
sum = append(sum, `l`)
} else {
if stdOk {
p.P(`l = `, stdSizeCall)
} else if valuegoTyp != valuegoAliasTyp {
p.P(`l = ((*`, valuegoTyp, `)(&v)).`, sizeName, `()`)
} else {
p.P(`l = v.`, sizeName, `()`)
}
sum = append(sum, strconv.Itoa(valueKeySize))
sum = append(sum, `l+sov`+p.localName+`(uint64(l))`)
}
}
p.P(`mapEntrySize := `, strings.Join(sum, "+"))
p.P(`n+=mapEntrySize+`, fieldKeySize, `+sov`, p.localName, `(uint64(mapEntrySize))`)
p.Out()
p.P(`}`)
} else if repeated {
p.P(`for _, e := range m.`, fieldname, ` { `)
p.In()
stdSizeCall, stdOk := p.std(field, "e")
if stdOk {
p.P(`l=`, stdSizeCall)
} else {
p.P(`l=e.`, sizeName, `()`)
}
p.P(`n+=`, strconv.Itoa(key), `+l+sov`, p.localName, `(uint64(l))`)
p.Out()
p.P(`}`)
} else {
stdSizeCall, stdOk := p.std(field, "m."+fieldname)
if stdOk {
p.P(`l=`, stdSizeCall)
} else {
p.P(`l=m.`, fieldname, `.`, sizeName, `()`)
}
p.P(`n+=`, strconv.Itoa(key), `+l+sov`, p.localName, `(uint64(l))`)
}
case descriptor.FieldDescriptorProto_TYPE_BYTES:
if !gogoproto.IsCustomType(field) {
if repeated {
p.P(`for _, b := range m.`, fieldname, ` { `)
p.In()
p.P(`l = len(b)`)
p.P(`n+=`, strconv.Itoa(key), `+l+sov`, p.localName, `(uint64(l))`)
p.Out()
p.P(`}`)
} else if proto3 {
p.P(`l=len(m.`, fieldname, `)`)
p.P(`if l > 0 {`)
p.In()
p.P(`n+=`, strconv.Itoa(key), `+l+sov`, p.localName, `(uint64(l))`)
p.Out()
p.P(`}`)
} else {
p.P(`l=len(m.`, fieldname, `)`)
p.P(`n+=`, strconv.Itoa(key), `+l+sov`, p.localName, `(uint64(l))`)
}
} else {
if repeated {
p.P(`for _, e := range m.`, fieldname, ` { `)
p.In()
p.P(`l=e.`, sizeName, `()`)
p.P(`n+=`, strconv.Itoa(key), `+l+sov`, p.localName, `(uint64(l))`)
p.Out()
p.P(`}`)
} else {
p.P(`l=m.`, fieldname, `.`, sizeName, `()`)
p.P(`n+=`, strconv.Itoa(key), `+l+sov`, p.localName, `(uint64(l))`)
}
}
case descriptor.FieldDescriptorProto_TYPE_SINT32,
descriptor.FieldDescriptorProto_TYPE_SINT64:
if packed {
p.P(`l = 0`)
p.P(`for _, e := range m.`, fieldname, ` {`)
p.In()
p.P(`l+=soz`, p.localName, `(uint64(e))`)
p.Out()
p.P(`}`)
p.P(`n+=`, strconv.Itoa(key), `+sov`, p.localName, `(uint64(l))+l`)
} else if repeated {
p.P(`for _, e := range m.`, fieldname, ` {`)
p.In()
p.P(`n+=`, strconv.Itoa(key), `+soz`, p.localName, `(uint64(e))`)
p.Out()
p.P(`}`)
} else if proto3 {
p.P(`if m.`, fieldname, ` != 0 {`)
p.In()
p.P(`n+=`, strconv.Itoa(key), `+soz`, p.localName, `(uint64(m.`, fieldname, `))`)
p.Out()
p.P(`}`)
} else if nullable {
p.P(`n+=`, strconv.Itoa(key), `+soz`, p.localName, `(uint64(*m.`, fieldname, `))`)
} else {
p.P(`n+=`, strconv.Itoa(key), `+soz`, p.localName, `(uint64(m.`, fieldname, `))`)
}
default:
panic("not implemented")
}
if repeated || doNilCheck {
p.Out()
p.P(`}`)
}
}
func (p *size) Generate(file *generator.FileDescriptor) {
p.PluginImports = generator.NewPluginImports(p.Generator)
p.atleastOne = false
p.localName = generator.FileName(file)
p.typesPkg = p.NewImport("github.com/gogo/protobuf/types")
protoPkg := p.NewImport("github.com/gogo/protobuf/proto")
p.bitsPkg = p.NewImport("math/bits")
if !gogoproto.ImportsGoGoProto(file.FileDescriptorProto) {
protoPkg = p.NewImport("github.com/golang/protobuf/proto")
}
for _, message := range file.Messages() {
sizeName := ""
if gogoproto.IsSizer(file.FileDescriptorProto, message.DescriptorProto) && gogoproto.IsProtoSizer(file.FileDescriptorProto, message.DescriptorProto) {
fmt.Fprintf(os.Stderr, "ERROR: message %v cannot support both sizer and protosizer plugins\n", generator.CamelCase(*message.Name))
os.Exit(1)
}
if gogoproto.IsSizer(file.FileDescriptorProto, message.DescriptorProto) {
sizeName = "Size"
} else if gogoproto.IsProtoSizer(file.FileDescriptorProto, message.DescriptorProto) {
sizeName = "ProtoSize"
} else {
continue
}
if message.DescriptorProto.GetOptions().GetMapEntry() {
continue
}
p.atleastOne = true
ccTypeName := generator.CamelCaseSlice(message.TypeName())
p.P(`func (m *`, ccTypeName, `) `, sizeName, `() (n int) {`)
p.In()
p.P(`if m == nil {`)
p.In()
p.P(`return 0`)
p.Out()
p.P(`}`)
p.P(`var l int`)
p.P(`_ = l`)
oneofs := make(map[string]struct{})
for _, field := range message.Field {
oneof := field.OneofIndex != nil
if !oneof {
proto3 := gogoproto.IsProto3(file.FileDescriptorProto)
p.generateField(proto3, file, message, field, sizeName)
} else {
fieldname := p.GetFieldName(message, field)
if _, ok := oneofs[fieldname]; ok {
continue
} else {
oneofs[fieldname] = struct{}{}
}
p.P(`if m.`, fieldname, ` != nil {`)
p.In()
p.P(`n+=m.`, fieldname, `.`, sizeName, `()`)
p.Out()
p.P(`}`)
}
}
if message.DescriptorProto.HasExtension() {
if gogoproto.HasExtensionsMap(file.FileDescriptorProto, message.DescriptorProto) {
p.P(`n += `, protoPkg.Use(), `.SizeOfInternalExtension(m)`)
} else {
p.P(`if m.XXX_extensions != nil {`)
p.In()
p.P(`n+=len(m.XXX_extensions)`)
p.Out()
p.P(`}`)
}
}
if gogoproto.HasUnrecognized(file.FileDescriptorProto, message.DescriptorProto) {
p.P(`if m.XXX_unrecognized != nil {`)
p.In()
p.P(`n+=len(m.XXX_unrecognized)`)
p.Out()
p.P(`}`)
}
p.P(`return n`)
p.Out()
p.P(`}`)
p.P()
//Generate Size methods for oneof fields
m := proto.Clone(message.DescriptorProto).(*descriptor.DescriptorProto)
for _, f := range m.Field {
oneof := f.OneofIndex != nil
if !oneof {
continue
}
ccTypeName := p.OneOfTypeName(message, f)
p.P(`func (m *`, ccTypeName, `) `, sizeName, `() (n int) {`)
p.In()
p.P(`if m == nil {`)
p.In()
p.P(`return 0`)
p.Out()
p.P(`}`)
p.P(`var l int`)
p.P(`_ = l`)
vanity.TurnOffNullableForNativeTypes(f)
p.generateField(false, file, message, f, sizeName)
p.P(`return n`)
p.Out()
p.P(`}`)
}
}
if !p.atleastOne {
return
}
p.sizeVarint()
p.sizeZigZag()
}
func init() {
generator.RegisterPlugin(NewSize())
}

134
vendor/github.com/gogo/protobuf/plugin/size/sizetest.go generated vendored Normal file
View file

@ -0,0 +1,134 @@
// Protocol Buffers for Go with Gadgets
//
// Copyright (c) 2013, The GoGo Authors. All rights reserved.
// http://github.com/gogo/protobuf
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package size
import (
"github.com/gogo/protobuf/gogoproto"
"github.com/gogo/protobuf/plugin/testgen"
"github.com/gogo/protobuf/protoc-gen-gogo/generator"
)
type test struct {
*generator.Generator
}
func NewTest(g *generator.Generator) testgen.TestPlugin {
return &test{g}
}
func (p *test) Generate(imports generator.PluginImports, file *generator.FileDescriptor) bool {
used := false
randPkg := imports.NewImport("math/rand")
timePkg := imports.NewImport("time")
testingPkg := imports.NewImport("testing")
protoPkg := imports.NewImport("github.com/gogo/protobuf/proto")
if !gogoproto.ImportsGoGoProto(file.FileDescriptorProto) {
protoPkg = imports.NewImport("github.com/golang/protobuf/proto")
}
for _, message := range file.Messages() {
ccTypeName := generator.CamelCaseSlice(message.TypeName())
sizeName := ""
if gogoproto.IsSizer(file.FileDescriptorProto, message.DescriptorProto) {
sizeName = "Size"
} else if gogoproto.IsProtoSizer(file.FileDescriptorProto, message.DescriptorProto) {
sizeName = "ProtoSize"
} else {
continue
}
if message.DescriptorProto.GetOptions().GetMapEntry() {
continue
}
if gogoproto.HasTestGen(file.FileDescriptorProto, message.DescriptorProto) {
used = true
p.P(`func Test`, ccTypeName, sizeName, `(t *`, testingPkg.Use(), `.T) {`)
p.In()
p.P(`seed := `, timePkg.Use(), `.Now().UnixNano()`)
p.P(`popr := `, randPkg.Use(), `.New(`, randPkg.Use(), `.NewSource(seed))`)
p.P(`p := NewPopulated`, ccTypeName, `(popr, true)`)
p.P(`size2 := `, protoPkg.Use(), `.Size(p)`)
p.P(`dAtA, err := `, protoPkg.Use(), `.Marshal(p)`)
p.P(`if err != nil {`)
p.In()
p.P(`t.Fatalf("seed = %d, err = %v", seed, err)`)
p.Out()
p.P(`}`)
p.P(`size := p.`, sizeName, `()`)
p.P(`if len(dAtA) != size {`)
p.In()
p.P(`t.Errorf("seed = %d, size %v != marshalled size %v", seed, size, len(dAtA))`)
p.Out()
p.P(`}`)
p.P(`if size2 != size {`)
p.In()
p.P(`t.Errorf("seed = %d, size %v != before marshal proto.Size %v", seed, size, size2)`)
p.Out()
p.P(`}`)
p.P(`size3 := `, protoPkg.Use(), `.Size(p)`)
p.P(`if size3 != size {`)
p.In()
p.P(`t.Errorf("seed = %d, size %v != after marshal proto.Size %v", seed, size, size3)`)
p.Out()
p.P(`}`)
p.Out()
p.P(`}`)
p.P()
}
if gogoproto.HasBenchGen(file.FileDescriptorProto, message.DescriptorProto) {
used = true
p.P(`func Benchmark`, ccTypeName, sizeName, `(b *`, testingPkg.Use(), `.B) {`)
p.In()
p.P(`popr := `, randPkg.Use(), `.New(`, randPkg.Use(), `.NewSource(616))`)
p.P(`total := 0`)
p.P(`pops := make([]*`, ccTypeName, `, 1000)`)
p.P(`for i := 0; i < 1000; i++ {`)
p.In()
p.P(`pops[i] = NewPopulated`, ccTypeName, `(popr, false)`)
p.Out()
p.P(`}`)
p.P(`b.ResetTimer()`)
p.P(`for i := 0; i < b.N; i++ {`)
p.In()
p.P(`total += pops[i%1000].`, sizeName, `()`)
p.Out()
p.P(`}`)
p.P(`b.SetBytes(int64(total / b.N))`)
p.Out()
p.P(`}`)
p.P()
}
}
return used
}
func init() {
testgen.RegisterTestPlugin(NewTest)
}

View file

@ -0,0 +1,347 @@
// Protocol Buffers for Go with Gadgets
//
// Copyright (c) 2013, The GoGo Authors. All rights reserved.
// http://github.com/gogo/protobuf
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/*
The stringer plugin generates a String method for each message.
It is enabled by the following extensions:
- stringer
- stringer_all
The stringer plugin also generates a test given it is enabled using one of the following extensions:
- testgen
- testgen_all
Let us look at:
github.com/gogo/protobuf/test/example/example.proto
Btw all the output can be seen at:
github.com/gogo/protobuf/test/example/*
The following message:
option (gogoproto.goproto_stringer_all) = false;
option (gogoproto.stringer_all) = true;
message A {
optional string Description = 1 [(gogoproto.nullable) = false];
optional int64 Number = 2 [(gogoproto.nullable) = false];
optional bytes Id = 3 [(gogoproto.customtype) = "github.com/gogo/protobuf/test/custom.Uuid", (gogoproto.nullable) = false];
}
given to the stringer stringer, will generate the following code:
func (this *A) String() string {
if this == nil {
return "nil"
}
s := strings.Join([]string{`&A{`,
`Description:` + fmt.Sprintf("%v", this.Description) + `,`,
`Number:` + fmt.Sprintf("%v", this.Number) + `,`,
`Id:` + fmt.Sprintf("%v", this.Id) + `,`,
`XXX_unrecognized:` + fmt.Sprintf("%v", this.XXX_unrecognized) + `,`,
`}`,
}, "")
return s
}
and the following test code:
func TestAStringer(t *testing4.T) {
popr := math_rand4.New(math_rand4.NewSource(time4.Now().UnixNano()))
p := NewPopulatedA(popr, false)
s1 := p.String()
s2 := fmt1.Sprintf("%v", p)
if s1 != s2 {
t.Fatalf("String want %v got %v", s1, s2)
}
}
Typically fmt.Printf("%v") will stop to print when it reaches a pointer and
not print their values, while the generated String method will always print all values, recursively.
*/
package stringer
import (
"github.com/gogo/protobuf/gogoproto"
"github.com/gogo/protobuf/protoc-gen-gogo/generator"
"strings"
)
type stringer struct {
*generator.Generator
generator.PluginImports
atleastOne bool
localName string
}
func NewStringer() *stringer {
return &stringer{}
}
func (p *stringer) Name() string {
return "stringer"
}
func (p *stringer) Init(g *generator.Generator) {
p.Generator = g
}
func (p *stringer) Generate(file *generator.FileDescriptor) {
proto3 := gogoproto.IsProto3(file.FileDescriptorProto)
p.PluginImports = generator.NewPluginImports(p.Generator)
p.atleastOne = false
p.localName = generator.FileName(file)
fmtPkg := p.NewImport("fmt")
stringsPkg := p.NewImport("strings")
reflectPkg := p.NewImport("reflect")
sortKeysPkg := p.NewImport("github.com/gogo/protobuf/sortkeys")
protoPkg := p.NewImport("github.com/gogo/protobuf/proto")
for _, message := range file.Messages() {
if !gogoproto.IsStringer(file.FileDescriptorProto, message.DescriptorProto) {
continue
}
if gogoproto.EnabledGoStringer(file.FileDescriptorProto, message.DescriptorProto) {
panic("old string method needs to be disabled, please use gogoproto.goproto_stringer or gogoproto.goproto_stringer_all and set it to false")
}
if message.DescriptorProto.GetOptions().GetMapEntry() {
continue
}
p.atleastOne = true
ccTypeName := generator.CamelCaseSlice(message.TypeName())
p.P(`func (this *`, ccTypeName, `) String() string {`)
p.In()
p.P(`if this == nil {`)
p.In()
p.P(`return "nil"`)
p.Out()
p.P(`}`)
for _, field := range message.Field {
if p.IsMap(field) || !field.IsRepeated() {
continue
}
if (field.IsMessage() && !gogoproto.IsCustomType(field)) || p.IsGroup(field) {
nullable := gogoproto.IsNullable(field)
desc := p.ObjectNamed(field.GetTypeName())
msgname := p.TypeName(desc)
msgnames := strings.Split(msgname, ".")
typeName := msgnames[len(msgnames)-1]
fieldMessageDesc := file.GetMessage(msgname)
gogoStringer := false
if fieldMessageDesc != nil {
gogoStringer = gogoproto.IsStringer(file.FileDescriptorProto, fieldMessageDesc)
}
fieldname := p.GetFieldName(message, field)
stringfunc := fmtPkg.Use() + `.Sprintf("%v", f)`
if gogoStringer {
stringfunc = `f.String()`
}
repeatedName := `repeatedStringFor` + fieldname
if nullable {
p.P(repeatedName, ` := "[]*`, typeName, `{"`)
} else {
p.P(repeatedName, ` := "[]`, typeName, `{"`)
}
p.P(`for _, f := range `, `this.`, fieldname, ` {`)
p.In()
if nullable {
p.P(repeatedName, " += ", stringsPkg.Use(), `.Replace(`, stringfunc, `, "`, typeName, `","`, msgname, `"`, ", 1)", ` + ","`)
} else if gogoStringer {
p.P(repeatedName, " += ", stringsPkg.Use(), `.Replace(`, stringsPkg.Use(), `.Replace(`, stringfunc, `, "`, typeName, `","`, msgname, `"`, ", 1),`&`,``,1)", ` + ","`)
} else {
p.P(repeatedName, " += ", stringfunc, ` + ","`)
}
p.Out()
p.P(`}`)
p.P(repeatedName, ` += "}"`)
}
}
for _, field := range message.Field {
if !p.IsMap(field) {
continue
}
fieldname := p.GetFieldName(message, field)
m := p.GoMapType(nil, field)
mapgoTyp, keyField, keyAliasField := m.GoType, m.KeyField, m.KeyAliasField
keysName := `keysFor` + fieldname
keygoTyp, _ := p.GoType(nil, keyField)
keygoTyp = strings.Replace(keygoTyp, "*", "", 1)
keygoAliasTyp, _ := p.GoType(nil, keyAliasField)
keygoAliasTyp = strings.Replace(keygoAliasTyp, "*", "", 1)
keyCapTyp := generator.CamelCase(keygoTyp)
p.P(keysName, ` := make([]`, keygoTyp, `, 0, len(this.`, fieldname, `))`)
p.P(`for k, _ := range this.`, fieldname, ` {`)
p.In()
if keygoAliasTyp == keygoTyp {
p.P(keysName, ` = append(`, keysName, `, k)`)
} else {
p.P(keysName, ` = append(`, keysName, `, `, keygoTyp, `(k))`)
}
p.Out()
p.P(`}`)
p.P(sortKeysPkg.Use(), `.`, keyCapTyp, `s(`, keysName, `)`)
mapName := `mapStringFor` + fieldname
p.P(mapName, ` := "`, mapgoTyp, `{"`)
p.P(`for _, k := range `, keysName, ` {`)
p.In()
if keygoAliasTyp == keygoTyp {
p.P(mapName, ` += fmt.Sprintf("%v: %v,", k, this.`, fieldname, `[k])`)
} else {
p.P(mapName, ` += fmt.Sprintf("%v: %v,", k, this.`, fieldname, `[`, keygoAliasTyp, `(k)])`)
}
p.Out()
p.P(`}`)
p.P(mapName, ` += "}"`)
}
p.P("s := ", stringsPkg.Use(), ".Join([]string{`&", ccTypeName, "{`,")
oneofs := make(map[string]struct{})
for _, field := range message.Field {
nullable := gogoproto.IsNullable(field)
repeated := field.IsRepeated()
fieldname := p.GetFieldName(message, field)
oneof := field.OneofIndex != nil
if oneof {
if _, ok := oneofs[fieldname]; ok {
continue
} else {
oneofs[fieldname] = struct{}{}
}
p.P("`", fieldname, ":`", ` + `, fmtPkg.Use(), `.Sprintf("%v", this.`, fieldname, ") + `,", "`,")
} else if p.IsMap(field) {
mapName := `mapStringFor` + fieldname
p.P("`", fieldname, ":`", ` + `, mapName, " + `,", "`,")
} else if (field.IsMessage() && !gogoproto.IsCustomType(field)) || p.IsGroup(field) {
desc := p.ObjectNamed(field.GetTypeName())
msgname := p.TypeName(desc)
msgnames := strings.Split(msgname, ".")
typeName := msgnames[len(msgnames)-1]
fieldMessageDesc := file.GetMessage(msgname)
gogoStringer := false
if fieldMessageDesc != nil {
gogoStringer = gogoproto.IsStringer(file.FileDescriptorProto, fieldMessageDesc)
}
stringfunc := fmtPkg.Use() + `.Sprintf("%v", this.` + fieldname + `)`
if gogoStringer {
stringfunc = `this.` + fieldname + `.String()`
}
if nullable && !repeated {
p.P("`", fieldname, ":`", ` + `, stringsPkg.Use(), `.Replace(`, stringfunc, `, "`, typeName, `","`, msgname, `"`, ", 1) + `,", "`,")
} else if repeated {
repeatedName := `repeatedStringFor` + fieldname
p.P("`", fieldname, ":`", ` + `, repeatedName, " + `,", "`,")
} else {
p.P("`", fieldname, ":`", ` + `, stringsPkg.Use(), `.Replace(`, stringsPkg.Use(), `.Replace(`, stringfunc, `, "`, typeName, `","`, msgname, `"`, ", 1),`&`,``,1) + `,", "`,")
}
} else {
if nullable && !repeated && !proto3 {
p.P("`", fieldname, ":`", ` + valueToString`, p.localName, `(this.`, fieldname, ") + `,", "`,")
} else {
p.P("`", fieldname, ":`", ` + `, fmtPkg.Use(), `.Sprintf("%v", this.`, fieldname, ") + `,", "`,")
}
}
}
if message.DescriptorProto.HasExtension() {
if gogoproto.HasExtensionsMap(file.FileDescriptorProto, message.DescriptorProto) {
p.P("`XXX_InternalExtensions:` + ", protoPkg.Use(), ".StringFromInternalExtension(this) + `,`,")
} else {
p.P("`XXX_extensions:` + ", protoPkg.Use(), ".StringFromExtensionsBytes(this.XXX_extensions) + `,`,")
}
}
if gogoproto.HasUnrecognized(file.FileDescriptorProto, message.DescriptorProto) {
p.P("`XXX_unrecognized:` + ", fmtPkg.Use(), `.Sprintf("%v", this.XXX_unrecognized) + `, "`,`,")
}
p.P("`}`,")
p.P(`}`, `,""`, ")")
p.P(`return s`)
p.Out()
p.P(`}`)
//Generate String methods for oneof fields
for _, field := range message.Field {
oneof := field.OneofIndex != nil
if !oneof {
continue
}
ccTypeName := p.OneOfTypeName(message, field)
p.P(`func (this *`, ccTypeName, `) String() string {`)
p.In()
p.P(`if this == nil {`)
p.In()
p.P(`return "nil"`)
p.Out()
p.P(`}`)
p.P("s := ", stringsPkg.Use(), ".Join([]string{`&", ccTypeName, "{`,")
fieldname := p.GetOneOfFieldName(message, field)
if field.IsMessage() || p.IsGroup(field) {
desc := p.ObjectNamed(field.GetTypeName())
msgname := p.TypeName(desc)
msgnames := strings.Split(msgname, ".")
typeName := msgnames[len(msgnames)-1]
p.P("`", fieldname, ":`", ` + `, stringsPkg.Use(), `.Replace(`, fmtPkg.Use(), `.Sprintf("%v", this.`, fieldname, `), "`, typeName, `","`, msgname, `"`, ", 1) + `,", "`,")
} else {
p.P("`", fieldname, ":`", ` + `, fmtPkg.Use(), `.Sprintf("%v", this.`, fieldname, ") + `,", "`,")
}
p.P("`}`,")
p.P(`}`, `,""`, ")")
p.P(`return s`)
p.Out()
p.P(`}`)
}
}
if !p.atleastOne {
return
}
p.P(`func valueToString`, p.localName, `(v interface{}) string {`)
p.In()
p.P(`rv := `, reflectPkg.Use(), `.ValueOf(v)`)
p.P(`if rv.IsNil() {`)
p.In()
p.P(`return "nil"`)
p.Out()
p.P(`}`)
p.P(`pv := `, reflectPkg.Use(), `.Indirect(rv).Interface()`)
p.P(`return `, fmtPkg.Use(), `.Sprintf("*%v", pv)`)
p.Out()
p.P(`}`)
}
func init() {
generator.RegisterPlugin(NewStringer())
}

View file

@ -0,0 +1,83 @@
// Protocol Buffers for Go with Gadgets
//
// Copyright (c) 2013, The GoGo Authors. All rights reserved.
// http://github.com/gogo/protobuf
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package stringer
import (
"github.com/gogo/protobuf/gogoproto"
"github.com/gogo/protobuf/plugin/testgen"
"github.com/gogo/protobuf/protoc-gen-gogo/generator"
)
type test struct {
*generator.Generator
}
func NewTest(g *generator.Generator) testgen.TestPlugin {
return &test{g}
}
func (p *test) Generate(imports generator.PluginImports, file *generator.FileDescriptor) bool {
used := false
randPkg := imports.NewImport("math/rand")
timePkg := imports.NewImport("time")
testingPkg := imports.NewImport("testing")
fmtPkg := imports.NewImport("fmt")
for _, message := range file.Messages() {
ccTypeName := generator.CamelCaseSlice(message.TypeName())
if !gogoproto.IsStringer(file.FileDescriptorProto, message.DescriptorProto) {
continue
}
if message.DescriptorProto.GetOptions().GetMapEntry() {
continue
}
if gogoproto.HasTestGen(file.FileDescriptorProto, message.DescriptorProto) {
used = true
p.P(`func Test`, ccTypeName, `Stringer(t *`, testingPkg.Use(), `.T) {`)
p.In()
p.P(`popr := `, randPkg.Use(), `.New(`, randPkg.Use(), `.NewSource(`, timePkg.Use(), `.Now().UnixNano()))`)
p.P(`p := NewPopulated`, ccTypeName, `(popr, false)`)
p.P(`s1 := p.String()`)
p.P(`s2 := `, fmtPkg.Use(), `.Sprintf("%v", p)`)
p.P(`if s1 != s2 {`)
p.In()
p.P(`t.Fatalf("String want %v got %v", s1, s2)`)
p.Out()
p.P(`}`)
p.Out()
p.P(`}`)
}
}
return used
}
func init() {
testgen.RegisterTestPlugin(NewTest)
}

View file

@ -0,0 +1,608 @@
// Protocol Buffers for Go with Gadgets
//
// Copyright (c) 2013, The GoGo Authors. All rights reserved.
// http://github.com/gogo/protobuf
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/*
The testgen plugin generates Test and Benchmark functions for each message.
Tests are enabled using the following extensions:
- testgen
- testgen_all
Benchmarks are enabled using the following extensions:
- benchgen
- benchgen_all
Let us look at:
github.com/gogo/protobuf/test/example/example.proto
Btw all the output can be seen at:
github.com/gogo/protobuf/test/example/*
The following message:
option (gogoproto.testgen_all) = true;
option (gogoproto.benchgen_all) = true;
message A {
optional string Description = 1 [(gogoproto.nullable) = false];
optional int64 Number = 2 [(gogoproto.nullable) = false];
optional bytes Id = 3 [(gogoproto.customtype) = "github.com/gogo/protobuf/test/custom.Uuid", (gogoproto.nullable) = false];
}
given to the testgen plugin, will generate the following test code:
func TestAProto(t *testing.T) {
popr := math_rand.New(math_rand.NewSource(time.Now().UnixNano()))
p := NewPopulatedA(popr, false)
dAtA, err := github_com_gogo_protobuf_proto.Marshal(p)
if err != nil {
panic(err)
}
msg := &A{}
if err := github_com_gogo_protobuf_proto.Unmarshal(dAtA, msg); err != nil {
panic(err)
}
for i := range dAtA {
dAtA[i] = byte(popr.Intn(256))
}
if err := p.VerboseEqual(msg); err != nil {
t.Fatalf("%#v !VerboseProto %#v, since %v", msg, p, err)
}
if !p.Equal(msg) {
t.Fatalf("%#v !Proto %#v", msg, p)
}
}
func BenchmarkAProtoMarshal(b *testing.B) {
popr := math_rand.New(math_rand.NewSource(616))
total := 0
pops := make([]*A, 10000)
for i := 0; i < 10000; i++ {
pops[i] = NewPopulatedA(popr, false)
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
dAtA, err := github_com_gogo_protobuf_proto.Marshal(pops[i%10000])
if err != nil {
panic(err)
}
total += len(dAtA)
}
b.SetBytes(int64(total / b.N))
}
func BenchmarkAProtoUnmarshal(b *testing.B) {
popr := math_rand.New(math_rand.NewSource(616))
total := 0
datas := make([][]byte, 10000)
for i := 0; i < 10000; i++ {
dAtA, err := github_com_gogo_protobuf_proto.Marshal(NewPopulatedA(popr, false))
if err != nil {
panic(err)
}
datas[i] = dAtA
}
msg := &A{}
b.ResetTimer()
for i := 0; i < b.N; i++ {
total += len(datas[i%10000])
if err := github_com_gogo_protobuf_proto.Unmarshal(datas[i%10000], msg); err != nil {
panic(err)
}
}
b.SetBytes(int64(total / b.N))
}
func TestAJSON(t *testing1.T) {
popr := math_rand1.New(math_rand1.NewSource(time1.Now().UnixNano()))
p := NewPopulatedA(popr, true)
jsondata, err := encoding_json.Marshal(p)
if err != nil {
panic(err)
}
msg := &A{}
err = encoding_json.Unmarshal(jsondata, msg)
if err != nil {
panic(err)
}
if err := p.VerboseEqual(msg); err != nil {
t.Fatalf("%#v !VerboseProto %#v, since %v", msg, p, err)
}
if !p.Equal(msg) {
t.Fatalf("%#v !Json Equal %#v", msg, p)
}
}
func TestAProtoText(t *testing2.T) {
popr := math_rand2.New(math_rand2.NewSource(time2.Now().UnixNano()))
p := NewPopulatedA(popr, true)
dAtA := github_com_gogo_protobuf_proto1.MarshalTextString(p)
msg := &A{}
if err := github_com_gogo_protobuf_proto1.UnmarshalText(dAtA, msg); err != nil {
panic(err)
}
if err := p.VerboseEqual(msg); err != nil {
t.Fatalf("%#v !VerboseProto %#v, since %v", msg, p, err)
}
if !p.Equal(msg) {
t.Fatalf("%#v !Proto %#v", msg, p)
}
}
func TestAProtoCompactText(t *testing2.T) {
popr := math_rand2.New(math_rand2.NewSource(time2.Now().UnixNano()))
p := NewPopulatedA(popr, true)
dAtA := github_com_gogo_protobuf_proto1.CompactTextString(p)
msg := &A{}
if err := github_com_gogo_protobuf_proto1.UnmarshalText(dAtA, msg); err != nil {
panic(err)
}
if err := p.VerboseEqual(msg); err != nil {
t.Fatalf("%#v !VerboseProto %#v, since %v", msg, p, err)
}
if !p.Equal(msg) {
t.Fatalf("%#v !Proto %#v", msg, p)
}
}
Other registered tests are also generated.
Tests are registered to this test plugin by calling the following function.
func RegisterTestPlugin(newFunc NewTestPlugin)
where NewTestPlugin is:
type NewTestPlugin func(g *generator.Generator) TestPlugin
and TestPlugin is an interface:
type TestPlugin interface {
Generate(imports generator.PluginImports, file *generator.FileDescriptor) (used bool)
}
Plugins that use this interface include:
- populate
- gostring
- equal
- union
- and more
Please look at these plugins as examples of how to create your own.
A good idea is to let each plugin generate its own tests.
*/
package testgen
import (
"github.com/gogo/protobuf/gogoproto"
"github.com/gogo/protobuf/protoc-gen-gogo/generator"
)
type TestPlugin interface {
Generate(imports generator.PluginImports, file *generator.FileDescriptor) (used bool)
}
type NewTestPlugin func(g *generator.Generator) TestPlugin
var testplugins = make([]NewTestPlugin, 0)
func RegisterTestPlugin(newFunc NewTestPlugin) {
testplugins = append(testplugins, newFunc)
}
type plugin struct {
*generator.Generator
generator.PluginImports
tests []TestPlugin
}
func NewPlugin() *plugin {
return &plugin{}
}
func (p *plugin) Name() string {
return "testgen"
}
func (p *plugin) Init(g *generator.Generator) {
p.Generator = g
p.tests = make([]TestPlugin, 0, len(testplugins))
for i := range testplugins {
p.tests = append(p.tests, testplugins[i](g))
}
}
func (p *plugin) Generate(file *generator.FileDescriptor) {
p.PluginImports = generator.NewPluginImports(p.Generator)
atLeastOne := false
for i := range p.tests {
used := p.tests[i].Generate(p.PluginImports, file)
if used {
atLeastOne = true
}
}
if atLeastOne {
p.P(`//These tests are generated by github.com/gogo/protobuf/plugin/testgen`)
}
}
type testProto struct {
*generator.Generator
}
func newProto(g *generator.Generator) TestPlugin {
return &testProto{g}
}
func (p *testProto) Generate(imports generator.PluginImports, file *generator.FileDescriptor) bool {
used := false
testingPkg := imports.NewImport("testing")
randPkg := imports.NewImport("math/rand")
timePkg := imports.NewImport("time")
protoPkg := imports.NewImport("github.com/gogo/protobuf/proto")
if !gogoproto.ImportsGoGoProto(file.FileDescriptorProto) {
protoPkg = imports.NewImport("github.com/golang/protobuf/proto")
}
for _, message := range file.Messages() {
ccTypeName := generator.CamelCaseSlice(message.TypeName())
if message.DescriptorProto.GetOptions().GetMapEntry() {
continue
}
if gogoproto.HasTestGen(file.FileDescriptorProto, message.DescriptorProto) {
used = true
p.P(`func Test`, ccTypeName, `Proto(t *`, testingPkg.Use(), `.T) {`)
p.In()
p.P(`seed := `, timePkg.Use(), `.Now().UnixNano()`)
p.P(`popr := `, randPkg.Use(), `.New(`, randPkg.Use(), `.NewSource(seed))`)
p.P(`p := NewPopulated`, ccTypeName, `(popr, false)`)
p.P(`dAtA, err := `, protoPkg.Use(), `.Marshal(p)`)
p.P(`if err != nil {`)
p.In()
p.P(`t.Fatalf("seed = %d, err = %v", seed, err)`)
p.Out()
p.P(`}`)
p.P(`msg := &`, ccTypeName, `{}`)
p.P(`if err := `, protoPkg.Use(), `.Unmarshal(dAtA, msg); err != nil {`)
p.In()
p.P(`t.Fatalf("seed = %d, err = %v", seed, err)`)
p.Out()
p.P(`}`)
p.P(`littlefuzz := make([]byte, len(dAtA))`)
p.P(`copy(littlefuzz, dAtA)`)
p.P(`for i := range dAtA {`)
p.In()
p.P(`dAtA[i] = byte(popr.Intn(256))`)
p.Out()
p.P(`}`)
if gogoproto.HasVerboseEqual(file.FileDescriptorProto, message.DescriptorProto) {
p.P(`if err := p.VerboseEqual(msg); err != nil {`)
p.In()
p.P(`t.Fatalf("seed = %d, %#v !VerboseProto %#v, since %v", seed, msg, p, err)`)
p.Out()
p.P(`}`)
}
p.P(`if !p.Equal(msg) {`)
p.In()
p.P(`t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p)`)
p.Out()
p.P(`}`)
p.P(`if len(littlefuzz) > 0 {`)
p.In()
p.P(`fuzzamount := 100`)
p.P(`for i := 0; i < fuzzamount; i++ {`)
p.In()
p.P(`littlefuzz[popr.Intn(len(littlefuzz))] = byte(popr.Intn(256))`)
p.P(`littlefuzz = append(littlefuzz, byte(popr.Intn(256)))`)
p.Out()
p.P(`}`)
p.P(`// shouldn't panic`)
p.P(`_ = `, protoPkg.Use(), `.Unmarshal(littlefuzz, msg)`)
p.Out()
p.P(`}`)
p.Out()
p.P(`}`)
p.P()
}
if gogoproto.HasTestGen(file.FileDescriptorProto, message.DescriptorProto) {
if gogoproto.IsMarshaler(file.FileDescriptorProto, message.DescriptorProto) || gogoproto.IsUnsafeMarshaler(file.FileDescriptorProto, message.DescriptorProto) {
p.P(`func Test`, ccTypeName, `MarshalTo(t *`, testingPkg.Use(), `.T) {`)
p.In()
p.P(`seed := `, timePkg.Use(), `.Now().UnixNano()`)
p.P(`popr := `, randPkg.Use(), `.New(`, randPkg.Use(), `.NewSource(seed))`)
p.P(`p := NewPopulated`, ccTypeName, `(popr, false)`)
if gogoproto.IsProtoSizer(file.FileDescriptorProto, message.DescriptorProto) {
p.P(`size := p.ProtoSize()`)
} else {
p.P(`size := p.Size()`)
}
p.P(`dAtA := make([]byte, size)`)
p.P(`for i := range dAtA {`)
p.In()
p.P(`dAtA[i] = byte(popr.Intn(256))`)
p.Out()
p.P(`}`)
p.P(`_, err := p.MarshalTo(dAtA)`)
p.P(`if err != nil {`)
p.In()
p.P(`t.Fatalf("seed = %d, err = %v", seed, err)`)
p.Out()
p.P(`}`)
p.P(`msg := &`, ccTypeName, `{}`)
p.P(`if err := `, protoPkg.Use(), `.Unmarshal(dAtA, msg); err != nil {`)
p.In()
p.P(`t.Fatalf("seed = %d, err = %v", seed, err)`)
p.Out()
p.P(`}`)
p.P(`for i := range dAtA {`)
p.In()
p.P(`dAtA[i] = byte(popr.Intn(256))`)
p.Out()
p.P(`}`)
if gogoproto.HasVerboseEqual(file.FileDescriptorProto, message.DescriptorProto) {
p.P(`if err := p.VerboseEqual(msg); err != nil {`)
p.In()
p.P(`t.Fatalf("seed = %d, %#v !VerboseProto %#v, since %v", seed, msg, p, err)`)
p.Out()
p.P(`}`)
}
p.P(`if !p.Equal(msg) {`)
p.In()
p.P(`t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p)`)
p.Out()
p.P(`}`)
p.Out()
p.P(`}`)
p.P()
}
}
if gogoproto.HasBenchGen(file.FileDescriptorProto, message.DescriptorProto) {
used = true
p.P(`func Benchmark`, ccTypeName, `ProtoMarshal(b *`, testingPkg.Use(), `.B) {`)
p.In()
p.P(`popr := `, randPkg.Use(), `.New(`, randPkg.Use(), `.NewSource(616))`)
p.P(`total := 0`)
p.P(`pops := make([]*`, ccTypeName, `, 10000)`)
p.P(`for i := 0; i < 10000; i++ {`)
p.In()
p.P(`pops[i] = NewPopulated`, ccTypeName, `(popr, false)`)
p.Out()
p.P(`}`)
p.P(`b.ResetTimer()`)
p.P(`for i := 0; i < b.N; i++ {`)
p.In()
p.P(`dAtA, err := `, protoPkg.Use(), `.Marshal(pops[i%10000])`)
p.P(`if err != nil {`)
p.In()
p.P(`panic(err)`)
p.Out()
p.P(`}`)
p.P(`total += len(dAtA)`)
p.Out()
p.P(`}`)
p.P(`b.SetBytes(int64(total / b.N))`)
p.Out()
p.P(`}`)
p.P()
p.P(`func Benchmark`, ccTypeName, `ProtoUnmarshal(b *`, testingPkg.Use(), `.B) {`)
p.In()
p.P(`popr := `, randPkg.Use(), `.New(`, randPkg.Use(), `.NewSource(616))`)
p.P(`total := 0`)
p.P(`datas := make([][]byte, 10000)`)
p.P(`for i := 0; i < 10000; i++ {`)
p.In()
p.P(`dAtA, err := `, protoPkg.Use(), `.Marshal(NewPopulated`, ccTypeName, `(popr, false))`)
p.P(`if err != nil {`)
p.In()
p.P(`panic(err)`)
p.Out()
p.P(`}`)
p.P(`datas[i] = dAtA`)
p.Out()
p.P(`}`)
p.P(`msg := &`, ccTypeName, `{}`)
p.P(`b.ResetTimer()`)
p.P(`for i := 0; i < b.N; i++ {`)
p.In()
p.P(`total += len(datas[i%10000])`)
p.P(`if err := `, protoPkg.Use(), `.Unmarshal(datas[i%10000], msg); err != nil {`)
p.In()
p.P(`panic(err)`)
p.Out()
p.P(`}`)
p.Out()
p.P(`}`)
p.P(`b.SetBytes(int64(total / b.N))`)
p.Out()
p.P(`}`)
p.P()
}
}
return used
}
type testJson struct {
*generator.Generator
}
func newJson(g *generator.Generator) TestPlugin {
return &testJson{g}
}
func (p *testJson) Generate(imports generator.PluginImports, file *generator.FileDescriptor) bool {
used := false
testingPkg := imports.NewImport("testing")
randPkg := imports.NewImport("math/rand")
timePkg := imports.NewImport("time")
jsonPkg := imports.NewImport("github.com/gogo/protobuf/jsonpb")
for _, message := range file.Messages() {
ccTypeName := generator.CamelCaseSlice(message.TypeName())
if message.DescriptorProto.GetOptions().GetMapEntry() {
continue
}
if gogoproto.HasTestGen(file.FileDescriptorProto, message.DescriptorProto) {
used = true
p.P(`func Test`, ccTypeName, `JSON(t *`, testingPkg.Use(), `.T) {`)
p.In()
p.P(`seed := `, timePkg.Use(), `.Now().UnixNano()`)
p.P(`popr := `, randPkg.Use(), `.New(`, randPkg.Use(), `.NewSource(seed))`)
p.P(`p := NewPopulated`, ccTypeName, `(popr, true)`)
p.P(`marshaler := `, jsonPkg.Use(), `.Marshaler{}`)
p.P(`jsondata, err := marshaler.MarshalToString(p)`)
p.P(`if err != nil {`)
p.In()
p.P(`t.Fatalf("seed = %d, err = %v", seed, err)`)
p.Out()
p.P(`}`)
p.P(`msg := &`, ccTypeName, `{}`)
p.P(`err = `, jsonPkg.Use(), `.UnmarshalString(jsondata, msg)`)
p.P(`if err != nil {`)
p.In()
p.P(`t.Fatalf("seed = %d, err = %v", seed, err)`)
p.Out()
p.P(`}`)
if gogoproto.HasVerboseEqual(file.FileDescriptorProto, message.DescriptorProto) {
p.P(`if err := p.VerboseEqual(msg); err != nil {`)
p.In()
p.P(`t.Fatalf("seed = %d, %#v !VerboseProto %#v, since %v", seed, msg, p, err)`)
p.Out()
p.P(`}`)
}
p.P(`if !p.Equal(msg) {`)
p.In()
p.P(`t.Fatalf("seed = %d, %#v !Json Equal %#v", seed, msg, p)`)
p.Out()
p.P(`}`)
p.Out()
p.P(`}`)
}
}
return used
}
type testText struct {
*generator.Generator
}
func newText(g *generator.Generator) TestPlugin {
return &testText{g}
}
func (p *testText) Generate(imports generator.PluginImports, file *generator.FileDescriptor) bool {
used := false
testingPkg := imports.NewImport("testing")
randPkg := imports.NewImport("math/rand")
timePkg := imports.NewImport("time")
protoPkg := imports.NewImport("github.com/gogo/protobuf/proto")
if !gogoproto.ImportsGoGoProto(file.FileDescriptorProto) {
protoPkg = imports.NewImport("github.com/golang/protobuf/proto")
}
//fmtPkg := imports.NewImport("fmt")
for _, message := range file.Messages() {
ccTypeName := generator.CamelCaseSlice(message.TypeName())
if message.DescriptorProto.GetOptions().GetMapEntry() {
continue
}
if gogoproto.HasTestGen(file.FileDescriptorProto, message.DescriptorProto) {
used = true
p.P(`func Test`, ccTypeName, `ProtoText(t *`, testingPkg.Use(), `.T) {`)
p.In()
p.P(`seed := `, timePkg.Use(), `.Now().UnixNano()`)
p.P(`popr := `, randPkg.Use(), `.New(`, randPkg.Use(), `.NewSource(seed))`)
p.P(`p := NewPopulated`, ccTypeName, `(popr, true)`)
p.P(`dAtA := `, protoPkg.Use(), `.MarshalTextString(p)`)
p.P(`msg := &`, ccTypeName, `{}`)
p.P(`if err := `, protoPkg.Use(), `.UnmarshalText(dAtA, msg); err != nil {`)
p.In()
p.P(`t.Fatalf("seed = %d, err = %v", seed, err)`)
p.Out()
p.P(`}`)
if gogoproto.HasVerboseEqual(file.FileDescriptorProto, message.DescriptorProto) {
p.P(`if err := p.VerboseEqual(msg); err != nil {`)
p.In()
p.P(`t.Fatalf("seed = %d, %#v !VerboseProto %#v, since %v", seed, msg, p, err)`)
p.Out()
p.P(`}`)
}
p.P(`if !p.Equal(msg) {`)
p.In()
p.P(`t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p)`)
p.Out()
p.P(`}`)
p.Out()
p.P(`}`)
p.P()
p.P(`func Test`, ccTypeName, `ProtoCompactText(t *`, testingPkg.Use(), `.T) {`)
p.In()
p.P(`seed := `, timePkg.Use(), `.Now().UnixNano()`)
p.P(`popr := `, randPkg.Use(), `.New(`, randPkg.Use(), `.NewSource(seed))`)
p.P(`p := NewPopulated`, ccTypeName, `(popr, true)`)
p.P(`dAtA := `, protoPkg.Use(), `.CompactTextString(p)`)
p.P(`msg := &`, ccTypeName, `{}`)
p.P(`if err := `, protoPkg.Use(), `.UnmarshalText(dAtA, msg); err != nil {`)
p.In()
p.P(`t.Fatalf("seed = %d, err = %v", seed, err)`)
p.Out()
p.P(`}`)
if gogoproto.HasVerboseEqual(file.FileDescriptorProto, message.DescriptorProto) {
p.P(`if err := p.VerboseEqual(msg); err != nil {`)
p.In()
p.P(`t.Fatalf("seed = %d, %#v !VerboseProto %#v, since %v", seed, msg, p, err)`)
p.Out()
p.P(`}`)
}
p.P(`if !p.Equal(msg) {`)
p.In()
p.P(`t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p)`)
p.Out()
p.P(`}`)
p.Out()
p.P(`}`)
p.P()
}
}
return used
}
func init() {
RegisterTestPlugin(newProto)
RegisterTestPlugin(newJson)
RegisterTestPlugin(newText)
}

209
vendor/github.com/gogo/protobuf/plugin/union/union.go generated vendored Normal file
View file

@ -0,0 +1,209 @@
// Protocol Buffers for Go with Gadgets
//
// Copyright (c) 2013, The GoGo Authors. All rights reserved.
// http://github.com/gogo/protobuf
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/*
The onlyone plugin generates code for the onlyone extension.
All fields must be nullable and only one of the fields may be set, like a union.
Two methods are generated
GetValue() interface{}
and
SetValue(v interface{}) (set bool)
These provide easier interaction with a onlyone.
The onlyone extension is not called union as this causes compile errors in the C++ generated code.
There can only be one ;)
It is enabled by the following extensions:
- onlyone
- onlyone_all
The onlyone plugin also generates a test given it is enabled using one of the following extensions:
- testgen
- testgen_all
Lets look at:
github.com/gogo/protobuf/test/example/example.proto
Btw all the output can be seen at:
github.com/gogo/protobuf/test/example/*
The following message:
message U {
option (gogoproto.onlyone) = true;
optional A A = 1;
optional B B = 2;
}
given to the onlyone plugin, will generate code which looks a lot like this:
func (this *U) GetValue() interface{} {
if this.A != nil {
return this.A
}
if this.B != nil {
return this.B
}
return nil
}
func (this *U) SetValue(value interface{}) bool {
switch vt := value.(type) {
case *A:
this.A = vt
case *B:
this.B = vt
default:
return false
}
return true
}
and the following test code:
func TestUUnion(t *testing.T) {
popr := math_rand.New(math_rand.NewSource(time.Now().UnixNano()))
p := NewPopulatedU(popr)
v := p.GetValue()
msg := &U{}
if !msg.SetValue(v) {
t.Fatalf("Union: Could not set Value")
}
if !p.Equal(msg) {
t.Fatalf("%#v !Union Equal %#v", msg, p)
}
}
*/
package union
import (
"github.com/gogo/protobuf/gogoproto"
"github.com/gogo/protobuf/protoc-gen-gogo/generator"
)
type union struct {
*generator.Generator
generator.PluginImports
}
func NewUnion() *union {
return &union{}
}
func (p *union) Name() string {
return "union"
}
func (p *union) Init(g *generator.Generator) {
p.Generator = g
}
func (p *union) Generate(file *generator.FileDescriptor) {
p.PluginImports = generator.NewPluginImports(p.Generator)
for _, message := range file.Messages() {
if !gogoproto.IsUnion(file.FileDescriptorProto, message.DescriptorProto) {
continue
}
if message.DescriptorProto.HasExtension() {
panic("onlyone does not currently support extensions")
}
if message.DescriptorProto.GetOptions().GetMapEntry() {
continue
}
ccTypeName := generator.CamelCaseSlice(message.TypeName())
p.P(`func (this *`, ccTypeName, `) GetValue() interface{} {`)
p.In()
for _, field := range message.Field {
fieldname := p.GetFieldName(message, field)
if fieldname == "Value" {
panic("cannot have a onlyone message " + ccTypeName + " with a field named Value")
}
p.P(`if this.`, fieldname, ` != nil {`)
p.In()
p.P(`return this.`, fieldname)
p.Out()
p.P(`}`)
}
p.P(`return nil`)
p.Out()
p.P(`}`)
p.P(``)
p.P(`func (this *`, ccTypeName, `) SetValue(value interface{}) bool {`)
p.In()
p.P(`switch vt := value.(type) {`)
p.In()
for _, field := range message.Field {
fieldname := p.GetFieldName(message, field)
goTyp, _ := p.GoType(message, field)
p.P(`case `, goTyp, `:`)
p.In()
p.P(`this.`, fieldname, ` = vt`)
p.Out()
}
p.P(`default:`)
p.In()
for _, field := range message.Field {
fieldname := p.GetFieldName(message, field)
if field.IsMessage() {
goTyp, _ := p.GoType(message, field)
obj := p.ObjectNamed(field.GetTypeName()).(*generator.Descriptor)
if gogoproto.IsUnion(obj.File().FileDescriptorProto, obj.DescriptorProto) {
p.P(`this.`, fieldname, ` = new(`, generator.GoTypeToName(goTyp), `)`)
p.P(`if set := this.`, fieldname, `.SetValue(value); set {`)
p.In()
p.P(`return true`)
p.Out()
p.P(`}`)
p.P(`this.`, fieldname, ` = nil`)
}
}
}
p.P(`return false`)
p.Out()
p.P(`}`)
p.P(`return true`)
p.Out()
p.P(`}`)
}
}
func init() {
generator.RegisterPlugin(NewUnion())
}

View file

@ -0,0 +1,86 @@
// Protocol Buffers for Go with Gadgets
//
// Copyright (c) 2013, The GoGo Authors. All rights reserved.
// http://github.com/gogo/protobuf
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package union
import (
"github.com/gogo/protobuf/gogoproto"
"github.com/gogo/protobuf/plugin/testgen"
"github.com/gogo/protobuf/protoc-gen-gogo/generator"
)
type test struct {
*generator.Generator
}
func NewTest(g *generator.Generator) testgen.TestPlugin {
return &test{g}
}
func (p *test) Generate(imports generator.PluginImports, file *generator.FileDescriptor) bool {
used := false
randPkg := imports.NewImport("math/rand")
timePkg := imports.NewImport("time")
testingPkg := imports.NewImport("testing")
for _, message := range file.Messages() {
if !gogoproto.IsUnion(file.FileDescriptorProto, message.DescriptorProto) ||
!gogoproto.HasTestGen(file.FileDescriptorProto, message.DescriptorProto) {
continue
}
if message.DescriptorProto.GetOptions().GetMapEntry() {
continue
}
used = true
ccTypeName := generator.CamelCaseSlice(message.TypeName())
p.P(`func Test`, ccTypeName, `OnlyOne(t *`, testingPkg.Use(), `.T) {`)
p.In()
p.P(`popr := `, randPkg.Use(), `.New(`, randPkg.Use(), `.NewSource(`, timePkg.Use(), `.Now().UnixNano()))`)
p.P(`p := NewPopulated`, ccTypeName, `(popr, true)`)
p.P(`v := p.GetValue()`)
p.P(`msg := &`, ccTypeName, `{}`)
p.P(`if !msg.SetValue(v) {`)
p.In()
p.P(`t.Fatalf("OnlyOne: Could not set Value")`)
p.Out()
p.P(`}`)
p.P(`if !p.Equal(msg) {`)
p.In()
p.P(`t.Fatalf("%#v !OnlyOne Equal %#v", msg, p)`)
p.Out()
p.P(`}`)
p.Out()
p.P(`}`)
}
return used
}
func init() {
testgen.RegisterTestPlugin(NewTest)
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,41 @@
# Go support for Protocol Buffers - Google's data interchange format
#
# Copyright 2010 The Go Authors. All rights reserved.
# https://github.com/golang/protobuf
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
all: test
test:
go test
make -C testdata test
regenerate:
go test --regenerate
make -C descriptor regenerate
make -C plugin regenerate

51
vendor/github.com/gogo/protobuf/protoc-gen-gogo/doc.go generated vendored Normal file
View file

@ -0,0 +1,51 @@
// Go support for Protocol Buffers - Google's data interchange format
//
// Copyright 2010 The Go Authors. All rights reserved.
// https://github.com/golang/protobuf
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/*
A plugin for the Google protocol buffer compiler to generate Go code.
Run it by building this program and putting it in your path with the name
protoc-gen-gogo
That word 'gogo' at the end becomes part of the option string set for the
protocol compiler, so once the protocol compiler (protoc) is installed
you can run
protoc --gogo_out=output_directory input_directory/file.proto
to generate Go bindings for the protocol defined by file.proto.
With that input, the output will be written to
output_directory/go_package/file.pb.go
The generated code is documented in the package comment for
the library.
See the README and documentation for protocol buffers to learn more:
https://developers.google.com/protocol-buffers/
*/
package documentation

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,461 @@
// Protocol Buffers for Go with Gadgets
//
// Copyright (c) 2013, The GoGo Authors. All rights reserved.
// http://github.com/gogo/protobuf
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package generator
import (
"bytes"
"go/parser"
"go/printer"
"go/token"
"path"
"strings"
"github.com/gogo/protobuf/gogoproto"
"github.com/gogo/protobuf/proto"
descriptor "github.com/gogo/protobuf/protoc-gen-gogo/descriptor"
plugin "github.com/gogo/protobuf/protoc-gen-gogo/plugin"
)
func (d *FileDescriptor) Messages() []*Descriptor {
return d.desc
}
func (d *FileDescriptor) Enums() []*EnumDescriptor {
return d.enum
}
func (d *Descriptor) IsGroup() bool {
return d.group
}
func (g *Generator) IsGroup(field *descriptor.FieldDescriptorProto) bool {
if d, ok := g.typeNameToObject[field.GetTypeName()].(*Descriptor); ok {
return d.IsGroup()
}
return false
}
func (g *Generator) TypeNameByObject(typeName string) Object {
o, ok := g.typeNameToObject[typeName]
if !ok {
g.Fail("can't find object with type", typeName)
}
return o
}
func (g *Generator) OneOfTypeName(message *Descriptor, field *descriptor.FieldDescriptorProto) string {
typeName := message.TypeName()
ccTypeName := CamelCaseSlice(typeName)
fieldName := g.GetOneOfFieldName(message, field)
tname := ccTypeName + "_" + fieldName
// It is possible for this to collide with a message or enum
// nested in this message. Check for collisions.
ok := true
for _, desc := range message.nested {
if strings.Join(desc.TypeName(), "_") == tname {
ok = false
break
}
}
for _, enum := range message.enums {
if strings.Join(enum.TypeName(), "_") == tname {
ok = false
break
}
}
if !ok {
tname += "_"
}
return tname
}
type PluginImports interface {
NewImport(pkg string) Single
GenerateImports(file *FileDescriptor)
}
type pluginImports struct {
generator *Generator
singles []Single
}
func NewPluginImports(generator *Generator) *pluginImports {
return &pluginImports{generator, make([]Single, 0)}
}
func (this *pluginImports) NewImport(pkg string) Single {
imp := newImportedPackage(this.generator.ImportPrefix, pkg)
this.singles = append(this.singles, imp)
return imp
}
func (this *pluginImports) GenerateImports(file *FileDescriptor) {
for _, s := range this.singles {
if s.IsUsed() {
this.generator.PrintImport(GoPackageName(s.Name()), GoImportPath(s.Location()))
}
}
}
type Single interface {
Use() string
IsUsed() bool
Name() string
Location() string
}
type importedPackage struct {
used bool
pkg string
name string
importPrefix string
}
func newImportedPackage(importPrefix string, pkg string) *importedPackage {
return &importedPackage{
pkg: pkg,
importPrefix: importPrefix,
}
}
func (this *importedPackage) Use() string {
if !this.used {
this.name = string(cleanPackageName(this.pkg))
this.used = true
}
return this.name
}
func (this *importedPackage) IsUsed() bool {
return this.used
}
func (this *importedPackage) Name() string {
return this.name
}
func (this *importedPackage) Location() string {
return this.importPrefix + this.pkg
}
func (g *Generator) GetFieldName(message *Descriptor, field *descriptor.FieldDescriptorProto) string {
goTyp, _ := g.GoType(message, field)
fieldname := CamelCase(*field.Name)
if gogoproto.IsCustomName(field) {
fieldname = gogoproto.GetCustomName(field)
}
if gogoproto.IsEmbed(field) {
fieldname = EmbedFieldName(goTyp)
}
if field.OneofIndex != nil {
fieldname = message.OneofDecl[int(*field.OneofIndex)].GetName()
fieldname = CamelCase(fieldname)
}
for _, f := range methodNames {
if f == fieldname {
return fieldname + "_"
}
}
if !gogoproto.IsProtoSizer(message.file.FileDescriptorProto, message.DescriptorProto) {
if fieldname == "Size" {
return fieldname + "_"
}
}
return fieldname
}
func (g *Generator) GetOneOfFieldName(message *Descriptor, field *descriptor.FieldDescriptorProto) string {
goTyp, _ := g.GoType(message, field)
fieldname := CamelCase(*field.Name)
if gogoproto.IsCustomName(field) {
fieldname = gogoproto.GetCustomName(field)
}
if gogoproto.IsEmbed(field) {
fieldname = EmbedFieldName(goTyp)
}
for _, f := range methodNames {
if f == fieldname {
return fieldname + "_"
}
}
if !gogoproto.IsProtoSizer(message.file.FileDescriptorProto, message.DescriptorProto) {
if fieldname == "Size" {
return fieldname + "_"
}
}
return fieldname
}
func (g *Generator) IsMap(field *descriptor.FieldDescriptorProto) bool {
if !field.IsMessage() {
return false
}
byName := g.ObjectNamed(field.GetTypeName())
desc, ok := byName.(*Descriptor)
if byName == nil || !ok || !desc.GetOptions().GetMapEntry() {
return false
}
return true
}
func (g *Generator) GetMapKeyField(field, keyField *descriptor.FieldDescriptorProto) *descriptor.FieldDescriptorProto {
if !gogoproto.IsCastKey(field) {
return keyField
}
keyField = proto.Clone(keyField).(*descriptor.FieldDescriptorProto)
if keyField.Options == nil {
keyField.Options = &descriptor.FieldOptions{}
}
keyType := gogoproto.GetCastKey(field)
if err := proto.SetExtension(keyField.Options, gogoproto.E_Casttype, &keyType); err != nil {
g.Fail(err.Error())
}
return keyField
}
func (g *Generator) GetMapValueField(field, valField *descriptor.FieldDescriptorProto) *descriptor.FieldDescriptorProto {
if gogoproto.IsCustomType(field) && gogoproto.IsCastValue(field) {
g.Fail("cannot have a customtype and casttype: ", field.String())
}
valField = proto.Clone(valField).(*descriptor.FieldDescriptorProto)
if valField.Options == nil {
valField.Options = &descriptor.FieldOptions{}
}
stdtime := gogoproto.IsStdTime(field)
if stdtime {
if err := proto.SetExtension(valField.Options, gogoproto.E_Stdtime, &stdtime); err != nil {
g.Fail(err.Error())
}
}
stddur := gogoproto.IsStdDuration(field)
if stddur {
if err := proto.SetExtension(valField.Options, gogoproto.E_Stdduration, &stddur); err != nil {
g.Fail(err.Error())
}
}
wktptr := gogoproto.IsWktPtr(field)
if wktptr {
if err := proto.SetExtension(valField.Options, gogoproto.E_Wktpointer, &wktptr); err != nil {
g.Fail(err.Error())
}
}
if valType := gogoproto.GetCastValue(field); len(valType) > 0 {
if err := proto.SetExtension(valField.Options, gogoproto.E_Casttype, &valType); err != nil {
g.Fail(err.Error())
}
}
if valType := gogoproto.GetCustomType(field); len(valType) > 0 {
if err := proto.SetExtension(valField.Options, gogoproto.E_Customtype, &valType); err != nil {
g.Fail(err.Error())
}
}
nullable := gogoproto.IsNullable(field)
if err := proto.SetExtension(valField.Options, gogoproto.E_Nullable, &nullable); err != nil {
g.Fail(err.Error())
}
return valField
}
// GoMapValueTypes returns the map value Go type and the alias map value Go type (for casting), taking into
// account whether the map is nullable or the value is a message.
func GoMapValueTypes(mapField, valueField *descriptor.FieldDescriptorProto, goValueType, goValueAliasType string) (nullable bool, outGoType string, outGoAliasType string) {
nullable = gogoproto.IsNullable(mapField) && (valueField.IsMessage() || gogoproto.IsCustomType(mapField))
if nullable {
// ensure the non-aliased Go value type is a pointer for consistency
if strings.HasPrefix(goValueType, "*") {
outGoType = goValueType
} else {
outGoType = "*" + goValueType
}
outGoAliasType = goValueAliasType
} else {
outGoType = strings.Replace(goValueType, "*", "", 1)
outGoAliasType = strings.Replace(goValueAliasType, "*", "", 1)
}
return
}
func GoTypeToName(goTyp string) string {
return strings.Replace(strings.Replace(goTyp, "*", "", -1), "[]", "", -1)
}
func EmbedFieldName(goTyp string) string {
goTyp = GoTypeToName(goTyp)
goTyps := strings.Split(goTyp, ".")
if len(goTyps) == 1 {
return goTyp
}
if len(goTyps) == 2 {
return goTyps[1]
}
panic("unreachable")
}
func (g *Generator) GeneratePlugin(p Plugin) {
plugins = []Plugin{p}
p.Init(g)
// Generate the output. The generator runs for every file, even the files
// that we don't generate output for, so that we can collate the full list
// of exported symbols to support public imports.
genFileMap := make(map[*FileDescriptor]bool, len(g.genFiles))
for _, file := range g.genFiles {
genFileMap[file] = true
}
for _, file := range g.allFiles {
g.Reset()
g.writeOutput = genFileMap[file]
g.generatePlugin(file, p)
if !g.writeOutput {
continue
}
g.Response.File = append(g.Response.File, &plugin.CodeGeneratorResponse_File{
Name: proto.String(file.goFileName(g.pathType)),
Content: proto.String(g.String()),
})
}
}
func (g *Generator) SetFile(filename string) {
g.file = g.fileByName(filename)
}
func (g *Generator) generatePlugin(file *FileDescriptor, p Plugin) {
g.writtenImports = make(map[string]bool)
g.usedPackages = make(map[GoImportPath]bool)
g.packageNames = make(map[GoImportPath]GoPackageName)
g.usedPackageNames = make(map[GoPackageName]bool)
g.addedImports = make(map[GoImportPath]bool)
g.file = file
// Run the plugins before the imports so we know which imports are necessary.
p.Generate(file)
// Generate header and imports last, though they appear first in the output.
rem := g.Buffer
g.Buffer = new(bytes.Buffer)
g.generateHeader()
// p.GenerateImports(g.file)
g.generateImports()
if !g.writeOutput {
return
}
g.Write(rem.Bytes())
// Reformat generated code.
contents := string(g.Buffer.Bytes())
fset := token.NewFileSet()
ast, err := parser.ParseFile(fset, "", g, parser.ParseComments)
if err != nil {
g.Fail("bad Go source code was generated:", contents, err.Error())
return
}
g.Reset()
err = (&printer.Config{Mode: printer.TabIndent | printer.UseSpaces, Tabwidth: 8}).Fprint(g, fset, ast)
if err != nil {
g.Fail("generated Go source code could not be reformatted:", err.Error())
}
}
func GetCustomType(field *descriptor.FieldDescriptorProto) (packageName string, typ string, err error) {
return getCustomType(field)
}
func getCustomType(field *descriptor.FieldDescriptorProto) (packageName string, typ string, err error) {
if field.Options != nil {
var v interface{}
v, err = proto.GetExtension(field.Options, gogoproto.E_Customtype)
if err == nil && v.(*string) != nil {
ctype := *(v.(*string))
packageName, typ = splitCPackageType(ctype)
return packageName, typ, nil
}
}
return "", "", err
}
func splitCPackageType(ctype string) (packageName string, typ string) {
ss := strings.Split(ctype, ".")
if len(ss) == 1 {
return "", ctype
}
packageName = strings.Join(ss[0:len(ss)-1], ".")
typeName := ss[len(ss)-1]
importStr := strings.Map(badToUnderscore, packageName)
typ = importStr + "." + typeName
return packageName, typ
}
func getCastType(field *descriptor.FieldDescriptorProto) (packageName string, typ string, err error) {
if field.Options != nil {
var v interface{}
v, err = proto.GetExtension(field.Options, gogoproto.E_Casttype)
if err == nil && v.(*string) != nil {
ctype := *(v.(*string))
packageName, typ = splitCPackageType(ctype)
return packageName, typ, nil
}
}
return "", "", err
}
func FileName(file *FileDescriptor) string {
fname := path.Base(file.FileDescriptorProto.GetName())
fname = strings.Replace(fname, ".proto", "", -1)
fname = strings.Replace(fname, "-", "_", -1)
fname = strings.Replace(fname, ".", "_", -1)
return CamelCase(fname)
}
func (g *Generator) AllFiles() *descriptor.FileDescriptorSet {
set := &descriptor.FileDescriptorSet{}
set.File = make([]*descriptor.FileDescriptorProto, len(g.allFiles))
for i := range g.allFiles {
set.File[i] = g.allFiles[i].FileDescriptorProto
}
return set
}
func (d *Descriptor) Path() string {
return d.path
}
func (g *Generator) useTypes() string {
pkg := strings.Map(badToUnderscore, "github.com/gogo/protobuf/types")
g.customImports = append(g.customImports, "github.com/gogo/protobuf/types")
return pkg
}
func (d *FileDescriptor) GoPackageName() string {
return string(d.packageName)
}

View file

@ -0,0 +1,117 @@
// Go support for Protocol Buffers - Google's data interchange format
//
// Copyright 2017 The Go Authors. All rights reserved.
// https://github.com/golang/protobuf
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/*
Package remap handles tracking the locations of Go tokens in a source text
across a rewrite by the Go formatter.
*/
package remap
import (
"fmt"
"go/scanner"
"go/token"
)
// A Location represents a span of byte offsets in the source text.
type Location struct {
Pos, End int // End is exclusive
}
// A Map represents a mapping between token locations in an input source text
// and locations in the correspnding output text.
type Map map[Location]Location
// Find reports whether the specified span is recorded by m, and if so returns
// the new location it was mapped to. If the input span was not found, the
// returned location is the same as the input.
func (m Map) Find(pos, end int) (Location, bool) {
key := Location{
Pos: pos,
End: end,
}
if loc, ok := m[key]; ok {
return loc, true
}
return key, false
}
func (m Map) add(opos, oend, npos, nend int) {
m[Location{Pos: opos, End: oend}] = Location{Pos: npos, End: nend}
}
// Compute constructs a location mapping from input to output. An error is
// reported if any of the tokens of output cannot be mapped.
func Compute(input, output []byte) (Map, error) {
itok := tokenize(input)
otok := tokenize(output)
if len(itok) != len(otok) {
return nil, fmt.Errorf("wrong number of tokens, %d ≠ %d", len(itok), len(otok))
}
m := make(Map)
for i, ti := range itok {
to := otok[i]
if ti.Token != to.Token {
return nil, fmt.Errorf("token %d type mismatch: %s ≠ %s", i+1, ti, to)
}
m.add(ti.pos, ti.end, to.pos, to.end)
}
return m, nil
}
// tokinfo records the span and type of a source token.
type tokinfo struct {
pos, end int
token.Token
}
func tokenize(src []byte) []tokinfo {
fs := token.NewFileSet()
var s scanner.Scanner
s.Init(fs.AddFile("src", fs.Base(), len(src)), src, nil, scanner.ScanComments)
var info []tokinfo
for {
pos, next, lit := s.Scan()
switch next {
case token.SEMICOLON:
continue
}
info = append(info, tokinfo{
pos: int(pos - 1),
end: int(pos + token.Pos(len(lit)) - 1),
Token: next,
})
if next == token.EOF {
break
}
}
return info
}

View file

@ -0,0 +1,536 @@
// Go support for Protocol Buffers - Google's data interchange format
//
// Copyright 2015 The Go Authors. All rights reserved.
// https://github.com/golang/protobuf
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Package grpc outputs gRPC service descriptions in Go code.
// It runs as a plugin for the Go protocol buffer compiler plugin.
// It is linked in to protoc-gen-go.
package grpc
import (
"fmt"
"strconv"
"strings"
pb "github.com/gogo/protobuf/protoc-gen-gogo/descriptor"
"github.com/gogo/protobuf/protoc-gen-gogo/generator"
)
// generatedCodeVersion indicates a version of the generated code.
// It is incremented whenever an incompatibility between the generated code and
// the grpc package is introduced; the generated code references
// a constant, grpc.SupportPackageIsVersionN (where N is generatedCodeVersion).
const generatedCodeVersion = 4
// Paths for packages used by code generated in this file,
// relative to the import_prefix of the generator.Generator.
const (
contextPkgPath = "context"
grpcPkgPath = "google.golang.org/grpc"
codePkgPath = "google.golang.org/grpc/codes"
statusPkgPath = "google.golang.org/grpc/status"
)
func init() {
generator.RegisterPlugin(new(grpc))
}
// grpc is an implementation of the Go protocol buffer compiler's
// plugin architecture. It generates bindings for gRPC support.
type grpc struct {
gen *generator.Generator
}
// Name returns the name of this plugin, "grpc".
func (g *grpc) Name() string {
return "grpc"
}
// The names for packages imported in the generated code.
// They may vary from the final path component of the import path
// if the name is used by other packages.
var (
contextPkg string
grpcPkg string
)
// Init initializes the plugin.
func (g *grpc) Init(gen *generator.Generator) {
g.gen = gen
}
// Given a type name defined in a .proto, return its object.
// Also record that we're using it, to guarantee the associated import.
func (g *grpc) objectNamed(name string) generator.Object {
g.gen.RecordTypeUse(name)
return g.gen.ObjectNamed(name)
}
// Given a type name defined in a .proto, return its name as we will print it.
func (g *grpc) typeName(str string) string {
return g.gen.TypeName(g.objectNamed(str))
}
// P forwards to g.gen.P.
func (g *grpc) P(args ...interface{}) { g.gen.P(args...) }
// Generate generates code for the services in the given file.
func (g *grpc) Generate(file *generator.FileDescriptor) {
if len(file.FileDescriptorProto.Service) == 0 {
return
}
contextPkg = string(g.gen.AddImport(contextPkgPath))
grpcPkg = string(g.gen.AddImport(grpcPkgPath))
g.P("// Reference imports to suppress errors if they are not otherwise used.")
g.P("var _ ", contextPkg, ".Context")
g.P("var _ ", grpcPkg, ".ClientConn")
g.P()
// Assert version compatibility.
g.P("// This is a compile-time assertion to ensure that this generated file")
g.P("// is compatible with the grpc package it is being compiled against.")
g.P("const _ = ", grpcPkg, ".SupportPackageIsVersion", generatedCodeVersion)
g.P()
for i, service := range file.FileDescriptorProto.Service {
g.generateService(file, service, i)
}
}
// GenerateImports generates the import declaration for this file.
func (g *grpc) GenerateImports(file *generator.FileDescriptor) {}
// reservedClientName records whether a client name is reserved on the client side.
var reservedClientName = map[string]bool{
// TODO: do we need any in gRPC?
}
func unexport(s string) string { return strings.ToLower(s[:1]) + s[1:] }
// deprecationComment is the standard comment added to deprecated
// messages, fields, enums, and enum values.
var deprecationComment = "// Deprecated: Do not use."
// generateService generates all the code for the named service.
func (g *grpc) generateService(file *generator.FileDescriptor, service *pb.ServiceDescriptorProto, index int) {
path := fmt.Sprintf("6,%d", index) // 6 means service.
origServName := service.GetName()
fullServName := origServName
if pkg := file.GetPackage(); pkg != "" {
fullServName = pkg + "." + fullServName
}
servName := generator.CamelCase(origServName)
deprecated := service.GetOptions().GetDeprecated()
g.P()
g.P(fmt.Sprintf(`// %sClient is the client API for %s service.
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.`, servName, servName))
// Client interface.
if deprecated {
g.P("//")
g.P(deprecationComment)
}
g.P("type ", servName, "Client interface {")
for i, method := range service.Method {
g.gen.PrintComments(fmt.Sprintf("%s,2,%d", path, i)) // 2 means method in a service.
g.P(g.generateClientSignature(servName, method))
}
g.P("}")
g.P()
// Client structure.
g.P("type ", unexport(servName), "Client struct {")
g.P("cc *", grpcPkg, ".ClientConn")
g.P("}")
g.P()
// NewClient factory.
if deprecated {
g.P(deprecationComment)
}
g.P("func New", servName, "Client (cc *", grpcPkg, ".ClientConn) ", servName, "Client {")
g.P("return &", unexport(servName), "Client{cc}")
g.P("}")
g.P()
var methodIndex, streamIndex int
serviceDescVar := "_" + servName + "_serviceDesc"
// Client method implementations.
for _, method := range service.Method {
var descExpr string
if !method.GetServerStreaming() && !method.GetClientStreaming() {
// Unary RPC method
descExpr = fmt.Sprintf("&%s.Methods[%d]", serviceDescVar, methodIndex)
methodIndex++
} else {
// Streaming RPC method
descExpr = fmt.Sprintf("&%s.Streams[%d]", serviceDescVar, streamIndex)
streamIndex++
}
g.generateClientMethod(servName, fullServName, serviceDescVar, method, descExpr)
}
// Server interface.
serverType := servName + "Server"
g.P("// ", serverType, " is the server API for ", servName, " service.")
if deprecated {
g.P("//")
g.P(deprecationComment)
}
g.P("type ", serverType, " interface {")
for i, method := range service.Method {
g.gen.PrintComments(fmt.Sprintf("%s,2,%d", path, i)) // 2 means method in a service.
g.P(g.generateServerSignature(servName, method))
}
g.P("}")
g.P()
// Server Unimplemented struct for forward compatability.
if deprecated {
g.P(deprecationComment)
}
g.generateUnimplementedServer(servName, service)
// Server registration.
if deprecated {
g.P(deprecationComment)
}
g.P("func Register", servName, "Server(s *", grpcPkg, ".Server, srv ", serverType, ") {")
g.P("s.RegisterService(&", serviceDescVar, `, srv)`)
g.P("}")
g.P()
// Server handler implementations.
var handlerNames []string
for _, method := range service.Method {
hname := g.generateServerMethod(servName, fullServName, method)
handlerNames = append(handlerNames, hname)
}
// Service descriptor.
g.P("var ", serviceDescVar, " = ", grpcPkg, ".ServiceDesc {")
g.P("ServiceName: ", strconv.Quote(fullServName), ",")
g.P("HandlerType: (*", serverType, ")(nil),")
g.P("Methods: []", grpcPkg, ".MethodDesc{")
for i, method := range service.Method {
if method.GetServerStreaming() || method.GetClientStreaming() {
continue
}
g.P("{")
g.P("MethodName: ", strconv.Quote(method.GetName()), ",")
g.P("Handler: ", handlerNames[i], ",")
g.P("},")
}
g.P("},")
g.P("Streams: []", grpcPkg, ".StreamDesc{")
for i, method := range service.Method {
if !method.GetServerStreaming() && !method.GetClientStreaming() {
continue
}
g.P("{")
g.P("StreamName: ", strconv.Quote(method.GetName()), ",")
g.P("Handler: ", handlerNames[i], ",")
if method.GetServerStreaming() {
g.P("ServerStreams: true,")
}
if method.GetClientStreaming() {
g.P("ClientStreams: true,")
}
g.P("},")
}
g.P("},")
g.P("Metadata: \"", file.GetName(), "\",")
g.P("}")
g.P()
}
// generateUnimplementedServer creates the unimplemented server struct
func (g *grpc) generateUnimplementedServer(servName string, service *pb.ServiceDescriptorProto) {
serverType := servName + "Server"
g.P("// Unimplemented", serverType, " can be embedded to have forward compatible implementations.")
g.P("type Unimplemented", serverType, " struct {")
g.P("}")
g.P()
// Unimplemented<service_name>Server's concrete methods
for _, method := range service.Method {
g.generateServerMethodConcrete(servName, method)
}
g.P()
}
// generateServerMethodConcrete returns unimplemented methods which ensure forward compatibility
func (g *grpc) generateServerMethodConcrete(servName string, method *pb.MethodDescriptorProto) {
header := g.generateServerSignatureWithParamNames(servName, method)
g.P("func (*Unimplemented", servName, "Server) ", header, " {")
var nilArg string
if !method.GetServerStreaming() && !method.GetClientStreaming() {
nilArg = "nil, "
}
methName := generator.CamelCase(method.GetName())
statusPkg := string(g.gen.AddImport(statusPkgPath))
codePkg := string(g.gen.AddImport(codePkgPath))
g.P("return ", nilArg, statusPkg, `.Errorf(`, codePkg, `.Unimplemented, "method `, methName, ` not implemented")`)
g.P("}")
}
// generateClientSignature returns the client-side signature for a method.
func (g *grpc) generateClientSignature(servName string, method *pb.MethodDescriptorProto) string {
origMethName := method.GetName()
methName := generator.CamelCase(origMethName)
if reservedClientName[methName] {
methName += "_"
}
reqArg := ", in *" + g.typeName(method.GetInputType())
if method.GetClientStreaming() {
reqArg = ""
}
respName := "*" + g.typeName(method.GetOutputType())
if method.GetServerStreaming() || method.GetClientStreaming() {
respName = servName + "_" + generator.CamelCase(origMethName) + "Client"
}
return fmt.Sprintf("%s(ctx %s.Context%s, opts ...%s.CallOption) (%s, error)", methName, contextPkg, reqArg, grpcPkg, respName)
}
func (g *grpc) generateClientMethod(servName, fullServName, serviceDescVar string, method *pb.MethodDescriptorProto, descExpr string) {
sname := fmt.Sprintf("/%s/%s", fullServName, method.GetName())
methName := generator.CamelCase(method.GetName())
inType := g.typeName(method.GetInputType())
outType := g.typeName(method.GetOutputType())
if method.GetOptions().GetDeprecated() {
g.P(deprecationComment)
}
g.P("func (c *", unexport(servName), "Client) ", g.generateClientSignature(servName, method), "{")
if !method.GetServerStreaming() && !method.GetClientStreaming() {
g.P("out := new(", outType, ")")
// TODO: Pass descExpr to Invoke.
g.P(`err := c.cc.Invoke(ctx, "`, sname, `", in, out, opts...)`)
g.P("if err != nil { return nil, err }")
g.P("return out, nil")
g.P("}")
g.P()
return
}
streamType := unexport(servName) + methName + "Client"
g.P("stream, err := c.cc.NewStream(ctx, ", descExpr, `, "`, sname, `", opts...)`)
g.P("if err != nil { return nil, err }")
g.P("x := &", streamType, "{stream}")
if !method.GetClientStreaming() {
g.P("if err := x.ClientStream.SendMsg(in); err != nil { return nil, err }")
g.P("if err := x.ClientStream.CloseSend(); err != nil { return nil, err }")
}
g.P("return x, nil")
g.P("}")
g.P()
genSend := method.GetClientStreaming()
genRecv := method.GetServerStreaming()
genCloseAndRecv := !method.GetServerStreaming()
// Stream auxiliary types and methods.
g.P("type ", servName, "_", methName, "Client interface {")
if genSend {
g.P("Send(*", inType, ") error")
}
if genRecv {
g.P("Recv() (*", outType, ", error)")
}
if genCloseAndRecv {
g.P("CloseAndRecv() (*", outType, ", error)")
}
g.P(grpcPkg, ".ClientStream")
g.P("}")
g.P()
g.P("type ", streamType, " struct {")
g.P(grpcPkg, ".ClientStream")
g.P("}")
g.P()
if genSend {
g.P("func (x *", streamType, ") Send(m *", inType, ") error {")
g.P("return x.ClientStream.SendMsg(m)")
g.P("}")
g.P()
}
if genRecv {
g.P("func (x *", streamType, ") Recv() (*", outType, ", error) {")
g.P("m := new(", outType, ")")
g.P("if err := x.ClientStream.RecvMsg(m); err != nil { return nil, err }")
g.P("return m, nil")
g.P("}")
g.P()
}
if genCloseAndRecv {
g.P("func (x *", streamType, ") CloseAndRecv() (*", outType, ", error) {")
g.P("if err := x.ClientStream.CloseSend(); err != nil { return nil, err }")
g.P("m := new(", outType, ")")
g.P("if err := x.ClientStream.RecvMsg(m); err != nil { return nil, err }")
g.P("return m, nil")
g.P("}")
g.P()
}
}
// generateServerSignatureWithParamNames returns the server-side signature for a method with parameter names.
func (g *grpc) generateServerSignatureWithParamNames(servName string, method *pb.MethodDescriptorProto) string {
origMethName := method.GetName()
methName := generator.CamelCase(origMethName)
if reservedClientName[methName] {
methName += "_"
}
var reqArgs []string
ret := "error"
if !method.GetServerStreaming() && !method.GetClientStreaming() {
reqArgs = append(reqArgs, "ctx "+contextPkg+".Context")
ret = "(*" + g.typeName(method.GetOutputType()) + ", error)"
}
if !method.GetClientStreaming() {
reqArgs = append(reqArgs, "req *"+g.typeName(method.GetInputType()))
}
if method.GetServerStreaming() || method.GetClientStreaming() {
reqArgs = append(reqArgs, "srv "+servName+"_"+generator.CamelCase(origMethName)+"Server")
}
return methName + "(" + strings.Join(reqArgs, ", ") + ") " + ret
}
// generateServerSignature returns the server-side signature for a method.
func (g *grpc) generateServerSignature(servName string, method *pb.MethodDescriptorProto) string {
origMethName := method.GetName()
methName := generator.CamelCase(origMethName)
if reservedClientName[methName] {
methName += "_"
}
var reqArgs []string
ret := "error"
if !method.GetServerStreaming() && !method.GetClientStreaming() {
reqArgs = append(reqArgs, contextPkg+".Context")
ret = "(*" + g.typeName(method.GetOutputType()) + ", error)"
}
if !method.GetClientStreaming() {
reqArgs = append(reqArgs, "*"+g.typeName(method.GetInputType()))
}
if method.GetServerStreaming() || method.GetClientStreaming() {
reqArgs = append(reqArgs, servName+"_"+generator.CamelCase(origMethName)+"Server")
}
return methName + "(" + strings.Join(reqArgs, ", ") + ") " + ret
}
func (g *grpc) generateServerMethod(servName, fullServName string, method *pb.MethodDescriptorProto) string {
methName := generator.CamelCase(method.GetName())
hname := fmt.Sprintf("_%s_%s_Handler", servName, methName)
inType := g.typeName(method.GetInputType())
outType := g.typeName(method.GetOutputType())
if !method.GetServerStreaming() && !method.GetClientStreaming() {
g.P("func ", hname, "(srv interface{}, ctx ", contextPkg, ".Context, dec func(interface{}) error, interceptor ", grpcPkg, ".UnaryServerInterceptor) (interface{}, error) {")
g.P("in := new(", inType, ")")
g.P("if err := dec(in); err != nil { return nil, err }")
g.P("if interceptor == nil { return srv.(", servName, "Server).", methName, "(ctx, in) }")
g.P("info := &", grpcPkg, ".UnaryServerInfo{")
g.P("Server: srv,")
g.P("FullMethod: ", strconv.Quote(fmt.Sprintf("/%s/%s", fullServName, methName)), ",")
g.P("}")
g.P("handler := func(ctx ", contextPkg, ".Context, req interface{}) (interface{}, error) {")
g.P("return srv.(", servName, "Server).", methName, "(ctx, req.(*", inType, "))")
g.P("}")
g.P("return interceptor(ctx, in, info, handler)")
g.P("}")
g.P()
return hname
}
streamType := unexport(servName) + methName + "Server"
g.P("func ", hname, "(srv interface{}, stream ", grpcPkg, ".ServerStream) error {")
if !method.GetClientStreaming() {
g.P("m := new(", inType, ")")
g.P("if err := stream.RecvMsg(m); err != nil { return err }")
g.P("return srv.(", servName, "Server).", methName, "(m, &", streamType, "{stream})")
} else {
g.P("return srv.(", servName, "Server).", methName, "(&", streamType, "{stream})")
}
g.P("}")
g.P()
genSend := method.GetServerStreaming()
genSendAndClose := !method.GetServerStreaming()
genRecv := method.GetClientStreaming()
// Stream auxiliary types and methods.
g.P("type ", servName, "_", methName, "Server interface {")
if genSend {
g.P("Send(*", outType, ") error")
}
if genSendAndClose {
g.P("SendAndClose(*", outType, ") error")
}
if genRecv {
g.P("Recv() (*", inType, ", error)")
}
g.P(grpcPkg, ".ServerStream")
g.P("}")
g.P()
g.P("type ", streamType, " struct {")
g.P(grpcPkg, ".ServerStream")
g.P("}")
g.P()
if genSend {
g.P("func (x *", streamType, ") Send(m *", outType, ") error {")
g.P("return x.ServerStream.SendMsg(m)")
g.P("}")
g.P()
}
if genSendAndClose {
g.P("func (x *", streamType, ") SendAndClose(m *", outType, ") error {")
g.P("return x.ServerStream.SendMsg(m)")
g.P("}")
g.P()
}
if genRecv {
g.P("func (x *", streamType, ") Recv() (*", inType, ", error) {")
g.P("m := new(", inType, ")")
g.P("if err := x.ServerStream.RecvMsg(m); err != nil { return nil, err }")
g.P("return m, nil")
g.P("}")
g.P()
}
return hname
}

View file

@ -0,0 +1,57 @@
// Go support for Protocol Buffers - Google's data interchange format
//
// Copyright 2010 The Go Authors. All rights reserved.
// https://github.com/golang/protobuf
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// protoc-gen-go is a plugin for the Google protocol buffer compiler to generate
// Go code. Run it by building this program and putting it in your path with
// the name
// protoc-gen-gogo
// That word 'gogo' at the end becomes part of the option string set for the
// protocol compiler, so once the protocol compiler (protoc) is installed
// you can run
// protoc --gogo_out=output_directory input_directory/file.proto
// to generate Go bindings for the protocol defined by file.proto.
// With that input, the output will be written to
// output_directory/file.pb.go
//
// The generated code is documented in the package comment for
// the library.
//
// See the README and documentation for protocol buffers to learn more:
// https://developers.google.com/protocol-buffers/
package main
import (
"github.com/gogo/protobuf/vanity/command"
)
func main() {
command.Write(command.Generate(command.Read()))
}

View file

@ -0,0 +1,37 @@
# Go support for Protocol Buffers - Google's data interchange format
#
# Copyright 2010 The Go Authors. All rights reserved.
# https://github.com/golang/protobuf
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# Not stored here, but plugin.proto is in https://github.com/google/protobuf/
# at src/google/protobuf/compiler/plugin.proto
# Also we need to fix an import.
regenerate:
go install github.com/gogo/protobuf/protoc-gen-gogo
protoc --gogo_out=Mgoogle/protobuf/descriptor.proto=github.com/gogo/protobuf/protoc-gen-gogo/descriptor:. -I=../../protobuf/google/protobuf/compiler/:../../protobuf/ ../../protobuf/google/protobuf/compiler/plugin.proto

View file

@ -0,0 +1,365 @@
// Code generated by protoc-gen-gogo. DO NOT EDIT.
// source: plugin.proto
package plugin_go
import (
fmt "fmt"
proto "github.com/gogo/protobuf/proto"
descriptor "github.com/gogo/protobuf/protoc-gen-gogo/descriptor"
math "math"
)
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
// The version number of protocol compiler.
type Version struct {
Major *int32 `protobuf:"varint,1,opt,name=major" json:"major,omitempty"`
Minor *int32 `protobuf:"varint,2,opt,name=minor" json:"minor,omitempty"`
Patch *int32 `protobuf:"varint,3,opt,name=patch" json:"patch,omitempty"`
// A suffix for alpha, beta or rc release, e.g., "alpha-1", "rc2". It should
// be empty for mainline stable releases.
Suffix *string `protobuf:"bytes,4,opt,name=suffix" json:"suffix,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *Version) Reset() { *m = Version{} }
func (m *Version) String() string { return proto.CompactTextString(m) }
func (*Version) ProtoMessage() {}
func (*Version) Descriptor() ([]byte, []int) {
return fileDescriptor_22a625af4bc1cc87, []int{0}
}
func (m *Version) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_Version.Unmarshal(m, b)
}
func (m *Version) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_Version.Marshal(b, m, deterministic)
}
func (m *Version) XXX_Merge(src proto.Message) {
xxx_messageInfo_Version.Merge(m, src)
}
func (m *Version) XXX_Size() int {
return xxx_messageInfo_Version.Size(m)
}
func (m *Version) XXX_DiscardUnknown() {
xxx_messageInfo_Version.DiscardUnknown(m)
}
var xxx_messageInfo_Version proto.InternalMessageInfo
func (m *Version) GetMajor() int32 {
if m != nil && m.Major != nil {
return *m.Major
}
return 0
}
func (m *Version) GetMinor() int32 {
if m != nil && m.Minor != nil {
return *m.Minor
}
return 0
}
func (m *Version) GetPatch() int32 {
if m != nil && m.Patch != nil {
return *m.Patch
}
return 0
}
func (m *Version) GetSuffix() string {
if m != nil && m.Suffix != nil {
return *m.Suffix
}
return ""
}
// An encoded CodeGeneratorRequest is written to the plugin's stdin.
type CodeGeneratorRequest struct {
// The .proto files that were explicitly listed on the command-line. The
// code generator should generate code only for these files. Each file's
// descriptor will be included in proto_file, below.
FileToGenerate []string `protobuf:"bytes,1,rep,name=file_to_generate,json=fileToGenerate" json:"file_to_generate,omitempty"`
// The generator parameter passed on the command-line.
Parameter *string `protobuf:"bytes,2,opt,name=parameter" json:"parameter,omitempty"`
// FileDescriptorProtos for all files in files_to_generate and everything
// they import. The files will appear in topological order, so each file
// appears before any file that imports it.
//
// protoc guarantees that all proto_files will be written after
// the fields above, even though this is not technically guaranteed by the
// protobuf wire format. This theoretically could allow a plugin to stream
// in the FileDescriptorProtos and handle them one by one rather than read
// the entire set into memory at once. However, as of this writing, this
// is not similarly optimized on protoc's end -- it will store all fields in
// memory at once before sending them to the plugin.
//
// Type names of fields and extensions in the FileDescriptorProto are always
// fully qualified.
ProtoFile []*descriptor.FileDescriptorProto `protobuf:"bytes,15,rep,name=proto_file,json=protoFile" json:"proto_file,omitempty"`
// The version number of protocol compiler.
CompilerVersion *Version `protobuf:"bytes,3,opt,name=compiler_version,json=compilerVersion" json:"compiler_version,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *CodeGeneratorRequest) Reset() { *m = CodeGeneratorRequest{} }
func (m *CodeGeneratorRequest) String() string { return proto.CompactTextString(m) }
func (*CodeGeneratorRequest) ProtoMessage() {}
func (*CodeGeneratorRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_22a625af4bc1cc87, []int{1}
}
func (m *CodeGeneratorRequest) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_CodeGeneratorRequest.Unmarshal(m, b)
}
func (m *CodeGeneratorRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_CodeGeneratorRequest.Marshal(b, m, deterministic)
}
func (m *CodeGeneratorRequest) XXX_Merge(src proto.Message) {
xxx_messageInfo_CodeGeneratorRequest.Merge(m, src)
}
func (m *CodeGeneratorRequest) XXX_Size() int {
return xxx_messageInfo_CodeGeneratorRequest.Size(m)
}
func (m *CodeGeneratorRequest) XXX_DiscardUnknown() {
xxx_messageInfo_CodeGeneratorRequest.DiscardUnknown(m)
}
var xxx_messageInfo_CodeGeneratorRequest proto.InternalMessageInfo
func (m *CodeGeneratorRequest) GetFileToGenerate() []string {
if m != nil {
return m.FileToGenerate
}
return nil
}
func (m *CodeGeneratorRequest) GetParameter() string {
if m != nil && m.Parameter != nil {
return *m.Parameter
}
return ""
}
func (m *CodeGeneratorRequest) GetProtoFile() []*descriptor.FileDescriptorProto {
if m != nil {
return m.ProtoFile
}
return nil
}
func (m *CodeGeneratorRequest) GetCompilerVersion() *Version {
if m != nil {
return m.CompilerVersion
}
return nil
}
// The plugin writes an encoded CodeGeneratorResponse to stdout.
type CodeGeneratorResponse struct {
// Error message. If non-empty, code generation failed. The plugin process
// should exit with status code zero even if it reports an error in this way.
//
// This should be used to indicate errors in .proto files which prevent the
// code generator from generating correct code. Errors which indicate a
// problem in protoc itself -- such as the input CodeGeneratorRequest being
// unparseable -- should be reported by writing a message to stderr and
// exiting with a non-zero status code.
Error *string `protobuf:"bytes,1,opt,name=error" json:"error,omitempty"`
File []*CodeGeneratorResponse_File `protobuf:"bytes,15,rep,name=file" json:"file,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *CodeGeneratorResponse) Reset() { *m = CodeGeneratorResponse{} }
func (m *CodeGeneratorResponse) String() string { return proto.CompactTextString(m) }
func (*CodeGeneratorResponse) ProtoMessage() {}
func (*CodeGeneratorResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_22a625af4bc1cc87, []int{2}
}
func (m *CodeGeneratorResponse) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_CodeGeneratorResponse.Unmarshal(m, b)
}
func (m *CodeGeneratorResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_CodeGeneratorResponse.Marshal(b, m, deterministic)
}
func (m *CodeGeneratorResponse) XXX_Merge(src proto.Message) {
xxx_messageInfo_CodeGeneratorResponse.Merge(m, src)
}
func (m *CodeGeneratorResponse) XXX_Size() int {
return xxx_messageInfo_CodeGeneratorResponse.Size(m)
}
func (m *CodeGeneratorResponse) XXX_DiscardUnknown() {
xxx_messageInfo_CodeGeneratorResponse.DiscardUnknown(m)
}
var xxx_messageInfo_CodeGeneratorResponse proto.InternalMessageInfo
func (m *CodeGeneratorResponse) GetError() string {
if m != nil && m.Error != nil {
return *m.Error
}
return ""
}
func (m *CodeGeneratorResponse) GetFile() []*CodeGeneratorResponse_File {
if m != nil {
return m.File
}
return nil
}
// Represents a single generated file.
type CodeGeneratorResponse_File struct {
// The file name, relative to the output directory. The name must not
// contain "." or ".." components and must be relative, not be absolute (so,
// the file cannot lie outside the output directory). "/" must be used as
// the path separator, not "\".
//
// If the name is omitted, the content will be appended to the previous
// file. This allows the generator to break large files into small chunks,
// and allows the generated text to be streamed back to protoc so that large
// files need not reside completely in memory at one time. Note that as of
// this writing protoc does not optimize for this -- it will read the entire
// CodeGeneratorResponse before writing files to disk.
Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"`
// If non-empty, indicates that the named file should already exist, and the
// content here is to be inserted into that file at a defined insertion
// point. This feature allows a code generator to extend the output
// produced by another code generator. The original generator may provide
// insertion points by placing special annotations in the file that look
// like:
// @@protoc_insertion_point(NAME)
// The annotation can have arbitrary text before and after it on the line,
// which allows it to be placed in a comment. NAME should be replaced with
// an identifier naming the point -- this is what other generators will use
// as the insertion_point. Code inserted at this point will be placed
// immediately above the line containing the insertion point (thus multiple
// insertions to the same point will come out in the order they were added).
// The double-@ is intended to make it unlikely that the generated code
// could contain things that look like insertion points by accident.
//
// For example, the C++ code generator places the following line in the
// .pb.h files that it generates:
// // @@protoc_insertion_point(namespace_scope)
// This line appears within the scope of the file's package namespace, but
// outside of any particular class. Another plugin can then specify the
// insertion_point "namespace_scope" to generate additional classes or
// other declarations that should be placed in this scope.
//
// Note that if the line containing the insertion point begins with
// whitespace, the same whitespace will be added to every line of the
// inserted text. This is useful for languages like Python, where
// indentation matters. In these languages, the insertion point comment
// should be indented the same amount as any inserted code will need to be
// in order to work correctly in that context.
//
// The code generator that generates the initial file and the one which
// inserts into it must both run as part of a single invocation of protoc.
// Code generators are executed in the order in which they appear on the
// command line.
//
// If |insertion_point| is present, |name| must also be present.
InsertionPoint *string `protobuf:"bytes,2,opt,name=insertion_point,json=insertionPoint" json:"insertion_point,omitempty"`
// The file contents.
Content *string `protobuf:"bytes,15,opt,name=content" json:"content,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *CodeGeneratorResponse_File) Reset() { *m = CodeGeneratorResponse_File{} }
func (m *CodeGeneratorResponse_File) String() string { return proto.CompactTextString(m) }
func (*CodeGeneratorResponse_File) ProtoMessage() {}
func (*CodeGeneratorResponse_File) Descriptor() ([]byte, []int) {
return fileDescriptor_22a625af4bc1cc87, []int{2, 0}
}
func (m *CodeGeneratorResponse_File) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_CodeGeneratorResponse_File.Unmarshal(m, b)
}
func (m *CodeGeneratorResponse_File) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_CodeGeneratorResponse_File.Marshal(b, m, deterministic)
}
func (m *CodeGeneratorResponse_File) XXX_Merge(src proto.Message) {
xxx_messageInfo_CodeGeneratorResponse_File.Merge(m, src)
}
func (m *CodeGeneratorResponse_File) XXX_Size() int {
return xxx_messageInfo_CodeGeneratorResponse_File.Size(m)
}
func (m *CodeGeneratorResponse_File) XXX_DiscardUnknown() {
xxx_messageInfo_CodeGeneratorResponse_File.DiscardUnknown(m)
}
var xxx_messageInfo_CodeGeneratorResponse_File proto.InternalMessageInfo
func (m *CodeGeneratorResponse_File) GetName() string {
if m != nil && m.Name != nil {
return *m.Name
}
return ""
}
func (m *CodeGeneratorResponse_File) GetInsertionPoint() string {
if m != nil && m.InsertionPoint != nil {
return *m.InsertionPoint
}
return ""
}
func (m *CodeGeneratorResponse_File) GetContent() string {
if m != nil && m.Content != nil {
return *m.Content
}
return ""
}
func init() {
proto.RegisterType((*Version)(nil), "google.protobuf.compiler.Version")
proto.RegisterType((*CodeGeneratorRequest)(nil), "google.protobuf.compiler.CodeGeneratorRequest")
proto.RegisterType((*CodeGeneratorResponse)(nil), "google.protobuf.compiler.CodeGeneratorResponse")
proto.RegisterType((*CodeGeneratorResponse_File)(nil), "google.protobuf.compiler.CodeGeneratorResponse.File")
}
func init() { proto.RegisterFile("plugin.proto", fileDescriptor_22a625af4bc1cc87) }
var fileDescriptor_22a625af4bc1cc87 = []byte{
// 383 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x74, 0x92, 0xcd, 0x6a, 0xd5, 0x40,
0x14, 0xc7, 0x89, 0x37, 0xb5, 0xe4, 0xb4, 0x34, 0x65, 0xa8, 0x32, 0x94, 0x2e, 0xe2, 0x45, 0x30,
0xab, 0x14, 0x8a, 0xe0, 0xbe, 0x15, 0x75, 0xe1, 0xe2, 0x32, 0x88, 0x0b, 0x41, 0x42, 0x4c, 0x4f,
0xe2, 0x48, 0x32, 0x67, 0x9c, 0x99, 0x88, 0x4f, 0xea, 0x7b, 0xf8, 0x06, 0x32, 0x1f, 0xa9, 0x72,
0xf1, 0xee, 0xe6, 0xff, 0x3b, 0xf3, 0x71, 0xce, 0x8f, 0x81, 0x53, 0x3d, 0x2d, 0xa3, 0x54, 0x8d,
0x36, 0xe4, 0x88, 0xf1, 0x91, 0x68, 0x9c, 0x30, 0xa6, 0x2f, 0xcb, 0xd0, 0xf4, 0x34, 0x6b, 0x39,
0xa1, 0xb9, 0xac, 0x62, 0xe5, 0x7a, 0xad, 0x5c, 0xdf, 0xa3, 0xed, 0x8d, 0xd4, 0x8e, 0x4c, 0xdc,
0xbd, 0xed, 0xe1, 0xf8, 0x23, 0x1a, 0x2b, 0x49, 0xb1, 0x0b, 0x38, 0x9a, 0xbb, 0x6f, 0x64, 0x78,
0x56, 0x65, 0xf5, 0x91, 0x88, 0x21, 0x50, 0xa9, 0xc8, 0xf0, 0x47, 0x89, 0xfa, 0xe0, 0xa9, 0xee,
0x5c, 0xff, 0x95, 0x6f, 0x22, 0x0d, 0x81, 0x3d, 0x85, 0xc7, 0x76, 0x19, 0x06, 0xf9, 0x93, 0xe7,
0x55, 0x56, 0x17, 0x22, 0xa5, 0xed, 0xef, 0x0c, 0x2e, 0xee, 0xe8, 0x1e, 0xdf, 0xa2, 0x42, 0xd3,
0x39, 0x32, 0x02, 0xbf, 0x2f, 0x68, 0x1d, 0xab, 0xe1, 0x7c, 0x90, 0x13, 0xb6, 0x8e, 0xda, 0x31,
0xd6, 0x90, 0x67, 0xd5, 0xa6, 0x2e, 0xc4, 0x99, 0xe7, 0x1f, 0x28, 0x9d, 0x40, 0x76, 0x05, 0x85,
0xee, 0x4c, 0x37, 0xa3, 0xc3, 0xd8, 0x4a, 0x21, 0xfe, 0x02, 0x76, 0x07, 0x10, 0xc6, 0x69, 0xfd,
0x29, 0x5e, 0x56, 0x9b, 0xfa, 0xe4, 0xe6, 0x79, 0xb3, 0xaf, 0xe5, 0x8d, 0x9c, 0xf0, 0xf5, 0x83,
0x80, 0x9d, 0xc7, 0xa2, 0x08, 0x55, 0x5f, 0x61, 0xef, 0xe1, 0x7c, 0x15, 0xd7, 0xfe, 0x88, 0x4e,
0xc2, 0x78, 0x27, 0x37, 0xcf, 0x9a, 0x43, 0x86, 0x9b, 0x24, 0x4f, 0x94, 0x2b, 0x49, 0x60, 0xfb,
0x2b, 0x83, 0x27, 0x7b, 0x33, 0x5b, 0x4d, 0xca, 0xa2, 0x77, 0x87, 0xc6, 0x24, 0xcf, 0x85, 0x88,
0x81, 0xbd, 0x83, 0xfc, 0x9f, 0xe6, 0x5f, 0x1e, 0x7e, 0xf1, 0xbf, 0x97, 0x86, 0xd9, 0x44, 0xb8,
0xe1, 0xf2, 0x33, 0xe4, 0x61, 0x1e, 0x06, 0xb9, 0xea, 0x66, 0x4c, 0xcf, 0x84, 0x35, 0x7b, 0x01,
0xa5, 0x54, 0x16, 0x8d, 0x93, 0xa4, 0x5a, 0x4d, 0x52, 0xb9, 0x24, 0xf3, 0xec, 0x01, 0xef, 0x3c,
0x65, 0x1c, 0x8e, 0x7b, 0x52, 0x0e, 0x95, 0xe3, 0x65, 0xd8, 0xb0, 0xc6, 0xdb, 0x57, 0x70, 0xd5,
0xd3, 0x7c, 0xb0, 0xbf, 0xdb, 0xd3, 0x5d, 0xf8, 0x9b, 0x41, 0xaf, 0xfd, 0x54, 0xc4, 0x9f, 0xda,
0x8e, 0xf4, 0x27, 0x00, 0x00, 0xff, 0xff, 0x7a, 0x72, 0x3d, 0x18, 0xb5, 0x02, 0x00, 0x00,
}

View file

@ -0,0 +1,47 @@
// Protocol Buffers for Go with Gadgets
//
// Copyright (c) 2015, The GoGo Authors. All rights reserved.
// http://github.com/gogo/protobuf
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package main
import (
"github.com/gogo/protobuf/vanity"
"github.com/gogo/protobuf/vanity/command"
)
func main() {
req := command.Read()
files := req.GetProtoFile()
files = vanity.FilterFiles(files, vanity.NotGoogleProtobufDescriptorProto)
vanity.ForEachFile(files, vanity.TurnOnMarshalerAll)
vanity.ForEachFile(files, vanity.TurnOnSizerAll)
vanity.ForEachFile(files, vanity.TurnOnUnmarshalerAll)
resp := command.Generate(req)
command.Write(resp)
}

View file

@ -0,0 +1,61 @@
// Protocol Buffers for Go with Gadgets
//
// Copyright (c) 2015, The GoGo Authors. All rights reserved.
// http://github.com/gogo/protobuf
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package main
import (
"github.com/gogo/protobuf/vanity"
"github.com/gogo/protobuf/vanity/command"
)
func main() {
req := command.Read()
files := req.GetProtoFile()
files = vanity.FilterFiles(files, vanity.NotGoogleProtobufDescriptorProto)
vanity.ForEachFile(files, vanity.TurnOnMarshalerAll)
vanity.ForEachFile(files, vanity.TurnOnSizerAll)
vanity.ForEachFile(files, vanity.TurnOnUnmarshalerAll)
vanity.ForEachFieldInFilesExcludingExtensions(vanity.OnlyProto2(files), vanity.TurnOffNullableForNativeTypesWithoutDefaultsOnly)
vanity.ForEachFile(files, vanity.TurnOffGoUnrecognizedAll)
vanity.ForEachFile(files, vanity.TurnOffGoUnkeyedAll)
vanity.ForEachFile(files, vanity.TurnOffGoSizecacheAll)
vanity.ForEachFile(files, vanity.TurnOffGoEnumPrefixAll)
vanity.ForEachFile(files, vanity.TurnOffGoEnumStringerAll)
vanity.ForEachFile(files, vanity.TurnOnEnumStringerAll)
vanity.ForEachFile(files, vanity.TurnOnEqualAll)
vanity.ForEachFile(files, vanity.TurnOnGoStringAll)
vanity.ForEachFile(files, vanity.TurnOffGoStringerAll)
vanity.ForEachFile(files, vanity.TurnOnStringerAll)
resp := command.Generate(req)
command.Write(resp)
}

View file

@ -0,0 +1,161 @@
// Protocol Buffers for Go with Gadgets
//
// Copyright (c) 2015, The GoGo Authors. All rights reserved.
// http://github.com/gogo/protobuf
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package command
import (
"fmt"
"go/format"
"io/ioutil"
"os"
"strings"
_ "github.com/gogo/protobuf/plugin/compare"
_ "github.com/gogo/protobuf/plugin/defaultcheck"
_ "github.com/gogo/protobuf/plugin/description"
_ "github.com/gogo/protobuf/plugin/embedcheck"
_ "github.com/gogo/protobuf/plugin/enumstringer"
_ "github.com/gogo/protobuf/plugin/equal"
_ "github.com/gogo/protobuf/plugin/face"
_ "github.com/gogo/protobuf/plugin/gostring"
_ "github.com/gogo/protobuf/plugin/marshalto"
_ "github.com/gogo/protobuf/plugin/oneofcheck"
_ "github.com/gogo/protobuf/plugin/populate"
_ "github.com/gogo/protobuf/plugin/size"
_ "github.com/gogo/protobuf/plugin/stringer"
"github.com/gogo/protobuf/plugin/testgen"
_ "github.com/gogo/protobuf/plugin/union"
_ "github.com/gogo/protobuf/plugin/unmarshal"
"github.com/gogo/protobuf/proto"
"github.com/gogo/protobuf/protoc-gen-gogo/generator"
_ "github.com/gogo/protobuf/protoc-gen-gogo/grpc"
plugin "github.com/gogo/protobuf/protoc-gen-gogo/plugin"
)
func Read() *plugin.CodeGeneratorRequest {
g := generator.New()
data, err := ioutil.ReadAll(os.Stdin)
if err != nil {
g.Error(err, "reading input")
}
if err := proto.Unmarshal(data, g.Request); err != nil {
g.Error(err, "parsing input proto")
}
if len(g.Request.FileToGenerate) == 0 {
g.Fail("no files to generate")
}
return g.Request
}
// filenameSuffix replaces the .pb.go at the end of each filename.
func GeneratePlugin(req *plugin.CodeGeneratorRequest, p generator.Plugin, filenameSuffix string) *plugin.CodeGeneratorResponse {
g := generator.New()
g.Request = req
if len(g.Request.FileToGenerate) == 0 {
g.Fail("no files to generate")
}
g.CommandLineParameters(g.Request.GetParameter())
g.WrapTypes()
g.SetPackageNames()
g.BuildTypeNameMap()
g.GeneratePlugin(p)
for i := 0; i < len(g.Response.File); i++ {
g.Response.File[i].Name = proto.String(
strings.Replace(*g.Response.File[i].Name, ".pb.go", filenameSuffix, -1),
)
}
if err := goformat(g.Response); err != nil {
g.Error(err)
}
return g.Response
}
func goformat(resp *plugin.CodeGeneratorResponse) error {
for i := 0; i < len(resp.File); i++ {
formatted, err := format.Source([]byte(resp.File[i].GetContent()))
if err != nil {
return fmt.Errorf("go format error: %v", err)
}
fmts := string(formatted)
resp.File[i].Content = &fmts
}
return nil
}
func Generate(req *plugin.CodeGeneratorRequest) *plugin.CodeGeneratorResponse {
// Begin by allocating a generator. The request and response structures are stored there
// so we can do error handling easily - the response structure contains the field to
// report failure.
g := generator.New()
g.Request = req
g.CommandLineParameters(g.Request.GetParameter())
// Create a wrapped version of the Descriptors and EnumDescriptors that
// point to the file that defines them.
g.WrapTypes()
g.SetPackageNames()
g.BuildTypeNameMap()
g.GenerateAllFiles()
if err := goformat(g.Response); err != nil {
g.Error(err)
}
testReq := proto.Clone(req).(*plugin.CodeGeneratorRequest)
testResp := GeneratePlugin(testReq, testgen.NewPlugin(), "pb_test.go")
for i := 0; i < len(testResp.File); i++ {
if strings.Contains(*testResp.File[i].Content, `//These tests are generated by github.com/gogo/protobuf/plugin/testgen`) {
g.Response.File = append(g.Response.File, testResp.File[i])
}
}
return g.Response
}
func Write(resp *plugin.CodeGeneratorResponse) {
g := generator.New()
// Send back the results.
data, err := proto.Marshal(resp)
if err != nil {
g.Error(err, "failed to marshal output proto")
}
_, err = os.Stdout.Write(data)
if err != nil {
g.Error(err, "failed to write output proto")
}
}

78
vendor/github.com/gogo/protobuf/vanity/enum.go generated vendored Normal file
View file

@ -0,0 +1,78 @@
// Protocol Buffers for Go with Gadgets
//
// Copyright (c) 2015, The GoGo Authors. rights reserved.
// http://github.com/gogo/protobuf
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package vanity
import (
"github.com/gogo/protobuf/gogoproto"
"github.com/gogo/protobuf/proto"
descriptor "github.com/gogo/protobuf/protoc-gen-gogo/descriptor"
)
func EnumHasBoolExtension(enum *descriptor.EnumDescriptorProto, extension *proto.ExtensionDesc) bool {
if enum.Options == nil {
return false
}
value, err := proto.GetExtension(enum.Options, extension)
if err != nil {
return false
}
if value == nil {
return false
}
if value.(*bool) == nil {
return false
}
return true
}
func SetBoolEnumOption(extension *proto.ExtensionDesc, value bool) func(enum *descriptor.EnumDescriptorProto) {
return func(enum *descriptor.EnumDescriptorProto) {
if EnumHasBoolExtension(enum, extension) {
return
}
if enum.Options == nil {
enum.Options = &descriptor.EnumOptions{}
}
if err := proto.SetExtension(enum.Options, extension, &value); err != nil {
panic(err)
}
}
}
func TurnOffGoEnumPrefix(enum *descriptor.EnumDescriptorProto) {
SetBoolEnumOption(gogoproto.E_GoprotoEnumPrefix, false)(enum)
}
func TurnOffGoEnumStringer(enum *descriptor.EnumDescriptorProto) {
SetBoolEnumOption(gogoproto.E_GoprotoEnumStringer, false)(enum)
}
func TurnOnEnumStringer(enum *descriptor.EnumDescriptorProto) {
SetBoolEnumOption(gogoproto.E_EnumStringer, true)(enum)
}

90
vendor/github.com/gogo/protobuf/vanity/field.go generated vendored Normal file
View file

@ -0,0 +1,90 @@
// Protocol Buffers for Go with Gadgets
//
// Copyright (c) 2015, The GoGo Authors. rights reserved.
// http://github.com/gogo/protobuf
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package vanity
import (
"github.com/gogo/protobuf/gogoproto"
"github.com/gogo/protobuf/proto"
descriptor "github.com/gogo/protobuf/protoc-gen-gogo/descriptor"
)
func FieldHasBoolExtension(field *descriptor.FieldDescriptorProto, extension *proto.ExtensionDesc) bool {
if field.Options == nil {
return false
}
value, err := proto.GetExtension(field.Options, extension)
if err != nil {
return false
}
if value == nil {
return false
}
if value.(*bool) == nil {
return false
}
return true
}
func SetBoolFieldOption(extension *proto.ExtensionDesc, value bool) func(field *descriptor.FieldDescriptorProto) {
return func(field *descriptor.FieldDescriptorProto) {
if FieldHasBoolExtension(field, extension) {
return
}
if field.Options == nil {
field.Options = &descriptor.FieldOptions{}
}
if err := proto.SetExtension(field.Options, extension, &value); err != nil {
panic(err)
}
}
}
func TurnOffNullable(field *descriptor.FieldDescriptorProto) {
if field.IsRepeated() && !field.IsMessage() {
return
}
SetBoolFieldOption(gogoproto.E_Nullable, false)(field)
}
func TurnOffNullableForNativeTypes(field *descriptor.FieldDescriptorProto) {
if field.IsRepeated() || field.IsMessage() {
return
}
SetBoolFieldOption(gogoproto.E_Nullable, false)(field)
}
func TurnOffNullableForNativeTypesWithoutDefaultsOnly(field *descriptor.FieldDescriptorProto) {
if field.IsRepeated() || field.IsMessage() {
return
}
if field.DefaultValue != nil {
return
}
SetBoolFieldOption(gogoproto.E_Nullable, false)(field)
}

197
vendor/github.com/gogo/protobuf/vanity/file.go generated vendored Normal file
View file

@ -0,0 +1,197 @@
// Protocol Buffers for Go with Gadgets
//
// Copyright (c) 2015, The GoGo Authors. All rights reserved.
// http://github.com/gogo/protobuf
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package vanity
import (
"path/filepath"
"github.com/gogo/protobuf/gogoproto"
"github.com/gogo/protobuf/proto"
descriptor "github.com/gogo/protobuf/protoc-gen-gogo/descriptor"
)
func NotGoogleProtobufDescriptorProto(file *descriptor.FileDescriptorProto) bool {
// can not just check if file.GetName() == "google/protobuf/descriptor.proto" because we do not want to assume compile path
_, fileName := filepath.Split(file.GetName())
return !(file.GetPackage() == "google.protobuf" && fileName == "descriptor.proto")
}
func FilterFiles(files []*descriptor.FileDescriptorProto, f func(file *descriptor.FileDescriptorProto) bool) []*descriptor.FileDescriptorProto {
filtered := make([]*descriptor.FileDescriptorProto, 0, len(files))
for i := range files {
if !f(files[i]) {
continue
}
filtered = append(filtered, files[i])
}
return filtered
}
func FileHasBoolExtension(file *descriptor.FileDescriptorProto, extension *proto.ExtensionDesc) bool {
if file.Options == nil {
return false
}
value, err := proto.GetExtension(file.Options, extension)
if err != nil {
return false
}
if value == nil {
return false
}
if value.(*bool) == nil {
return false
}
return true
}
func SetBoolFileOption(extension *proto.ExtensionDesc, value bool) func(file *descriptor.FileDescriptorProto) {
return func(file *descriptor.FileDescriptorProto) {
if FileHasBoolExtension(file, extension) {
return
}
if file.Options == nil {
file.Options = &descriptor.FileOptions{}
}
if err := proto.SetExtension(file.Options, extension, &value); err != nil {
panic(err)
}
}
}
func TurnOffGoGettersAll(file *descriptor.FileDescriptorProto) {
SetBoolFileOption(gogoproto.E_GoprotoGettersAll, false)(file)
}
func TurnOffGoEnumPrefixAll(file *descriptor.FileDescriptorProto) {
SetBoolFileOption(gogoproto.E_GoprotoEnumPrefixAll, false)(file)
}
func TurnOffGoStringerAll(file *descriptor.FileDescriptorProto) {
SetBoolFileOption(gogoproto.E_GoprotoStringerAll, false)(file)
}
func TurnOnVerboseEqualAll(file *descriptor.FileDescriptorProto) {
SetBoolFileOption(gogoproto.E_VerboseEqualAll, true)(file)
}
func TurnOnFaceAll(file *descriptor.FileDescriptorProto) {
SetBoolFileOption(gogoproto.E_FaceAll, true)(file)
}
func TurnOnGoStringAll(file *descriptor.FileDescriptorProto) {
SetBoolFileOption(gogoproto.E_GostringAll, true)(file)
}
func TurnOnPopulateAll(file *descriptor.FileDescriptorProto) {
SetBoolFileOption(gogoproto.E_PopulateAll, true)(file)
}
func TurnOnStringerAll(file *descriptor.FileDescriptorProto) {
SetBoolFileOption(gogoproto.E_StringerAll, true)(file)
}
func TurnOnEqualAll(file *descriptor.FileDescriptorProto) {
SetBoolFileOption(gogoproto.E_EqualAll, true)(file)
}
func TurnOnDescriptionAll(file *descriptor.FileDescriptorProto) {
SetBoolFileOption(gogoproto.E_DescriptionAll, true)(file)
}
func TurnOnTestGenAll(file *descriptor.FileDescriptorProto) {
SetBoolFileOption(gogoproto.E_TestgenAll, true)(file)
}
func TurnOnBenchGenAll(file *descriptor.FileDescriptorProto) {
SetBoolFileOption(gogoproto.E_BenchgenAll, true)(file)
}
func TurnOnMarshalerAll(file *descriptor.FileDescriptorProto) {
SetBoolFileOption(gogoproto.E_MarshalerAll, true)(file)
}
func TurnOnUnmarshalerAll(file *descriptor.FileDescriptorProto) {
SetBoolFileOption(gogoproto.E_UnmarshalerAll, true)(file)
}
func TurnOnStable_MarshalerAll(file *descriptor.FileDescriptorProto) {
SetBoolFileOption(gogoproto.E_StableMarshalerAll, true)(file)
}
func TurnOnSizerAll(file *descriptor.FileDescriptorProto) {
SetBoolFileOption(gogoproto.E_SizerAll, true)(file)
}
func TurnOffGoEnumStringerAll(file *descriptor.FileDescriptorProto) {
SetBoolFileOption(gogoproto.E_GoprotoEnumStringerAll, false)(file)
}
func TurnOnEnumStringerAll(file *descriptor.FileDescriptorProto) {
SetBoolFileOption(gogoproto.E_EnumStringerAll, true)(file)
}
func TurnOnUnsafeUnmarshalerAll(file *descriptor.FileDescriptorProto) {
SetBoolFileOption(gogoproto.E_UnsafeUnmarshalerAll, true)(file)
}
func TurnOnUnsafeMarshalerAll(file *descriptor.FileDescriptorProto) {
SetBoolFileOption(gogoproto.E_UnsafeMarshalerAll, true)(file)
}
func TurnOffGoExtensionsMapAll(file *descriptor.FileDescriptorProto) {
SetBoolFileOption(gogoproto.E_GoprotoExtensionsMapAll, false)(file)
}
func TurnOffGoUnrecognizedAll(file *descriptor.FileDescriptorProto) {
SetBoolFileOption(gogoproto.E_GoprotoUnrecognizedAll, false)(file)
}
func TurnOffGoUnkeyedAll(file *descriptor.FileDescriptorProto) {
SetBoolFileOption(gogoproto.E_GoprotoUnkeyedAll, false)(file)
}
func TurnOffGoSizecacheAll(file *descriptor.FileDescriptorProto) {
SetBoolFileOption(gogoproto.E_GoprotoSizecacheAll, false)(file)
}
func TurnOffGogoImport(file *descriptor.FileDescriptorProto) {
SetBoolFileOption(gogoproto.E_GogoprotoImport, false)(file)
}
func TurnOnCompareAll(file *descriptor.FileDescriptorProto) {
SetBoolFileOption(gogoproto.E_CompareAll, true)(file)
}
func TurnOnMessageNameAll(file *descriptor.FileDescriptorProto) {
SetBoolFileOption(gogoproto.E_MessagenameAll, true)(file)
}
func TurnOnGoRegistration(file *descriptor.FileDescriptorProto) {
SetBoolFileOption(gogoproto.E_GoprotoRegistration, true)(file)
}

125
vendor/github.com/gogo/protobuf/vanity/foreach.go generated vendored Normal file
View file

@ -0,0 +1,125 @@
// Protocol Buffers for Go with Gadgets
//
// Copyright (c) 2015, The GoGo Authors. All rights reserved.
// http://github.com/gogo/protobuf
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package vanity
import descriptor "github.com/gogo/protobuf/protoc-gen-gogo/descriptor"
func ForEachFile(files []*descriptor.FileDescriptorProto, f func(file *descriptor.FileDescriptorProto)) {
for _, file := range files {
f(file)
}
}
func OnlyProto2(files []*descriptor.FileDescriptorProto) []*descriptor.FileDescriptorProto {
outs := make([]*descriptor.FileDescriptorProto, 0, len(files))
for i, file := range files {
if file.GetSyntax() == "proto3" {
continue
}
outs = append(outs, files[i])
}
return outs
}
func OnlyProto3(files []*descriptor.FileDescriptorProto) []*descriptor.FileDescriptorProto {
outs := make([]*descriptor.FileDescriptorProto, 0, len(files))
for i, file := range files {
if file.GetSyntax() != "proto3" {
continue
}
outs = append(outs, files[i])
}
return outs
}
func ForEachMessageInFiles(files []*descriptor.FileDescriptorProto, f func(msg *descriptor.DescriptorProto)) {
for _, file := range files {
ForEachMessage(file.MessageType, f)
}
}
func ForEachMessage(msgs []*descriptor.DescriptorProto, f func(msg *descriptor.DescriptorProto)) {
for _, msg := range msgs {
f(msg)
ForEachMessage(msg.NestedType, f)
}
}
func ForEachFieldInFilesExcludingExtensions(files []*descriptor.FileDescriptorProto, f func(field *descriptor.FieldDescriptorProto)) {
for _, file := range files {
ForEachFieldExcludingExtensions(file.MessageType, f)
}
}
func ForEachFieldInFiles(files []*descriptor.FileDescriptorProto, f func(field *descriptor.FieldDescriptorProto)) {
for _, file := range files {
for _, ext := range file.Extension {
f(ext)
}
ForEachField(file.MessageType, f)
}
}
func ForEachFieldExcludingExtensions(msgs []*descriptor.DescriptorProto, f func(field *descriptor.FieldDescriptorProto)) {
for _, msg := range msgs {
for _, field := range msg.Field {
f(field)
}
ForEachField(msg.NestedType, f)
}
}
func ForEachField(msgs []*descriptor.DescriptorProto, f func(field *descriptor.FieldDescriptorProto)) {
for _, msg := range msgs {
for _, field := range msg.Field {
f(field)
}
for _, ext := range msg.Extension {
f(ext)
}
ForEachField(msg.NestedType, f)
}
}
func ForEachEnumInFiles(files []*descriptor.FileDescriptorProto, f func(enum *descriptor.EnumDescriptorProto)) {
for _, file := range files {
for _, enum := range file.EnumType {
f(enum)
}
}
}
func ForEachEnum(msgs []*descriptor.DescriptorProto, f func(field *descriptor.EnumDescriptorProto)) {
for _, msg := range msgs {
for _, field := range msg.EnumType {
f(field)
}
ForEachEnum(msg.NestedType, f)
}
}

154
vendor/github.com/gogo/protobuf/vanity/msg.go generated vendored Normal file
View file

@ -0,0 +1,154 @@
// Protocol Buffers for Go with Gadgets
//
// Copyright (c) 2015, The GoGo Authors. rights reserved.
// http://github.com/gogo/protobuf
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package vanity
import (
"github.com/gogo/protobuf/gogoproto"
"github.com/gogo/protobuf/proto"
descriptor "github.com/gogo/protobuf/protoc-gen-gogo/descriptor"
)
func MessageHasBoolExtension(msg *descriptor.DescriptorProto, extension *proto.ExtensionDesc) bool {
if msg.Options == nil {
return false
}
value, err := proto.GetExtension(msg.Options, extension)
if err != nil {
return false
}
if value == nil {
return false
}
if value.(*bool) == nil {
return false
}
return true
}
func SetBoolMessageOption(extension *proto.ExtensionDesc, value bool) func(msg *descriptor.DescriptorProto) {
return func(msg *descriptor.DescriptorProto) {
if MessageHasBoolExtension(msg, extension) {
return
}
if msg.Options == nil {
msg.Options = &descriptor.MessageOptions{}
}
if err := proto.SetExtension(msg.Options, extension, &value); err != nil {
panic(err)
}
}
}
func TurnOffGoGetters(msg *descriptor.DescriptorProto) {
SetBoolMessageOption(gogoproto.E_GoprotoGetters, false)(msg)
}
func TurnOffGoStringer(msg *descriptor.DescriptorProto) {
SetBoolMessageOption(gogoproto.E_GoprotoStringer, false)(msg)
}
func TurnOnVerboseEqual(msg *descriptor.DescriptorProto) {
SetBoolMessageOption(gogoproto.E_VerboseEqual, true)(msg)
}
func TurnOnFace(msg *descriptor.DescriptorProto) {
SetBoolMessageOption(gogoproto.E_Face, true)(msg)
}
func TurnOnGoString(msg *descriptor.DescriptorProto) {
SetBoolMessageOption(gogoproto.E_Face, true)(msg)
}
func TurnOnPopulate(msg *descriptor.DescriptorProto) {
SetBoolMessageOption(gogoproto.E_Populate, true)(msg)
}
func TurnOnStringer(msg *descriptor.DescriptorProto) {
SetBoolMessageOption(gogoproto.E_Stringer, true)(msg)
}
func TurnOnEqual(msg *descriptor.DescriptorProto) {
SetBoolMessageOption(gogoproto.E_Equal, true)(msg)
}
func TurnOnDescription(msg *descriptor.DescriptorProto) {
SetBoolMessageOption(gogoproto.E_Description, true)(msg)
}
func TurnOnTestGen(msg *descriptor.DescriptorProto) {
SetBoolMessageOption(gogoproto.E_Testgen, true)(msg)
}
func TurnOnBenchGen(msg *descriptor.DescriptorProto) {
SetBoolMessageOption(gogoproto.E_Benchgen, true)(msg)
}
func TurnOnMarshaler(msg *descriptor.DescriptorProto) {
SetBoolMessageOption(gogoproto.E_Marshaler, true)(msg)
}
func TurnOnUnmarshaler(msg *descriptor.DescriptorProto) {
SetBoolMessageOption(gogoproto.E_Unmarshaler, true)(msg)
}
func TurnOnSizer(msg *descriptor.DescriptorProto) {
SetBoolMessageOption(gogoproto.E_Sizer, true)(msg)
}
func TurnOnUnsafeUnmarshaler(msg *descriptor.DescriptorProto) {
SetBoolMessageOption(gogoproto.E_UnsafeUnmarshaler, true)(msg)
}
func TurnOnUnsafeMarshaler(msg *descriptor.DescriptorProto) {
SetBoolMessageOption(gogoproto.E_UnsafeMarshaler, true)(msg)
}
func TurnOffGoExtensionsMap(msg *descriptor.DescriptorProto) {
SetBoolMessageOption(gogoproto.E_GoprotoExtensionsMap, false)(msg)
}
func TurnOffGoUnrecognized(msg *descriptor.DescriptorProto) {
SetBoolMessageOption(gogoproto.E_GoprotoUnrecognized, false)(msg)
}
func TurnOffGoUnkeyed(msg *descriptor.DescriptorProto) {
SetBoolMessageOption(gogoproto.E_GoprotoUnkeyed, false)(msg)
}
func TurnOffGoSizecache(msg *descriptor.DescriptorProto) {
SetBoolMessageOption(gogoproto.E_GoprotoSizecache, false)(msg)
}
func TurnOnCompare(msg *descriptor.DescriptorProto) {
SetBoolMessageOption(gogoproto.E_Compare, true)(msg)
}
func TurnOnMessageName(msg *descriptor.DescriptorProto) {
SetBoolMessageOption(gogoproto.E_Messagename, true)(msg)
}

View file

@ -0,0 +1,398 @@
// Copyright 2018 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package gengogrpc contains the gRPC code generator.
package gengogrpc
import (
"fmt"
"strconv"
"strings"
"google.golang.org/protobuf/compiler/protogen"
"google.golang.org/protobuf/types/descriptorpb"
)
const (
contextPackage = protogen.GoImportPath("context")
grpcPackage = protogen.GoImportPath("google.golang.org/grpc")
codesPackage = protogen.GoImportPath("google.golang.org/grpc/codes")
statusPackage = protogen.GoImportPath("google.golang.org/grpc/status")
)
// GenerateFile generates a _grpc.pb.go file containing gRPC service definitions.
func GenerateFile(gen *protogen.Plugin, file *protogen.File) *protogen.GeneratedFile {
if len(file.Services) == 0 {
return nil
}
filename := file.GeneratedFilenamePrefix + "_grpc.pb.go"
g := gen.NewGeneratedFile(filename, file.GoImportPath)
g.P("// Code generated by protoc-gen-go-grpc. DO NOT EDIT.")
g.P()
g.P("package ", file.GoPackageName)
g.P()
GenerateFileContent(gen, file, g)
return g
}
// GenerateFileContent generates the gRPC service definitions, excluding the package statement.
func GenerateFileContent(gen *protogen.Plugin, file *protogen.File, g *protogen.GeneratedFile) {
if len(file.Services) == 0 {
return
}
// TODO: Remove this. We don't need to include these references any more.
g.P("// Reference imports to suppress errors if they are not otherwise used.")
g.P("var _ ", contextPackage.Ident("Context"))
g.P("var _ ", grpcPackage.Ident("ClientConnInterface"))
g.P()
g.P("// This is a compile-time assertion to ensure that this generated file")
g.P("// is compatible with the grpc package it is being compiled against.")
g.P("const _ = ", grpcPackage.Ident("SupportPackageIsVersion6"))
g.P()
for _, service := range file.Services {
genService(gen, file, g, service)
}
}
func genService(gen *protogen.Plugin, file *protogen.File, g *protogen.GeneratedFile, service *protogen.Service) {
clientName := service.GoName + "Client"
g.P("// ", clientName, " is the client API for ", service.GoName, " service.")
g.P("//")
g.P("// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.")
// Client interface.
if service.Desc.Options().(*descriptorpb.ServiceOptions).GetDeprecated() {
g.P("//")
g.P(deprecationComment)
}
g.Annotate(clientName, service.Location)
g.P("type ", clientName, " interface {")
for _, method := range service.Methods {
g.Annotate(clientName+"."+method.GoName, method.Location)
if method.Desc.Options().(*descriptorpb.MethodOptions).GetDeprecated() {
g.P(deprecationComment)
}
g.P(method.Comments.Leading,
clientSignature(g, method))
}
g.P("}")
g.P()
// Client structure.
g.P("type ", unexport(clientName), " struct {")
g.P("cc ", grpcPackage.Ident("ClientConnInterface"))
g.P("}")
g.P()
// NewClient factory.
if service.Desc.Options().(*descriptorpb.ServiceOptions).GetDeprecated() {
g.P(deprecationComment)
}
g.P("func New", clientName, " (cc ", grpcPackage.Ident("ClientConnInterface"), ") ", clientName, " {")
g.P("return &", unexport(clientName), "{cc}")
g.P("}")
g.P()
var methodIndex, streamIndex int
// Client method implementations.
for _, method := range service.Methods {
if !method.Desc.IsStreamingServer() && !method.Desc.IsStreamingClient() {
// Unary RPC method
genClientMethod(gen, file, g, method, methodIndex)
methodIndex++
} else {
// Streaming RPC method
genClientMethod(gen, file, g, method, streamIndex)
streamIndex++
}
}
// Server interface.
serverType := service.GoName + "Server"
g.P("// ", serverType, " is the server API for ", service.GoName, " service.")
if service.Desc.Options().(*descriptorpb.ServiceOptions).GetDeprecated() {
g.P("//")
g.P(deprecationComment)
}
g.Annotate(serverType, service.Location)
g.P("type ", serverType, " interface {")
for _, method := range service.Methods {
g.Annotate(serverType+"."+method.GoName, method.Location)
if method.Desc.Options().(*descriptorpb.MethodOptions).GetDeprecated() {
g.P(deprecationComment)
}
g.P(method.Comments.Leading,
serverSignature(g, method))
}
g.P("}")
g.P()
// Server Unimplemented struct for forward compatibility.
g.P("// Unimplemented", serverType, " can be embedded to have forward compatible implementations.")
g.P("type Unimplemented", serverType, " struct {")
g.P("}")
g.P()
for _, method := range service.Methods {
nilArg := ""
if !method.Desc.IsStreamingClient() && !method.Desc.IsStreamingServer() {
nilArg = "nil,"
}
g.P("func (*Unimplemented", serverType, ") ", serverSignature(g, method), "{")
g.P("return ", nilArg, statusPackage.Ident("Errorf"), "(", codesPackage.Ident("Unimplemented"), `, "method `, method.GoName, ` not implemented")`)
g.P("}")
}
g.P()
// Server registration.
if service.Desc.Options().(*descriptorpb.ServiceOptions).GetDeprecated() {
g.P(deprecationComment)
}
serviceDescVar := "_" + service.GoName + "_serviceDesc"
g.P("func Register", service.GoName, "Server(s *", grpcPackage.Ident("Server"), ", srv ", serverType, ") {")
g.P("s.RegisterService(&", serviceDescVar, `, srv)`)
g.P("}")
g.P()
// Server handler implementations.
var handlerNames []string
for _, method := range service.Methods {
hname := genServerMethod(gen, file, g, method)
handlerNames = append(handlerNames, hname)
}
// Service descriptor.
g.P("var ", serviceDescVar, " = ", grpcPackage.Ident("ServiceDesc"), " {")
g.P("ServiceName: ", strconv.Quote(string(service.Desc.FullName())), ",")
g.P("HandlerType: (*", serverType, ")(nil),")
g.P("Methods: []", grpcPackage.Ident("MethodDesc"), "{")
for i, method := range service.Methods {
if method.Desc.IsStreamingClient() || method.Desc.IsStreamingServer() {
continue
}
g.P("{")
g.P("MethodName: ", strconv.Quote(string(method.Desc.Name())), ",")
g.P("Handler: ", handlerNames[i], ",")
g.P("},")
}
g.P("},")
g.P("Streams: []", grpcPackage.Ident("StreamDesc"), "{")
for i, method := range service.Methods {
if !method.Desc.IsStreamingClient() && !method.Desc.IsStreamingServer() {
continue
}
g.P("{")
g.P("StreamName: ", strconv.Quote(string(method.Desc.Name())), ",")
g.P("Handler: ", handlerNames[i], ",")
if method.Desc.IsStreamingServer() {
g.P("ServerStreams: true,")
}
if method.Desc.IsStreamingClient() {
g.P("ClientStreams: true,")
}
g.P("},")
}
g.P("},")
g.P("Metadata: \"", file.Desc.Path(), "\",")
g.P("}")
g.P()
}
func clientSignature(g *protogen.GeneratedFile, method *protogen.Method) string {
s := method.GoName + "(ctx " + g.QualifiedGoIdent(contextPackage.Ident("Context"))
if !method.Desc.IsStreamingClient() {
s += ", in *" + g.QualifiedGoIdent(method.Input.GoIdent)
}
s += ", opts ..." + g.QualifiedGoIdent(grpcPackage.Ident("CallOption")) + ") ("
if !method.Desc.IsStreamingClient() && !method.Desc.IsStreamingServer() {
s += "*" + g.QualifiedGoIdent(method.Output.GoIdent)
} else {
s += method.Parent.GoName + "_" + method.GoName + "Client"
}
s += ", error)"
return s
}
func genClientMethod(gen *protogen.Plugin, file *protogen.File, g *protogen.GeneratedFile, method *protogen.Method, index int) {
service := method.Parent
sname := fmt.Sprintf("/%s/%s", service.Desc.FullName(), method.Desc.Name())
if method.Desc.Options().(*descriptorpb.MethodOptions).GetDeprecated() {
g.P(deprecationComment)
}
g.P("func (c *", unexport(service.GoName), "Client) ", clientSignature(g, method), "{")
if !method.Desc.IsStreamingServer() && !method.Desc.IsStreamingClient() {
g.P("out := new(", method.Output.GoIdent, ")")
g.P(`err := c.cc.Invoke(ctx, "`, sname, `", in, out, opts...)`)
g.P("if err != nil { return nil, err }")
g.P("return out, nil")
g.P("}")
g.P()
return
}
streamType := unexport(service.GoName) + method.GoName + "Client"
serviceDescVar := "_" + service.GoName + "_serviceDesc"
g.P("stream, err := c.cc.NewStream(ctx, &", serviceDescVar, ".Streams[", index, `], "`, sname, `", opts...)`)
g.P("if err != nil { return nil, err }")
g.P("x := &", streamType, "{stream}")
if !method.Desc.IsStreamingClient() {
g.P("if err := x.ClientStream.SendMsg(in); err != nil { return nil, err }")
g.P("if err := x.ClientStream.CloseSend(); err != nil { return nil, err }")
}
g.P("return x, nil")
g.P("}")
g.P()
genSend := method.Desc.IsStreamingClient()
genRecv := method.Desc.IsStreamingServer()
genCloseAndRecv := !method.Desc.IsStreamingServer()
// Stream auxiliary types and methods.
g.P("type ", service.GoName, "_", method.GoName, "Client interface {")
if genSend {
g.P("Send(*", method.Input.GoIdent, ") error")
}
if genRecv {
g.P("Recv() (*", method.Output.GoIdent, ", error)")
}
if genCloseAndRecv {
g.P("CloseAndRecv() (*", method.Output.GoIdent, ", error)")
}
g.P(grpcPackage.Ident("ClientStream"))
g.P("}")
g.P()
g.P("type ", streamType, " struct {")
g.P(grpcPackage.Ident("ClientStream"))
g.P("}")
g.P()
if genSend {
g.P("func (x *", streamType, ") Send(m *", method.Input.GoIdent, ") error {")
g.P("return x.ClientStream.SendMsg(m)")
g.P("}")
g.P()
}
if genRecv {
g.P("func (x *", streamType, ") Recv() (*", method.Output.GoIdent, ", error) {")
g.P("m := new(", method.Output.GoIdent, ")")
g.P("if err := x.ClientStream.RecvMsg(m); err != nil { return nil, err }")
g.P("return m, nil")
g.P("}")
g.P()
}
if genCloseAndRecv {
g.P("func (x *", streamType, ") CloseAndRecv() (*", method.Output.GoIdent, ", error) {")
g.P("if err := x.ClientStream.CloseSend(); err != nil { return nil, err }")
g.P("m := new(", method.Output.GoIdent, ")")
g.P("if err := x.ClientStream.RecvMsg(m); err != nil { return nil, err }")
g.P("return m, nil")
g.P("}")
g.P()
}
}
func serverSignature(g *protogen.GeneratedFile, method *protogen.Method) string {
var reqArgs []string
ret := "error"
if !method.Desc.IsStreamingClient() && !method.Desc.IsStreamingServer() {
reqArgs = append(reqArgs, g.QualifiedGoIdent(contextPackage.Ident("Context")))
ret = "(*" + g.QualifiedGoIdent(method.Output.GoIdent) + ", error)"
}
if !method.Desc.IsStreamingClient() {
reqArgs = append(reqArgs, "*"+g.QualifiedGoIdent(method.Input.GoIdent))
}
if method.Desc.IsStreamingClient() || method.Desc.IsStreamingServer() {
reqArgs = append(reqArgs, method.Parent.GoName+"_"+method.GoName+"Server")
}
return method.GoName + "(" + strings.Join(reqArgs, ", ") + ") " + ret
}
func genServerMethod(gen *protogen.Plugin, file *protogen.File, g *protogen.GeneratedFile, method *protogen.Method) string {
service := method.Parent
hname := fmt.Sprintf("_%s_%s_Handler", service.GoName, method.GoName)
if !method.Desc.IsStreamingClient() && !method.Desc.IsStreamingServer() {
g.P("func ", hname, "(srv interface{}, ctx ", contextPackage.Ident("Context"), ", dec func(interface{}) error, interceptor ", grpcPackage.Ident("UnaryServerInterceptor"), ") (interface{}, error) {")
g.P("in := new(", method.Input.GoIdent, ")")
g.P("if err := dec(in); err != nil { return nil, err }")
g.P("if interceptor == nil { return srv.(", service.GoName, "Server).", method.GoName, "(ctx, in) }")
g.P("info := &", grpcPackage.Ident("UnaryServerInfo"), "{")
g.P("Server: srv,")
g.P("FullMethod: ", strconv.Quote(fmt.Sprintf("/%s/%s", service.Desc.FullName(), method.GoName)), ",")
g.P("}")
g.P("handler := func(ctx ", contextPackage.Ident("Context"), ", req interface{}) (interface{}, error) {")
g.P("return srv.(", service.GoName, "Server).", method.GoName, "(ctx, req.(*", method.Input.GoIdent, "))")
g.P("}")
g.P("return interceptor(ctx, in, info, handler)")
g.P("}")
g.P()
return hname
}
streamType := unexport(service.GoName) + method.GoName + "Server"
g.P("func ", hname, "(srv interface{}, stream ", grpcPackage.Ident("ServerStream"), ") error {")
if !method.Desc.IsStreamingClient() {
g.P("m := new(", method.Input.GoIdent, ")")
g.P("if err := stream.RecvMsg(m); err != nil { return err }")
g.P("return srv.(", service.GoName, "Server).", method.GoName, "(m, &", streamType, "{stream})")
} else {
g.P("return srv.(", service.GoName, "Server).", method.GoName, "(&", streamType, "{stream})")
}
g.P("}")
g.P()
genSend := method.Desc.IsStreamingServer()
genSendAndClose := !method.Desc.IsStreamingServer()
genRecv := method.Desc.IsStreamingClient()
// Stream auxiliary types and methods.
g.P("type ", service.GoName, "_", method.GoName, "Server interface {")
if genSend {
g.P("Send(*", method.Output.GoIdent, ") error")
}
if genSendAndClose {
g.P("SendAndClose(*", method.Output.GoIdent, ") error")
}
if genRecv {
g.P("Recv() (*", method.Input.GoIdent, ", error)")
}
g.P(grpcPackage.Ident("ServerStream"))
g.P("}")
g.P()
g.P("type ", streamType, " struct {")
g.P(grpcPackage.Ident("ServerStream"))
g.P("}")
g.P()
if genSend {
g.P("func (x *", streamType, ") Send(m *", method.Output.GoIdent, ") error {")
g.P("return x.ServerStream.SendMsg(m)")
g.P("}")
g.P()
}
if genSendAndClose {
g.P("func (x *", streamType, ") SendAndClose(m *", method.Output.GoIdent, ") error {")
g.P("return x.ServerStream.SendMsg(m)")
g.P("}")
g.P()
}
if genRecv {
g.P("func (x *", streamType, ") Recv() (*", method.Input.GoIdent, ", error) {")
g.P("m := new(", method.Input.GoIdent, ")")
g.P("if err := x.ServerStream.RecvMsg(m); err != nil { return nil, err }")
g.P("return m, nil")
g.P("}")
g.P()
}
return hname
}
const deprecationComment = "// Deprecated: Do not use."
func unexport(s string) string { return strings.ToLower(s[:1]) + s[1:] }

View file

@ -0,0 +1,74 @@
// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// protoc-gen-go is a plugin for the Google protocol buffer compiler to generate
// Go code. Install it by building this program and making it accessible within
// your PATH with the name:
// protoc-gen-go
//
// The 'go' suffix becomes part of the argument for the protocol compiler,
// such that it can be invoked as:
// protoc --go_out=paths=source_relative:. path/to/file.proto
//
// This generates Go bindings for the protocol buffer defined by file.proto.
// With that input, the output will be written to:
// path/to/file.pb.go
//
// See the README and documentation for protocol buffers to learn more:
// https://developers.google.com/protocol-buffers/
package main
import (
"flag"
"fmt"
"strings"
"github.com/golang/protobuf/internal/gengogrpc"
gengo "google.golang.org/protobuf/cmd/protoc-gen-go/internal_gengo"
"google.golang.org/protobuf/compiler/protogen"
)
func main() {
var (
flags flag.FlagSet
plugins = flags.String("plugins", "", "list of plugins to enable (supported values: grpc)")
importPrefix = flags.String("import_prefix", "", "prefix to prepend to import paths")
)
importRewriteFunc := func(importPath protogen.GoImportPath) protogen.GoImportPath {
switch importPath {
case "context", "fmt", "math":
return importPath
}
if *importPrefix != "" {
return protogen.GoImportPath(*importPrefix) + importPath
}
return importPath
}
protogen.Options{
ParamFunc: flags.Set,
ImportRewriteFunc: importRewriteFunc,
}.Run(func(gen *protogen.Plugin) error {
grpc := false
for _, plugin := range strings.Split(*plugins, ",") {
switch plugin {
case "grpc":
grpc = true
case "":
default:
return fmt.Errorf("protoc-gen-go: unknown plugin %q", plugin)
}
}
for _, f := range gen.Files {
if !f.Generate {
continue
}
g := gengo.GenerateFile(gen, f)
if grpc {
gengogrpc.GenerateFileContent(gen, f, g)
}
}
gen.SupportedFeatures = gengo.SupportedFeatures
return nil
})
}

View file

@ -0,0 +1,168 @@
// Copyright 2019 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package internal_gengo
import (
"unicode"
"unicode/utf8"
"google.golang.org/protobuf/compiler/protogen"
"google.golang.org/protobuf/encoding/protowire"
"google.golang.org/protobuf/types/descriptorpb"
)
type fileInfo struct {
*protogen.File
allEnums []*enumInfo
allMessages []*messageInfo
allExtensions []*extensionInfo
allEnumsByPtr map[*enumInfo]int // value is index into allEnums
allMessagesByPtr map[*messageInfo]int // value is index into allMessages
allMessageFieldsByPtr map[*messageInfo]*structFields
// needRawDesc specifies whether the generator should emit logic to provide
// the legacy raw descriptor in GZIP'd form.
// This is updated by enum and message generation logic as necessary,
// and checked at the end of file generation.
needRawDesc bool
}
type structFields struct {
count int
unexported map[int]string
}
func (sf *structFields) append(name string) {
if r, _ := utf8.DecodeRuneInString(name); !unicode.IsUpper(r) {
if sf.unexported == nil {
sf.unexported = make(map[int]string)
}
sf.unexported[sf.count] = name
}
sf.count++
}
func newFileInfo(file *protogen.File) *fileInfo {
f := &fileInfo{File: file}
// Collect all enums, messages, and extensions in "flattened ordering".
// See filetype.TypeBuilder.
var walkMessages func([]*protogen.Message, func(*protogen.Message))
walkMessages = func(messages []*protogen.Message, f func(*protogen.Message)) {
for _, m := range messages {
f(m)
walkMessages(m.Messages, f)
}
}
initEnumInfos := func(enums []*protogen.Enum) {
for _, enum := range enums {
f.allEnums = append(f.allEnums, newEnumInfo(f, enum))
}
}
initMessageInfos := func(messages []*protogen.Message) {
for _, message := range messages {
f.allMessages = append(f.allMessages, newMessageInfo(f, message))
}
}
initExtensionInfos := func(extensions []*protogen.Extension) {
for _, extension := range extensions {
f.allExtensions = append(f.allExtensions, newExtensionInfo(f, extension))
}
}
initEnumInfos(f.Enums)
initMessageInfos(f.Messages)
initExtensionInfos(f.Extensions)
walkMessages(f.Messages, func(m *protogen.Message) {
initEnumInfos(m.Enums)
initMessageInfos(m.Messages)
initExtensionInfos(m.Extensions)
})
// Derive a reverse mapping of enum and message pointers to their index
// in allEnums and allMessages.
if len(f.allEnums) > 0 {
f.allEnumsByPtr = make(map[*enumInfo]int)
for i, e := range f.allEnums {
f.allEnumsByPtr[e] = i
}
}
if len(f.allMessages) > 0 {
f.allMessagesByPtr = make(map[*messageInfo]int)
f.allMessageFieldsByPtr = make(map[*messageInfo]*structFields)
for i, m := range f.allMessages {
f.allMessagesByPtr[m] = i
f.allMessageFieldsByPtr[m] = new(structFields)
}
}
return f
}
type enumInfo struct {
*protogen.Enum
genJSONMethod bool
genRawDescMethod bool
}
func newEnumInfo(f *fileInfo, enum *protogen.Enum) *enumInfo {
e := &enumInfo{Enum: enum}
e.genJSONMethod = true
e.genRawDescMethod = true
return e
}
type messageInfo struct {
*protogen.Message
genRawDescMethod bool
genExtRangeMethod bool
isTracked bool
hasWeak bool
}
func newMessageInfo(f *fileInfo, message *protogen.Message) *messageInfo {
m := &messageInfo{Message: message}
m.genRawDescMethod = true
m.genExtRangeMethod = true
m.isTracked = isTrackedMessage(m)
for _, field := range m.Fields {
m.hasWeak = m.hasWeak || field.Desc.IsWeak()
}
return m
}
// isTrackedMessage reports whether field tracking is enabled on the message.
func isTrackedMessage(m *messageInfo) (tracked bool) {
const trackFieldUse_fieldNumber = 37383685
// Decode the option from unknown fields to avoid a dependency on the
// annotation proto from protoc-gen-go.
b := m.Desc.Options().(*descriptorpb.MessageOptions).ProtoReflect().GetUnknown()
for len(b) > 0 {
num, typ, n := protowire.ConsumeTag(b)
b = b[n:]
if num == trackFieldUse_fieldNumber && typ == protowire.VarintType {
v, _ := protowire.ConsumeVarint(b)
tracked = protowire.DecodeBool(v)
}
m := protowire.ConsumeFieldValue(num, typ, b)
b = b[m:]
}
return tracked
}
type extensionInfo struct {
*protogen.Extension
}
func newExtensionInfo(f *fileInfo, extension *protogen.Extension) *extensionInfo {
x := &extensionInfo{Extension: extension}
return x
}

View file

@ -0,0 +1,884 @@
// Copyright 2018 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package internal_gengo is internal to the protobuf module.
package internal_gengo
import (
"fmt"
"go/ast"
"go/parser"
"go/token"
"math"
"strconv"
"strings"
"unicode"
"unicode/utf8"
"google.golang.org/protobuf/compiler/protogen"
"google.golang.org/protobuf/internal/encoding/tag"
"google.golang.org/protobuf/internal/genid"
"google.golang.org/protobuf/internal/version"
"google.golang.org/protobuf/reflect/protoreflect"
"google.golang.org/protobuf/runtime/protoimpl"
"google.golang.org/protobuf/types/descriptorpb"
"google.golang.org/protobuf/types/pluginpb"
)
// SupportedFeatures reports the set of supported protobuf language features.
var SupportedFeatures = uint64(pluginpb.CodeGeneratorResponse_FEATURE_PROTO3_OPTIONAL)
// GenerateVersionMarkers specifies whether to generate version markers.
var GenerateVersionMarkers = true
// Standard library dependencies.
const (
base64Package = protogen.GoImportPath("encoding/base64")
mathPackage = protogen.GoImportPath("math")
reflectPackage = protogen.GoImportPath("reflect")
sortPackage = protogen.GoImportPath("sort")
stringsPackage = protogen.GoImportPath("strings")
syncPackage = protogen.GoImportPath("sync")
timePackage = protogen.GoImportPath("time")
utf8Package = protogen.GoImportPath("unicode/utf8")
)
// Protobuf library dependencies.
//
// These are declared as an interface type so that they can be more easily
// patched to support unique build environments that impose restrictions
// on the dependencies of generated source code.
var (
protoPackage goImportPath = protogen.GoImportPath("google.golang.org/protobuf/proto")
protoifacePackage goImportPath = protogen.GoImportPath("google.golang.org/protobuf/runtime/protoiface")
protoimplPackage goImportPath = protogen.GoImportPath("google.golang.org/protobuf/runtime/protoimpl")
protojsonPackage goImportPath = protogen.GoImportPath("google.golang.org/protobuf/encoding/protojson")
protoreflectPackage goImportPath = protogen.GoImportPath("google.golang.org/protobuf/reflect/protoreflect")
protoregistryPackage goImportPath = protogen.GoImportPath("google.golang.org/protobuf/reflect/protoregistry")
)
type goImportPath interface {
String() string
Ident(string) protogen.GoIdent
}
// GenerateFile generates the contents of a .pb.go file.
func GenerateFile(gen *protogen.Plugin, file *protogen.File) *protogen.GeneratedFile {
filename := file.GeneratedFilenamePrefix + ".pb.go"
g := gen.NewGeneratedFile(filename, file.GoImportPath)
f := newFileInfo(file)
genStandaloneComments(g, f, int32(genid.FileDescriptorProto_Syntax_field_number))
genGeneratedHeader(gen, g, f)
genStandaloneComments(g, f, int32(genid.FileDescriptorProto_Package_field_number))
packageDoc := genPackageKnownComment(f)
g.P(packageDoc, "package ", f.GoPackageName)
g.P()
// Emit a static check that enforces a minimum version of the proto package.
if GenerateVersionMarkers {
g.P("const (")
g.P("// Verify that this generated code is sufficiently up-to-date.")
g.P("_ = ", protoimplPackage.Ident("EnforceVersion"), "(", protoimpl.GenVersion, " - ", protoimplPackage.Ident("MinVersion"), ")")
g.P("// Verify that runtime/protoimpl is sufficiently up-to-date.")
g.P("_ = ", protoimplPackage.Ident("EnforceVersion"), "(", protoimplPackage.Ident("MaxVersion"), " - ", protoimpl.GenVersion, ")")
g.P(")")
g.P()
}
for i, imps := 0, f.Desc.Imports(); i < imps.Len(); i++ {
genImport(gen, g, f, imps.Get(i))
}
for _, enum := range f.allEnums {
genEnum(g, f, enum)
}
for _, message := range f.allMessages {
genMessage(g, f, message)
}
genExtensions(g, f)
genReflectFileDescriptor(gen, g, f)
return g
}
// genStandaloneComments prints all leading comments for a FileDescriptorProto
// location identified by the field number n.
func genStandaloneComments(g *protogen.GeneratedFile, f *fileInfo, n int32) {
loc := f.Desc.SourceLocations().ByPath(protoreflect.SourcePath{n})
for _, s := range loc.LeadingDetachedComments {
g.P(protogen.Comments(s))
g.P()
}
if s := loc.LeadingComments; s != "" {
g.P(protogen.Comments(s))
g.P()
}
}
func genGeneratedHeader(gen *protogen.Plugin, g *protogen.GeneratedFile, f *fileInfo) {
g.P("// Code generated by protoc-gen-go. DO NOT EDIT.")
if GenerateVersionMarkers {
g.P("// versions:")
protocGenGoVersion := version.String()
protocVersion := "(unknown)"
if v := gen.Request.GetCompilerVersion(); v != nil {
protocVersion = fmt.Sprintf("v%v.%v.%v", v.GetMajor(), v.GetMinor(), v.GetPatch())
if s := v.GetSuffix(); s != "" {
protocVersion += "-" + s
}
}
g.P("// \tprotoc-gen-go ", protocGenGoVersion)
g.P("// \tprotoc ", protocVersion)
}
if f.Proto.GetOptions().GetDeprecated() {
g.P("// ", f.Desc.Path(), " is a deprecated file.")
} else {
g.P("// source: ", f.Desc.Path())
}
g.P()
}
func genImport(gen *protogen.Plugin, g *protogen.GeneratedFile, f *fileInfo, imp protoreflect.FileImport) {
impFile, ok := gen.FilesByPath[imp.Path()]
if !ok {
return
}
if impFile.GoImportPath == f.GoImportPath {
// Don't generate imports or aliases for types in the same Go package.
return
}
// Generate imports for all non-weak dependencies, even if they are not
// referenced, because other code and tools depend on having the
// full transitive closure of protocol buffer types in the binary.
if !imp.IsWeak {
g.Import(impFile.GoImportPath)
}
if !imp.IsPublic {
return
}
// Generate public imports by generating the imported file, parsing it,
// and extracting every symbol that should receive a forwarding declaration.
impGen := GenerateFile(gen, impFile)
impGen.Skip()
b, err := impGen.Content()
if err != nil {
gen.Error(err)
return
}
fset := token.NewFileSet()
astFile, err := parser.ParseFile(fset, "", b, parser.ParseComments)
if err != nil {
gen.Error(err)
return
}
genForward := func(tok token.Token, name string, expr ast.Expr) {
// Don't import unexported symbols.
r, _ := utf8.DecodeRuneInString(name)
if !unicode.IsUpper(r) {
return
}
// Don't import the FileDescriptor.
if name == impFile.GoDescriptorIdent.GoName {
return
}
// Don't import decls referencing a symbol defined in another package.
// i.e., don't import decls which are themselves public imports:
//
// type T = somepackage.T
if _, ok := expr.(*ast.SelectorExpr); ok {
return
}
g.P(tok, " ", name, " = ", impFile.GoImportPath.Ident(name))
}
g.P("// Symbols defined in public import of ", imp.Path(), ".")
g.P()
for _, decl := range astFile.Decls {
switch decl := decl.(type) {
case *ast.GenDecl:
for _, spec := range decl.Specs {
switch spec := spec.(type) {
case *ast.TypeSpec:
genForward(decl.Tok, spec.Name.Name, spec.Type)
case *ast.ValueSpec:
for i, name := range spec.Names {
var expr ast.Expr
if i < len(spec.Values) {
expr = spec.Values[i]
}
genForward(decl.Tok, name.Name, expr)
}
case *ast.ImportSpec:
default:
panic(fmt.Sprintf("can't generate forward for spec type %T", spec))
}
}
}
}
g.P()
}
func genEnum(g *protogen.GeneratedFile, f *fileInfo, e *enumInfo) {
// Enum type declaration.
g.Annotate(e.GoIdent.GoName, e.Location)
leadingComments := appendDeprecationSuffix(e.Comments.Leading,
e.Desc.Options().(*descriptorpb.EnumOptions).GetDeprecated())
g.P(leadingComments,
"type ", e.GoIdent, " int32")
// Enum value constants.
g.P("const (")
for _, value := range e.Values {
g.Annotate(value.GoIdent.GoName, value.Location)
leadingComments := appendDeprecationSuffix(value.Comments.Leading,
value.Desc.Options().(*descriptorpb.EnumValueOptions).GetDeprecated())
g.P(leadingComments,
value.GoIdent, " ", e.GoIdent, " = ", value.Desc.Number(),
trailingComment(value.Comments.Trailing))
}
g.P(")")
g.P()
// Enum value maps.
g.P("// Enum value maps for ", e.GoIdent, ".")
g.P("var (")
g.P(e.GoIdent.GoName+"_name", " = map[int32]string{")
for _, value := range e.Values {
duplicate := ""
if value.Desc != e.Desc.Values().ByNumber(value.Desc.Number()) {
duplicate = "// Duplicate value: "
}
g.P(duplicate, value.Desc.Number(), ": ", strconv.Quote(string(value.Desc.Name())), ",")
}
g.P("}")
g.P(e.GoIdent.GoName+"_value", " = map[string]int32{")
for _, value := range e.Values {
g.P(strconv.Quote(string(value.Desc.Name())), ": ", value.Desc.Number(), ",")
}
g.P("}")
g.P(")")
g.P()
// Enum method.
//
// NOTE: A pointer value is needed to represent presence in proto2.
// Since a proto2 message can reference a proto3 enum, it is useful to
// always generate this method (even on proto3 enums) to support that case.
g.P("func (x ", e.GoIdent, ") Enum() *", e.GoIdent, " {")
g.P("p := new(", e.GoIdent, ")")
g.P("*p = x")
g.P("return p")
g.P("}")
g.P()
// String method.
g.P("func (x ", e.GoIdent, ") String() string {")
g.P("return ", protoimplPackage.Ident("X"), ".EnumStringOf(x.Descriptor(), ", protoreflectPackage.Ident("EnumNumber"), "(x))")
g.P("}")
g.P()
genEnumReflectMethods(g, f, e)
// UnmarshalJSON method.
if e.genJSONMethod && e.Desc.Syntax() == protoreflect.Proto2 {
g.P("// Deprecated: Do not use.")
g.P("func (x *", e.GoIdent, ") UnmarshalJSON(b []byte) error {")
g.P("num, err := ", protoimplPackage.Ident("X"), ".UnmarshalJSONEnum(x.Descriptor(), b)")
g.P("if err != nil {")
g.P("return err")
g.P("}")
g.P("*x = ", e.GoIdent, "(num)")
g.P("return nil")
g.P("}")
g.P()
}
// EnumDescriptor method.
if e.genRawDescMethod {
var indexes []string
for i := 1; i < len(e.Location.Path); i += 2 {
indexes = append(indexes, strconv.Itoa(int(e.Location.Path[i])))
}
g.P("// Deprecated: Use ", e.GoIdent, ".Descriptor instead.")
g.P("func (", e.GoIdent, ") EnumDescriptor() ([]byte, []int) {")
g.P("return ", rawDescVarName(f), "GZIP(), []int{", strings.Join(indexes, ","), "}")
g.P("}")
g.P()
f.needRawDesc = true
}
}
func genMessage(g *protogen.GeneratedFile, f *fileInfo, m *messageInfo) {
if m.Desc.IsMapEntry() {
return
}
// Message type declaration.
g.Annotate(m.GoIdent.GoName, m.Location)
leadingComments := appendDeprecationSuffix(m.Comments.Leading,
m.Desc.Options().(*descriptorpb.MessageOptions).GetDeprecated())
g.P(leadingComments,
"type ", m.GoIdent, " struct {")
genMessageFields(g, f, m)
g.P("}")
g.P()
genMessageKnownFunctions(g, f, m)
genMessageDefaultDecls(g, f, m)
genMessageMethods(g, f, m)
genMessageOneofWrapperTypes(g, f, m)
}
func genMessageFields(g *protogen.GeneratedFile, f *fileInfo, m *messageInfo) {
sf := f.allMessageFieldsByPtr[m]
genMessageInternalFields(g, f, m, sf)
for _, field := range m.Fields {
genMessageField(g, f, m, field, sf)
}
}
func genMessageInternalFields(g *protogen.GeneratedFile, f *fileInfo, m *messageInfo, sf *structFields) {
g.P(genid.State_goname, " ", protoimplPackage.Ident("MessageState"))
sf.append(genid.State_goname)
g.P(genid.SizeCache_goname, " ", protoimplPackage.Ident("SizeCache"))
sf.append(genid.SizeCache_goname)
if m.hasWeak {
g.P(genid.WeakFields_goname, " ", protoimplPackage.Ident("WeakFields"))
sf.append(genid.WeakFields_goname)
}
g.P(genid.UnknownFields_goname, " ", protoimplPackage.Ident("UnknownFields"))
sf.append(genid.UnknownFields_goname)
if m.Desc.ExtensionRanges().Len() > 0 {
g.P(genid.ExtensionFields_goname, " ", protoimplPackage.Ident("ExtensionFields"))
sf.append(genid.ExtensionFields_goname)
}
if sf.count > 0 {
g.P()
}
}
func genMessageField(g *protogen.GeneratedFile, f *fileInfo, m *messageInfo, field *protogen.Field, sf *structFields) {
if oneof := field.Oneof; oneof != nil && !oneof.Desc.IsSynthetic() {
// It would be a bit simpler to iterate over the oneofs below,
// but generating the field here keeps the contents of the Go
// struct in the same order as the contents of the source
// .proto file.
if oneof.Fields[0] != field {
return // only generate for first appearance
}
tags := structTags{
{"protobuf_oneof", string(oneof.Desc.Name())},
}
if m.isTracked {
tags = append(tags, gotrackTags...)
}
g.Annotate(m.GoIdent.GoName+"."+oneof.GoName, oneof.Location)
leadingComments := oneof.Comments.Leading
if leadingComments != "" {
leadingComments += "\n"
}
ss := []string{fmt.Sprintf(" Types that are assignable to %s:\n", oneof.GoName)}
for _, field := range oneof.Fields {
ss = append(ss, "\t*"+field.GoIdent.GoName+"\n")
}
leadingComments += protogen.Comments(strings.Join(ss, ""))
g.P(leadingComments,
oneof.GoName, " ", oneofInterfaceName(oneof), tags)
sf.append(oneof.GoName)
return
}
goType, pointer := fieldGoType(g, f, field)
if pointer {
goType = "*" + goType
}
tags := structTags{
{"protobuf", fieldProtobufTagValue(field)},
{"json", fieldJSONTagValue(field)},
}
if field.Desc.IsMap() {
key := field.Message.Fields[0]
val := field.Message.Fields[1]
tags = append(tags, structTags{
{"protobuf_key", fieldProtobufTagValue(key)},
{"protobuf_val", fieldProtobufTagValue(val)},
}...)
}
if m.isTracked {
tags = append(tags, gotrackTags...)
}
name := field.GoName
if field.Desc.IsWeak() {
name = genid.WeakFieldPrefix_goname + name
}
g.Annotate(m.GoIdent.GoName+"."+name, field.Location)
leadingComments := appendDeprecationSuffix(field.Comments.Leading,
field.Desc.Options().(*descriptorpb.FieldOptions).GetDeprecated())
g.P(leadingComments,
name, " ", goType, tags,
trailingComment(field.Comments.Trailing))
sf.append(field.GoName)
}
// genMessageDefaultDecls generates consts and vars holding the default
// values of fields.
func genMessageDefaultDecls(g *protogen.GeneratedFile, f *fileInfo, m *messageInfo) {
var consts, vars []string
for _, field := range m.Fields {
if !field.Desc.HasDefault() {
continue
}
name := "Default_" + m.GoIdent.GoName + "_" + field.GoName
goType, _ := fieldGoType(g, f, field)
defVal := field.Desc.Default()
switch field.Desc.Kind() {
case protoreflect.StringKind:
consts = append(consts, fmt.Sprintf("%s = %s(%q)", name, goType, defVal.String()))
case protoreflect.BytesKind:
vars = append(vars, fmt.Sprintf("%s = %s(%q)", name, goType, defVal.Bytes()))
case protoreflect.EnumKind:
idx := field.Desc.DefaultEnumValue().Index()
val := field.Enum.Values[idx]
if val.GoIdent.GoImportPath == f.GoImportPath {
consts = append(consts, fmt.Sprintf("%s = %s", name, g.QualifiedGoIdent(val.GoIdent)))
} else {
// If the enum value is declared in a different Go package,
// reference it by number since the name may not be correct.
// See https://github.com/golang/protobuf/issues/513.
consts = append(consts, fmt.Sprintf("%s = %s(%d) // %s",
name, g.QualifiedGoIdent(field.Enum.GoIdent), val.Desc.Number(), g.QualifiedGoIdent(val.GoIdent)))
}
case protoreflect.FloatKind, protoreflect.DoubleKind:
if f := defVal.Float(); math.IsNaN(f) || math.IsInf(f, 0) {
var fn, arg string
switch f := defVal.Float(); {
case math.IsInf(f, -1):
fn, arg = g.QualifiedGoIdent(mathPackage.Ident("Inf")), "-1"
case math.IsInf(f, +1):
fn, arg = g.QualifiedGoIdent(mathPackage.Ident("Inf")), "+1"
case math.IsNaN(f):
fn, arg = g.QualifiedGoIdent(mathPackage.Ident("NaN")), ""
}
vars = append(vars, fmt.Sprintf("%s = %s(%s(%s))", name, goType, fn, arg))
} else {
consts = append(consts, fmt.Sprintf("%s = %s(%v)", name, goType, f))
}
default:
consts = append(consts, fmt.Sprintf("%s = %s(%v)", name, goType, defVal.Interface()))
}
}
if len(consts) > 0 {
g.P("// Default values for ", m.GoIdent, " fields.")
g.P("const (")
for _, s := range consts {
g.P(s)
}
g.P(")")
}
if len(vars) > 0 {
g.P("// Default values for ", m.GoIdent, " fields.")
g.P("var (")
for _, s := range vars {
g.P(s)
}
g.P(")")
}
g.P()
}
func genMessageMethods(g *protogen.GeneratedFile, f *fileInfo, m *messageInfo) {
genMessageBaseMethods(g, f, m)
genMessageGetterMethods(g, f, m)
genMessageSetterMethods(g, f, m)
}
func genMessageBaseMethods(g *protogen.GeneratedFile, f *fileInfo, m *messageInfo) {
// Reset method.
g.P("func (x *", m.GoIdent, ") Reset() {")
g.P("*x = ", m.GoIdent, "{}")
g.P("if ", protoimplPackage.Ident("UnsafeEnabled"), " {")
g.P("mi := &", messageTypesVarName(f), "[", f.allMessagesByPtr[m], "]")
g.P("ms := ", protoimplPackage.Ident("X"), ".MessageStateOf(", protoimplPackage.Ident("Pointer"), "(x))")
g.P("ms.StoreMessageInfo(mi)")
g.P("}")
g.P("}")
g.P()
// String method.
g.P("func (x *", m.GoIdent, ") String() string {")
g.P("return ", protoimplPackage.Ident("X"), ".MessageStringOf(x)")
g.P("}")
g.P()
// ProtoMessage method.
g.P("func (*", m.GoIdent, ") ProtoMessage() {}")
g.P()
// ProtoReflect method.
genMessageReflectMethods(g, f, m)
// Descriptor method.
if m.genRawDescMethod {
var indexes []string
for i := 1; i < len(m.Location.Path); i += 2 {
indexes = append(indexes, strconv.Itoa(int(m.Location.Path[i])))
}
g.P("// Deprecated: Use ", m.GoIdent, ".ProtoReflect.Descriptor instead.")
g.P("func (*", m.GoIdent, ") Descriptor() ([]byte, []int) {")
g.P("return ", rawDescVarName(f), "GZIP(), []int{", strings.Join(indexes, ","), "}")
g.P("}")
g.P()
f.needRawDesc = true
}
}
func genMessageGetterMethods(g *protogen.GeneratedFile, f *fileInfo, m *messageInfo) {
for _, field := range m.Fields {
genNoInterfacePragma(g, m.isTracked)
// Getter for parent oneof.
if oneof := field.Oneof; oneof != nil && oneof.Fields[0] == field && !oneof.Desc.IsSynthetic() {
g.Annotate(m.GoIdent.GoName+".Get"+oneof.GoName, oneof.Location)
g.P("func (m *", m.GoIdent.GoName, ") Get", oneof.GoName, "() ", oneofInterfaceName(oneof), " {")
g.P("if m != nil {")
g.P("return m.", oneof.GoName)
g.P("}")
g.P("return nil")
g.P("}")
g.P()
}
// Getter for message field.
goType, pointer := fieldGoType(g, f, field)
defaultValue := fieldDefaultValue(g, f, m, field)
g.Annotate(m.GoIdent.GoName+".Get"+field.GoName, field.Location)
leadingComments := appendDeprecationSuffix("",
field.Desc.Options().(*descriptorpb.FieldOptions).GetDeprecated())
switch {
case field.Desc.IsWeak():
g.P(leadingComments, "func (x *", m.GoIdent, ") Get", field.GoName, "() ", protoPackage.Ident("Message"), "{")
g.P("var w ", protoimplPackage.Ident("WeakFields"))
g.P("if x != nil {")
g.P("w = x.", genid.WeakFields_goname)
if m.isTracked {
g.P("_ = x.", genid.WeakFieldPrefix_goname+field.GoName)
}
g.P("}")
g.P("return ", protoimplPackage.Ident("X"), ".GetWeak(w, ", field.Desc.Number(), ", ", strconv.Quote(string(field.Message.Desc.FullName())), ")")
g.P("}")
case field.Oneof != nil && !field.Oneof.Desc.IsSynthetic():
g.P(leadingComments, "func (x *", m.GoIdent, ") Get", field.GoName, "() ", goType, " {")
g.P("if x, ok := x.Get", field.Oneof.GoName, "().(*", field.GoIdent, "); ok {")
g.P("return x.", field.GoName)
g.P("}")
g.P("return ", defaultValue)
g.P("}")
default:
g.P(leadingComments, "func (x *", m.GoIdent, ") Get", field.GoName, "() ", goType, " {")
if !field.Desc.HasPresence() || defaultValue == "nil" {
g.P("if x != nil {")
} else {
g.P("if x != nil && x.", field.GoName, " != nil {")
}
star := ""
if pointer {
star = "*"
}
g.P("return ", star, " x.", field.GoName)
g.P("}")
g.P("return ", defaultValue)
g.P("}")
}
g.P()
}
}
func genMessageSetterMethods(g *protogen.GeneratedFile, f *fileInfo, m *messageInfo) {
for _, field := range m.Fields {
if !field.Desc.IsWeak() {
continue
}
genNoInterfacePragma(g, m.isTracked)
g.Annotate(m.GoIdent.GoName+".Set"+field.GoName, field.Location)
leadingComments := appendDeprecationSuffix("",
field.Desc.Options().(*descriptorpb.FieldOptions).GetDeprecated())
g.P(leadingComments, "func (x *", m.GoIdent, ") Set", field.GoName, "(v ", protoPackage.Ident("Message"), ") {")
g.P("var w *", protoimplPackage.Ident("WeakFields"))
g.P("if x != nil {")
g.P("w = &x.", genid.WeakFields_goname)
if m.isTracked {
g.P("_ = x.", genid.WeakFieldPrefix_goname+field.GoName)
}
g.P("}")
g.P(protoimplPackage.Ident("X"), ".SetWeak(w, ", field.Desc.Number(), ", ", strconv.Quote(string(field.Message.Desc.FullName())), ", v)")
g.P("}")
g.P()
}
}
// fieldGoType returns the Go type used for a field.
//
// If it returns pointer=true, the struct field is a pointer to the type.
func fieldGoType(g *protogen.GeneratedFile, f *fileInfo, field *protogen.Field) (goType string, pointer bool) {
if field.Desc.IsWeak() {
return "struct{}", false
}
pointer = field.Desc.HasPresence()
switch field.Desc.Kind() {
case protoreflect.BoolKind:
goType = "bool"
case protoreflect.EnumKind:
goType = g.QualifiedGoIdent(field.Enum.GoIdent)
case protoreflect.Int32Kind, protoreflect.Sint32Kind, protoreflect.Sfixed32Kind:
goType = "int32"
case protoreflect.Uint32Kind, protoreflect.Fixed32Kind:
goType = "uint32"
case protoreflect.Int64Kind, protoreflect.Sint64Kind, protoreflect.Sfixed64Kind:
goType = "int64"
case protoreflect.Uint64Kind, protoreflect.Fixed64Kind:
goType = "uint64"
case protoreflect.FloatKind:
goType = "float32"
case protoreflect.DoubleKind:
goType = "float64"
case protoreflect.StringKind:
goType = "string"
case protoreflect.BytesKind:
goType = "[]byte"
pointer = false // rely on nullability of slices for presence
case protoreflect.MessageKind, protoreflect.GroupKind:
goType = "*" + g.QualifiedGoIdent(field.Message.GoIdent)
pointer = false // pointer captured as part of the type
}
switch {
case field.Desc.IsList():
return "[]" + goType, false
case field.Desc.IsMap():
keyType, _ := fieldGoType(g, f, field.Message.Fields[0])
valType, _ := fieldGoType(g, f, field.Message.Fields[1])
return fmt.Sprintf("map[%v]%v", keyType, valType), false
}
return goType, pointer
}
func fieldProtobufTagValue(field *protogen.Field) string {
var enumName string
if field.Desc.Kind() == protoreflect.EnumKind {
enumName = protoimpl.X.LegacyEnumName(field.Enum.Desc)
}
return tag.Marshal(field.Desc, enumName)
}
func fieldDefaultValue(g *protogen.GeneratedFile, f *fileInfo, m *messageInfo, field *protogen.Field) string {
if field.Desc.IsList() {
return "nil"
}
if field.Desc.HasDefault() {
defVarName := "Default_" + m.GoIdent.GoName + "_" + field.GoName
if field.Desc.Kind() == protoreflect.BytesKind {
return "append([]byte(nil), " + defVarName + "...)"
}
return defVarName
}
switch field.Desc.Kind() {
case protoreflect.BoolKind:
return "false"
case protoreflect.StringKind:
return `""`
case protoreflect.MessageKind, protoreflect.GroupKind, protoreflect.BytesKind:
return "nil"
case protoreflect.EnumKind:
val := field.Enum.Values[0]
if val.GoIdent.GoImportPath == f.GoImportPath {
return g.QualifiedGoIdent(val.GoIdent)
} else {
// If the enum value is declared in a different Go package,
// reference it by number since the name may not be correct.
// See https://github.com/golang/protobuf/issues/513.
return g.QualifiedGoIdent(field.Enum.GoIdent) + "(" + strconv.FormatInt(int64(val.Desc.Number()), 10) + ")"
}
default:
return "0"
}
}
func fieldJSONTagValue(field *protogen.Field) string {
return string(field.Desc.Name()) + ",omitempty"
}
func genExtensions(g *protogen.GeneratedFile, f *fileInfo) {
if len(f.allExtensions) == 0 {
return
}
g.P("var ", extensionTypesVarName(f), " = []", protoimplPackage.Ident("ExtensionInfo"), "{")
for _, x := range f.allExtensions {
g.P("{")
g.P("ExtendedType: (*", x.Extendee.GoIdent, ")(nil),")
goType, pointer := fieldGoType(g, f, x.Extension)
if pointer {
goType = "*" + goType
}
g.P("ExtensionType: (", goType, ")(nil),")
g.P("Field: ", x.Desc.Number(), ",")
g.P("Name: ", strconv.Quote(string(x.Desc.FullName())), ",")
g.P("Tag: ", strconv.Quote(fieldProtobufTagValue(x.Extension)), ",")
g.P("Filename: ", strconv.Quote(f.Desc.Path()), ",")
g.P("},")
}
g.P("}")
g.P()
// Group extensions by the target message.
var orderedTargets []protogen.GoIdent
allExtensionsByTarget := make(map[protogen.GoIdent][]*extensionInfo)
allExtensionsByPtr := make(map[*extensionInfo]int)
for i, x := range f.allExtensions {
target := x.Extendee.GoIdent
if len(allExtensionsByTarget[target]) == 0 {
orderedTargets = append(orderedTargets, target)
}
allExtensionsByTarget[target] = append(allExtensionsByTarget[target], x)
allExtensionsByPtr[x] = i
}
for _, target := range orderedTargets {
g.P("// Extension fields to ", target, ".")
g.P("var (")
for _, x := range allExtensionsByTarget[target] {
xd := x.Desc
typeName := xd.Kind().String()
switch xd.Kind() {
case protoreflect.EnumKind:
typeName = string(xd.Enum().FullName())
case protoreflect.MessageKind, protoreflect.GroupKind:
typeName = string(xd.Message().FullName())
}
fieldName := string(xd.Name())
leadingComments := x.Comments.Leading
if leadingComments != "" {
leadingComments += "\n"
}
leadingComments += protogen.Comments(fmt.Sprintf(" %v %v %v = %v;\n",
xd.Cardinality(), typeName, fieldName, xd.Number()))
leadingComments = appendDeprecationSuffix(leadingComments,
x.Desc.Options().(*descriptorpb.FieldOptions).GetDeprecated())
g.P(leadingComments,
"E_", x.GoIdent, " = &", extensionTypesVarName(f), "[", allExtensionsByPtr[x], "]",
trailingComment(x.Comments.Trailing))
}
g.P(")")
g.P()
}
}
// genMessageOneofWrapperTypes generates the oneof wrapper types and
// associates the types with the parent message type.
func genMessageOneofWrapperTypes(g *protogen.GeneratedFile, f *fileInfo, m *messageInfo) {
for _, oneof := range m.Oneofs {
if oneof.Desc.IsSynthetic() {
continue
}
ifName := oneofInterfaceName(oneof)
g.P("type ", ifName, " interface {")
g.P(ifName, "()")
g.P("}")
g.P()
for _, field := range oneof.Fields {
g.Annotate(field.GoIdent.GoName, field.Location)
g.Annotate(field.GoIdent.GoName+"."+field.GoName, field.Location)
g.P("type ", field.GoIdent, " struct {")
goType, _ := fieldGoType(g, f, field)
tags := structTags{
{"protobuf", fieldProtobufTagValue(field)},
}
if m.isTracked {
tags = append(tags, gotrackTags...)
}
leadingComments := appendDeprecationSuffix(field.Comments.Leading,
field.Desc.Options().(*descriptorpb.FieldOptions).GetDeprecated())
g.P(leadingComments,
field.GoName, " ", goType, tags,
trailingComment(field.Comments.Trailing))
g.P("}")
g.P()
}
for _, field := range oneof.Fields {
g.P("func (*", field.GoIdent, ") ", ifName, "() {}")
g.P()
}
}
}
// oneofInterfaceName returns the name of the interface type implemented by
// the oneof field value types.
func oneofInterfaceName(oneof *protogen.Oneof) string {
return "is" + oneof.GoIdent.GoName
}
// genNoInterfacePragma generates a standalone "nointerface" pragma to
// decorate methods with field-tracking support.
func genNoInterfacePragma(g *protogen.GeneratedFile, tracked bool) {
if tracked {
g.P("//go:nointerface")
g.P()
}
}
var gotrackTags = structTags{{"go", "track"}}
// structTags is a data structure for build idiomatic Go struct tags.
// Each [2]string is a key-value pair, where value is the unescaped string.
//
// Example: structTags{{"key", "value"}}.String() -> `key:"value"`
type structTags [][2]string
func (tags structTags) String() string {
if len(tags) == 0 {
return ""
}
var ss []string
for _, tag := range tags {
// NOTE: When quoting the value, we need to make sure the backtick
// character does not appear. Convert all cases to the escaped hex form.
key := tag[0]
val := strings.Replace(strconv.Quote(tag[1]), "`", `\x60`, -1)
ss = append(ss, fmt.Sprintf("%s:%s", key, val))
}
return "`" + strings.Join(ss, " ") + "`"
}
// appendDeprecationSuffix optionally appends a deprecation notice as a suffix.
func appendDeprecationSuffix(prefix protogen.Comments, deprecated bool) protogen.Comments {
if !deprecated {
return prefix
}
if prefix != "" {
prefix += "\n"
}
return prefix + " Deprecated: Do not use.\n"
}
// trailingComment is like protogen.Comments, but lacks a trailing newline.
type trailingComment protogen.Comments
func (c trailingComment) String() string {
s := strings.TrimSuffix(protogen.Comments(c).String(), "\n")
if strings.Contains(s, "\n") {
// We don't support multi-lined trailing comments as it is unclear
// how to best render them in the generated code.
return ""
}
return s
}

View file

@ -0,0 +1,351 @@
// Copyright 2018 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package internal_gengo
import (
"fmt"
"math"
"strings"
"unicode/utf8"
"google.golang.org/protobuf/compiler/protogen"
"google.golang.org/protobuf/proto"
"google.golang.org/protobuf/reflect/protoreflect"
"google.golang.org/protobuf/types/descriptorpb"
)
func genReflectFileDescriptor(gen *protogen.Plugin, g *protogen.GeneratedFile, f *fileInfo) {
g.P("var ", f.GoDescriptorIdent, " ", protoreflectPackage.Ident("FileDescriptor"))
g.P()
genFileDescriptor(gen, g, f)
if len(f.allEnums) > 0 {
g.P("var ", enumTypesVarName(f), " = make([]", protoimplPackage.Ident("EnumInfo"), ",", len(f.allEnums), ")")
}
if len(f.allMessages) > 0 {
g.P("var ", messageTypesVarName(f), " = make([]", protoimplPackage.Ident("MessageInfo"), ",", len(f.allMessages), ")")
}
// Generate a unique list of Go types for all declarations and dependencies,
// and the associated index into the type list for all dependencies.
var goTypes []string
var depIdxs []string
seen := map[protoreflect.FullName]int{}
genDep := func(name protoreflect.FullName, depSource string) {
if depSource != "" {
line := fmt.Sprintf("%d, // %d: %s -> %s", seen[name], len(depIdxs), depSource, name)
depIdxs = append(depIdxs, line)
}
}
genEnum := func(e *protogen.Enum, depSource string) {
if e != nil {
name := e.Desc.FullName()
if _, ok := seen[name]; !ok {
line := fmt.Sprintf("(%s)(0), // %d: %s", g.QualifiedGoIdent(e.GoIdent), len(goTypes), name)
goTypes = append(goTypes, line)
seen[name] = len(seen)
}
if depSource != "" {
genDep(name, depSource)
}
}
}
genMessage := func(m *protogen.Message, depSource string) {
if m != nil {
name := m.Desc.FullName()
if _, ok := seen[name]; !ok {
line := fmt.Sprintf("(*%s)(nil), // %d: %s", g.QualifiedGoIdent(m.GoIdent), len(goTypes), name)
if m.Desc.IsMapEntry() {
// Map entry messages have no associated Go type.
line = fmt.Sprintf("nil, // %d: %s", len(goTypes), name)
}
goTypes = append(goTypes, line)
seen[name] = len(seen)
}
if depSource != "" {
genDep(name, depSource)
}
}
}
// This ordering is significant.
// See filetype.TypeBuilder.DependencyIndexes.
type offsetEntry struct {
start int
name string
}
var depOffsets []offsetEntry
for _, enum := range f.allEnums {
genEnum(enum.Enum, "")
}
for _, message := range f.allMessages {
genMessage(message.Message, "")
}
depOffsets = append(depOffsets, offsetEntry{len(depIdxs), "field type_name"})
for _, message := range f.allMessages {
for _, field := range message.Fields {
if field.Desc.IsWeak() {
continue
}
source := string(field.Desc.FullName())
genEnum(field.Enum, source+":type_name")
genMessage(field.Message, source+":type_name")
}
}
depOffsets = append(depOffsets, offsetEntry{len(depIdxs), "extension extendee"})
for _, extension := range f.allExtensions {
source := string(extension.Desc.FullName())
genMessage(extension.Extendee, source+":extendee")
}
depOffsets = append(depOffsets, offsetEntry{len(depIdxs), "extension type_name"})
for _, extension := range f.allExtensions {
source := string(extension.Desc.FullName())
genEnum(extension.Enum, source+":type_name")
genMessage(extension.Message, source+":type_name")
}
depOffsets = append(depOffsets, offsetEntry{len(depIdxs), "method input_type"})
for _, service := range f.Services {
for _, method := range service.Methods {
source := string(method.Desc.FullName())
genMessage(method.Input, source+":input_type")
}
}
depOffsets = append(depOffsets, offsetEntry{len(depIdxs), "method output_type"})
for _, service := range f.Services {
for _, method := range service.Methods {
source := string(method.Desc.FullName())
genMessage(method.Output, source+":output_type")
}
}
depOffsets = append(depOffsets, offsetEntry{len(depIdxs), ""})
for i := len(depOffsets) - 2; i >= 0; i-- {
curr, next := depOffsets[i], depOffsets[i+1]
depIdxs = append(depIdxs, fmt.Sprintf("%d, // [%d:%d] is the sub-list for %s",
curr.start, curr.start, next.start, curr.name))
}
if len(depIdxs) > math.MaxInt32 {
panic("too many dependencies") // sanity check
}
g.P("var ", goTypesVarName(f), " = []interface{}{")
for _, s := range goTypes {
g.P(s)
}
g.P("}")
g.P("var ", depIdxsVarName(f), " = []int32{")
for _, s := range depIdxs {
g.P(s)
}
g.P("}")
g.P("func init() { ", initFuncName(f.File), "() }")
g.P("func ", initFuncName(f.File), "() {")
g.P("if ", f.GoDescriptorIdent, " != nil {")
g.P("return")
g.P("}")
// Ensure that initialization functions for different files in the same Go
// package run in the correct order: Call the init funcs for every .proto file
// imported by this one that is in the same Go package.
for i, imps := 0, f.Desc.Imports(); i < imps.Len(); i++ {
impFile := gen.FilesByPath[imps.Get(i).Path()]
if impFile.GoImportPath != f.GoImportPath {
continue
}
g.P(initFuncName(impFile), "()")
}
if len(f.allMessages) > 0 {
// Populate MessageInfo.Exporters.
g.P("if !", protoimplPackage.Ident("UnsafeEnabled"), " {")
for _, message := range f.allMessages {
if sf := f.allMessageFieldsByPtr[message]; len(sf.unexported) > 0 {
idx := f.allMessagesByPtr[message]
typesVar := messageTypesVarName(f)
g.P(typesVar, "[", idx, "].Exporter = func(v interface{}, i int) interface{} {")
g.P("switch v := v.(*", message.GoIdent, "); i {")
for i := 0; i < sf.count; i++ {
if name := sf.unexported[i]; name != "" {
g.P("case ", i, ": return &v.", name)
}
}
g.P("default: return nil")
g.P("}")
g.P("}")
}
}
g.P("}")
// Populate MessageInfo.OneofWrappers.
for _, message := range f.allMessages {
if len(message.Oneofs) > 0 {
idx := f.allMessagesByPtr[message]
typesVar := messageTypesVarName(f)
// Associate the wrapper types by directly passing them to the MessageInfo.
g.P(typesVar, "[", idx, "].OneofWrappers = []interface{} {")
for _, oneof := range message.Oneofs {
if !oneof.Desc.IsSynthetic() {
for _, field := range oneof.Fields {
g.P("(*", field.GoIdent, ")(nil),")
}
}
}
g.P("}")
}
}
}
g.P("type x struct{}")
g.P("out := ", protoimplPackage.Ident("TypeBuilder"), "{")
g.P("File: ", protoimplPackage.Ident("DescBuilder"), "{")
g.P("GoPackagePath: ", reflectPackage.Ident("TypeOf"), "(x{}).PkgPath(),")
g.P("RawDescriptor: ", rawDescVarName(f), ",")
g.P("NumEnums: ", len(f.allEnums), ",")
g.P("NumMessages: ", len(f.allMessages), ",")
g.P("NumExtensions: ", len(f.allExtensions), ",")
g.P("NumServices: ", len(f.Services), ",")
g.P("},")
g.P("GoTypes: ", goTypesVarName(f), ",")
g.P("DependencyIndexes: ", depIdxsVarName(f), ",")
if len(f.allEnums) > 0 {
g.P("EnumInfos: ", enumTypesVarName(f), ",")
}
if len(f.allMessages) > 0 {
g.P("MessageInfos: ", messageTypesVarName(f), ",")
}
if len(f.allExtensions) > 0 {
g.P("ExtensionInfos: ", extensionTypesVarName(f), ",")
}
g.P("}.Build()")
g.P(f.GoDescriptorIdent, " = out.File")
// Set inputs to nil to allow GC to reclaim resources.
g.P(rawDescVarName(f), " = nil")
g.P(goTypesVarName(f), " = nil")
g.P(depIdxsVarName(f), " = nil")
g.P("}")
}
func genFileDescriptor(gen *protogen.Plugin, g *protogen.GeneratedFile, f *fileInfo) {
descProto := proto.Clone(f.Proto).(*descriptorpb.FileDescriptorProto)
descProto.SourceCodeInfo = nil // drop source code information
b, err := proto.MarshalOptions{AllowPartial: true, Deterministic: true}.Marshal(descProto)
if err != nil {
gen.Error(err)
return
}
g.P("var ", rawDescVarName(f), " = []byte{")
for len(b) > 0 {
n := 16
if n > len(b) {
n = len(b)
}
s := ""
for _, c := range b[:n] {
s += fmt.Sprintf("0x%02x,", c)
}
g.P(s)
b = b[n:]
}
g.P("}")
g.P()
if f.needRawDesc {
onceVar := rawDescVarName(f) + "Once"
dataVar := rawDescVarName(f) + "Data"
g.P("var (")
g.P(onceVar, " ", syncPackage.Ident("Once"))
g.P(dataVar, " = ", rawDescVarName(f))
g.P(")")
g.P()
g.P("func ", rawDescVarName(f), "GZIP() []byte {")
g.P(onceVar, ".Do(func() {")
g.P(dataVar, " = ", protoimplPackage.Ident("X"), ".CompressGZIP(", dataVar, ")")
g.P("})")
g.P("return ", dataVar)
g.P("}")
g.P()
}
}
func genEnumReflectMethods(g *protogen.GeneratedFile, f *fileInfo, e *enumInfo) {
idx := f.allEnumsByPtr[e]
typesVar := enumTypesVarName(f)
// Descriptor method.
g.P("func (", e.GoIdent, ") Descriptor() ", protoreflectPackage.Ident("EnumDescriptor"), " {")
g.P("return ", typesVar, "[", idx, "].Descriptor()")
g.P("}")
g.P()
// Type method.
g.P("func (", e.GoIdent, ") Type() ", protoreflectPackage.Ident("EnumType"), " {")
g.P("return &", typesVar, "[", idx, "]")
g.P("}")
g.P()
// Number method.
g.P("func (x ", e.GoIdent, ") Number() ", protoreflectPackage.Ident("EnumNumber"), " {")
g.P("return ", protoreflectPackage.Ident("EnumNumber"), "(x)")
g.P("}")
g.P()
}
func genMessageReflectMethods(g *protogen.GeneratedFile, f *fileInfo, m *messageInfo) {
idx := f.allMessagesByPtr[m]
typesVar := messageTypesVarName(f)
// ProtoReflect method.
g.P("func (x *", m.GoIdent, ") ProtoReflect() ", protoreflectPackage.Ident("Message"), " {")
g.P("mi := &", typesVar, "[", idx, "]")
g.P("if ", protoimplPackage.Ident("UnsafeEnabled"), " && x != nil {")
g.P("ms := ", protoimplPackage.Ident("X"), ".MessageStateOf(", protoimplPackage.Ident("Pointer"), "(x))")
g.P("if ms.LoadMessageInfo() == nil {")
g.P("ms.StoreMessageInfo(mi)")
g.P("}")
g.P("return ms")
g.P("}")
g.P("return mi.MessageOf(x)")
g.P("}")
g.P()
}
func fileVarName(f *protogen.File, suffix string) string {
prefix := f.GoDescriptorIdent.GoName
_, n := utf8.DecodeRuneInString(prefix)
prefix = strings.ToLower(prefix[:n]) + prefix[n:]
return prefix + "_" + suffix
}
func rawDescVarName(f *fileInfo) string {
return fileVarName(f.File, "rawDesc")
}
func goTypesVarName(f *fileInfo) string {
return fileVarName(f.File, "goTypes")
}
func depIdxsVarName(f *fileInfo) string {
return fileVarName(f.File, "depIdxs")
}
func enumTypesVarName(f *fileInfo) string {
return fileVarName(f.File, "enumTypes")
}
func messageTypesVarName(f *fileInfo) string {
return fileVarName(f.File, "msgTypes")
}
func extensionTypesVarName(f *fileInfo) string {
return fileVarName(f.File, "extTypes")
}
func initFuncName(f *protogen.File) string {
return fileVarName(f, "init")
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,653 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Author: kenton@google.com (Kenton Varda)
//
// WARNING: The plugin interface is currently EXPERIMENTAL and is subject to
// change.
//
// protoc (aka the Protocol Compiler) can be extended via plugins. A plugin is
// just a program that reads a CodeGeneratorRequest from stdin and writes a
// CodeGeneratorResponse to stdout.
//
// Plugins written using C++ can use google/protobuf/compiler/plugin.h instead
// of dealing with the raw protocol defined here.
//
// A plugin executable needs only to be placed somewhere in the path. The
// plugin should be named "protoc-gen-$NAME", and will then be used when the
// flag "--${NAME}_out" is passed to protoc.
// Code generated by protoc-gen-go. DO NOT EDIT.
// source: google/protobuf/compiler/plugin.proto
package pluginpb
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
descriptorpb "google.golang.org/protobuf/types/descriptorpb"
reflect "reflect"
sync "sync"
)
// Sync with code_generator.h.
type CodeGeneratorResponse_Feature int32
const (
CodeGeneratorResponse_FEATURE_NONE CodeGeneratorResponse_Feature = 0
CodeGeneratorResponse_FEATURE_PROTO3_OPTIONAL CodeGeneratorResponse_Feature = 1
)
// Enum value maps for CodeGeneratorResponse_Feature.
var (
CodeGeneratorResponse_Feature_name = map[int32]string{
0: "FEATURE_NONE",
1: "FEATURE_PROTO3_OPTIONAL",
}
CodeGeneratorResponse_Feature_value = map[string]int32{
"FEATURE_NONE": 0,
"FEATURE_PROTO3_OPTIONAL": 1,
}
)
func (x CodeGeneratorResponse_Feature) Enum() *CodeGeneratorResponse_Feature {
p := new(CodeGeneratorResponse_Feature)
*p = x
return p
}
func (x CodeGeneratorResponse_Feature) String() string {
return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
}
func (CodeGeneratorResponse_Feature) Descriptor() protoreflect.EnumDescriptor {
return file_google_protobuf_compiler_plugin_proto_enumTypes[0].Descriptor()
}
func (CodeGeneratorResponse_Feature) Type() protoreflect.EnumType {
return &file_google_protobuf_compiler_plugin_proto_enumTypes[0]
}
func (x CodeGeneratorResponse_Feature) Number() protoreflect.EnumNumber {
return protoreflect.EnumNumber(x)
}
// Deprecated: Do not use.
func (x *CodeGeneratorResponse_Feature) UnmarshalJSON(b []byte) error {
num, err := protoimpl.X.UnmarshalJSONEnum(x.Descriptor(), b)
if err != nil {
return err
}
*x = CodeGeneratorResponse_Feature(num)
return nil
}
// Deprecated: Use CodeGeneratorResponse_Feature.Descriptor instead.
func (CodeGeneratorResponse_Feature) EnumDescriptor() ([]byte, []int) {
return file_google_protobuf_compiler_plugin_proto_rawDescGZIP(), []int{2, 0}
}
// The version number of protocol compiler.
type Version struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Major *int32 `protobuf:"varint,1,opt,name=major" json:"major,omitempty"`
Minor *int32 `protobuf:"varint,2,opt,name=minor" json:"minor,omitempty"`
Patch *int32 `protobuf:"varint,3,opt,name=patch" json:"patch,omitempty"`
// A suffix for alpha, beta or rc release, e.g., "alpha-1", "rc2". It should
// be empty for mainline stable releases.
Suffix *string `protobuf:"bytes,4,opt,name=suffix" json:"suffix,omitempty"`
}
func (x *Version) Reset() {
*x = Version{}
if protoimpl.UnsafeEnabled {
mi := &file_google_protobuf_compiler_plugin_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *Version) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*Version) ProtoMessage() {}
func (x *Version) ProtoReflect() protoreflect.Message {
mi := &file_google_protobuf_compiler_plugin_proto_msgTypes[0]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use Version.ProtoReflect.Descriptor instead.
func (*Version) Descriptor() ([]byte, []int) {
return file_google_protobuf_compiler_plugin_proto_rawDescGZIP(), []int{0}
}
func (x *Version) GetMajor() int32 {
if x != nil && x.Major != nil {
return *x.Major
}
return 0
}
func (x *Version) GetMinor() int32 {
if x != nil && x.Minor != nil {
return *x.Minor
}
return 0
}
func (x *Version) GetPatch() int32 {
if x != nil && x.Patch != nil {
return *x.Patch
}
return 0
}
func (x *Version) GetSuffix() string {
if x != nil && x.Suffix != nil {
return *x.Suffix
}
return ""
}
// An encoded CodeGeneratorRequest is written to the plugin's stdin.
type CodeGeneratorRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
// The .proto files that were explicitly listed on the command-line. The
// code generator should generate code only for these files. Each file's
// descriptor will be included in proto_file, below.
FileToGenerate []string `protobuf:"bytes,1,rep,name=file_to_generate,json=fileToGenerate" json:"file_to_generate,omitempty"`
// The generator parameter passed on the command-line.
Parameter *string `protobuf:"bytes,2,opt,name=parameter" json:"parameter,omitempty"`
// FileDescriptorProtos for all files in files_to_generate and everything
// they import. The files will appear in topological order, so each file
// appears before any file that imports it.
//
// protoc guarantees that all proto_files will be written after
// the fields above, even though this is not technically guaranteed by the
// protobuf wire format. This theoretically could allow a plugin to stream
// in the FileDescriptorProtos and handle them one by one rather than read
// the entire set into memory at once. However, as of this writing, this
// is not similarly optimized on protoc's end -- it will store all fields in
// memory at once before sending them to the plugin.
//
// Type names of fields and extensions in the FileDescriptorProto are always
// fully qualified.
ProtoFile []*descriptorpb.FileDescriptorProto `protobuf:"bytes,15,rep,name=proto_file,json=protoFile" json:"proto_file,omitempty"`
// The version number of protocol compiler.
CompilerVersion *Version `protobuf:"bytes,3,opt,name=compiler_version,json=compilerVersion" json:"compiler_version,omitempty"`
}
func (x *CodeGeneratorRequest) Reset() {
*x = CodeGeneratorRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_google_protobuf_compiler_plugin_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *CodeGeneratorRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*CodeGeneratorRequest) ProtoMessage() {}
func (x *CodeGeneratorRequest) ProtoReflect() protoreflect.Message {
mi := &file_google_protobuf_compiler_plugin_proto_msgTypes[1]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use CodeGeneratorRequest.ProtoReflect.Descriptor instead.
func (*CodeGeneratorRequest) Descriptor() ([]byte, []int) {
return file_google_protobuf_compiler_plugin_proto_rawDescGZIP(), []int{1}
}
func (x *CodeGeneratorRequest) GetFileToGenerate() []string {
if x != nil {
return x.FileToGenerate
}
return nil
}
func (x *CodeGeneratorRequest) GetParameter() string {
if x != nil && x.Parameter != nil {
return *x.Parameter
}
return ""
}
func (x *CodeGeneratorRequest) GetProtoFile() []*descriptorpb.FileDescriptorProto {
if x != nil {
return x.ProtoFile
}
return nil
}
func (x *CodeGeneratorRequest) GetCompilerVersion() *Version {
if x != nil {
return x.CompilerVersion
}
return nil
}
// The plugin writes an encoded CodeGeneratorResponse to stdout.
type CodeGeneratorResponse struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
// Error message. If non-empty, code generation failed. The plugin process
// should exit with status code zero even if it reports an error in this way.
//
// This should be used to indicate errors in .proto files which prevent the
// code generator from generating correct code. Errors which indicate a
// problem in protoc itself -- such as the input CodeGeneratorRequest being
// unparseable -- should be reported by writing a message to stderr and
// exiting with a non-zero status code.
Error *string `protobuf:"bytes,1,opt,name=error" json:"error,omitempty"`
// A bitmask of supported features that the code generator supports.
// This is a bitwise "or" of values from the Feature enum.
SupportedFeatures *uint64 `protobuf:"varint,2,opt,name=supported_features,json=supportedFeatures" json:"supported_features,omitempty"`
File []*CodeGeneratorResponse_File `protobuf:"bytes,15,rep,name=file" json:"file,omitempty"`
}
func (x *CodeGeneratorResponse) Reset() {
*x = CodeGeneratorResponse{}
if protoimpl.UnsafeEnabled {
mi := &file_google_protobuf_compiler_plugin_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *CodeGeneratorResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*CodeGeneratorResponse) ProtoMessage() {}
func (x *CodeGeneratorResponse) ProtoReflect() protoreflect.Message {
mi := &file_google_protobuf_compiler_plugin_proto_msgTypes[2]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use CodeGeneratorResponse.ProtoReflect.Descriptor instead.
func (*CodeGeneratorResponse) Descriptor() ([]byte, []int) {
return file_google_protobuf_compiler_plugin_proto_rawDescGZIP(), []int{2}
}
func (x *CodeGeneratorResponse) GetError() string {
if x != nil && x.Error != nil {
return *x.Error
}
return ""
}
func (x *CodeGeneratorResponse) GetSupportedFeatures() uint64 {
if x != nil && x.SupportedFeatures != nil {
return *x.SupportedFeatures
}
return 0
}
func (x *CodeGeneratorResponse) GetFile() []*CodeGeneratorResponse_File {
if x != nil {
return x.File
}
return nil
}
// Represents a single generated file.
type CodeGeneratorResponse_File struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
// The file name, relative to the output directory. The name must not
// contain "." or ".." components and must be relative, not be absolute (so,
// the file cannot lie outside the output directory). "/" must be used as
// the path separator, not "\".
//
// If the name is omitted, the content will be appended to the previous
// file. This allows the generator to break large files into small chunks,
// and allows the generated text to be streamed back to protoc so that large
// files need not reside completely in memory at one time. Note that as of
// this writing protoc does not optimize for this -- it will read the entire
// CodeGeneratorResponse before writing files to disk.
Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"`
// If non-empty, indicates that the named file should already exist, and the
// content here is to be inserted into that file at a defined insertion
// point. This feature allows a code generator to extend the output
// produced by another code generator. The original generator may provide
// insertion points by placing special annotations in the file that look
// like:
// @@protoc_insertion_point(NAME)
// The annotation can have arbitrary text before and after it on the line,
// which allows it to be placed in a comment. NAME should be replaced with
// an identifier naming the point -- this is what other generators will use
// as the insertion_point. Code inserted at this point will be placed
// immediately above the line containing the insertion point (thus multiple
// insertions to the same point will come out in the order they were added).
// The double-@ is intended to make it unlikely that the generated code
// could contain things that look like insertion points by accident.
//
// For example, the C++ code generator places the following line in the
// .pb.h files that it generates:
// // @@protoc_insertion_point(namespace_scope)
// This line appears within the scope of the file's package namespace, but
// outside of any particular class. Another plugin can then specify the
// insertion_point "namespace_scope" to generate additional classes or
// other declarations that should be placed in this scope.
//
// Note that if the line containing the insertion point begins with
// whitespace, the same whitespace will be added to every line of the
// inserted text. This is useful for languages like Python, where
// indentation matters. In these languages, the insertion point comment
// should be indented the same amount as any inserted code will need to be
// in order to work correctly in that context.
//
// The code generator that generates the initial file and the one which
// inserts into it must both run as part of a single invocation of protoc.
// Code generators are executed in the order in which they appear on the
// command line.
//
// If |insertion_point| is present, |name| must also be present.
InsertionPoint *string `protobuf:"bytes,2,opt,name=insertion_point,json=insertionPoint" json:"insertion_point,omitempty"`
// The file contents.
Content *string `protobuf:"bytes,15,opt,name=content" json:"content,omitempty"`
// Information describing the file content being inserted. If an insertion
// point is used, this information will be appropriately offset and inserted
// into the code generation metadata for the generated files.
GeneratedCodeInfo *descriptorpb.GeneratedCodeInfo `protobuf:"bytes,16,opt,name=generated_code_info,json=generatedCodeInfo" json:"generated_code_info,omitempty"`
}
func (x *CodeGeneratorResponse_File) Reset() {
*x = CodeGeneratorResponse_File{}
if protoimpl.UnsafeEnabled {
mi := &file_google_protobuf_compiler_plugin_proto_msgTypes[3]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *CodeGeneratorResponse_File) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*CodeGeneratorResponse_File) ProtoMessage() {}
func (x *CodeGeneratorResponse_File) ProtoReflect() protoreflect.Message {
mi := &file_google_protobuf_compiler_plugin_proto_msgTypes[3]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use CodeGeneratorResponse_File.ProtoReflect.Descriptor instead.
func (*CodeGeneratorResponse_File) Descriptor() ([]byte, []int) {
return file_google_protobuf_compiler_plugin_proto_rawDescGZIP(), []int{2, 0}
}
func (x *CodeGeneratorResponse_File) GetName() string {
if x != nil && x.Name != nil {
return *x.Name
}
return ""
}
func (x *CodeGeneratorResponse_File) GetInsertionPoint() string {
if x != nil && x.InsertionPoint != nil {
return *x.InsertionPoint
}
return ""
}
func (x *CodeGeneratorResponse_File) GetContent() string {
if x != nil && x.Content != nil {
return *x.Content
}
return ""
}
func (x *CodeGeneratorResponse_File) GetGeneratedCodeInfo() *descriptorpb.GeneratedCodeInfo {
if x != nil {
return x.GeneratedCodeInfo
}
return nil
}
var File_google_protobuf_compiler_plugin_proto protoreflect.FileDescriptor
var file_google_protobuf_compiler_plugin_proto_rawDesc = []byte{
0x0a, 0x25, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75,
0x66, 0x2f, 0x63, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x72, 0x2f, 0x70, 0x6c, 0x75, 0x67, 0x69,
0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x18, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x63, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65,
0x72, 0x1a, 0x20, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62,
0x75, 0x66, 0x2f, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x2e, 0x70, 0x72,
0x6f, 0x74, 0x6f, 0x22, 0x63, 0x0a, 0x07, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x14,
0x0a, 0x05, 0x6d, 0x61, 0x6a, 0x6f, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x6d,
0x61, 0x6a, 0x6f, 0x72, 0x12, 0x14, 0x0a, 0x05, 0x6d, 0x69, 0x6e, 0x6f, 0x72, 0x18, 0x02, 0x20,
0x01, 0x28, 0x05, 0x52, 0x05, 0x6d, 0x69, 0x6e, 0x6f, 0x72, 0x12, 0x14, 0x0a, 0x05, 0x70, 0x61,
0x74, 0x63, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x70, 0x61, 0x74, 0x63, 0x68,
0x12, 0x16, 0x0a, 0x06, 0x73, 0x75, 0x66, 0x66, 0x69, 0x78, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09,
0x52, 0x06, 0x73, 0x75, 0x66, 0x66, 0x69, 0x78, 0x22, 0xf1, 0x01, 0x0a, 0x14, 0x43, 0x6f, 0x64,
0x65, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
0x74, 0x12, 0x28, 0x0a, 0x10, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x74, 0x6f, 0x5f, 0x67, 0x65, 0x6e,
0x65, 0x72, 0x61, 0x74, 0x65, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0e, 0x66, 0x69, 0x6c,
0x65, 0x54, 0x6f, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x70,
0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09,
0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x12, 0x43, 0x0a, 0x0a, 0x70, 0x72, 0x6f,
0x74, 0x6f, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x0f, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e,
0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e,
0x46, 0x69, 0x6c, 0x65, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72,
0x6f, 0x74, 0x6f, 0x52, 0x09, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x46, 0x69, 0x6c, 0x65, 0x12, 0x4c,
0x0a, 0x10, 0x63, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x72, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69,
0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x63, 0x6f, 0x6d, 0x70, 0x69,
0x6c, 0x65, 0x72, 0x2e, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x0f, 0x63, 0x6f, 0x6d,
0x70, 0x69, 0x6c, 0x65, 0x72, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x94, 0x03, 0x0a,
0x15, 0x43, 0x6f, 0x64, 0x65, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65,
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18,
0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x2d, 0x0a, 0x12,
0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x5f, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72,
0x65, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x11, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72,
0x74, 0x65, 0x64, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x12, 0x48, 0x0a, 0x04, 0x66,
0x69, 0x6c, 0x65, 0x18, 0x0f, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x34, 0x2e, 0x67, 0x6f, 0x6f, 0x67,
0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x63, 0x6f, 0x6d, 0x70,
0x69, 0x6c, 0x65, 0x72, 0x2e, 0x43, 0x6f, 0x64, 0x65, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74,
0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x52,
0x04, 0x66, 0x69, 0x6c, 0x65, 0x1a, 0xb1, 0x01, 0x0a, 0x04, 0x46, 0x69, 0x6c, 0x65, 0x12, 0x12,
0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61,
0x6d, 0x65, 0x12, 0x27, 0x0a, 0x0f, 0x69, 0x6e, 0x73, 0x65, 0x72, 0x74, 0x69, 0x6f, 0x6e, 0x5f,
0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x69, 0x6e, 0x73,
0x65, 0x72, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x63,
0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x6f,
0x6e, 0x74, 0x65, 0x6e, 0x74, 0x12, 0x52, 0x0a, 0x13, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74,
0x65, 0x64, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x10, 0x20, 0x01,
0x28, 0x0b, 0x32, 0x22, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74,
0x6f, 0x62, 0x75, 0x66, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x43, 0x6f,
0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x11, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65,
0x64, 0x43, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x22, 0x38, 0x0a, 0x07, 0x46, 0x65, 0x61,
0x74, 0x75, 0x72, 0x65, 0x12, 0x10, 0x0a, 0x0c, 0x46, 0x45, 0x41, 0x54, 0x55, 0x52, 0x45, 0x5f,
0x4e, 0x4f, 0x4e, 0x45, 0x10, 0x00, 0x12, 0x1b, 0x0a, 0x17, 0x46, 0x45, 0x41, 0x54, 0x55, 0x52,
0x45, 0x5f, 0x50, 0x52, 0x4f, 0x54, 0x4f, 0x33, 0x5f, 0x4f, 0x50, 0x54, 0x49, 0x4f, 0x4e, 0x41,
0x4c, 0x10, 0x01, 0x42, 0x57, 0x0a, 0x1c, 0x63, 0x6f, 0x6d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x63, 0x6f, 0x6d, 0x70, 0x69,
0x6c, 0x65, 0x72, 0x42, 0x0c, 0x50, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x50, 0x72, 0x6f, 0x74, 0x6f,
0x73, 0x5a, 0x29, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x67, 0x6f, 0x6c, 0x61, 0x6e, 0x67,
0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, 0x79,
0x70, 0x65, 0x73, 0x2f, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x70, 0x62,
}
var (
file_google_protobuf_compiler_plugin_proto_rawDescOnce sync.Once
file_google_protobuf_compiler_plugin_proto_rawDescData = file_google_protobuf_compiler_plugin_proto_rawDesc
)
func file_google_protobuf_compiler_plugin_proto_rawDescGZIP() []byte {
file_google_protobuf_compiler_plugin_proto_rawDescOnce.Do(func() {
file_google_protobuf_compiler_plugin_proto_rawDescData = protoimpl.X.CompressGZIP(file_google_protobuf_compiler_plugin_proto_rawDescData)
})
return file_google_protobuf_compiler_plugin_proto_rawDescData
}
var file_google_protobuf_compiler_plugin_proto_enumTypes = make([]protoimpl.EnumInfo, 1)
var file_google_protobuf_compiler_plugin_proto_msgTypes = make([]protoimpl.MessageInfo, 4)
var file_google_protobuf_compiler_plugin_proto_goTypes = []interface{}{
(CodeGeneratorResponse_Feature)(0), // 0: google.protobuf.compiler.CodeGeneratorResponse.Feature
(*Version)(nil), // 1: google.protobuf.compiler.Version
(*CodeGeneratorRequest)(nil), // 2: google.protobuf.compiler.CodeGeneratorRequest
(*CodeGeneratorResponse)(nil), // 3: google.protobuf.compiler.CodeGeneratorResponse
(*CodeGeneratorResponse_File)(nil), // 4: google.protobuf.compiler.CodeGeneratorResponse.File
(*descriptorpb.FileDescriptorProto)(nil), // 5: google.protobuf.FileDescriptorProto
(*descriptorpb.GeneratedCodeInfo)(nil), // 6: google.protobuf.GeneratedCodeInfo
}
var file_google_protobuf_compiler_plugin_proto_depIdxs = []int32{
5, // 0: google.protobuf.compiler.CodeGeneratorRequest.proto_file:type_name -> google.protobuf.FileDescriptorProto
1, // 1: google.protobuf.compiler.CodeGeneratorRequest.compiler_version:type_name -> google.protobuf.compiler.Version
4, // 2: google.protobuf.compiler.CodeGeneratorResponse.file:type_name -> google.protobuf.compiler.CodeGeneratorResponse.File
6, // 3: google.protobuf.compiler.CodeGeneratorResponse.File.generated_code_info:type_name -> google.protobuf.GeneratedCodeInfo
4, // [4:4] is the sub-list for method output_type
4, // [4:4] is the sub-list for method input_type
4, // [4:4] is the sub-list for extension type_name
4, // [4:4] is the sub-list for extension extendee
0, // [0:4] is the sub-list for field type_name
}
func init() { file_google_protobuf_compiler_plugin_proto_init() }
func file_google_protobuf_compiler_plugin_proto_init() {
if File_google_protobuf_compiler_plugin_proto != nil {
return
}
if !protoimpl.UnsafeEnabled {
file_google_protobuf_compiler_plugin_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Version); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_google_protobuf_compiler_plugin_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*CodeGeneratorRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_google_protobuf_compiler_plugin_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*CodeGeneratorResponse); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_google_protobuf_compiler_plugin_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*CodeGeneratorResponse_File); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_google_protobuf_compiler_plugin_proto_rawDesc,
NumEnums: 1,
NumMessages: 4,
NumExtensions: 0,
NumServices: 0,
},
GoTypes: file_google_protobuf_compiler_plugin_proto_goTypes,
DependencyIndexes: file_google_protobuf_compiler_plugin_proto_depIdxs,
EnumInfos: file_google_protobuf_compiler_plugin_proto_enumTypes,
MessageInfos: file_google_protobuf_compiler_plugin_proto_msgTypes,
}.Build()
File_google_protobuf_compiler_plugin_proto = out.File
file_google_protobuf_compiler_plugin_proto_rawDesc = nil
file_google_protobuf_compiler_plugin_proto_goTypes = nil
file_google_protobuf_compiler_plugin_proto_depIdxs = nil
}

30
vendor/modules.txt vendored
View file

@ -446,10 +446,35 @@ github.com/gogo/googleapis/google/rpc
## explicit; go 1.15
github.com/gogo/protobuf/gogoproto
github.com/gogo/protobuf/io
github.com/gogo/protobuf/plugin/compare
github.com/gogo/protobuf/plugin/defaultcheck
github.com/gogo/protobuf/plugin/description
github.com/gogo/protobuf/plugin/embedcheck
github.com/gogo/protobuf/plugin/enumstringer
github.com/gogo/protobuf/plugin/equal
github.com/gogo/protobuf/plugin/face
github.com/gogo/protobuf/plugin/gostring
github.com/gogo/protobuf/plugin/marshalto
github.com/gogo/protobuf/plugin/oneofcheck
github.com/gogo/protobuf/plugin/populate
github.com/gogo/protobuf/plugin/size
github.com/gogo/protobuf/plugin/stringer
github.com/gogo/protobuf/plugin/testgen
github.com/gogo/protobuf/plugin/union
github.com/gogo/protobuf/plugin/unmarshal
github.com/gogo/protobuf/proto
github.com/gogo/protobuf/protoc-gen-gogo
github.com/gogo/protobuf/protoc-gen-gogo/descriptor
github.com/gogo/protobuf/protoc-gen-gogo/generator
github.com/gogo/protobuf/protoc-gen-gogo/generator/internal/remap
github.com/gogo/protobuf/protoc-gen-gogo/grpc
github.com/gogo/protobuf/protoc-gen-gogo/plugin
github.com/gogo/protobuf/protoc-gen-gogofast
github.com/gogo/protobuf/protoc-gen-gogoslick
github.com/gogo/protobuf/sortkeys
github.com/gogo/protobuf/types
github.com/gogo/protobuf/vanity
github.com/gogo/protobuf/vanity/command
# github.com/golang-jwt/jwt/v4 v4.4.2
## explicit; go 1.16
github.com/golang-jwt/jwt/v4
@ -463,8 +488,10 @@ github.com/golang/groupcache/lru
# github.com/golang/protobuf v1.5.2
## explicit; go 1.9
github.com/golang/protobuf/descriptor
github.com/golang/protobuf/internal/gengogrpc
github.com/golang/protobuf/jsonpb
github.com/golang/protobuf/proto
github.com/golang/protobuf/protoc-gen-go
github.com/golang/protobuf/protoc-gen-go/descriptor
github.com/golang/protobuf/ptypes
github.com/golang/protobuf/ptypes/any
@ -1272,6 +1299,8 @@ google.golang.org/grpc/status
google.golang.org/grpc/tap
# google.golang.org/protobuf v1.28.1
## explicit; go 1.11
google.golang.org/protobuf/cmd/protoc-gen-go/internal_gengo
google.golang.org/protobuf/compiler/protogen
google.golang.org/protobuf/encoding/protojson
google.golang.org/protobuf/encoding/prototext
google.golang.org/protobuf/encoding/protowire
@ -1308,6 +1337,7 @@ google.golang.org/protobuf/types/known/fieldmaskpb
google.golang.org/protobuf/types/known/structpb
google.golang.org/protobuf/types/known/timestamppb
google.golang.org/protobuf/types/known/wrapperspb
google.golang.org/protobuf/types/pluginpb
# gopkg.in/yaml.v2 v2.4.0
## explicit; go 1.15
gopkg.in/yaml.v2