mirror of
https://github.com/ceph/ceph-csi.git
synced 2024-12-11 15:40:24 +00:00
1206 lines
36 KiB
Go
1206 lines
36 KiB
Go
|
// 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 marshalto plugin generates a Marshal and MarshalTo method for each message.
|
||
|
The `Marshal() ([]byte, error)` method results in the fact that the message
|
||
|
implements the Marshaler interface.
|
||
|
This allows proto.Marshal to be faster by calling the generated Marshal method rather than using reflect to Marshal the struct.
|
||
|
|
||
|
If is enabled by the following extensions:
|
||
|
|
||
|
- marshaler
|
||
|
- marshaler_all
|
||
|
|
||
|
Or the following extensions:
|
||
|
|
||
|
- unsafe_marshaler
|
||
|
- unsafe_marshaler_all
|
||
|
|
||
|
That is if you want to use the unsafe package in your generated code.
|
||
|
The speed up using the unsafe package is not very significant.
|
||
|
|
||
|
The generation of marshalling tests are enabled using one of the following extensions:
|
||
|
|
||
|
- testgen
|
||
|
- testgen_all
|
||
|
|
||
|
And benchmarks 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.marshaler_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 marshalto plugin, will generate the following code:
|
||
|
|
||
|
func (m *B) Marshal() (dAtA []byte, err error) {
|
||
|
size := m.Size()
|
||
|
dAtA = make([]byte, size)
|
||
|
n, err := m.MarshalTo(dAtA)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
return dAtA[:n], nil
|
||
|
}
|
||
|
|
||
|
func (m *B) MarshalTo(dAtA []byte) (int, error) {
|
||
|
var i int
|
||
|
_ = i
|
||
|
var l int
|
||
|
_ = l
|
||
|
dAtA[i] = 0xa
|
||
|
i++
|
||
|
i = encodeVarintExample(dAtA, i, uint64(m.A.Size()))
|
||
|
n2, err := m.A.MarshalTo(dAtA[i:])
|
||
|
if err != nil {
|
||
|
return 0, err
|
||
|
}
|
||
|
i += n2
|
||
|
if len(m.G) > 0 {
|
||
|
for _, msg := range m.G {
|
||
|
dAtA[i] = 0x12
|
||
|
i++
|
||
|
i = encodeVarintExample(dAtA, i, uint64(msg.Size()))
|
||
|
n, err := msg.MarshalTo(dAtA[i:])
|
||
|
if err != nil {
|
||
|
return 0, err
|
||
|
}
|
||
|
i += n
|
||
|
}
|
||
|
}
|
||
|
if m.XXX_unrecognized != nil {
|
||
|
i += copy(dAtA[i:], m.XXX_unrecognized)
|
||
|
}
|
||
|
return i, nil
|
||
|
}
|
||
|
|
||
|
As shown above Marshal calculates the size of the not yet marshalled message
|
||
|
and allocates the appropriate buffer.
|
||
|
This is followed by calling the MarshalTo method which requires a preallocated buffer.
|
||
|
The MarshalTo method allows a user to rather preallocated a reusable buffer.
|
||
|
|
||
|
The Size method is generated using the size plugin and the gogoproto.sizer, gogoproto.sizer_all extensions.
|
||
|
The user can also using the generated Size method to check that his reusable buffer is still big enough.
|
||
|
|
||
|
The generated tests and benchmarks will keep you safe and show that this is really a significant speed improvement.
|
||
|
|
||
|
An additional message-level option `stable_marshaler` (and the file-level
|
||
|
option `stable_marshaler_all`) exists which causes the generated marshalling
|
||
|
code to behave deterministically. Today, this only changes the serialization of
|
||
|
maps; they are serialized in sort order.
|
||
|
*/
|
||
|
package marshalto
|
||
|
|
||
|
import (
|
||
|
"fmt"
|
||
|
"sort"
|
||
|
"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 NumGen interface {
|
||
|
Next() string
|
||
|
Current() string
|
||
|
}
|
||
|
|
||
|
type numGen struct {
|
||
|
index int
|
||
|
}
|
||
|
|
||
|
func NewNumGen() NumGen {
|
||
|
return &numGen{0}
|
||
|
}
|
||
|
|
||
|
func (this *numGen) Next() string {
|
||
|
this.index++
|
||
|
return this.Current()
|
||
|
}
|
||
|
|
||
|
func (this *numGen) Current() string {
|
||
|
return strconv.Itoa(this.index)
|
||
|
}
|
||
|
|
||
|
type marshalto struct {
|
||
|
*generator.Generator
|
||
|
generator.PluginImports
|
||
|
atleastOne bool
|
||
|
errorsPkg generator.Single
|
||
|
protoPkg generator.Single
|
||
|
sortKeysPkg generator.Single
|
||
|
mathPkg generator.Single
|
||
|
typesPkg generator.Single
|
||
|
binaryPkg generator.Single
|
||
|
localName string
|
||
|
}
|
||
|
|
||
|
func NewMarshal() *marshalto {
|
||
|
return &marshalto{}
|
||
|
}
|
||
|
|
||
|
func (p *marshalto) Name() string {
|
||
|
return "marshalto"
|
||
|
}
|
||
|
|
||
|
func (p *marshalto) Init(g *generator.Generator) {
|
||
|
p.Generator = g
|
||
|
}
|
||
|
|
||
|
func (p *marshalto) callFixed64(varName ...string) {
|
||
|
p.P(p.binaryPkg.Use(), `.LittleEndian.PutUint64(dAtA[i:], uint64(`, strings.Join(varName, ""), `))`)
|
||
|
p.P(`i += 8`)
|
||
|
}
|
||
|
|
||
|
func (p *marshalto) callFixed32(varName ...string) {
|
||
|
p.P(p.binaryPkg.Use(), `.LittleEndian.PutUint32(dAtA[i:], uint32(`, strings.Join(varName, ""), `))`)
|
||
|
p.P(`i += 4`)
|
||
|
}
|
||
|
|
||
|
func (p *marshalto) callVarint(varName ...string) {
|
||
|
p.P(`i = encodeVarint`, p.localName, `(dAtA, i, uint64(`, strings.Join(varName, ""), `))`)
|
||
|
}
|
||
|
|
||
|
func (p *marshalto) encodeVarint(varName string) {
|
||
|
p.P(`for `, varName, ` >= 1<<7 {`)
|
||
|
p.In()
|
||
|
p.P(`dAtA[i] = uint8(uint64(`, varName, `)&0x7f|0x80)`)
|
||
|
p.P(varName, ` >>= 7`)
|
||
|
p.P(`i++`)
|
||
|
p.Out()
|
||
|
p.P(`}`)
|
||
|
p.P(`dAtA[i] = uint8(`, varName, `)`)
|
||
|
p.P(`i++`)
|
||
|
}
|
||
|
|
||
|
func (p *marshalto) encodeKey(fieldNumber int32, wireType int) {
|
||
|
x := uint32(fieldNumber)<<3 | uint32(wireType)
|
||
|
i := 0
|
||
|
keybuf := make([]byte, 0)
|
||
|
for i = 0; x > 127; i++ {
|
||
|
keybuf = append(keybuf, 0x80|uint8(x&0x7F))
|
||
|
x >>= 7
|
||
|
}
|
||
|
keybuf = append(keybuf, uint8(x))
|
||
|
for _, b := range keybuf {
|
||
|
p.P(`dAtA[i] = `, fmt.Sprintf("%#v", b))
|
||
|
p.P(`i++`)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
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 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 (p *marshalto) mapField(numGen NumGen, field *descriptor.FieldDescriptorProto, kvField *descriptor.FieldDescriptorProto, varName string, protoSizer bool) {
|
||
|
switch kvField.GetType() {
|
||
|
case descriptor.FieldDescriptorProto_TYPE_DOUBLE:
|
||
|
p.callFixed64(p.mathPkg.Use(), `.Float64bits(float64(`, varName, `))`)
|
||
|
case descriptor.FieldDescriptorProto_TYPE_FLOAT:
|
||
|
p.callFixed32(p.mathPkg.Use(), `.Float32bits(float32(`, varName, `))`)
|
||
|
case descriptor.FieldDescriptorProto_TYPE_INT64,
|
||
|
descriptor.FieldDescriptorProto_TYPE_UINT64,
|
||
|
descriptor.FieldDescriptorProto_TYPE_INT32,
|
||
|
descriptor.FieldDescriptorProto_TYPE_UINT32,
|
||
|
descriptor.FieldDescriptorProto_TYPE_ENUM:
|
||
|
p.callVarint(varName)
|
||
|
case descriptor.FieldDescriptorProto_TYPE_FIXED64,
|
||
|
descriptor.FieldDescriptorProto_TYPE_SFIXED64:
|
||
|
p.callFixed64(varName)
|
||
|
case descriptor.FieldDescriptorProto_TYPE_FIXED32,
|
||
|
descriptor.FieldDescriptorProto_TYPE_SFIXED32:
|
||
|
p.callFixed32(varName)
|
||
|
case descriptor.FieldDescriptorProto_TYPE_BOOL:
|
||
|
p.P(`if `, varName, ` {`)
|
||
|
p.In()
|
||
|
p.P(`dAtA[i] = 1`)
|
||
|
p.Out()
|
||
|
p.P(`} else {`)
|
||
|
p.In()
|
||
|
p.P(`dAtA[i] = 0`)
|
||
|
p.Out()
|
||
|
p.P(`}`)
|
||
|
p.P(`i++`)
|
||
|
case descriptor.FieldDescriptorProto_TYPE_STRING,
|
||
|
descriptor.FieldDescriptorProto_TYPE_BYTES:
|
||
|
if gogoproto.IsCustomType(field) && kvField.IsBytes() {
|
||
|
p.callVarint(varName, `.Size()`)
|
||
|
p.P(`n`, numGen.Next(), `, err := `, varName, `.MarshalTo(dAtA[i:])`)
|
||
|
p.P(`if err != nil {`)
|
||
|
p.In()
|
||
|
p.P(`return 0, err`)
|
||
|
p.Out()
|
||
|
p.P(`}`)
|
||
|
p.P(`i+=n`, numGen.Current())
|
||
|
} else {
|
||
|
p.callVarint(`len(`, varName, `)`)
|
||
|
p.P(`i+=copy(dAtA[i:], `, varName, `)`)
|
||
|
}
|
||
|
case descriptor.FieldDescriptorProto_TYPE_SINT32:
|
||
|
p.callVarint(`(uint32(`, varName, `) << 1) ^ uint32((`, varName, ` >> 31))`)
|
||
|
case descriptor.FieldDescriptorProto_TYPE_SINT64:
|
||
|
p.callVarint(`(uint64(`, varName, `) << 1) ^ uint64((`, varName, ` >> 63))`)
|
||
|
case descriptor.FieldDescriptorProto_TYPE_MESSAGE:
|
||
|
if gogoproto.IsStdTime(field) {
|
||
|
p.callVarint(p.typesPkg.Use(), `.SizeOfStdTime(*`, varName, `)`)
|
||
|
p.P(`n`, numGen.Next(), `, err := `, p.typesPkg.Use(), `.StdTimeMarshalTo(*`, varName, `, dAtA[i:])`)
|
||
|
} else if gogoproto.IsStdDuration(field) {
|
||
|
p.callVarint(p.typesPkg.Use(), `.SizeOfStdDuration(*`, varName, `)`)
|
||
|
p.P(`n`, numGen.Next(), `, err := `, p.typesPkg.Use(), `.StdDurationMarshalTo(*`, varName, `, dAtA[i:])`)
|
||
|
} else if protoSizer {
|
||
|
p.callVarint(varName, `.ProtoSize()`)
|
||
|
p.P(`n`, numGen.Next(), `, err := `, varName, `.MarshalTo(dAtA[i:])`)
|
||
|
} else {
|
||
|
p.callVarint(varName, `.Size()`)
|
||
|
p.P(`n`, numGen.Next(), `, err := `, varName, `.MarshalTo(dAtA[i:])`)
|
||
|
}
|
||
|
p.P(`if err != nil {`)
|
||
|
p.In()
|
||
|
p.P(`return 0, err`)
|
||
|
p.Out()
|
||
|
p.P(`}`)
|
||
|
p.P(`i+=n`, numGen.Current())
|
||
|
}
|
||
|
}
|
||
|
|
||
|
type orderFields []*descriptor.FieldDescriptorProto
|
||
|
|
||
|
func (this orderFields) Len() int {
|
||
|
return len(this)
|
||
|
}
|
||
|
|
||
|
func (this orderFields) Less(i, j int) bool {
|
||
|
return this[i].GetNumber() < this[j].GetNumber()
|
||
|
}
|
||
|
|
||
|
func (this orderFields) Swap(i, j int) {
|
||
|
this[i], this[j] = this[j], this[i]
|
||
|
}
|
||
|
|
||
|
func (p *marshalto) generateField(proto3 bool, numGen NumGen, file *generator.FileDescriptor, message *generator.Descriptor, field *descriptor.FieldDescriptorProto) {
|
||
|
fieldname := p.GetOneOfFieldName(message, field)
|
||
|
nullable := gogoproto.IsNullable(field)
|
||
|
repeated := field.IsRepeated()
|
||
|
required := field.IsRequired()
|
||
|
|
||
|
protoSizer := gogoproto.IsProtoSizer(file.FileDescriptorProto, message.DescriptorProto)
|
||
|
doNilCheck := gogoproto.NeedsNilCheck(proto3, field)
|
||
|
if required && nullable {
|
||
|
p.P(`if m.`, fieldname, `== nil {`)
|
||
|
p.In()
|
||
|
if !gogoproto.ImportsGoGoProto(file.FileDescriptorProto) {
|
||
|
p.P(`return 0, new(`, p.protoPkg.Use(), `.RequiredNotSetError)`)
|
||
|
} else {
|
||
|
p.P(`return 0, `, p.protoPkg.Use(), `.NewRequiredNotSetError("`, field.GetName(), `")`)
|
||
|
}
|
||
|
p.Out()
|
||
|
p.P(`} else {`)
|
||
|
} else 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())
|
||
|
wireType := field.WireType()
|
||
|
fieldNumber := field.GetNumber()
|
||
|
if packed {
|
||
|
wireType = proto.WireBytes
|
||
|
}
|
||
|
switch *field.Type {
|
||
|
case descriptor.FieldDescriptorProto_TYPE_DOUBLE:
|
||
|
if packed {
|
||
|
p.encodeKey(fieldNumber, wireType)
|
||
|
p.callVarint(`len(m.`, fieldname, `) * 8`)
|
||
|
p.P(`for _, num := range m.`, fieldname, ` {`)
|
||
|
p.In()
|
||
|
p.P(`f`, numGen.Next(), ` := `, p.mathPkg.Use(), `.Float64bits(float64(num))`)
|
||
|
p.callFixed64("f" + numGen.Current())
|
||
|
p.Out()
|
||
|
p.P(`}`)
|
||
|
} else if repeated {
|
||
|
p.P(`for _, num := range m.`, fieldname, ` {`)
|
||
|
p.In()
|
||
|
p.encodeKey(fieldNumber, wireType)
|
||
|
p.P(`f`, numGen.Next(), ` := `, p.mathPkg.Use(), `.Float64bits(float64(num))`)
|
||
|
p.callFixed64("f" + numGen.Current())
|
||
|
p.Out()
|
||
|
p.P(`}`)
|
||
|
} else if proto3 {
|
||
|
p.P(`if m.`, fieldname, ` != 0 {`)
|
||
|
p.In()
|
||
|
p.encodeKey(fieldNumber, wireType)
|
||
|
p.callFixed64(p.mathPkg.Use(), `.Float64bits(float64(m.`+fieldname, `))`)
|
||
|
p.Out()
|
||
|
p.P(`}`)
|
||
|
} else if !nullable {
|
||
|
p.encodeKey(fieldNumber, wireType)
|
||
|
p.callFixed64(p.mathPkg.Use(), `.Float64bits(float64(m.`+fieldname, `))`)
|
||
|
} else {
|
||
|
p.encodeKey(fieldNumber, wireType)
|
||
|
p.callFixed64(p.mathPkg.Use(), `.Float64bits(float64(*m.`+fieldname, `))`)
|
||
|
}
|
||
|
case descriptor.FieldDescriptorProto_TYPE_FLOAT:
|
||
|
if packed {
|
||
|
p.encodeKey(fieldNumber, wireType)
|
||
|
p.callVarint(`len(m.`, fieldname, `) * 4`)
|
||
|
p.P(`for _, num := range m.`, fieldname, ` {`)
|
||
|
p.In()
|
||
|
p.P(`f`, numGen.Next(), ` := `, p.mathPkg.Use(), `.Float32bits(float32(num))`)
|
||
|
p.callFixed32("f" + numGen.Current())
|
||
|
p.Out()
|
||
|
p.P(`}`)
|
||
|
} else if repeated {
|
||
|
p.P(`for _, num := range m.`, fieldname, ` {`)
|
||
|
p.In()
|
||
|
p.encodeKey(fieldNumber, wireType)
|
||
|
p.P(`f`, numGen.Next(), ` := `, p.mathPkg.Use(), `.Float32bits(float32(num))`)
|
||
|
p.callFixed32("f" + numGen.Current())
|
||
|
p.Out()
|
||
|
p.P(`}`)
|
||
|
} else if proto3 {
|
||
|
p.P(`if m.`, fieldname, ` != 0 {`)
|
||
|
p.In()
|
||
|
p.encodeKey(fieldNumber, wireType)
|
||
|
p.callFixed32(p.mathPkg.Use(), `.Float32bits(float32(m.`+fieldname, `))`)
|
||
|
p.Out()
|
||
|
p.P(`}`)
|
||
|
} else if !nullable {
|
||
|
p.encodeKey(fieldNumber, wireType)
|
||
|
p.callFixed32(p.mathPkg.Use(), `.Float32bits(float32(m.`+fieldname, `))`)
|
||
|
} else {
|
||
|
p.encodeKey(fieldNumber, wireType)
|
||
|
p.callFixed32(p.mathPkg.Use(), `.Float32bits(float32(*m.`+fieldname, `))`)
|
||
|
}
|
||
|
case descriptor.FieldDescriptorProto_TYPE_INT64,
|
||
|
descriptor.FieldDescriptorProto_TYPE_UINT64,
|
||
|
descriptor.FieldDescriptorProto_TYPE_INT32,
|
||
|
descriptor.FieldDescriptorProto_TYPE_UINT32,
|
||
|
descriptor.FieldDescriptorProto_TYPE_ENUM:
|
||
|
if packed {
|
||
|
jvar := "j" + numGen.Next()
|
||
|
p.P(`dAtA`, numGen.Next(), ` := make([]byte, len(m.`, fieldname, `)*10)`)
|
||
|
p.P(`var `, jvar, ` int`)
|
||
|
if *field.Type == descriptor.FieldDescriptorProto_TYPE_INT64 ||
|
||
|
*field.Type == descriptor.FieldDescriptorProto_TYPE_INT32 {
|
||
|
p.P(`for _, num1 := range m.`, fieldname, ` {`)
|
||
|
p.In()
|
||
|
p.P(`num := uint64(num1)`)
|
||
|
} else {
|
||
|
p.P(`for _, num := range m.`, fieldname, ` {`)
|
||
|
p.In()
|
||
|
}
|
||
|
p.P(`for num >= 1<<7 {`)
|
||
|
p.In()
|
||
|
p.P(`dAtA`, numGen.Current(), `[`, jvar, `] = uint8(uint64(num)&0x7f|0x80)`)
|
||
|
p.P(`num >>= 7`)
|
||
|
p.P(jvar, `++`)
|
||
|
p.Out()
|
||
|
p.P(`}`)
|
||
|
p.P(`dAtA`, numGen.Current(), `[`, jvar, `] = uint8(num)`)
|
||
|
p.P(jvar, `++`)
|
||
|
p.Out()
|
||
|
p.P(`}`)
|
||
|
p.encodeKey(fieldNumber, wireType)
|
||
|
p.callVarint(jvar)
|
||
|
p.P(`i += copy(dAtA[i:], dAtA`, numGen.Current(), `[:`, jvar, `])`)
|
||
|
} else if repeated {
|
||
|
p.P(`for _, num := range m.`, fieldname, ` {`)
|
||
|
p.In()
|
||
|
p.encodeKey(fieldNumber, wireType)
|
||
|
p.callVarint("num")
|
||
|
p.Out()
|
||
|
p.P(`}`)
|
||
|
} else if proto3 {
|
||
|
p.P(`if m.`, fieldname, ` != 0 {`)
|
||
|
p.In()
|
||
|
p.encodeKey(fieldNumber, wireType)
|
||
|
p.callVarint(`m.`, fieldname)
|
||
|
p.Out()
|
||
|
p.P(`}`)
|
||
|
} else if !nullable {
|
||
|
p.encodeKey(fieldNumber, wireType)
|
||
|
p.callVarint(`m.`, fieldname)
|
||
|
} else {
|
||
|
p.encodeKey(fieldNumber, wireType)
|
||
|
p.callVarint(`*m.`, fieldname)
|
||
|
}
|
||
|
case descriptor.FieldDescriptorProto_TYPE_FIXED64,
|
||
|
descriptor.FieldDescriptorProto_TYPE_SFIXED64:
|
||
|
if packed {
|
||
|
p.encodeKey(fieldNumber, wireType)
|
||
|
p.callVarint(`len(m.`, fieldname, `) * 8`)
|
||
|
p.P(`for _, num := range m.`, fieldname, ` {`)
|
||
|
p.In()
|
||
|
p.callFixed64("num")
|
||
|
p.Out()
|
||
|
p.P(`}`)
|
||
|
} else if repeated {
|
||
|
p.P(`for _, num := range m.`, fieldname, ` {`)
|
||
|
p.In()
|
||
|
p.encodeKey(fieldNumber, wireType)
|
||
|
p.callFixed64("num")
|
||
|
p.Out()
|
||
|
p.P(`}`)
|
||
|
} else if proto3 {
|
||
|
p.P(`if m.`, fieldname, ` != 0 {`)
|
||
|
p.In()
|
||
|
p.encodeKey(fieldNumber, wireType)
|
||
|
p.callFixed64("m." + fieldname)
|
||
|
p.Out()
|
||
|
p.P(`}`)
|
||
|
} else if !nullable {
|
||
|
p.encodeKey(fieldNumber, wireType)
|
||
|
p.callFixed64("m." + fieldname)
|
||
|
} else {
|
||
|
p.encodeKey(fieldNumber, wireType)
|
||
|
p.callFixed64("*m." + fieldname)
|
||
|
}
|
||
|
case descriptor.FieldDescriptorProto_TYPE_FIXED32,
|
||
|
descriptor.FieldDescriptorProto_TYPE_SFIXED32:
|
||
|
if packed {
|
||
|
p.encodeKey(fieldNumber, wireType)
|
||
|
p.callVarint(`len(m.`, fieldname, `) * 4`)
|
||
|
p.P(`for _, num := range m.`, fieldname, ` {`)
|
||
|
p.In()
|
||
|
p.callFixed32("num")
|
||
|
p.Out()
|
||
|
p.P(`}`)
|
||
|
} else if repeated {
|
||
|
p.P(`for _, num := range m.`, fieldname, ` {`)
|
||
|
p.In()
|
||
|
p.encodeKey(fieldNumber, wireType)
|
||
|
p.callFixed32("num")
|
||
|
p.Out()
|
||
|
p.P(`}`)
|
||
|
} else if proto3 {
|
||
|
p.P(`if m.`, fieldname, ` != 0 {`)
|
||
|
p.In()
|
||
|
p.encodeKey(fieldNumber, wireType)
|
||
|
p.callFixed32("m." + fieldname)
|
||
|
p.Out()
|
||
|
p.P(`}`)
|
||
|
} else if !nullable {
|
||
|
p.encodeKey(fieldNumber, wireType)
|
||
|
p.callFixed32("m." + fieldname)
|
||
|
} else {
|
||
|
p.encodeKey(fieldNumber, wireType)
|
||
|
p.callFixed32("*m." + fieldname)
|
||
|
}
|
||
|
case descriptor.FieldDescriptorProto_TYPE_BOOL:
|
||
|
if packed {
|
||
|
p.encodeKey(fieldNumber, wireType)
|
||
|
p.callVarint(`len(m.`, fieldname, `)`)
|
||
|
p.P(`for _, b := range m.`, fieldname, ` {`)
|
||
|
p.In()
|
||
|
p.P(`if b {`)
|
||
|
p.In()
|
||
|
p.P(`dAtA[i] = 1`)
|
||
|
p.Out()
|
||
|
p.P(`} else {`)
|
||
|
p.In()
|
||
|
p.P(`dAtA[i] = 0`)
|
||
|
p.Out()
|
||
|
p.P(`}`)
|
||
|
p.P(`i++`)
|
||
|
p.Out()
|
||
|
p.P(`}`)
|
||
|
} else if repeated {
|
||
|
p.P(`for _, b := range m.`, fieldname, ` {`)
|
||
|
p.In()
|
||
|
p.encodeKey(fieldNumber, wireType)
|
||
|
p.P(`if b {`)
|
||
|
p.In()
|
||
|
p.P(`dAtA[i] = 1`)
|
||
|
p.Out()
|
||
|
p.P(`} else {`)
|
||
|
p.In()
|
||
|
p.P(`dAtA[i] = 0`)
|
||
|
p.Out()
|
||
|
p.P(`}`)
|
||
|
p.P(`i++`)
|
||
|
p.Out()
|
||
|
p.P(`}`)
|
||
|
} else if proto3 {
|
||
|
p.P(`if m.`, fieldname, ` {`)
|
||
|
p.In()
|
||
|
p.encodeKey(fieldNumber, wireType)
|
||
|
p.P(`if m.`, fieldname, ` {`)
|
||
|
p.In()
|
||
|
p.P(`dAtA[i] = 1`)
|
||
|
p.Out()
|
||
|
p.P(`} else {`)
|
||
|
p.In()
|
||
|
p.P(`dAtA[i] = 0`)
|
||
|
p.Out()
|
||
|
p.P(`}`)
|
||
|
p.P(`i++`)
|
||
|
p.Out()
|
||
|
p.P(`}`)
|
||
|
} else if !nullable {
|
||
|
p.encodeKey(fieldNumber, wireType)
|
||
|
p.P(`if m.`, fieldname, ` {`)
|
||
|
p.In()
|
||
|
p.P(`dAtA[i] = 1`)
|
||
|
p.Out()
|
||
|
p.P(`} else {`)
|
||
|
p.In()
|
||
|
p.P(`dAtA[i] = 0`)
|
||
|
p.Out()
|
||
|
p.P(`}`)
|
||
|
p.P(`i++`)
|
||
|
} else {
|
||
|
p.encodeKey(fieldNumber, wireType)
|
||
|
p.P(`if *m.`, fieldname, ` {`)
|
||
|
p.In()
|
||
|
p.P(`dAtA[i] = 1`)
|
||
|
p.Out()
|
||
|
p.P(`} else {`)
|
||
|
p.In()
|
||
|
p.P(`dAtA[i] = 0`)
|
||
|
p.Out()
|
||
|
p.P(`}`)
|
||
|
p.P(`i++`)
|
||
|
}
|
||
|
case descriptor.FieldDescriptorProto_TYPE_STRING:
|
||
|
if repeated {
|
||
|
p.P(`for _, s := range m.`, fieldname, ` {`)
|
||
|
p.In()
|
||
|
p.encodeKey(fieldNumber, wireType)
|
||
|
p.P(`l = len(s)`)
|
||
|
p.encodeVarint("l")
|
||
|
p.P(`i+=copy(dAtA[i:], s)`)
|
||
|
p.Out()
|
||
|
p.P(`}`)
|
||
|
} else if proto3 {
|
||
|
p.P(`if len(m.`, fieldname, `) > 0 {`)
|
||
|
p.In()
|
||
|
p.encodeKey(fieldNumber, wireType)
|
||
|
p.callVarint(`len(m.`, fieldname, `)`)
|
||
|
p.P(`i+=copy(dAtA[i:], m.`, fieldname, `)`)
|
||
|
p.Out()
|
||
|
p.P(`}`)
|
||
|
} else if !nullable {
|
||
|
p.encodeKey(fieldNumber, wireType)
|
||
|
p.callVarint(`len(m.`, fieldname, `)`)
|
||
|
p.P(`i+=copy(dAtA[i:], m.`, fieldname, `)`)
|
||
|
} else {
|
||
|
p.encodeKey(fieldNumber, wireType)
|
||
|
p.callVarint(`len(*m.`, fieldname, `)`)
|
||
|
p.P(`i+=copy(dAtA[i:], *m.`, fieldname, `)`)
|
||
|
}
|
||
|
case descriptor.FieldDescriptorProto_TYPE_GROUP:
|
||
|
panic(fmt.Errorf("marshaler does not support group %v", fieldname))
|
||
|
case descriptor.FieldDescriptorProto_TYPE_MESSAGE:
|
||
|
if p.IsMap(field) {
|
||
|
m := p.GoMapType(nil, field)
|
||
|
keygoTyp, keywire := p.GoType(nil, m.KeyField)
|
||
|
keygoAliasTyp, _ := p.GoType(nil, m.KeyAliasField)
|
||
|
// keys may not be pointers
|
||
|
keygoTyp = strings.Replace(keygoTyp, "*", "", 1)
|
||
|
keygoAliasTyp = strings.Replace(keygoAliasTyp, "*", "", 1)
|
||
|
keyCapTyp := generator.CamelCase(keygoTyp)
|
||
|
valuegoTyp, valuewire := p.GoType(nil, m.ValueField)
|
||
|
valuegoAliasTyp, _ := p.GoType(nil, m.ValueAliasField)
|
||
|
nullable, valuegoTyp, valuegoAliasTyp = generator.GoMapValueTypes(field, m.ValueField, valuegoTyp, valuegoAliasTyp)
|
||
|
keyKeySize := keySize(1, wireToType(keywire))
|
||
|
valueKeySize := keySize(2, wireToType(valuewire))
|
||
|
if gogoproto.IsStableMarshaler(file.FileDescriptorProto, message.DescriptorProto) {
|
||
|
keysName := `keysFor` + fieldname
|
||
|
p.P(keysName, ` := make([]`, keygoTyp, `, 0, len(m.`, fieldname, `))`)
|
||
|
p.P(`for k, _ := range m.`, fieldname, ` {`)
|
||
|
p.In()
|
||
|
p.P(keysName, ` = append(`, keysName, `, `, keygoTyp, `(k))`)
|
||
|
p.Out()
|
||
|
p.P(`}`)
|
||
|
p.P(p.sortKeysPkg.Use(), `.`, keyCapTyp, `s(`, keysName, `)`)
|
||
|
p.P(`for _, k := range `, keysName, ` {`)
|
||
|
} else {
|
||
|
p.P(`for k, _ := range m.`, fieldname, ` {`)
|
||
|
}
|
||
|
p.In()
|
||
|
p.encodeKey(fieldNumber, wireType)
|
||
|
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))`)
|
||
|
}
|
||
|
if gogoproto.IsStableMarshaler(file.FileDescriptorProto, message.DescriptorProto) {
|
||
|
p.P(`v := m.`, fieldname, `[`, keygoAliasTyp, `(k)]`)
|
||
|
} else {
|
||
|
p.P(`v := m.`, fieldname, `[k]`)
|
||
|
}
|
||
|
accessor := `v`
|
||
|
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(`cSize := 0`)
|
||
|
if gogoproto.IsNullable(field) {
|
||
|
p.P(`if `, accessor, ` != nil {`)
|
||
|
p.In()
|
||
|
}
|
||
|
p.P(`cSize = `, accessor, `.Size()`)
|
||
|
p.P(`cSize += `, strconv.Itoa(valueKeySize), ` + sov`+p.localName+`(uint64(cSize))`)
|
||
|
if gogoproto.IsNullable(field) {
|
||
|
p.Out()
|
||
|
p.P(`}`)
|
||
|
}
|
||
|
sum = append(sum, `cSize`)
|
||
|
} else {
|
||
|
p.P(`byteSize := 0`)
|
||
|
if proto3 {
|
||
|
p.P(`if len(v) > 0 {`)
|
||
|
} else {
|
||
|
p.P(`if v != nil {`)
|
||
|
}
|
||
|
p.In()
|
||
|
p.P(`byteSize = `, strconv.Itoa(valueKeySize), ` + len(v)+sov`+p.localName+`(uint64(len(v)))`)
|
||
|
p.Out()
|
||
|
p.P(`}`)
|
||
|
sum = append(sum, `byteSize`)
|
||
|
}
|
||
|
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:
|
||
|
if valuegoTyp != valuegoAliasTyp &&
|
||
|
!gogoproto.IsStdTime(field) &&
|
||
|
!gogoproto.IsStdDuration(field) {
|
||
|
if nullable {
|
||
|
// cast back to the type that has the generated methods on it
|
||
|
accessor = `((` + valuegoTyp + `)(` + accessor + `))`
|
||
|
} else {
|
||
|
accessor = `((*` + valuegoTyp + `)(&` + accessor + `))`
|
||
|
}
|
||
|
} else if !nullable {
|
||
|
accessor = `(&v)`
|
||
|
}
|
||
|
p.P(`msgSize := 0`)
|
||
|
p.P(`if `, accessor, ` != nil {`)
|
||
|
p.In()
|
||
|
if gogoproto.IsStdTime(field) {
|
||
|
p.P(`msgSize = `, p.typesPkg.Use(), `.SizeOfStdTime(*`, accessor, `)`)
|
||
|
} else if gogoproto.IsStdDuration(field) {
|
||
|
p.P(`msgSize = `, p.typesPkg.Use(), `.SizeOfStdDuration(*`, accessor, `)`)
|
||
|
} else if protoSizer {
|
||
|
p.P(`msgSize = `, accessor, `.ProtoSize()`)
|
||
|
} else {
|
||
|
p.P(`msgSize = `, accessor, `.Size()`)
|
||
|
}
|
||
|
p.P(`msgSize += `, strconv.Itoa(valueKeySize), ` + sov`+p.localName+`(uint64(msgSize))`)
|
||
|
p.Out()
|
||
|
p.P(`}`)
|
||
|
sum = append(sum, `msgSize`)
|
||
|
}
|
||
|
p.P(`mapSize := `, strings.Join(sum, " + "))
|
||
|
p.callVarint("mapSize")
|
||
|
p.encodeKey(1, wireToType(keywire))
|
||
|
p.mapField(numGen, field, m.KeyField, "k", protoSizer)
|
||
|
nullableMsg := nullable && (m.ValueField.GetType() == descriptor.FieldDescriptorProto_TYPE_MESSAGE ||
|
||
|
gogoproto.IsCustomType(field) && m.ValueField.IsBytes())
|
||
|
plainBytes := m.ValueField.IsBytes() && !gogoproto.IsCustomType(field)
|
||
|
if nullableMsg {
|
||
|
p.P(`if `, accessor, ` != nil { `)
|
||
|
p.In()
|
||
|
} else if plainBytes {
|
||
|
if proto3 {
|
||
|
p.P(`if len(`, accessor, `) > 0 {`)
|
||
|
} else {
|
||
|
p.P(`if `, accessor, ` != nil {`)
|
||
|
}
|
||
|
p.In()
|
||
|
}
|
||
|
p.encodeKey(2, wireToType(valuewire))
|
||
|
p.mapField(numGen, field, m.ValueField, accessor, protoSizer)
|
||
|
if nullableMsg || plainBytes {
|
||
|
p.Out()
|
||
|
p.P(`}`)
|
||
|
}
|
||
|
p.Out()
|
||
|
p.P(`}`)
|
||
|
} else if repeated {
|
||
|
p.P(`for _, msg := range m.`, fieldname, ` {`)
|
||
|
p.In()
|
||
|
p.encodeKey(fieldNumber, wireType)
|
||
|
varName := "msg"
|
||
|
if gogoproto.IsStdTime(field) {
|
||
|
if gogoproto.IsNullable(field) {
|
||
|
varName = "*" + varName
|
||
|
}
|
||
|
p.callVarint(p.typesPkg.Use(), `.SizeOfStdTime(`, varName, `)`)
|
||
|
p.P(`n, err := `, p.typesPkg.Use(), `.StdTimeMarshalTo(`, varName, `, dAtA[i:])`)
|
||
|
} else if gogoproto.IsStdDuration(field) {
|
||
|
if gogoproto.IsNullable(field) {
|
||
|
varName = "*" + varName
|
||
|
}
|
||
|
p.callVarint(p.typesPkg.Use(), `.SizeOfStdDuration(`, varName, `)`)
|
||
|
p.P(`n, err := `, p.typesPkg.Use(), `.StdDurationMarshalTo(`, varName, `, dAtA[i:])`)
|
||
|
} else if protoSizer {
|
||
|
p.callVarint(varName, ".ProtoSize()")
|
||
|
p.P(`n, err := `, varName, `.MarshalTo(dAtA[i:])`)
|
||
|
} else {
|
||
|
p.callVarint(varName, ".Size()")
|
||
|
p.P(`n, err := `, varName, `.MarshalTo(dAtA[i:])`)
|
||
|
}
|
||
|
p.P(`if err != nil {`)
|
||
|
p.In()
|
||
|
p.P(`return 0, err`)
|
||
|
p.Out()
|
||
|
p.P(`}`)
|
||
|
p.P(`i+=n`)
|
||
|
p.Out()
|
||
|
p.P(`}`)
|
||
|
} else {
|
||
|
p.encodeKey(fieldNumber, wireType)
|
||
|
varName := `m.` + fieldname
|
||
|
if gogoproto.IsStdTime(field) {
|
||
|
if gogoproto.IsNullable(field) {
|
||
|
varName = "*" + varName
|
||
|
}
|
||
|
p.callVarint(p.typesPkg.Use(), `.SizeOfStdTime(`, varName, `)`)
|
||
|
p.P(`n`, numGen.Next(), `, err := `, p.typesPkg.Use(), `.StdTimeMarshalTo(`, varName, `, dAtA[i:])`)
|
||
|
} else if gogoproto.IsStdDuration(field) {
|
||
|
if gogoproto.IsNullable(field) {
|
||
|
varName = "*" + varName
|
||
|
}
|
||
|
p.callVarint(p.typesPkg.Use(), `.SizeOfStdDuration(`, varName, `)`)
|
||
|
p.P(`n`, numGen.Next(), `, err := `, p.typesPkg.Use(), `.StdDurationMarshalTo(`, varName, `, dAtA[i:])`)
|
||
|
} else if protoSizer {
|
||
|
p.callVarint(varName, `.ProtoSize()`)
|
||
|
p.P(`n`, numGen.Next(), `, err := `, varName, `.MarshalTo(dAtA[i:])`)
|
||
|
} else {
|
||
|
p.callVarint(varName, `.Size()`)
|
||
|
p.P(`n`, numGen.Next(), `, err := `, varName, `.MarshalTo(dAtA[i:])`)
|
||
|
}
|
||
|
p.P(`if err != nil {`)
|
||
|
p.In()
|
||
|
p.P(`return 0, err`)
|
||
|
p.Out()
|
||
|
p.P(`}`)
|
||
|
p.P(`i+=n`, numGen.Current())
|
||
|
}
|
||
|
case descriptor.FieldDescriptorProto_TYPE_BYTES:
|
||
|
if !gogoproto.IsCustomType(field) {
|
||
|
if repeated {
|
||
|
p.P(`for _, b := range m.`, fieldname, ` {`)
|
||
|
p.In()
|
||
|
p.encodeKey(fieldNumber, wireType)
|
||
|
p.callVarint("len(b)")
|
||
|
p.P(`i+=copy(dAtA[i:], b)`)
|
||
|
p.Out()
|
||
|
p.P(`}`)
|
||
|
} else if proto3 {
|
||
|
p.P(`if len(m.`, fieldname, `) > 0 {`)
|
||
|
p.In()
|
||
|
p.encodeKey(fieldNumber, wireType)
|
||
|
p.callVarint(`len(m.`, fieldname, `)`)
|
||
|
p.P(`i+=copy(dAtA[i:], m.`, fieldname, `)`)
|
||
|
p.Out()
|
||
|
p.P(`}`)
|
||
|
} else {
|
||
|
p.encodeKey(fieldNumber, wireType)
|
||
|
p.callVarint(`len(m.`, fieldname, `)`)
|
||
|
p.P(`i+=copy(dAtA[i:], m.`, fieldname, `)`)
|
||
|
}
|
||
|
} else {
|
||
|
if repeated {
|
||
|
p.P(`for _, msg := range m.`, fieldname, ` {`)
|
||
|
p.In()
|
||
|
p.encodeKey(fieldNumber, wireType)
|
||
|
if protoSizer {
|
||
|
p.callVarint(`msg.ProtoSize()`)
|
||
|
} else {
|
||
|
p.callVarint(`msg.Size()`)
|
||
|
}
|
||
|
p.P(`n, err := msg.MarshalTo(dAtA[i:])`)
|
||
|
p.P(`if err != nil {`)
|
||
|
p.In()
|
||
|
p.P(`return 0, err`)
|
||
|
p.Out()
|
||
|
p.P(`}`)
|
||
|
p.P(`i+=n`)
|
||
|
p.Out()
|
||
|
p.P(`}`)
|
||
|
} else {
|
||
|
p.encodeKey(fieldNumber, wireType)
|
||
|
if protoSizer {
|
||
|
p.callVarint(`m.`, fieldname, `.ProtoSize()`)
|
||
|
} else {
|
||
|
p.callVarint(`m.`, fieldname, `.Size()`)
|
||
|
}
|
||
|
p.P(`n`, numGen.Next(), `, err := m.`, fieldname, `.MarshalTo(dAtA[i:])`)
|
||
|
p.P(`if err != nil {`)
|
||
|
p.In()
|
||
|
p.P(`return 0, err`)
|
||
|
p.Out()
|
||
|
p.P(`}`)
|
||
|
p.P(`i+=n`, numGen.Current())
|
||
|
}
|
||
|
}
|
||
|
case descriptor.FieldDescriptorProto_TYPE_SINT32:
|
||
|
if packed {
|
||
|
datavar := "dAtA" + numGen.Next()
|
||
|
jvar := "j" + numGen.Next()
|
||
|
p.P(datavar, ` := make([]byte, len(m.`, fieldname, ")*5)")
|
||
|
p.P(`var `, jvar, ` int`)
|
||
|
p.P(`for _, num := range m.`, fieldname, ` {`)
|
||
|
p.In()
|
||
|
xvar := "x" + numGen.Next()
|
||
|
p.P(xvar, ` := (uint32(num) << 1) ^ uint32((num >> 31))`)
|
||
|
p.P(`for `, xvar, ` >= 1<<7 {`)
|
||
|
p.In()
|
||
|
p.P(datavar, `[`, jvar, `] = uint8(uint64(`, xvar, `)&0x7f|0x80)`)
|
||
|
p.P(jvar, `++`)
|
||
|
p.P(xvar, ` >>= 7`)
|
||
|
p.Out()
|
||
|
p.P(`}`)
|
||
|
p.P(datavar, `[`, jvar, `] = uint8(`, xvar, `)`)
|
||
|
p.P(jvar, `++`)
|
||
|
p.Out()
|
||
|
p.P(`}`)
|
||
|
p.encodeKey(fieldNumber, wireType)
|
||
|
p.callVarint(jvar)
|
||
|
p.P(`i+=copy(dAtA[i:], `, datavar, `[:`, jvar, `])`)
|
||
|
} else if repeated {
|
||
|
p.P(`for _, num := range m.`, fieldname, ` {`)
|
||
|
p.In()
|
||
|
p.encodeKey(fieldNumber, wireType)
|
||
|
p.P(`x`, numGen.Next(), ` := (uint32(num) << 1) ^ uint32((num >> 31))`)
|
||
|
p.encodeVarint("x" + numGen.Current())
|
||
|
p.Out()
|
||
|
p.P(`}`)
|
||
|
} else if proto3 {
|
||
|
p.P(`if m.`, fieldname, ` != 0 {`)
|
||
|
p.In()
|
||
|
p.encodeKey(fieldNumber, wireType)
|
||
|
p.callVarint(`(uint32(m.`, fieldname, `) << 1) ^ uint32((m.`, fieldname, ` >> 31))`)
|
||
|
p.Out()
|
||
|
p.P(`}`)
|
||
|
} else if !nullable {
|
||
|
p.encodeKey(fieldNumber, wireType)
|
||
|
p.callVarint(`(uint32(m.`, fieldname, `) << 1) ^ uint32((m.`, fieldname, ` >> 31))`)
|
||
|
} else {
|
||
|
p.encodeKey(fieldNumber, wireType)
|
||
|
p.callVarint(`(uint32(*m.`, fieldname, `) << 1) ^ uint32((*m.`, fieldname, ` >> 31))`)
|
||
|
}
|
||
|
case descriptor.FieldDescriptorProto_TYPE_SINT64:
|
||
|
if packed {
|
||
|
jvar := "j" + numGen.Next()
|
||
|
xvar := "x" + numGen.Next()
|
||
|
datavar := "dAtA" + numGen.Next()
|
||
|
p.P(`var `, jvar, ` int`)
|
||
|
p.P(datavar, ` := make([]byte, len(m.`, fieldname, `)*10)`)
|
||
|
p.P(`for _, num := range m.`, fieldname, ` {`)
|
||
|
p.In()
|
||
|
p.P(xvar, ` := (uint64(num) << 1) ^ uint64((num >> 63))`)
|
||
|
p.P(`for `, xvar, ` >= 1<<7 {`)
|
||
|
p.In()
|
||
|
p.P(datavar, `[`, jvar, `] = uint8(uint64(`, xvar, `)&0x7f|0x80)`)
|
||
|
p.P(jvar, `++`)
|
||
|
p.P(xvar, ` >>= 7`)
|
||
|
p.Out()
|
||
|
p.P(`}`)
|
||
|
p.P(datavar, `[`, jvar, `] = uint8(`, xvar, `)`)
|
||
|
p.P(jvar, `++`)
|
||
|
p.Out()
|
||
|
p.P(`}`)
|
||
|
p.encodeKey(fieldNumber, wireType)
|
||
|
p.callVarint(jvar)
|
||
|
p.P(`i+=copy(dAtA[i:], `, datavar, `[:`, jvar, `])`)
|
||
|
} else if repeated {
|
||
|
p.P(`for _, num := range m.`, fieldname, ` {`)
|
||
|
p.In()
|
||
|
p.encodeKey(fieldNumber, wireType)
|
||
|
p.P(`x`, numGen.Next(), ` := (uint64(num) << 1) ^ uint64((num >> 63))`)
|
||
|
p.encodeVarint("x" + numGen.Current())
|
||
|
p.Out()
|
||
|
p.P(`}`)
|
||
|
} else if proto3 {
|
||
|
p.P(`if m.`, fieldname, ` != 0 {`)
|
||
|
p.In()
|
||
|
p.encodeKey(fieldNumber, wireType)
|
||
|
p.callVarint(`(uint64(m.`, fieldname, `) << 1) ^ uint64((m.`, fieldname, ` >> 63))`)
|
||
|
p.Out()
|
||
|
p.P(`}`)
|
||
|
} else if !nullable {
|
||
|
p.encodeKey(fieldNumber, wireType)
|
||
|
p.callVarint(`(uint64(m.`, fieldname, `) << 1) ^ uint64((m.`, fieldname, ` >> 63))`)
|
||
|
} else {
|
||
|
p.encodeKey(fieldNumber, wireType)
|
||
|
p.callVarint(`(uint64(*m.`, fieldname, `) << 1) ^ uint64((*m.`, fieldname, ` >> 63))`)
|
||
|
}
|
||
|
default:
|
||
|
panic("not implemented")
|
||
|
}
|
||
|
if (required && nullable) || repeated || doNilCheck {
|
||
|
p.Out()
|
||
|
p.P(`}`)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func (p *marshalto) Generate(file *generator.FileDescriptor) {
|
||
|
numGen := NewNumGen()
|
||
|
p.PluginImports = generator.NewPluginImports(p.Generator)
|
||
|
|
||
|
p.atleastOne = false
|
||
|
p.localName = generator.FileName(file)
|
||
|
|
||
|
p.mathPkg = p.NewImport("math")
|
||
|
p.sortKeysPkg = p.NewImport("github.com/gogo/protobuf/sortkeys")
|
||
|
p.protoPkg = p.NewImport("github.com/gogo/protobuf/proto")
|
||
|
if !gogoproto.ImportsGoGoProto(file.FileDescriptorProto) {
|
||
|
p.protoPkg = p.NewImport("github.com/golang/protobuf/proto")
|
||
|
}
|
||
|
p.errorsPkg = p.NewImport("errors")
|
||
|
p.binaryPkg = p.NewImport("encoding/binary")
|
||
|
p.typesPkg = p.NewImport("github.com/gogo/protobuf/types")
|
||
|
|
||
|
for _, message := range file.Messages() {
|
||
|
if message.DescriptorProto.GetOptions().GetMapEntry() {
|
||
|
continue
|
||
|
}
|
||
|
ccTypeName := generator.CamelCaseSlice(message.TypeName())
|
||
|
if !gogoproto.IsMarshaler(file.FileDescriptorProto, message.DescriptorProto) &&
|
||
|
!gogoproto.IsUnsafeMarshaler(file.FileDescriptorProto, message.DescriptorProto) {
|
||
|
continue
|
||
|
}
|
||
|
p.atleastOne = true
|
||
|
|
||
|
p.P(`func (m *`, ccTypeName, `) Marshal() (dAtA []byte, err error) {`)
|
||
|
p.In()
|
||
|
if gogoproto.IsProtoSizer(file.FileDescriptorProto, message.DescriptorProto) {
|
||
|
p.P(`size := m.ProtoSize()`)
|
||
|
} else {
|
||
|
p.P(`size := m.Size()`)
|
||
|
}
|
||
|
p.P(`dAtA = make([]byte, size)`)
|
||
|
p.P(`n, err := m.MarshalTo(dAtA)`)
|
||
|
p.P(`if err != nil {`)
|
||
|
p.In()
|
||
|
p.P(`return nil, err`)
|
||
|
p.Out()
|
||
|
p.P(`}`)
|
||
|
p.P(`return dAtA[:n], nil`)
|
||
|
p.Out()
|
||
|
p.P(`}`)
|
||
|
p.P(``)
|
||
|
p.P(`func (m *`, ccTypeName, `) MarshalTo(dAtA []byte) (int, error) {`)
|
||
|
p.In()
|
||
|
p.P(`var i int`)
|
||
|
p.P(`_ = i`)
|
||
|
p.P(`var l int`)
|
||
|
p.P(`_ = l`)
|
||
|
fields := orderFields(message.GetField())
|
||
|
sort.Sort(fields)
|
||
|
oneofs := make(map[string]struct{})
|
||
|
for _, field := range message.Field {
|
||
|
oneof := field.OneofIndex != nil
|
||
|
if !oneof {
|
||
|
proto3 := gogoproto.IsProto3(file.FileDescriptorProto)
|
||
|
p.generateField(proto3, numGen, file, message, field)
|
||
|
} else {
|
||
|
fieldname := p.GetFieldName(message, field)
|
||
|
if _, ok := oneofs[fieldname]; !ok {
|
||
|
oneofs[fieldname] = struct{}{}
|
||
|
p.P(`if m.`, fieldname, ` != nil {`)
|
||
|
p.In()
|
||
|
p.P(`nn`, numGen.Next(), `, err := m.`, fieldname, `.MarshalTo(dAtA[i:])`)
|
||
|
p.P(`if err != nil {`)
|
||
|
p.In()
|
||
|
p.P(`return 0, err`)
|
||
|
p.Out()
|
||
|
p.P(`}`)
|
||
|
p.P(`i+=nn`, numGen.Current())
|
||
|
p.Out()
|
||
|
p.P(`}`)
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
if message.DescriptorProto.HasExtension() {
|
||
|
if gogoproto.HasExtensionsMap(file.FileDescriptorProto, message.DescriptorProto) {
|
||
|
p.P(`n, err := `, p.protoPkg.Use(), `.EncodeInternalExtension(m, dAtA[i:])`)
|
||
|
p.P(`if err != nil {`)
|
||
|
p.In()
|
||
|
p.P(`return 0, err`)
|
||
|
p.Out()
|
||
|
p.P(`}`)
|
||
|
p.P(`i+=n`)
|
||
|
} else {
|
||
|
p.P(`if m.XXX_extensions != nil {`)
|
||
|
p.In()
|
||
|
p.P(`i+=copy(dAtA[i:], 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(`i+=copy(dAtA[i:], m.XXX_unrecognized)`)
|
||
|
p.Out()
|
||
|
p.P(`}`)
|
||
|
}
|
||
|
|
||
|
p.P(`return i, nil`)
|
||
|
p.Out()
|
||
|
p.P(`}`)
|
||
|
p.P()
|
||
|
|
||
|
//Generate MarshalTo 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 (m *`, ccTypeName, `) MarshalTo(dAtA []byte) (int, error) {`)
|
||
|
p.In()
|
||
|
p.P(`i := 0`)
|
||
|
vanity.TurnOffNullableForNativeTypes(field)
|
||
|
p.generateField(false, numGen, file, message, field)
|
||
|
p.P(`return i, nil`)
|
||
|
p.Out()
|
||
|
p.P(`}`)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if p.atleastOne {
|
||
|
p.P(`func encodeVarint`, p.localName, `(dAtA []byte, offset int, v uint64) int {`)
|
||
|
p.In()
|
||
|
p.P(`for v >= 1<<7 {`)
|
||
|
p.In()
|
||
|
p.P(`dAtA[offset] = uint8(v&0x7f|0x80)`)
|
||
|
p.P(`v >>= 7`)
|
||
|
p.P(`offset++`)
|
||
|
p.Out()
|
||
|
p.P(`}`)
|
||
|
p.P(`dAtA[offset] = uint8(v)`)
|
||
|
p.P(`return offset+1`)
|
||
|
p.Out()
|
||
|
p.P(`}`)
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
func init() {
|
||
|
generator.RegisterPlugin(NewMarshal())
|
||
|
}
|