lib/protocol, lib/discover, lib/db: Use protocol buffer serialization (fixes #3080)
This changes the BEP protocol to use protocol buffer serialization instead of XDR, and therefore also the database format. The local discovery protocol is also updated to be protocol buffer format. GitHub-Pull-Request: https://github.com/syncthing/syncthing/pull/3276 LGTM: AudriusButkevicius
This commit is contained in:
committed by
Audrius Butkevicius
parent
21f5b16e47
commit
fa0101bd60
599
vendor/github.com/gogo/protobuf/plugin/size/size.go
generated
vendored
Normal file
599
vendor/github.com/gogo/protobuf/plugin/size/size.go
generated
vendored
Normal file
@@ -0,0 +1,599 @@
|
||||
// Copyright (c) 2013, Vastech SA (PTY) LTD. 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) {
|
||||
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"
|
||||
"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
|
||||
}
|
||||
|
||||
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) {
|
||||
for {
|
||||
n++
|
||||
x >>= 7
|
||||
if x == 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
return n
|
||||
}`)
|
||||
}
|
||||
|
||||
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) 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()
|
||||
_, 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))`)
|
||||
}
|
||||
sum = append(sum, strconv.Itoa(valueKeySize))
|
||||
switch m.ValueField.GetType() {
|
||||
case descriptor.FieldDescriptorProto_TYPE_DOUBLE,
|
||||
descriptor.FieldDescriptorProto_TYPE_FIXED64,
|
||||
descriptor.FieldDescriptorProto_TYPE_SFIXED64:
|
||||
sum = append(sum, strconv.Itoa(8))
|
||||
case descriptor.FieldDescriptorProto_TYPE_FLOAT,
|
||||
descriptor.FieldDescriptorProto_TYPE_FIXED32,
|
||||
descriptor.FieldDescriptorProto_TYPE_SFIXED32:
|
||||
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, `sov`+p.localName+`(uint64(v))`)
|
||||
case descriptor.FieldDescriptorProto_TYPE_BOOL:
|
||||
sum = append(sum, `1`)
|
||||
case descriptor.FieldDescriptorProto_TYPE_STRING,
|
||||
descriptor.FieldDescriptorProto_TYPE_BYTES:
|
||||
sum = append(sum, `len(v)+sov`+p.localName+`(uint64(len(v)))`)
|
||||
case descriptor.FieldDescriptorProto_TYPE_SINT32,
|
||||
descriptor.FieldDescriptorProto_TYPE_SINT64:
|
||||
sum = append(sum, `soz`+p.localName+`(uint64(v))`)
|
||||
case descriptor.FieldDescriptorProto_TYPE_MESSAGE:
|
||||
if nullable {
|
||||
p.P(`l = 0`)
|
||||
p.P(`if v != nil {`)
|
||||
p.In()
|
||||
if valuegoTyp != valuegoAliasTyp {
|
||||
p.P(`l = ((`, valuegoTyp, `)(v)).`, sizeName, `()`)
|
||||
} else {
|
||||
p.P(`l = v.`, sizeName, `()`)
|
||||
}
|
||||
p.Out()
|
||||
p.P(`}`)
|
||||
} else {
|
||||
if valuegoTyp != valuegoAliasTyp {
|
||||
p.P(`l = ((*`, valuegoTyp, `)(&v)).`, sizeName, `()`)
|
||||
} else {
|
||||
p.P(`l = v.`, sizeName, `()`)
|
||||
}
|
||||
}
|
||||
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()
|
||||
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_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)
|
||||
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() {
|
||||
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
|
||||
}
|
||||
p.atleastOne = true
|
||||
ccTypeName := generator.CamelCaseSlice(message.TypeName())
|
||||
p.P(`func (m *`, ccTypeName, `) `, sizeName, `() (n int) {`)
|
||||
p.In()
|
||||
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() {
|
||||
p.P(`if m.XXX_extensions != nil {`)
|
||||
p.In()
|
||||
if gogoproto.HasExtensionsMap(file.FileDescriptorProto, message.DescriptorProto) {
|
||||
p.P(`n += `, protoPkg.Use(), `.SizeOfExtensionMap(m.XXX_extensions)`)
|
||||
} else {
|
||||
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(`var l int`)
|
||||
p.P(`_ = l`)
|
||||
vanity.TurnOffNullableForNativeTypesWithoutDefaultsOnly(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())
|
||||
}
|
||||
132
vendor/github.com/gogo/protobuf/plugin/size/sizetest.go
generated
vendored
Normal file
132
vendor/github.com/gogo/protobuf/plugin/size/sizetest.go
generated
vendored
Normal file
@@ -0,0 +1,132 @@
|
||||
// Copyright (c) 2013, Vastech SA (PTY) LTD. 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)
|
||||
}
|
||||
Reference in New Issue
Block a user