mirror of
https://github.com/minio/minio.git
synced 2024-12-29 08:33:21 -05:00
2aa18cafc6
With CoreDNS now supporting etcdv3 as the DNS backend, we can update our federation target to etcdv3. Users will now be able to use etcdv3 server as the federation backbone. Minio will update bucket data to etcdv3 and CoreDNS can pick that data up and serve it as bucket style DNS path.
2682 lines
70 KiB
Go
2682 lines
70 KiB
Go
// Go support for Protocol Buffers - Google's data interchange format
|
|
//
|
|
// Copyright 2016 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 proto
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"math"
|
|
"reflect"
|
|
"sort"
|
|
"strconv"
|
|
"strings"
|
|
"sync"
|
|
"sync/atomic"
|
|
"unicode/utf8"
|
|
)
|
|
|
|
// a sizer takes a pointer to a field and the size of its tag, computes the size of
|
|
// the encoded data.
|
|
type sizer func(pointer, int) int
|
|
|
|
// a marshaler takes a byte slice, a pointer to a field, and its tag (in wire format),
|
|
// marshals the field to the end of the slice, returns the slice and error (if any).
|
|
type marshaler func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error)
|
|
|
|
// marshalInfo is the information used for marshaling a message.
|
|
type marshalInfo struct {
|
|
typ reflect.Type
|
|
fields []*marshalFieldInfo
|
|
unrecognized field // offset of XXX_unrecognized
|
|
extensions field // offset of XXX_InternalExtensions
|
|
v1extensions field // offset of XXX_extensions
|
|
sizecache field // offset of XXX_sizecache
|
|
initialized int32 // 0 -- only typ is set, 1 -- fully initialized
|
|
messageset bool // uses message set wire format
|
|
hasmarshaler bool // has custom marshaler
|
|
sync.RWMutex // protect extElems map, also for initialization
|
|
extElems map[int32]*marshalElemInfo // info of extension elements
|
|
}
|
|
|
|
// marshalFieldInfo is the information used for marshaling a field of a message.
|
|
type marshalFieldInfo struct {
|
|
field field
|
|
wiretag uint64 // tag in wire format
|
|
tagsize int // size of tag in wire format
|
|
sizer sizer
|
|
marshaler marshaler
|
|
isPointer bool
|
|
required bool // field is required
|
|
name string // name of the field, for error reporting
|
|
oneofElems map[reflect.Type]*marshalElemInfo // info of oneof elements
|
|
}
|
|
|
|
// marshalElemInfo is the information used for marshaling an extension or oneof element.
|
|
type marshalElemInfo struct {
|
|
wiretag uint64 // tag in wire format
|
|
tagsize int // size of tag in wire format
|
|
sizer sizer
|
|
marshaler marshaler
|
|
isptr bool // elem is pointer typed, thus interface of this type is a direct interface (extension only)
|
|
}
|
|
|
|
var (
|
|
marshalInfoMap = map[reflect.Type]*marshalInfo{}
|
|
marshalInfoLock sync.Mutex
|
|
)
|
|
|
|
// getMarshalInfo returns the information to marshal a given type of message.
|
|
// The info it returns may not necessarily initialized.
|
|
// t is the type of the message (NOT the pointer to it).
|
|
func getMarshalInfo(t reflect.Type) *marshalInfo {
|
|
marshalInfoLock.Lock()
|
|
u, ok := marshalInfoMap[t]
|
|
if !ok {
|
|
u = &marshalInfo{typ: t}
|
|
marshalInfoMap[t] = u
|
|
}
|
|
marshalInfoLock.Unlock()
|
|
return u
|
|
}
|
|
|
|
// Size is the entry point from generated code,
|
|
// and should be ONLY called by generated code.
|
|
// It computes the size of encoded data of msg.
|
|
// a is a pointer to a place to store cached marshal info.
|
|
func (a *InternalMessageInfo) Size(msg Message) int {
|
|
u := getMessageMarshalInfo(msg, a)
|
|
ptr := toPointer(&msg)
|
|
if ptr.isNil() {
|
|
// We get here if msg is a typed nil ((*SomeMessage)(nil)),
|
|
// so it satisfies the interface, and msg == nil wouldn't
|
|
// catch it. We don't want crash in this case.
|
|
return 0
|
|
}
|
|
return u.size(ptr)
|
|
}
|
|
|
|
// Marshal is the entry point from generated code,
|
|
// and should be ONLY called by generated code.
|
|
// It marshals msg to the end of b.
|
|
// a is a pointer to a place to store cached marshal info.
|
|
func (a *InternalMessageInfo) Marshal(b []byte, msg Message, deterministic bool) ([]byte, error) {
|
|
u := getMessageMarshalInfo(msg, a)
|
|
ptr := toPointer(&msg)
|
|
if ptr.isNil() {
|
|
// We get here if msg is a typed nil ((*SomeMessage)(nil)),
|
|
// so it satisfies the interface, and msg == nil wouldn't
|
|
// catch it. We don't want crash in this case.
|
|
return b, ErrNil
|
|
}
|
|
return u.marshal(b, ptr, deterministic)
|
|
}
|
|
|
|
func getMessageMarshalInfo(msg interface{}, a *InternalMessageInfo) *marshalInfo {
|
|
// u := a.marshal, but atomically.
|
|
// We use an atomic here to ensure memory consistency.
|
|
u := atomicLoadMarshalInfo(&a.marshal)
|
|
if u == nil {
|
|
// Get marshal information from type of message.
|
|
t := reflect.ValueOf(msg).Type()
|
|
if t.Kind() != reflect.Ptr {
|
|
panic(fmt.Sprintf("cannot handle non-pointer message type %v", t))
|
|
}
|
|
u = getMarshalInfo(t.Elem())
|
|
// Store it in the cache for later users.
|
|
// a.marshal = u, but atomically.
|
|
atomicStoreMarshalInfo(&a.marshal, u)
|
|
}
|
|
return u
|
|
}
|
|
|
|
// size is the main function to compute the size of the encoded data of a message.
|
|
// ptr is the pointer to the message.
|
|
func (u *marshalInfo) size(ptr pointer) int {
|
|
if atomic.LoadInt32(&u.initialized) == 0 {
|
|
u.computeMarshalInfo()
|
|
}
|
|
|
|
// If the message can marshal itself, let it do it, for compatibility.
|
|
// NOTE: This is not efficient.
|
|
if u.hasmarshaler {
|
|
m := ptr.asPointerTo(u.typ).Interface().(Marshaler)
|
|
b, _ := m.Marshal()
|
|
return len(b)
|
|
}
|
|
|
|
n := 0
|
|
for _, f := range u.fields {
|
|
if f.isPointer && ptr.offset(f.field).getPointer().isNil() {
|
|
// nil pointer always marshals to nothing
|
|
continue
|
|
}
|
|
n += f.sizer(ptr.offset(f.field), f.tagsize)
|
|
}
|
|
if u.extensions.IsValid() {
|
|
e := ptr.offset(u.extensions).toExtensions()
|
|
if u.messageset {
|
|
n += u.sizeMessageSet(e)
|
|
} else {
|
|
n += u.sizeExtensions(e)
|
|
}
|
|
}
|
|
if u.v1extensions.IsValid() {
|
|
m := *ptr.offset(u.v1extensions).toOldExtensions()
|
|
n += u.sizeV1Extensions(m)
|
|
}
|
|
if u.unrecognized.IsValid() {
|
|
s := *ptr.offset(u.unrecognized).toBytes()
|
|
n += len(s)
|
|
}
|
|
// cache the result for use in marshal
|
|
if u.sizecache.IsValid() {
|
|
atomic.StoreInt32(ptr.offset(u.sizecache).toInt32(), int32(n))
|
|
}
|
|
return n
|
|
}
|
|
|
|
// cachedsize gets the size from cache. If there is no cache (i.e. message is not generated),
|
|
// fall back to compute the size.
|
|
func (u *marshalInfo) cachedsize(ptr pointer) int {
|
|
if u.sizecache.IsValid() {
|
|
return int(atomic.LoadInt32(ptr.offset(u.sizecache).toInt32()))
|
|
}
|
|
return u.size(ptr)
|
|
}
|
|
|
|
// marshal is the main function to marshal a message. It takes a byte slice and appends
|
|
// the encoded data to the end of the slice, returns the slice and error (if any).
|
|
// ptr is the pointer to the message.
|
|
// If deterministic is true, map is marshaled in deterministic order.
|
|
func (u *marshalInfo) marshal(b []byte, ptr pointer, deterministic bool) ([]byte, error) {
|
|
if atomic.LoadInt32(&u.initialized) == 0 {
|
|
u.computeMarshalInfo()
|
|
}
|
|
|
|
// If the message can marshal itself, let it do it, for compatibility.
|
|
// NOTE: This is not efficient.
|
|
if u.hasmarshaler {
|
|
m := ptr.asPointerTo(u.typ).Interface().(Marshaler)
|
|
b1, err := m.Marshal()
|
|
b = append(b, b1...)
|
|
return b, err
|
|
}
|
|
|
|
var err, errreq error
|
|
// The old marshaler encodes extensions at beginning.
|
|
if u.extensions.IsValid() {
|
|
e := ptr.offset(u.extensions).toExtensions()
|
|
if u.messageset {
|
|
b, err = u.appendMessageSet(b, e, deterministic)
|
|
} else {
|
|
b, err = u.appendExtensions(b, e, deterministic)
|
|
}
|
|
if err != nil {
|
|
return b, err
|
|
}
|
|
}
|
|
if u.v1extensions.IsValid() {
|
|
m := *ptr.offset(u.v1extensions).toOldExtensions()
|
|
b, err = u.appendV1Extensions(b, m, deterministic)
|
|
if err != nil {
|
|
return b, err
|
|
}
|
|
}
|
|
for _, f := range u.fields {
|
|
if f.required && errreq == nil {
|
|
if ptr.offset(f.field).getPointer().isNil() {
|
|
// Required field is not set.
|
|
// We record the error but keep going, to give a complete marshaling.
|
|
errreq = &RequiredNotSetError{f.name}
|
|
continue
|
|
}
|
|
}
|
|
if f.isPointer && ptr.offset(f.field).getPointer().isNil() {
|
|
// nil pointer always marshals to nothing
|
|
continue
|
|
}
|
|
b, err = f.marshaler(b, ptr.offset(f.field), f.wiretag, deterministic)
|
|
if err != nil {
|
|
if err1, ok := err.(*RequiredNotSetError); ok {
|
|
// Required field in submessage is not set.
|
|
// We record the error but keep going, to give a complete marshaling.
|
|
if errreq == nil {
|
|
errreq = &RequiredNotSetError{f.name + "." + err1.field}
|
|
}
|
|
continue
|
|
}
|
|
if err == errRepeatedHasNil {
|
|
err = errors.New("proto: repeated field " + f.name + " has nil element")
|
|
}
|
|
return b, err
|
|
}
|
|
}
|
|
if u.unrecognized.IsValid() {
|
|
s := *ptr.offset(u.unrecognized).toBytes()
|
|
b = append(b, s...)
|
|
}
|
|
return b, errreq
|
|
}
|
|
|
|
// computeMarshalInfo initializes the marshal info.
|
|
func (u *marshalInfo) computeMarshalInfo() {
|
|
u.Lock()
|
|
defer u.Unlock()
|
|
if u.initialized != 0 { // non-atomic read is ok as it is protected by the lock
|
|
return
|
|
}
|
|
|
|
t := u.typ
|
|
u.unrecognized = invalidField
|
|
u.extensions = invalidField
|
|
u.v1extensions = invalidField
|
|
u.sizecache = invalidField
|
|
|
|
// If the message can marshal itself, let it do it, for compatibility.
|
|
// NOTE: This is not efficient.
|
|
if reflect.PtrTo(t).Implements(marshalerType) {
|
|
u.hasmarshaler = true
|
|
atomic.StoreInt32(&u.initialized, 1)
|
|
return
|
|
}
|
|
|
|
// get oneof implementers
|
|
var oneofImplementers []interface{}
|
|
if m, ok := reflect.Zero(reflect.PtrTo(t)).Interface().(oneofMessage); ok {
|
|
_, _, _, oneofImplementers = m.XXX_OneofFuncs()
|
|
}
|
|
|
|
n := t.NumField()
|
|
|
|
// deal with XXX fields first
|
|
for i := 0; i < t.NumField(); i++ {
|
|
f := t.Field(i)
|
|
if !strings.HasPrefix(f.Name, "XXX_") {
|
|
continue
|
|
}
|
|
switch f.Name {
|
|
case "XXX_sizecache":
|
|
u.sizecache = toField(&f)
|
|
case "XXX_unrecognized":
|
|
u.unrecognized = toField(&f)
|
|
case "XXX_InternalExtensions":
|
|
u.extensions = toField(&f)
|
|
u.messageset = f.Tag.Get("protobuf_messageset") == "1"
|
|
case "XXX_extensions":
|
|
u.v1extensions = toField(&f)
|
|
case "XXX_NoUnkeyedLiteral":
|
|
// nothing to do
|
|
default:
|
|
panic("unknown XXX field: " + f.Name)
|
|
}
|
|
n--
|
|
}
|
|
|
|
// normal fields
|
|
fields := make([]marshalFieldInfo, n) // batch allocation
|
|
u.fields = make([]*marshalFieldInfo, 0, n)
|
|
for i, j := 0, 0; i < t.NumField(); i++ {
|
|
f := t.Field(i)
|
|
|
|
if strings.HasPrefix(f.Name, "XXX_") {
|
|
continue
|
|
}
|
|
field := &fields[j]
|
|
j++
|
|
field.name = f.Name
|
|
u.fields = append(u.fields, field)
|
|
if f.Tag.Get("protobuf_oneof") != "" {
|
|
field.computeOneofFieldInfo(&f, oneofImplementers)
|
|
continue
|
|
}
|
|
if f.Tag.Get("protobuf") == "" {
|
|
// field has no tag (not in generated message), ignore it
|
|
u.fields = u.fields[:len(u.fields)-1]
|
|
j--
|
|
continue
|
|
}
|
|
field.computeMarshalFieldInfo(&f)
|
|
}
|
|
|
|
// fields are marshaled in tag order on the wire.
|
|
sort.Sort(byTag(u.fields))
|
|
|
|
atomic.StoreInt32(&u.initialized, 1)
|
|
}
|
|
|
|
// helper for sorting fields by tag
|
|
type byTag []*marshalFieldInfo
|
|
|
|
func (a byTag) Len() int { return len(a) }
|
|
func (a byTag) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
|
|
func (a byTag) Less(i, j int) bool { return a[i].wiretag < a[j].wiretag }
|
|
|
|
// getExtElemInfo returns the information to marshal an extension element.
|
|
// The info it returns is initialized.
|
|
func (u *marshalInfo) getExtElemInfo(desc *ExtensionDesc) *marshalElemInfo {
|
|
// get from cache first
|
|
u.RLock()
|
|
e, ok := u.extElems[desc.Field]
|
|
u.RUnlock()
|
|
if ok {
|
|
return e
|
|
}
|
|
|
|
t := reflect.TypeOf(desc.ExtensionType) // pointer or slice to basic type or struct
|
|
tags := strings.Split(desc.Tag, ",")
|
|
tag, err := strconv.Atoi(tags[1])
|
|
if err != nil {
|
|
panic("tag is not an integer")
|
|
}
|
|
wt := wiretype(tags[0])
|
|
sizer, marshaler := typeMarshaler(t, tags, false, false)
|
|
e = &marshalElemInfo{
|
|
wiretag: uint64(tag)<<3 | wt,
|
|
tagsize: SizeVarint(uint64(tag) << 3),
|
|
sizer: sizer,
|
|
marshaler: marshaler,
|
|
isptr: t.Kind() == reflect.Ptr,
|
|
}
|
|
|
|
// update cache
|
|
u.Lock()
|
|
if u.extElems == nil {
|
|
u.extElems = make(map[int32]*marshalElemInfo)
|
|
}
|
|
u.extElems[desc.Field] = e
|
|
u.Unlock()
|
|
return e
|
|
}
|
|
|
|
// computeMarshalFieldInfo fills up the information to marshal a field.
|
|
func (fi *marshalFieldInfo) computeMarshalFieldInfo(f *reflect.StructField) {
|
|
// parse protobuf tag of the field.
|
|
// tag has format of "bytes,49,opt,name=foo,def=hello!"
|
|
tags := strings.Split(f.Tag.Get("protobuf"), ",")
|
|
if tags[0] == "" {
|
|
return
|
|
}
|
|
tag, err := strconv.Atoi(tags[1])
|
|
if err != nil {
|
|
panic("tag is not an integer")
|
|
}
|
|
wt := wiretype(tags[0])
|
|
if tags[2] == "req" {
|
|
fi.required = true
|
|
}
|
|
fi.setTag(f, tag, wt)
|
|
fi.setMarshaler(f, tags)
|
|
}
|
|
|
|
func (fi *marshalFieldInfo) computeOneofFieldInfo(f *reflect.StructField, oneofImplementers []interface{}) {
|
|
fi.field = toField(f)
|
|
fi.wiretag = 1<<31 - 1 // Use a large tag number, make oneofs sorted at the end. This tag will not appear on the wire.
|
|
fi.isPointer = true
|
|
fi.sizer, fi.marshaler = makeOneOfMarshaler(fi, f)
|
|
fi.oneofElems = make(map[reflect.Type]*marshalElemInfo)
|
|
|
|
ityp := f.Type // interface type
|
|
for _, o := range oneofImplementers {
|
|
t := reflect.TypeOf(o)
|
|
if !t.Implements(ityp) {
|
|
continue
|
|
}
|
|
sf := t.Elem().Field(0) // oneof implementer is a struct with a single field
|
|
tags := strings.Split(sf.Tag.Get("protobuf"), ",")
|
|
tag, err := strconv.Atoi(tags[1])
|
|
if err != nil {
|
|
panic("tag is not an integer")
|
|
}
|
|
wt := wiretype(tags[0])
|
|
sizer, marshaler := typeMarshaler(sf.Type, tags, false, true) // oneof should not omit any zero value
|
|
fi.oneofElems[t.Elem()] = &marshalElemInfo{
|
|
wiretag: uint64(tag)<<3 | wt,
|
|
tagsize: SizeVarint(uint64(tag) << 3),
|
|
sizer: sizer,
|
|
marshaler: marshaler,
|
|
}
|
|
}
|
|
}
|
|
|
|
type oneofMessage interface {
|
|
XXX_OneofFuncs() (func(Message, *Buffer) error, func(Message, int, int, *Buffer) (bool, error), func(Message) int, []interface{})
|
|
}
|
|
|
|
// wiretype returns the wire encoding of the type.
|
|
func wiretype(encoding string) uint64 {
|
|
switch encoding {
|
|
case "fixed32":
|
|
return WireFixed32
|
|
case "fixed64":
|
|
return WireFixed64
|
|
case "varint", "zigzag32", "zigzag64":
|
|
return WireVarint
|
|
case "bytes":
|
|
return WireBytes
|
|
case "group":
|
|
return WireStartGroup
|
|
}
|
|
panic("unknown wire type " + encoding)
|
|
}
|
|
|
|
// setTag fills up the tag (in wire format) and its size in the info of a field.
|
|
func (fi *marshalFieldInfo) setTag(f *reflect.StructField, tag int, wt uint64) {
|
|
fi.field = toField(f)
|
|
fi.wiretag = uint64(tag)<<3 | wt
|
|
fi.tagsize = SizeVarint(uint64(tag) << 3)
|
|
}
|
|
|
|
// setMarshaler fills up the sizer and marshaler in the info of a field.
|
|
func (fi *marshalFieldInfo) setMarshaler(f *reflect.StructField, tags []string) {
|
|
switch f.Type.Kind() {
|
|
case reflect.Map:
|
|
// map field
|
|
fi.isPointer = true
|
|
fi.sizer, fi.marshaler = makeMapMarshaler(f)
|
|
return
|
|
case reflect.Ptr, reflect.Slice:
|
|
fi.isPointer = true
|
|
}
|
|
fi.sizer, fi.marshaler = typeMarshaler(f.Type, tags, true, false)
|
|
}
|
|
|
|
// typeMarshaler returns the sizer and marshaler of a given field.
|
|
// t is the type of the field.
|
|
// tags is the generated "protobuf" tag of the field.
|
|
// If nozero is true, zero value is not marshaled to the wire.
|
|
// If oneof is true, it is a oneof field.
|
|
func typeMarshaler(t reflect.Type, tags []string, nozero, oneof bool) (sizer, marshaler) {
|
|
encoding := tags[0]
|
|
|
|
pointer := false
|
|
slice := false
|
|
if t.Kind() == reflect.Slice && t.Elem().Kind() != reflect.Uint8 {
|
|
slice = true
|
|
t = t.Elem()
|
|
}
|
|
if t.Kind() == reflect.Ptr {
|
|
pointer = true
|
|
t = t.Elem()
|
|
}
|
|
|
|
packed := false
|
|
proto3 := false
|
|
for i := 2; i < len(tags); i++ {
|
|
if tags[i] == "packed" {
|
|
packed = true
|
|
}
|
|
if tags[i] == "proto3" {
|
|
proto3 = true
|
|
}
|
|
}
|
|
|
|
switch t.Kind() {
|
|
case reflect.Bool:
|
|
if pointer {
|
|
return sizeBoolPtr, appendBoolPtr
|
|
}
|
|
if slice {
|
|
if packed {
|
|
return sizeBoolPackedSlice, appendBoolPackedSlice
|
|
}
|
|
return sizeBoolSlice, appendBoolSlice
|
|
}
|
|
if nozero {
|
|
return sizeBoolValueNoZero, appendBoolValueNoZero
|
|
}
|
|
return sizeBoolValue, appendBoolValue
|
|
case reflect.Uint32:
|
|
switch encoding {
|
|
case "fixed32":
|
|
if pointer {
|
|
return sizeFixed32Ptr, appendFixed32Ptr
|
|
}
|
|
if slice {
|
|
if packed {
|
|
return sizeFixed32PackedSlice, appendFixed32PackedSlice
|
|
}
|
|
return sizeFixed32Slice, appendFixed32Slice
|
|
}
|
|
if nozero {
|
|
return sizeFixed32ValueNoZero, appendFixed32ValueNoZero
|
|
}
|
|
return sizeFixed32Value, appendFixed32Value
|
|
case "varint":
|
|
if pointer {
|
|
return sizeVarint32Ptr, appendVarint32Ptr
|
|
}
|
|
if slice {
|
|
if packed {
|
|
return sizeVarint32PackedSlice, appendVarint32PackedSlice
|
|
}
|
|
return sizeVarint32Slice, appendVarint32Slice
|
|
}
|
|
if nozero {
|
|
return sizeVarint32ValueNoZero, appendVarint32ValueNoZero
|
|
}
|
|
return sizeVarint32Value, appendVarint32Value
|
|
}
|
|
case reflect.Int32:
|
|
switch encoding {
|
|
case "fixed32":
|
|
if pointer {
|
|
return sizeFixedS32Ptr, appendFixedS32Ptr
|
|
}
|
|
if slice {
|
|
if packed {
|
|
return sizeFixedS32PackedSlice, appendFixedS32PackedSlice
|
|
}
|
|
return sizeFixedS32Slice, appendFixedS32Slice
|
|
}
|
|
if nozero {
|
|
return sizeFixedS32ValueNoZero, appendFixedS32ValueNoZero
|
|
}
|
|
return sizeFixedS32Value, appendFixedS32Value
|
|
case "varint":
|
|
if pointer {
|
|
return sizeVarintS32Ptr, appendVarintS32Ptr
|
|
}
|
|
if slice {
|
|
if packed {
|
|
return sizeVarintS32PackedSlice, appendVarintS32PackedSlice
|
|
}
|
|
return sizeVarintS32Slice, appendVarintS32Slice
|
|
}
|
|
if nozero {
|
|
return sizeVarintS32ValueNoZero, appendVarintS32ValueNoZero
|
|
}
|
|
return sizeVarintS32Value, appendVarintS32Value
|
|
case "zigzag32":
|
|
if pointer {
|
|
return sizeZigzag32Ptr, appendZigzag32Ptr
|
|
}
|
|
if slice {
|
|
if packed {
|
|
return sizeZigzag32PackedSlice, appendZigzag32PackedSlice
|
|
}
|
|
return sizeZigzag32Slice, appendZigzag32Slice
|
|
}
|
|
if nozero {
|
|
return sizeZigzag32ValueNoZero, appendZigzag32ValueNoZero
|
|
}
|
|
return sizeZigzag32Value, appendZigzag32Value
|
|
}
|
|
case reflect.Uint64:
|
|
switch encoding {
|
|
case "fixed64":
|
|
if pointer {
|
|
return sizeFixed64Ptr, appendFixed64Ptr
|
|
}
|
|
if slice {
|
|
if packed {
|
|
return sizeFixed64PackedSlice, appendFixed64PackedSlice
|
|
}
|
|
return sizeFixed64Slice, appendFixed64Slice
|
|
}
|
|
if nozero {
|
|
return sizeFixed64ValueNoZero, appendFixed64ValueNoZero
|
|
}
|
|
return sizeFixed64Value, appendFixed64Value
|
|
case "varint":
|
|
if pointer {
|
|
return sizeVarint64Ptr, appendVarint64Ptr
|
|
}
|
|
if slice {
|
|
if packed {
|
|
return sizeVarint64PackedSlice, appendVarint64PackedSlice
|
|
}
|
|
return sizeVarint64Slice, appendVarint64Slice
|
|
}
|
|
if nozero {
|
|
return sizeVarint64ValueNoZero, appendVarint64ValueNoZero
|
|
}
|
|
return sizeVarint64Value, appendVarint64Value
|
|
}
|
|
case reflect.Int64:
|
|
switch encoding {
|
|
case "fixed64":
|
|
if pointer {
|
|
return sizeFixedS64Ptr, appendFixedS64Ptr
|
|
}
|
|
if slice {
|
|
if packed {
|
|
return sizeFixedS64PackedSlice, appendFixedS64PackedSlice
|
|
}
|
|
return sizeFixedS64Slice, appendFixedS64Slice
|
|
}
|
|
if nozero {
|
|
return sizeFixedS64ValueNoZero, appendFixedS64ValueNoZero
|
|
}
|
|
return sizeFixedS64Value, appendFixedS64Value
|
|
case "varint":
|
|
if pointer {
|
|
return sizeVarintS64Ptr, appendVarintS64Ptr
|
|
}
|
|
if slice {
|
|
if packed {
|
|
return sizeVarintS64PackedSlice, appendVarintS64PackedSlice
|
|
}
|
|
return sizeVarintS64Slice, appendVarintS64Slice
|
|
}
|
|
if nozero {
|
|
return sizeVarintS64ValueNoZero, appendVarintS64ValueNoZero
|
|
}
|
|
return sizeVarintS64Value, appendVarintS64Value
|
|
case "zigzag64":
|
|
if pointer {
|
|
return sizeZigzag64Ptr, appendZigzag64Ptr
|
|
}
|
|
if slice {
|
|
if packed {
|
|
return sizeZigzag64PackedSlice, appendZigzag64PackedSlice
|
|
}
|
|
return sizeZigzag64Slice, appendZigzag64Slice
|
|
}
|
|
if nozero {
|
|
return sizeZigzag64ValueNoZero, appendZigzag64ValueNoZero
|
|
}
|
|
return sizeZigzag64Value, appendZigzag64Value
|
|
}
|
|
case reflect.Float32:
|
|
if pointer {
|
|
return sizeFloat32Ptr, appendFloat32Ptr
|
|
}
|
|
if slice {
|
|
if packed {
|
|
return sizeFloat32PackedSlice, appendFloat32PackedSlice
|
|
}
|
|
return sizeFloat32Slice, appendFloat32Slice
|
|
}
|
|
if nozero {
|
|
return sizeFloat32ValueNoZero, appendFloat32ValueNoZero
|
|
}
|
|
return sizeFloat32Value, appendFloat32Value
|
|
case reflect.Float64:
|
|
if pointer {
|
|
return sizeFloat64Ptr, appendFloat64Ptr
|
|
}
|
|
if slice {
|
|
if packed {
|
|
return sizeFloat64PackedSlice, appendFloat64PackedSlice
|
|
}
|
|
return sizeFloat64Slice, appendFloat64Slice
|
|
}
|
|
if nozero {
|
|
return sizeFloat64ValueNoZero, appendFloat64ValueNoZero
|
|
}
|
|
return sizeFloat64Value, appendFloat64Value
|
|
case reflect.String:
|
|
if pointer {
|
|
return sizeStringPtr, appendStringPtr
|
|
}
|
|
if slice {
|
|
return sizeStringSlice, appendStringSlice
|
|
}
|
|
if nozero {
|
|
return sizeStringValueNoZero, appendStringValueNoZero
|
|
}
|
|
return sizeStringValue, appendStringValue
|
|
case reflect.Slice:
|
|
if slice {
|
|
return sizeBytesSlice, appendBytesSlice
|
|
}
|
|
if oneof {
|
|
// Oneof bytes field may also have "proto3" tag.
|
|
// We want to marshal it as a oneof field. Do this
|
|
// check before the proto3 check.
|
|
return sizeBytesOneof, appendBytesOneof
|
|
}
|
|
if proto3 {
|
|
return sizeBytes3, appendBytes3
|
|
}
|
|
return sizeBytes, appendBytes
|
|
case reflect.Struct:
|
|
switch encoding {
|
|
case "group":
|
|
if slice {
|
|
return makeGroupSliceMarshaler(getMarshalInfo(t))
|
|
}
|
|
return makeGroupMarshaler(getMarshalInfo(t))
|
|
case "bytes":
|
|
if slice {
|
|
return makeMessageSliceMarshaler(getMarshalInfo(t))
|
|
}
|
|
return makeMessageMarshaler(getMarshalInfo(t))
|
|
}
|
|
}
|
|
panic(fmt.Sprintf("unknown or mismatched type: type: %v, wire type: %v", t, encoding))
|
|
}
|
|
|
|
// Below are functions to size/marshal a specific type of a field.
|
|
// They are stored in the field's info, and called by function pointers.
|
|
// They have type sizer or marshaler.
|
|
|
|
func sizeFixed32Value(_ pointer, tagsize int) int {
|
|
return 4 + tagsize
|
|
}
|
|
func sizeFixed32ValueNoZero(ptr pointer, tagsize int) int {
|
|
v := *ptr.toUint32()
|
|
if v == 0 {
|
|
return 0
|
|
}
|
|
return 4 + tagsize
|
|
}
|
|
func sizeFixed32Ptr(ptr pointer, tagsize int) int {
|
|
p := *ptr.toUint32Ptr()
|
|
if p == nil {
|
|
return 0
|
|
}
|
|
return 4 + tagsize
|
|
}
|
|
func sizeFixed32Slice(ptr pointer, tagsize int) int {
|
|
s := *ptr.toUint32Slice()
|
|
return (4 + tagsize) * len(s)
|
|
}
|
|
func sizeFixed32PackedSlice(ptr pointer, tagsize int) int {
|
|
s := *ptr.toUint32Slice()
|
|
if len(s) == 0 {
|
|
return 0
|
|
}
|
|
return 4*len(s) + SizeVarint(uint64(4*len(s))) + tagsize
|
|
}
|
|
func sizeFixedS32Value(_ pointer, tagsize int) int {
|
|
return 4 + tagsize
|
|
}
|
|
func sizeFixedS32ValueNoZero(ptr pointer, tagsize int) int {
|
|
v := *ptr.toInt32()
|
|
if v == 0 {
|
|
return 0
|
|
}
|
|
return 4 + tagsize
|
|
}
|
|
func sizeFixedS32Ptr(ptr pointer, tagsize int) int {
|
|
p := ptr.getInt32Ptr()
|
|
if p == nil {
|
|
return 0
|
|
}
|
|
return 4 + tagsize
|
|
}
|
|
func sizeFixedS32Slice(ptr pointer, tagsize int) int {
|
|
s := ptr.getInt32Slice()
|
|
return (4 + tagsize) * len(s)
|
|
}
|
|
func sizeFixedS32PackedSlice(ptr pointer, tagsize int) int {
|
|
s := ptr.getInt32Slice()
|
|
if len(s) == 0 {
|
|
return 0
|
|
}
|
|
return 4*len(s) + SizeVarint(uint64(4*len(s))) + tagsize
|
|
}
|
|
func sizeFloat32Value(_ pointer, tagsize int) int {
|
|
return 4 + tagsize
|
|
}
|
|
func sizeFloat32ValueNoZero(ptr pointer, tagsize int) int {
|
|
v := math.Float32bits(*ptr.toFloat32())
|
|
if v == 0 {
|
|
return 0
|
|
}
|
|
return 4 + tagsize
|
|
}
|
|
func sizeFloat32Ptr(ptr pointer, tagsize int) int {
|
|
p := *ptr.toFloat32Ptr()
|
|
if p == nil {
|
|
return 0
|
|
}
|
|
return 4 + tagsize
|
|
}
|
|
func sizeFloat32Slice(ptr pointer, tagsize int) int {
|
|
s := *ptr.toFloat32Slice()
|
|
return (4 + tagsize) * len(s)
|
|
}
|
|
func sizeFloat32PackedSlice(ptr pointer, tagsize int) int {
|
|
s := *ptr.toFloat32Slice()
|
|
if len(s) == 0 {
|
|
return 0
|
|
}
|
|
return 4*len(s) + SizeVarint(uint64(4*len(s))) + tagsize
|
|
}
|
|
func sizeFixed64Value(_ pointer, tagsize int) int {
|
|
return 8 + tagsize
|
|
}
|
|
func sizeFixed64ValueNoZero(ptr pointer, tagsize int) int {
|
|
v := *ptr.toUint64()
|
|
if v == 0 {
|
|
return 0
|
|
}
|
|
return 8 + tagsize
|
|
}
|
|
func sizeFixed64Ptr(ptr pointer, tagsize int) int {
|
|
p := *ptr.toUint64Ptr()
|
|
if p == nil {
|
|
return 0
|
|
}
|
|
return 8 + tagsize
|
|
}
|
|
func sizeFixed64Slice(ptr pointer, tagsize int) int {
|
|
s := *ptr.toUint64Slice()
|
|
return (8 + tagsize) * len(s)
|
|
}
|
|
func sizeFixed64PackedSlice(ptr pointer, tagsize int) int {
|
|
s := *ptr.toUint64Slice()
|
|
if len(s) == 0 {
|
|
return 0
|
|
}
|
|
return 8*len(s) + SizeVarint(uint64(8*len(s))) + tagsize
|
|
}
|
|
func sizeFixedS64Value(_ pointer, tagsize int) int {
|
|
return 8 + tagsize
|
|
}
|
|
func sizeFixedS64ValueNoZero(ptr pointer, tagsize int) int {
|
|
v := *ptr.toInt64()
|
|
if v == 0 {
|
|
return 0
|
|
}
|
|
return 8 + tagsize
|
|
}
|
|
func sizeFixedS64Ptr(ptr pointer, tagsize int) int {
|
|
p := *ptr.toInt64Ptr()
|
|
if p == nil {
|
|
return 0
|
|
}
|
|
return 8 + tagsize
|
|
}
|
|
func sizeFixedS64Slice(ptr pointer, tagsize int) int {
|
|
s := *ptr.toInt64Slice()
|
|
return (8 + tagsize) * len(s)
|
|
}
|
|
func sizeFixedS64PackedSlice(ptr pointer, tagsize int) int {
|
|
s := *ptr.toInt64Slice()
|
|
if len(s) == 0 {
|
|
return 0
|
|
}
|
|
return 8*len(s) + SizeVarint(uint64(8*len(s))) + tagsize
|
|
}
|
|
func sizeFloat64Value(_ pointer, tagsize int) int {
|
|
return 8 + tagsize
|
|
}
|
|
func sizeFloat64ValueNoZero(ptr pointer, tagsize int) int {
|
|
v := math.Float64bits(*ptr.toFloat64())
|
|
if v == 0 {
|
|
return 0
|
|
}
|
|
return 8 + tagsize
|
|
}
|
|
func sizeFloat64Ptr(ptr pointer, tagsize int) int {
|
|
p := *ptr.toFloat64Ptr()
|
|
if p == nil {
|
|
return 0
|
|
}
|
|
return 8 + tagsize
|
|
}
|
|
func sizeFloat64Slice(ptr pointer, tagsize int) int {
|
|
s := *ptr.toFloat64Slice()
|
|
return (8 + tagsize) * len(s)
|
|
}
|
|
func sizeFloat64PackedSlice(ptr pointer, tagsize int) int {
|
|
s := *ptr.toFloat64Slice()
|
|
if len(s) == 0 {
|
|
return 0
|
|
}
|
|
return 8*len(s) + SizeVarint(uint64(8*len(s))) + tagsize
|
|
}
|
|
func sizeVarint32Value(ptr pointer, tagsize int) int {
|
|
v := *ptr.toUint32()
|
|
return SizeVarint(uint64(v)) + tagsize
|
|
}
|
|
func sizeVarint32ValueNoZero(ptr pointer, tagsize int) int {
|
|
v := *ptr.toUint32()
|
|
if v == 0 {
|
|
return 0
|
|
}
|
|
return SizeVarint(uint64(v)) + tagsize
|
|
}
|
|
func sizeVarint32Ptr(ptr pointer, tagsize int) int {
|
|
p := *ptr.toUint32Ptr()
|
|
if p == nil {
|
|
return 0
|
|
}
|
|
return SizeVarint(uint64(*p)) + tagsize
|
|
}
|
|
func sizeVarint32Slice(ptr pointer, tagsize int) int {
|
|
s := *ptr.toUint32Slice()
|
|
n := 0
|
|
for _, v := range s {
|
|
n += SizeVarint(uint64(v)) + tagsize
|
|
}
|
|
return n
|
|
}
|
|
func sizeVarint32PackedSlice(ptr pointer, tagsize int) int {
|
|
s := *ptr.toUint32Slice()
|
|
if len(s) == 0 {
|
|
return 0
|
|
}
|
|
n := 0
|
|
for _, v := range s {
|
|
n += SizeVarint(uint64(v))
|
|
}
|
|
return n + SizeVarint(uint64(n)) + tagsize
|
|
}
|
|
func sizeVarintS32Value(ptr pointer, tagsize int) int {
|
|
v := *ptr.toInt32()
|
|
return SizeVarint(uint64(v)) + tagsize
|
|
}
|
|
func sizeVarintS32ValueNoZero(ptr pointer, tagsize int) int {
|
|
v := *ptr.toInt32()
|
|
if v == 0 {
|
|
return 0
|
|
}
|
|
return SizeVarint(uint64(v)) + tagsize
|
|
}
|
|
func sizeVarintS32Ptr(ptr pointer, tagsize int) int {
|
|
p := ptr.getInt32Ptr()
|
|
if p == nil {
|
|
return 0
|
|
}
|
|
return SizeVarint(uint64(*p)) + tagsize
|
|
}
|
|
func sizeVarintS32Slice(ptr pointer, tagsize int) int {
|
|
s := ptr.getInt32Slice()
|
|
n := 0
|
|
for _, v := range s {
|
|
n += SizeVarint(uint64(v)) + tagsize
|
|
}
|
|
return n
|
|
}
|
|
func sizeVarintS32PackedSlice(ptr pointer, tagsize int) int {
|
|
s := ptr.getInt32Slice()
|
|
if len(s) == 0 {
|
|
return 0
|
|
}
|
|
n := 0
|
|
for _, v := range s {
|
|
n += SizeVarint(uint64(v))
|
|
}
|
|
return n + SizeVarint(uint64(n)) + tagsize
|
|
}
|
|
func sizeVarint64Value(ptr pointer, tagsize int) int {
|
|
v := *ptr.toUint64()
|
|
return SizeVarint(v) + tagsize
|
|
}
|
|
func sizeVarint64ValueNoZero(ptr pointer, tagsize int) int {
|
|
v := *ptr.toUint64()
|
|
if v == 0 {
|
|
return 0
|
|
}
|
|
return SizeVarint(v) + tagsize
|
|
}
|
|
func sizeVarint64Ptr(ptr pointer, tagsize int) int {
|
|
p := *ptr.toUint64Ptr()
|
|
if p == nil {
|
|
return 0
|
|
}
|
|
return SizeVarint(*p) + tagsize
|
|
}
|
|
func sizeVarint64Slice(ptr pointer, tagsize int) int {
|
|
s := *ptr.toUint64Slice()
|
|
n := 0
|
|
for _, v := range s {
|
|
n += SizeVarint(v) + tagsize
|
|
}
|
|
return n
|
|
}
|
|
func sizeVarint64PackedSlice(ptr pointer, tagsize int) int {
|
|
s := *ptr.toUint64Slice()
|
|
if len(s) == 0 {
|
|
return 0
|
|
}
|
|
n := 0
|
|
for _, v := range s {
|
|
n += SizeVarint(v)
|
|
}
|
|
return n + SizeVarint(uint64(n)) + tagsize
|
|
}
|
|
func sizeVarintS64Value(ptr pointer, tagsize int) int {
|
|
v := *ptr.toInt64()
|
|
return SizeVarint(uint64(v)) + tagsize
|
|
}
|
|
func sizeVarintS64ValueNoZero(ptr pointer, tagsize int) int {
|
|
v := *ptr.toInt64()
|
|
if v == 0 {
|
|
return 0
|
|
}
|
|
return SizeVarint(uint64(v)) + tagsize
|
|
}
|
|
func sizeVarintS64Ptr(ptr pointer, tagsize int) int {
|
|
p := *ptr.toInt64Ptr()
|
|
if p == nil {
|
|
return 0
|
|
}
|
|
return SizeVarint(uint64(*p)) + tagsize
|
|
}
|
|
func sizeVarintS64Slice(ptr pointer, tagsize int) int {
|
|
s := *ptr.toInt64Slice()
|
|
n := 0
|
|
for _, v := range s {
|
|
n += SizeVarint(uint64(v)) + tagsize
|
|
}
|
|
return n
|
|
}
|
|
func sizeVarintS64PackedSlice(ptr pointer, tagsize int) int {
|
|
s := *ptr.toInt64Slice()
|
|
if len(s) == 0 {
|
|
return 0
|
|
}
|
|
n := 0
|
|
for _, v := range s {
|
|
n += SizeVarint(uint64(v))
|
|
}
|
|
return n + SizeVarint(uint64(n)) + tagsize
|
|
}
|
|
func sizeZigzag32Value(ptr pointer, tagsize int) int {
|
|
v := *ptr.toInt32()
|
|
return SizeVarint(uint64((uint32(v)<<1)^uint32((int32(v)>>31)))) + tagsize
|
|
}
|
|
func sizeZigzag32ValueNoZero(ptr pointer, tagsize int) int {
|
|
v := *ptr.toInt32()
|
|
if v == 0 {
|
|
return 0
|
|
}
|
|
return SizeVarint(uint64((uint32(v)<<1)^uint32((int32(v)>>31)))) + tagsize
|
|
}
|
|
func sizeZigzag32Ptr(ptr pointer, tagsize int) int {
|
|
p := ptr.getInt32Ptr()
|
|
if p == nil {
|
|
return 0
|
|
}
|
|
v := *p
|
|
return SizeVarint(uint64((uint32(v)<<1)^uint32((int32(v)>>31)))) + tagsize
|
|
}
|
|
func sizeZigzag32Slice(ptr pointer, tagsize int) int {
|
|
s := ptr.getInt32Slice()
|
|
n := 0
|
|
for _, v := range s {
|
|
n += SizeVarint(uint64((uint32(v)<<1)^uint32((int32(v)>>31)))) + tagsize
|
|
}
|
|
return n
|
|
}
|
|
func sizeZigzag32PackedSlice(ptr pointer, tagsize int) int {
|
|
s := ptr.getInt32Slice()
|
|
if len(s) == 0 {
|
|
return 0
|
|
}
|
|
n := 0
|
|
for _, v := range s {
|
|
n += SizeVarint(uint64((uint32(v) << 1) ^ uint32((int32(v) >> 31))))
|
|
}
|
|
return n + SizeVarint(uint64(n)) + tagsize
|
|
}
|
|
func sizeZigzag64Value(ptr pointer, tagsize int) int {
|
|
v := *ptr.toInt64()
|
|
return SizeVarint(uint64(v<<1)^uint64((int64(v)>>63))) + tagsize
|
|
}
|
|
func sizeZigzag64ValueNoZero(ptr pointer, tagsize int) int {
|
|
v := *ptr.toInt64()
|
|
if v == 0 {
|
|
return 0
|
|
}
|
|
return SizeVarint(uint64(v<<1)^uint64((int64(v)>>63))) + tagsize
|
|
}
|
|
func sizeZigzag64Ptr(ptr pointer, tagsize int) int {
|
|
p := *ptr.toInt64Ptr()
|
|
if p == nil {
|
|
return 0
|
|
}
|
|
v := *p
|
|
return SizeVarint(uint64(v<<1)^uint64((int64(v)>>63))) + tagsize
|
|
}
|
|
func sizeZigzag64Slice(ptr pointer, tagsize int) int {
|
|
s := *ptr.toInt64Slice()
|
|
n := 0
|
|
for _, v := range s {
|
|
n += SizeVarint(uint64(v<<1)^uint64((int64(v)>>63))) + tagsize
|
|
}
|
|
return n
|
|
}
|
|
func sizeZigzag64PackedSlice(ptr pointer, tagsize int) int {
|
|
s := *ptr.toInt64Slice()
|
|
if len(s) == 0 {
|
|
return 0
|
|
}
|
|
n := 0
|
|
for _, v := range s {
|
|
n += SizeVarint(uint64(v<<1) ^ uint64((int64(v) >> 63)))
|
|
}
|
|
return n + SizeVarint(uint64(n)) + tagsize
|
|
}
|
|
func sizeBoolValue(_ pointer, tagsize int) int {
|
|
return 1 + tagsize
|
|
}
|
|
func sizeBoolValueNoZero(ptr pointer, tagsize int) int {
|
|
v := *ptr.toBool()
|
|
if !v {
|
|
return 0
|
|
}
|
|
return 1 + tagsize
|
|
}
|
|
func sizeBoolPtr(ptr pointer, tagsize int) int {
|
|
p := *ptr.toBoolPtr()
|
|
if p == nil {
|
|
return 0
|
|
}
|
|
return 1 + tagsize
|
|
}
|
|
func sizeBoolSlice(ptr pointer, tagsize int) int {
|
|
s := *ptr.toBoolSlice()
|
|
return (1 + tagsize) * len(s)
|
|
}
|
|
func sizeBoolPackedSlice(ptr pointer, tagsize int) int {
|
|
s := *ptr.toBoolSlice()
|
|
if len(s) == 0 {
|
|
return 0
|
|
}
|
|
return len(s) + SizeVarint(uint64(len(s))) + tagsize
|
|
}
|
|
func sizeStringValue(ptr pointer, tagsize int) int {
|
|
v := *ptr.toString()
|
|
return len(v) + SizeVarint(uint64(len(v))) + tagsize
|
|
}
|
|
func sizeStringValueNoZero(ptr pointer, tagsize int) int {
|
|
v := *ptr.toString()
|
|
if v == "" {
|
|
return 0
|
|
}
|
|
return len(v) + SizeVarint(uint64(len(v))) + tagsize
|
|
}
|
|
func sizeStringPtr(ptr pointer, tagsize int) int {
|
|
p := *ptr.toStringPtr()
|
|
if p == nil {
|
|
return 0
|
|
}
|
|
v := *p
|
|
return len(v) + SizeVarint(uint64(len(v))) + tagsize
|
|
}
|
|
func sizeStringSlice(ptr pointer, tagsize int) int {
|
|
s := *ptr.toStringSlice()
|
|
n := 0
|
|
for _, v := range s {
|
|
n += len(v) + SizeVarint(uint64(len(v))) + tagsize
|
|
}
|
|
return n
|
|
}
|
|
func sizeBytes(ptr pointer, tagsize int) int {
|
|
v := *ptr.toBytes()
|
|
if v == nil {
|
|
return 0
|
|
}
|
|
return len(v) + SizeVarint(uint64(len(v))) + tagsize
|
|
}
|
|
func sizeBytes3(ptr pointer, tagsize int) int {
|
|
v := *ptr.toBytes()
|
|
if len(v) == 0 {
|
|
return 0
|
|
}
|
|
return len(v) + SizeVarint(uint64(len(v))) + tagsize
|
|
}
|
|
func sizeBytesOneof(ptr pointer, tagsize int) int {
|
|
v := *ptr.toBytes()
|
|
return len(v) + SizeVarint(uint64(len(v))) + tagsize
|
|
}
|
|
func sizeBytesSlice(ptr pointer, tagsize int) int {
|
|
s := *ptr.toBytesSlice()
|
|
n := 0
|
|
for _, v := range s {
|
|
n += len(v) + SizeVarint(uint64(len(v))) + tagsize
|
|
}
|
|
return n
|
|
}
|
|
|
|
// appendFixed32 appends an encoded fixed32 to b.
|
|
func appendFixed32(b []byte, v uint32) []byte {
|
|
b = append(b,
|
|
byte(v),
|
|
byte(v>>8),
|
|
byte(v>>16),
|
|
byte(v>>24))
|
|
return b
|
|
}
|
|
|
|
// appendFixed64 appends an encoded fixed64 to b.
|
|
func appendFixed64(b []byte, v uint64) []byte {
|
|
b = append(b,
|
|
byte(v),
|
|
byte(v>>8),
|
|
byte(v>>16),
|
|
byte(v>>24),
|
|
byte(v>>32),
|
|
byte(v>>40),
|
|
byte(v>>48),
|
|
byte(v>>56))
|
|
return b
|
|
}
|
|
|
|
// appendVarint appends an encoded varint to b.
|
|
func appendVarint(b []byte, v uint64) []byte {
|
|
// TODO: make 1-byte (maybe 2-byte) case inline-able, once we
|
|
// have non-leaf inliner.
|
|
switch {
|
|
case v < 1<<7:
|
|
b = append(b, byte(v))
|
|
case v < 1<<14:
|
|
b = append(b,
|
|
byte(v&0x7f|0x80),
|
|
byte(v>>7))
|
|
case v < 1<<21:
|
|
b = append(b,
|
|
byte(v&0x7f|0x80),
|
|
byte((v>>7)&0x7f|0x80),
|
|
byte(v>>14))
|
|
case v < 1<<28:
|
|
b = append(b,
|
|
byte(v&0x7f|0x80),
|
|
byte((v>>7)&0x7f|0x80),
|
|
byte((v>>14)&0x7f|0x80),
|
|
byte(v>>21))
|
|
case v < 1<<35:
|
|
b = append(b,
|
|
byte(v&0x7f|0x80),
|
|
byte((v>>7)&0x7f|0x80),
|
|
byte((v>>14)&0x7f|0x80),
|
|
byte((v>>21)&0x7f|0x80),
|
|
byte(v>>28))
|
|
case v < 1<<42:
|
|
b = append(b,
|
|
byte(v&0x7f|0x80),
|
|
byte((v>>7)&0x7f|0x80),
|
|
byte((v>>14)&0x7f|0x80),
|
|
byte((v>>21)&0x7f|0x80),
|
|
byte((v>>28)&0x7f|0x80),
|
|
byte(v>>35))
|
|
case v < 1<<49:
|
|
b = append(b,
|
|
byte(v&0x7f|0x80),
|
|
byte((v>>7)&0x7f|0x80),
|
|
byte((v>>14)&0x7f|0x80),
|
|
byte((v>>21)&0x7f|0x80),
|
|
byte((v>>28)&0x7f|0x80),
|
|
byte((v>>35)&0x7f|0x80),
|
|
byte(v>>42))
|
|
case v < 1<<56:
|
|
b = append(b,
|
|
byte(v&0x7f|0x80),
|
|
byte((v>>7)&0x7f|0x80),
|
|
byte((v>>14)&0x7f|0x80),
|
|
byte((v>>21)&0x7f|0x80),
|
|
byte((v>>28)&0x7f|0x80),
|
|
byte((v>>35)&0x7f|0x80),
|
|
byte((v>>42)&0x7f|0x80),
|
|
byte(v>>49))
|
|
case v < 1<<63:
|
|
b = append(b,
|
|
byte(v&0x7f|0x80),
|
|
byte((v>>7)&0x7f|0x80),
|
|
byte((v>>14)&0x7f|0x80),
|
|
byte((v>>21)&0x7f|0x80),
|
|
byte((v>>28)&0x7f|0x80),
|
|
byte((v>>35)&0x7f|0x80),
|
|
byte((v>>42)&0x7f|0x80),
|
|
byte((v>>49)&0x7f|0x80),
|
|
byte(v>>56))
|
|
default:
|
|
b = append(b,
|
|
byte(v&0x7f|0x80),
|
|
byte((v>>7)&0x7f|0x80),
|
|
byte((v>>14)&0x7f|0x80),
|
|
byte((v>>21)&0x7f|0x80),
|
|
byte((v>>28)&0x7f|0x80),
|
|
byte((v>>35)&0x7f|0x80),
|
|
byte((v>>42)&0x7f|0x80),
|
|
byte((v>>49)&0x7f|0x80),
|
|
byte((v>>56)&0x7f|0x80),
|
|
1)
|
|
}
|
|
return b
|
|
}
|
|
|
|
func appendFixed32Value(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
|
|
v := *ptr.toUint32()
|
|
b = appendVarint(b, wiretag)
|
|
b = appendFixed32(b, v)
|
|
return b, nil
|
|
}
|
|
func appendFixed32ValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
|
|
v := *ptr.toUint32()
|
|
if v == 0 {
|
|
return b, nil
|
|
}
|
|
b = appendVarint(b, wiretag)
|
|
b = appendFixed32(b, v)
|
|
return b, nil
|
|
}
|
|
func appendFixed32Ptr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
|
|
p := *ptr.toUint32Ptr()
|
|
if p == nil {
|
|
return b, nil
|
|
}
|
|
b = appendVarint(b, wiretag)
|
|
b = appendFixed32(b, *p)
|
|
return b, nil
|
|
}
|
|
func appendFixed32Slice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
|
|
s := *ptr.toUint32Slice()
|
|
for _, v := range s {
|
|
b = appendVarint(b, wiretag)
|
|
b = appendFixed32(b, v)
|
|
}
|
|
return b, nil
|
|
}
|
|
func appendFixed32PackedSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
|
|
s := *ptr.toUint32Slice()
|
|
if len(s) == 0 {
|
|
return b, nil
|
|
}
|
|
b = appendVarint(b, wiretag&^7|WireBytes)
|
|
b = appendVarint(b, uint64(4*len(s)))
|
|
for _, v := range s {
|
|
b = appendFixed32(b, v)
|
|
}
|
|
return b, nil
|
|
}
|
|
func appendFixedS32Value(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
|
|
v := *ptr.toInt32()
|
|
b = appendVarint(b, wiretag)
|
|
b = appendFixed32(b, uint32(v))
|
|
return b, nil
|
|
}
|
|
func appendFixedS32ValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
|
|
v := *ptr.toInt32()
|
|
if v == 0 {
|
|
return b, nil
|
|
}
|
|
b = appendVarint(b, wiretag)
|
|
b = appendFixed32(b, uint32(v))
|
|
return b, nil
|
|
}
|
|
func appendFixedS32Ptr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
|
|
p := ptr.getInt32Ptr()
|
|
if p == nil {
|
|
return b, nil
|
|
}
|
|
b = appendVarint(b, wiretag)
|
|
b = appendFixed32(b, uint32(*p))
|
|
return b, nil
|
|
}
|
|
func appendFixedS32Slice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
|
|
s := ptr.getInt32Slice()
|
|
for _, v := range s {
|
|
b = appendVarint(b, wiretag)
|
|
b = appendFixed32(b, uint32(v))
|
|
}
|
|
return b, nil
|
|
}
|
|
func appendFixedS32PackedSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
|
|
s := ptr.getInt32Slice()
|
|
if len(s) == 0 {
|
|
return b, nil
|
|
}
|
|
b = appendVarint(b, wiretag&^7|WireBytes)
|
|
b = appendVarint(b, uint64(4*len(s)))
|
|
for _, v := range s {
|
|
b = appendFixed32(b, uint32(v))
|
|
}
|
|
return b, nil
|
|
}
|
|
func appendFloat32Value(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
|
|
v := math.Float32bits(*ptr.toFloat32())
|
|
b = appendVarint(b, wiretag)
|
|
b = appendFixed32(b, v)
|
|
return b, nil
|
|
}
|
|
func appendFloat32ValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
|
|
v := math.Float32bits(*ptr.toFloat32())
|
|
if v == 0 {
|
|
return b, nil
|
|
}
|
|
b = appendVarint(b, wiretag)
|
|
b = appendFixed32(b, v)
|
|
return b, nil
|
|
}
|
|
func appendFloat32Ptr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
|
|
p := *ptr.toFloat32Ptr()
|
|
if p == nil {
|
|
return b, nil
|
|
}
|
|
b = appendVarint(b, wiretag)
|
|
b = appendFixed32(b, math.Float32bits(*p))
|
|
return b, nil
|
|
}
|
|
func appendFloat32Slice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
|
|
s := *ptr.toFloat32Slice()
|
|
for _, v := range s {
|
|
b = appendVarint(b, wiretag)
|
|
b = appendFixed32(b, math.Float32bits(v))
|
|
}
|
|
return b, nil
|
|
}
|
|
func appendFloat32PackedSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
|
|
s := *ptr.toFloat32Slice()
|
|
if len(s) == 0 {
|
|
return b, nil
|
|
}
|
|
b = appendVarint(b, wiretag&^7|WireBytes)
|
|
b = appendVarint(b, uint64(4*len(s)))
|
|
for _, v := range s {
|
|
b = appendFixed32(b, math.Float32bits(v))
|
|
}
|
|
return b, nil
|
|
}
|
|
func appendFixed64Value(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
|
|
v := *ptr.toUint64()
|
|
b = appendVarint(b, wiretag)
|
|
b = appendFixed64(b, v)
|
|
return b, nil
|
|
}
|
|
func appendFixed64ValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
|
|
v := *ptr.toUint64()
|
|
if v == 0 {
|
|
return b, nil
|
|
}
|
|
b = appendVarint(b, wiretag)
|
|
b = appendFixed64(b, v)
|
|
return b, nil
|
|
}
|
|
func appendFixed64Ptr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
|
|
p := *ptr.toUint64Ptr()
|
|
if p == nil {
|
|
return b, nil
|
|
}
|
|
b = appendVarint(b, wiretag)
|
|
b = appendFixed64(b, *p)
|
|
return b, nil
|
|
}
|
|
func appendFixed64Slice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
|
|
s := *ptr.toUint64Slice()
|
|
for _, v := range s {
|
|
b = appendVarint(b, wiretag)
|
|
b = appendFixed64(b, v)
|
|
}
|
|
return b, nil
|
|
}
|
|
func appendFixed64PackedSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
|
|
s := *ptr.toUint64Slice()
|
|
if len(s) == 0 {
|
|
return b, nil
|
|
}
|
|
b = appendVarint(b, wiretag&^7|WireBytes)
|
|
b = appendVarint(b, uint64(8*len(s)))
|
|
for _, v := range s {
|
|
b = appendFixed64(b, v)
|
|
}
|
|
return b, nil
|
|
}
|
|
func appendFixedS64Value(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
|
|
v := *ptr.toInt64()
|
|
b = appendVarint(b, wiretag)
|
|
b = appendFixed64(b, uint64(v))
|
|
return b, nil
|
|
}
|
|
func appendFixedS64ValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
|
|
v := *ptr.toInt64()
|
|
if v == 0 {
|
|
return b, nil
|
|
}
|
|
b = appendVarint(b, wiretag)
|
|
b = appendFixed64(b, uint64(v))
|
|
return b, nil
|
|
}
|
|
func appendFixedS64Ptr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
|
|
p := *ptr.toInt64Ptr()
|
|
if p == nil {
|
|
return b, nil
|
|
}
|
|
b = appendVarint(b, wiretag)
|
|
b = appendFixed64(b, uint64(*p))
|
|
return b, nil
|
|
}
|
|
func appendFixedS64Slice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
|
|
s := *ptr.toInt64Slice()
|
|
for _, v := range s {
|
|
b = appendVarint(b, wiretag)
|
|
b = appendFixed64(b, uint64(v))
|
|
}
|
|
return b, nil
|
|
}
|
|
func appendFixedS64PackedSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
|
|
s := *ptr.toInt64Slice()
|
|
if len(s) == 0 {
|
|
return b, nil
|
|
}
|
|
b = appendVarint(b, wiretag&^7|WireBytes)
|
|
b = appendVarint(b, uint64(8*len(s)))
|
|
for _, v := range s {
|
|
b = appendFixed64(b, uint64(v))
|
|
}
|
|
return b, nil
|
|
}
|
|
func appendFloat64Value(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
|
|
v := math.Float64bits(*ptr.toFloat64())
|
|
b = appendVarint(b, wiretag)
|
|
b = appendFixed64(b, v)
|
|
return b, nil
|
|
}
|
|
func appendFloat64ValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
|
|
v := math.Float64bits(*ptr.toFloat64())
|
|
if v == 0 {
|
|
return b, nil
|
|
}
|
|
b = appendVarint(b, wiretag)
|
|
b = appendFixed64(b, v)
|
|
return b, nil
|
|
}
|
|
func appendFloat64Ptr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
|
|
p := *ptr.toFloat64Ptr()
|
|
if p == nil {
|
|
return b, nil
|
|
}
|
|
b = appendVarint(b, wiretag)
|
|
b = appendFixed64(b, math.Float64bits(*p))
|
|
return b, nil
|
|
}
|
|
func appendFloat64Slice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
|
|
s := *ptr.toFloat64Slice()
|
|
for _, v := range s {
|
|
b = appendVarint(b, wiretag)
|
|
b = appendFixed64(b, math.Float64bits(v))
|
|
}
|
|
return b, nil
|
|
}
|
|
func appendFloat64PackedSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
|
|
s := *ptr.toFloat64Slice()
|
|
if len(s) == 0 {
|
|
return b, nil
|
|
}
|
|
b = appendVarint(b, wiretag&^7|WireBytes)
|
|
b = appendVarint(b, uint64(8*len(s)))
|
|
for _, v := range s {
|
|
b = appendFixed64(b, math.Float64bits(v))
|
|
}
|
|
return b, nil
|
|
}
|
|
func appendVarint32Value(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
|
|
v := *ptr.toUint32()
|
|
b = appendVarint(b, wiretag)
|
|
b = appendVarint(b, uint64(v))
|
|
return b, nil
|
|
}
|
|
func appendVarint32ValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
|
|
v := *ptr.toUint32()
|
|
if v == 0 {
|
|
return b, nil
|
|
}
|
|
b = appendVarint(b, wiretag)
|
|
b = appendVarint(b, uint64(v))
|
|
return b, nil
|
|
}
|
|
func appendVarint32Ptr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
|
|
p := *ptr.toUint32Ptr()
|
|
if p == nil {
|
|
return b, nil
|
|
}
|
|
b = appendVarint(b, wiretag)
|
|
b = appendVarint(b, uint64(*p))
|
|
return b, nil
|
|
}
|
|
func appendVarint32Slice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
|
|
s := *ptr.toUint32Slice()
|
|
for _, v := range s {
|
|
b = appendVarint(b, wiretag)
|
|
b = appendVarint(b, uint64(v))
|
|
}
|
|
return b, nil
|
|
}
|
|
func appendVarint32PackedSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
|
|
s := *ptr.toUint32Slice()
|
|
if len(s) == 0 {
|
|
return b, nil
|
|
}
|
|
b = appendVarint(b, wiretag&^7|WireBytes)
|
|
// compute size
|
|
n := 0
|
|
for _, v := range s {
|
|
n += SizeVarint(uint64(v))
|
|
}
|
|
b = appendVarint(b, uint64(n))
|
|
for _, v := range s {
|
|
b = appendVarint(b, uint64(v))
|
|
}
|
|
return b, nil
|
|
}
|
|
func appendVarintS32Value(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
|
|
v := *ptr.toInt32()
|
|
b = appendVarint(b, wiretag)
|
|
b = appendVarint(b, uint64(v))
|
|
return b, nil
|
|
}
|
|
func appendVarintS32ValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
|
|
v := *ptr.toInt32()
|
|
if v == 0 {
|
|
return b, nil
|
|
}
|
|
b = appendVarint(b, wiretag)
|
|
b = appendVarint(b, uint64(v))
|
|
return b, nil
|
|
}
|
|
func appendVarintS32Ptr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
|
|
p := ptr.getInt32Ptr()
|
|
if p == nil {
|
|
return b, nil
|
|
}
|
|
b = appendVarint(b, wiretag)
|
|
b = appendVarint(b, uint64(*p))
|
|
return b, nil
|
|
}
|
|
func appendVarintS32Slice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
|
|
s := ptr.getInt32Slice()
|
|
for _, v := range s {
|
|
b = appendVarint(b, wiretag)
|
|
b = appendVarint(b, uint64(v))
|
|
}
|
|
return b, nil
|
|
}
|
|
func appendVarintS32PackedSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
|
|
s := ptr.getInt32Slice()
|
|
if len(s) == 0 {
|
|
return b, nil
|
|
}
|
|
b = appendVarint(b, wiretag&^7|WireBytes)
|
|
// compute size
|
|
n := 0
|
|
for _, v := range s {
|
|
n += SizeVarint(uint64(v))
|
|
}
|
|
b = appendVarint(b, uint64(n))
|
|
for _, v := range s {
|
|
b = appendVarint(b, uint64(v))
|
|
}
|
|
return b, nil
|
|
}
|
|
func appendVarint64Value(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
|
|
v := *ptr.toUint64()
|
|
b = appendVarint(b, wiretag)
|
|
b = appendVarint(b, v)
|
|
return b, nil
|
|
}
|
|
func appendVarint64ValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
|
|
v := *ptr.toUint64()
|
|
if v == 0 {
|
|
return b, nil
|
|
}
|
|
b = appendVarint(b, wiretag)
|
|
b = appendVarint(b, v)
|
|
return b, nil
|
|
}
|
|
func appendVarint64Ptr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
|
|
p := *ptr.toUint64Ptr()
|
|
if p == nil {
|
|
return b, nil
|
|
}
|
|
b = appendVarint(b, wiretag)
|
|
b = appendVarint(b, *p)
|
|
return b, nil
|
|
}
|
|
func appendVarint64Slice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
|
|
s := *ptr.toUint64Slice()
|
|
for _, v := range s {
|
|
b = appendVarint(b, wiretag)
|
|
b = appendVarint(b, v)
|
|
}
|
|
return b, nil
|
|
}
|
|
func appendVarint64PackedSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
|
|
s := *ptr.toUint64Slice()
|
|
if len(s) == 0 {
|
|
return b, nil
|
|
}
|
|
b = appendVarint(b, wiretag&^7|WireBytes)
|
|
// compute size
|
|
n := 0
|
|
for _, v := range s {
|
|
n += SizeVarint(v)
|
|
}
|
|
b = appendVarint(b, uint64(n))
|
|
for _, v := range s {
|
|
b = appendVarint(b, v)
|
|
}
|
|
return b, nil
|
|
}
|
|
func appendVarintS64Value(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
|
|
v := *ptr.toInt64()
|
|
b = appendVarint(b, wiretag)
|
|
b = appendVarint(b, uint64(v))
|
|
return b, nil
|
|
}
|
|
func appendVarintS64ValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
|
|
v := *ptr.toInt64()
|
|
if v == 0 {
|
|
return b, nil
|
|
}
|
|
b = appendVarint(b, wiretag)
|
|
b = appendVarint(b, uint64(v))
|
|
return b, nil
|
|
}
|
|
func appendVarintS64Ptr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
|
|
p := *ptr.toInt64Ptr()
|
|
if p == nil {
|
|
return b, nil
|
|
}
|
|
b = appendVarint(b, wiretag)
|
|
b = appendVarint(b, uint64(*p))
|
|
return b, nil
|
|
}
|
|
func appendVarintS64Slice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
|
|
s := *ptr.toInt64Slice()
|
|
for _, v := range s {
|
|
b = appendVarint(b, wiretag)
|
|
b = appendVarint(b, uint64(v))
|
|
}
|
|
return b, nil
|
|
}
|
|
func appendVarintS64PackedSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
|
|
s := *ptr.toInt64Slice()
|
|
if len(s) == 0 {
|
|
return b, nil
|
|
}
|
|
b = appendVarint(b, wiretag&^7|WireBytes)
|
|
// compute size
|
|
n := 0
|
|
for _, v := range s {
|
|
n += SizeVarint(uint64(v))
|
|
}
|
|
b = appendVarint(b, uint64(n))
|
|
for _, v := range s {
|
|
b = appendVarint(b, uint64(v))
|
|
}
|
|
return b, nil
|
|
}
|
|
func appendZigzag32Value(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
|
|
v := *ptr.toInt32()
|
|
b = appendVarint(b, wiretag)
|
|
b = appendVarint(b, uint64((uint32(v)<<1)^uint32((int32(v)>>31))))
|
|
return b, nil
|
|
}
|
|
func appendZigzag32ValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
|
|
v := *ptr.toInt32()
|
|
if v == 0 {
|
|
return b, nil
|
|
}
|
|
b = appendVarint(b, wiretag)
|
|
b = appendVarint(b, uint64((uint32(v)<<1)^uint32((int32(v)>>31))))
|
|
return b, nil
|
|
}
|
|
func appendZigzag32Ptr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
|
|
p := ptr.getInt32Ptr()
|
|
if p == nil {
|
|
return b, nil
|
|
}
|
|
b = appendVarint(b, wiretag)
|
|
v := *p
|
|
b = appendVarint(b, uint64((uint32(v)<<1)^uint32((int32(v)>>31))))
|
|
return b, nil
|
|
}
|
|
func appendZigzag32Slice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
|
|
s := ptr.getInt32Slice()
|
|
for _, v := range s {
|
|
b = appendVarint(b, wiretag)
|
|
b = appendVarint(b, uint64((uint32(v)<<1)^uint32((int32(v)>>31))))
|
|
}
|
|
return b, nil
|
|
}
|
|
func appendZigzag32PackedSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
|
|
s := ptr.getInt32Slice()
|
|
if len(s) == 0 {
|
|
return b, nil
|
|
}
|
|
b = appendVarint(b, wiretag&^7|WireBytes)
|
|
// compute size
|
|
n := 0
|
|
for _, v := range s {
|
|
n += SizeVarint(uint64((uint32(v) << 1) ^ uint32((int32(v) >> 31))))
|
|
}
|
|
b = appendVarint(b, uint64(n))
|
|
for _, v := range s {
|
|
b = appendVarint(b, uint64((uint32(v)<<1)^uint32((int32(v)>>31))))
|
|
}
|
|
return b, nil
|
|
}
|
|
func appendZigzag64Value(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
|
|
v := *ptr.toInt64()
|
|
b = appendVarint(b, wiretag)
|
|
b = appendVarint(b, uint64(v<<1)^uint64((int64(v)>>63)))
|
|
return b, nil
|
|
}
|
|
func appendZigzag64ValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
|
|
v := *ptr.toInt64()
|
|
if v == 0 {
|
|
return b, nil
|
|
}
|
|
b = appendVarint(b, wiretag)
|
|
b = appendVarint(b, uint64(v<<1)^uint64((int64(v)>>63)))
|
|
return b, nil
|
|
}
|
|
func appendZigzag64Ptr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
|
|
p := *ptr.toInt64Ptr()
|
|
if p == nil {
|
|
return b, nil
|
|
}
|
|
b = appendVarint(b, wiretag)
|
|
v := *p
|
|
b = appendVarint(b, uint64(v<<1)^uint64((int64(v)>>63)))
|
|
return b, nil
|
|
}
|
|
func appendZigzag64Slice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
|
|
s := *ptr.toInt64Slice()
|
|
for _, v := range s {
|
|
b = appendVarint(b, wiretag)
|
|
b = appendVarint(b, uint64(v<<1)^uint64((int64(v)>>63)))
|
|
}
|
|
return b, nil
|
|
}
|
|
func appendZigzag64PackedSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
|
|
s := *ptr.toInt64Slice()
|
|
if len(s) == 0 {
|
|
return b, nil
|
|
}
|
|
b = appendVarint(b, wiretag&^7|WireBytes)
|
|
// compute size
|
|
n := 0
|
|
for _, v := range s {
|
|
n += SizeVarint(uint64(v<<1) ^ uint64((int64(v) >> 63)))
|
|
}
|
|
b = appendVarint(b, uint64(n))
|
|
for _, v := range s {
|
|
b = appendVarint(b, uint64(v<<1)^uint64((int64(v)>>63)))
|
|
}
|
|
return b, nil
|
|
}
|
|
func appendBoolValue(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
|
|
v := *ptr.toBool()
|
|
b = appendVarint(b, wiretag)
|
|
if v {
|
|
b = append(b, 1)
|
|
} else {
|
|
b = append(b, 0)
|
|
}
|
|
return b, nil
|
|
}
|
|
func appendBoolValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
|
|
v := *ptr.toBool()
|
|
if !v {
|
|
return b, nil
|
|
}
|
|
b = appendVarint(b, wiretag)
|
|
b = append(b, 1)
|
|
return b, nil
|
|
}
|
|
|
|
func appendBoolPtr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
|
|
p := *ptr.toBoolPtr()
|
|
if p == nil {
|
|
return b, nil
|
|
}
|
|
b = appendVarint(b, wiretag)
|
|
if *p {
|
|
b = append(b, 1)
|
|
} else {
|
|
b = append(b, 0)
|
|
}
|
|
return b, nil
|
|
}
|
|
func appendBoolSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
|
|
s := *ptr.toBoolSlice()
|
|
for _, v := range s {
|
|
b = appendVarint(b, wiretag)
|
|
if v {
|
|
b = append(b, 1)
|
|
} else {
|
|
b = append(b, 0)
|
|
}
|
|
}
|
|
return b, nil
|
|
}
|
|
func appendBoolPackedSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
|
|
s := *ptr.toBoolSlice()
|
|
if len(s) == 0 {
|
|
return b, nil
|
|
}
|
|
b = appendVarint(b, wiretag&^7|WireBytes)
|
|
b = appendVarint(b, uint64(len(s)))
|
|
for _, v := range s {
|
|
if v {
|
|
b = append(b, 1)
|
|
} else {
|
|
b = append(b, 0)
|
|
}
|
|
}
|
|
return b, nil
|
|
}
|
|
func appendStringValue(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
|
|
v := *ptr.toString()
|
|
if !utf8.ValidString(v) {
|
|
return nil, errInvalidUTF8
|
|
}
|
|
b = appendVarint(b, wiretag)
|
|
b = appendVarint(b, uint64(len(v)))
|
|
b = append(b, v...)
|
|
return b, nil
|
|
}
|
|
func appendStringValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
|
|
v := *ptr.toString()
|
|
if v == "" {
|
|
return b, nil
|
|
}
|
|
if !utf8.ValidString(v) {
|
|
return nil, errInvalidUTF8
|
|
}
|
|
b = appendVarint(b, wiretag)
|
|
b = appendVarint(b, uint64(len(v)))
|
|
b = append(b, v...)
|
|
return b, nil
|
|
}
|
|
func appendStringPtr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
|
|
p := *ptr.toStringPtr()
|
|
if p == nil {
|
|
return b, nil
|
|
}
|
|
v := *p
|
|
if !utf8.ValidString(v) {
|
|
return nil, errInvalidUTF8
|
|
}
|
|
b = appendVarint(b, wiretag)
|
|
b = appendVarint(b, uint64(len(v)))
|
|
b = append(b, v...)
|
|
return b, nil
|
|
}
|
|
func appendStringSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
|
|
s := *ptr.toStringSlice()
|
|
for _, v := range s {
|
|
if !utf8.ValidString(v) {
|
|
return nil, errInvalidUTF8
|
|
}
|
|
b = appendVarint(b, wiretag)
|
|
b = appendVarint(b, uint64(len(v)))
|
|
b = append(b, v...)
|
|
}
|
|
return b, nil
|
|
}
|
|
func appendBytes(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
|
|
v := *ptr.toBytes()
|
|
if v == nil {
|
|
return b, nil
|
|
}
|
|
b = appendVarint(b, wiretag)
|
|
b = appendVarint(b, uint64(len(v)))
|
|
b = append(b, v...)
|
|
return b, nil
|
|
}
|
|
func appendBytes3(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
|
|
v := *ptr.toBytes()
|
|
if len(v) == 0 {
|
|
return b, nil
|
|
}
|
|
b = appendVarint(b, wiretag)
|
|
b = appendVarint(b, uint64(len(v)))
|
|
b = append(b, v...)
|
|
return b, nil
|
|
}
|
|
func appendBytesOneof(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
|
|
v := *ptr.toBytes()
|
|
b = appendVarint(b, wiretag)
|
|
b = appendVarint(b, uint64(len(v)))
|
|
b = append(b, v...)
|
|
return b, nil
|
|
}
|
|
func appendBytesSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
|
|
s := *ptr.toBytesSlice()
|
|
for _, v := range s {
|
|
b = appendVarint(b, wiretag)
|
|
b = appendVarint(b, uint64(len(v)))
|
|
b = append(b, v...)
|
|
}
|
|
return b, nil
|
|
}
|
|
|
|
// makeGroupMarshaler returns the sizer and marshaler for a group.
|
|
// u is the marshal info of the underlying message.
|
|
func makeGroupMarshaler(u *marshalInfo) (sizer, marshaler) {
|
|
return func(ptr pointer, tagsize int) int {
|
|
p := ptr.getPointer()
|
|
if p.isNil() {
|
|
return 0
|
|
}
|
|
return u.size(p) + 2*tagsize
|
|
},
|
|
func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) {
|
|
p := ptr.getPointer()
|
|
if p.isNil() {
|
|
return b, nil
|
|
}
|
|
var err error
|
|
b = appendVarint(b, wiretag) // start group
|
|
b, err = u.marshal(b, p, deterministic)
|
|
b = appendVarint(b, wiretag+(WireEndGroup-WireStartGroup)) // end group
|
|
return b, err
|
|
}
|
|
}
|
|
|
|
// makeGroupSliceMarshaler returns the sizer and marshaler for a group slice.
|
|
// u is the marshal info of the underlying message.
|
|
func makeGroupSliceMarshaler(u *marshalInfo) (sizer, marshaler) {
|
|
return func(ptr pointer, tagsize int) int {
|
|
s := ptr.getPointerSlice()
|
|
n := 0
|
|
for _, v := range s {
|
|
if v.isNil() {
|
|
continue
|
|
}
|
|
n += u.size(v) + 2*tagsize
|
|
}
|
|
return n
|
|
},
|
|
func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) {
|
|
s := ptr.getPointerSlice()
|
|
var err, errreq error
|
|
for _, v := range s {
|
|
if v.isNil() {
|
|
return b, errRepeatedHasNil
|
|
}
|
|
b = appendVarint(b, wiretag) // start group
|
|
b, err = u.marshal(b, v, deterministic)
|
|
b = appendVarint(b, wiretag+(WireEndGroup-WireStartGroup)) // end group
|
|
if err != nil {
|
|
if _, ok := err.(*RequiredNotSetError); ok {
|
|
// Required field in submessage is not set.
|
|
// We record the error but keep going, to give a complete marshaling.
|
|
if errreq == nil {
|
|
errreq = err
|
|
}
|
|
continue
|
|
}
|
|
if err == ErrNil {
|
|
err = errRepeatedHasNil
|
|
}
|
|
return b, err
|
|
}
|
|
}
|
|
return b, errreq
|
|
}
|
|
}
|
|
|
|
// makeMessageMarshaler returns the sizer and marshaler for a message field.
|
|
// u is the marshal info of the message.
|
|
func makeMessageMarshaler(u *marshalInfo) (sizer, marshaler) {
|
|
return func(ptr pointer, tagsize int) int {
|
|
p := ptr.getPointer()
|
|
if p.isNil() {
|
|
return 0
|
|
}
|
|
siz := u.size(p)
|
|
return siz + SizeVarint(uint64(siz)) + tagsize
|
|
},
|
|
func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) {
|
|
p := ptr.getPointer()
|
|
if p.isNil() {
|
|
return b, nil
|
|
}
|
|
b = appendVarint(b, wiretag)
|
|
siz := u.cachedsize(p)
|
|
b = appendVarint(b, uint64(siz))
|
|
return u.marshal(b, p, deterministic)
|
|
}
|
|
}
|
|
|
|
// makeMessageSliceMarshaler returns the sizer and marshaler for a message slice.
|
|
// u is the marshal info of the message.
|
|
func makeMessageSliceMarshaler(u *marshalInfo) (sizer, marshaler) {
|
|
return func(ptr pointer, tagsize int) int {
|
|
s := ptr.getPointerSlice()
|
|
n := 0
|
|
for _, v := range s {
|
|
if v.isNil() {
|
|
continue
|
|
}
|
|
siz := u.size(v)
|
|
n += siz + SizeVarint(uint64(siz)) + tagsize
|
|
}
|
|
return n
|
|
},
|
|
func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) {
|
|
s := ptr.getPointerSlice()
|
|
var err, errreq error
|
|
for _, v := range s {
|
|
if v.isNil() {
|
|
return b, errRepeatedHasNil
|
|
}
|
|
b = appendVarint(b, wiretag)
|
|
siz := u.cachedsize(v)
|
|
b = appendVarint(b, uint64(siz))
|
|
b, err = u.marshal(b, v, deterministic)
|
|
|
|
if err != nil {
|
|
if _, ok := err.(*RequiredNotSetError); ok {
|
|
// Required field in submessage is not set.
|
|
// We record the error but keep going, to give a complete marshaling.
|
|
if errreq == nil {
|
|
errreq = err
|
|
}
|
|
continue
|
|
}
|
|
if err == ErrNil {
|
|
err = errRepeatedHasNil
|
|
}
|
|
return b, err
|
|
}
|
|
}
|
|
return b, errreq
|
|
}
|
|
}
|
|
|
|
// makeMapMarshaler returns the sizer and marshaler for a map field.
|
|
// f is the pointer to the reflect data structure of the field.
|
|
func makeMapMarshaler(f *reflect.StructField) (sizer, marshaler) {
|
|
// figure out key and value type
|
|
t := f.Type
|
|
keyType := t.Key()
|
|
valType := t.Elem()
|
|
keyTags := strings.Split(f.Tag.Get("protobuf_key"), ",")
|
|
valTags := strings.Split(f.Tag.Get("protobuf_val"), ",")
|
|
keySizer, keyMarshaler := typeMarshaler(keyType, keyTags, false, false) // don't omit zero value in map
|
|
valSizer, valMarshaler := typeMarshaler(valType, valTags, false, false) // don't omit zero value in map
|
|
keyWireTag := 1<<3 | wiretype(keyTags[0])
|
|
valWireTag := 2<<3 | wiretype(valTags[0])
|
|
|
|
// We create an interface to get the addresses of the map key and value.
|
|
// If value is pointer-typed, the interface is a direct interface, the
|
|
// idata itself is the value. Otherwise, the idata is the pointer to the
|
|
// value.
|
|
// Key cannot be pointer-typed.
|
|
valIsPtr := valType.Kind() == reflect.Ptr
|
|
return func(ptr pointer, tagsize int) int {
|
|
m := ptr.asPointerTo(t).Elem() // the map
|
|
n := 0
|
|
for _, k := range m.MapKeys() {
|
|
ki := k.Interface()
|
|
vi := m.MapIndex(k).Interface()
|
|
kaddr := toAddrPointer(&ki, false) // pointer to key
|
|
vaddr := toAddrPointer(&vi, valIsPtr) // pointer to value
|
|
siz := keySizer(kaddr, 1) + valSizer(vaddr, 1) // tag of key = 1 (size=1), tag of val = 2 (size=1)
|
|
n += siz + SizeVarint(uint64(siz)) + tagsize
|
|
}
|
|
return n
|
|
},
|
|
func(b []byte, ptr pointer, tag uint64, deterministic bool) ([]byte, error) {
|
|
m := ptr.asPointerTo(t).Elem() // the map
|
|
var err error
|
|
keys := m.MapKeys()
|
|
if len(keys) > 1 && deterministic {
|
|
sort.Sort(mapKeys(keys))
|
|
}
|
|
for _, k := range keys {
|
|
ki := k.Interface()
|
|
vi := m.MapIndex(k).Interface()
|
|
kaddr := toAddrPointer(&ki, false) // pointer to key
|
|
vaddr := toAddrPointer(&vi, valIsPtr) // pointer to value
|
|
b = appendVarint(b, tag)
|
|
siz := keySizer(kaddr, 1) + valSizer(vaddr, 1) // tag of key = 1 (size=1), tag of val = 2 (size=1)
|
|
b = appendVarint(b, uint64(siz))
|
|
b, err = keyMarshaler(b, kaddr, keyWireTag, deterministic)
|
|
if err != nil {
|
|
return b, err
|
|
}
|
|
b, err = valMarshaler(b, vaddr, valWireTag, deterministic)
|
|
if err != nil && err != ErrNil { // allow nil value in map
|
|
return b, err
|
|
}
|
|
}
|
|
return b, nil
|
|
}
|
|
}
|
|
|
|
// makeOneOfMarshaler returns the sizer and marshaler for a oneof field.
|
|
// fi is the marshal info of the field.
|
|
// f is the pointer to the reflect data structure of the field.
|
|
func makeOneOfMarshaler(fi *marshalFieldInfo, f *reflect.StructField) (sizer, marshaler) {
|
|
// Oneof field is an interface. We need to get the actual data type on the fly.
|
|
t := f.Type
|
|
return func(ptr pointer, _ int) int {
|
|
p := ptr.getInterfacePointer()
|
|
if p.isNil() {
|
|
return 0
|
|
}
|
|
v := ptr.asPointerTo(t).Elem().Elem().Elem() // *interface -> interface -> *struct -> struct
|
|
telem := v.Type()
|
|
e := fi.oneofElems[telem]
|
|
return e.sizer(p, e.tagsize)
|
|
},
|
|
func(b []byte, ptr pointer, _ uint64, deterministic bool) ([]byte, error) {
|
|
p := ptr.getInterfacePointer()
|
|
if p.isNil() {
|
|
return b, nil
|
|
}
|
|
v := ptr.asPointerTo(t).Elem().Elem().Elem() // *interface -> interface -> *struct -> struct
|
|
telem := v.Type()
|
|
if telem.Field(0).Type.Kind() == reflect.Ptr && p.getPointer().isNil() {
|
|
return b, errOneofHasNil
|
|
}
|
|
e := fi.oneofElems[telem]
|
|
return e.marshaler(b, p, e.wiretag, deterministic)
|
|
}
|
|
}
|
|
|
|
// sizeExtensions computes the size of encoded data for a XXX_InternalExtensions field.
|
|
func (u *marshalInfo) sizeExtensions(ext *XXX_InternalExtensions) int {
|
|
m, mu := ext.extensionsRead()
|
|
if m == nil {
|
|
return 0
|
|
}
|
|
mu.Lock()
|
|
|
|
n := 0
|
|
for _, e := range m {
|
|
if e.value == nil || e.desc == nil {
|
|
// Extension is only in its encoded form.
|
|
n += len(e.enc)
|
|
continue
|
|
}
|
|
|
|
// We don't skip extensions that have an encoded form set,
|
|
// because the extension value may have been mutated after
|
|
// the last time this function was called.
|
|
ei := u.getExtElemInfo(e.desc)
|
|
v := e.value
|
|
p := toAddrPointer(&v, ei.isptr)
|
|
n += ei.sizer(p, ei.tagsize)
|
|
}
|
|
mu.Unlock()
|
|
return n
|
|
}
|
|
|
|
// appendExtensions marshals a XXX_InternalExtensions field to the end of byte slice b.
|
|
func (u *marshalInfo) appendExtensions(b []byte, ext *XXX_InternalExtensions, deterministic bool) ([]byte, error) {
|
|
m, mu := ext.extensionsRead()
|
|
if m == nil {
|
|
return b, nil
|
|
}
|
|
mu.Lock()
|
|
defer mu.Unlock()
|
|
|
|
var err error
|
|
|
|
// Fast-path for common cases: zero or one extensions.
|
|
// Don't bother sorting the keys.
|
|
if len(m) <= 1 {
|
|
for _, e := range m {
|
|
if e.value == nil || e.desc == nil {
|
|
// Extension is only in its encoded form.
|
|
b = append(b, e.enc...)
|
|
continue
|
|
}
|
|
|
|
// We don't skip extensions that have an encoded form set,
|
|
// because the extension value may have been mutated after
|
|
// the last time this function was called.
|
|
|
|
ei := u.getExtElemInfo(e.desc)
|
|
v := e.value
|
|
p := toAddrPointer(&v, ei.isptr)
|
|
b, err = ei.marshaler(b, p, ei.wiretag, deterministic)
|
|
if err != nil {
|
|
return b, err
|
|
}
|
|
}
|
|
return b, nil
|
|
}
|
|
|
|
// Sort the keys to provide a deterministic encoding.
|
|
// Not sure this is required, but the old code does it.
|
|
keys := make([]int, 0, len(m))
|
|
for k := range m {
|
|
keys = append(keys, int(k))
|
|
}
|
|
sort.Ints(keys)
|
|
|
|
for _, k := range keys {
|
|
e := m[int32(k)]
|
|
if e.value == nil || e.desc == nil {
|
|
// Extension is only in its encoded form.
|
|
b = append(b, e.enc...)
|
|
continue
|
|
}
|
|
|
|
// We don't skip extensions that have an encoded form set,
|
|
// because the extension value may have been mutated after
|
|
// the last time this function was called.
|
|
|
|
ei := u.getExtElemInfo(e.desc)
|
|
v := e.value
|
|
p := toAddrPointer(&v, ei.isptr)
|
|
b, err = ei.marshaler(b, p, ei.wiretag, deterministic)
|
|
if err != nil {
|
|
return b, err
|
|
}
|
|
}
|
|
return b, nil
|
|
}
|
|
|
|
// message set format is:
|
|
// message MessageSet {
|
|
// repeated group Item = 1 {
|
|
// required int32 type_id = 2;
|
|
// required string message = 3;
|
|
// };
|
|
// }
|
|
|
|
// sizeMessageSet computes the size of encoded data for a XXX_InternalExtensions field
|
|
// in message set format (above).
|
|
func (u *marshalInfo) sizeMessageSet(ext *XXX_InternalExtensions) int {
|
|
m, mu := ext.extensionsRead()
|
|
if m == nil {
|
|
return 0
|
|
}
|
|
mu.Lock()
|
|
|
|
n := 0
|
|
for id, e := range m {
|
|
n += 2 // start group, end group. tag = 1 (size=1)
|
|
n += SizeVarint(uint64(id)) + 1 // type_id, tag = 2 (size=1)
|
|
|
|
if e.value == nil || e.desc == nil {
|
|
// Extension is only in its encoded form.
|
|
msgWithLen := skipVarint(e.enc) // skip old tag, but leave the length varint
|
|
siz := len(msgWithLen)
|
|
n += siz + 1 // message, tag = 3 (size=1)
|
|
continue
|
|
}
|
|
|
|
// We don't skip extensions that have an encoded form set,
|
|
// because the extension value may have been mutated after
|
|
// the last time this function was called.
|
|
|
|
ei := u.getExtElemInfo(e.desc)
|
|
v := e.value
|
|
p := toAddrPointer(&v, ei.isptr)
|
|
n += ei.sizer(p, 1) // message, tag = 3 (size=1)
|
|
}
|
|
mu.Unlock()
|
|
return n
|
|
}
|
|
|
|
// appendMessageSet marshals a XXX_InternalExtensions field in message set format (above)
|
|
// to the end of byte slice b.
|
|
func (u *marshalInfo) appendMessageSet(b []byte, ext *XXX_InternalExtensions, deterministic bool) ([]byte, error) {
|
|
m, mu := ext.extensionsRead()
|
|
if m == nil {
|
|
return b, nil
|
|
}
|
|
mu.Lock()
|
|
defer mu.Unlock()
|
|
|
|
var err error
|
|
|
|
// Fast-path for common cases: zero or one extensions.
|
|
// Don't bother sorting the keys.
|
|
if len(m) <= 1 {
|
|
for id, e := range m {
|
|
b = append(b, 1<<3|WireStartGroup)
|
|
b = append(b, 2<<3|WireVarint)
|
|
b = appendVarint(b, uint64(id))
|
|
|
|
if e.value == nil || e.desc == nil {
|
|
// Extension is only in its encoded form.
|
|
msgWithLen := skipVarint(e.enc) // skip old tag, but leave the length varint
|
|
b = append(b, 3<<3|WireBytes)
|
|
b = append(b, msgWithLen...)
|
|
b = append(b, 1<<3|WireEndGroup)
|
|
continue
|
|
}
|
|
|
|
// We don't skip extensions that have an encoded form set,
|
|
// because the extension value may have been mutated after
|
|
// the last time this function was called.
|
|
|
|
ei := u.getExtElemInfo(e.desc)
|
|
v := e.value
|
|
p := toAddrPointer(&v, ei.isptr)
|
|
b, err = ei.marshaler(b, p, 3<<3|WireBytes, deterministic)
|
|
if err != nil {
|
|
return b, err
|
|
}
|
|
b = append(b, 1<<3|WireEndGroup)
|
|
}
|
|
return b, nil
|
|
}
|
|
|
|
// Sort the keys to provide a deterministic encoding.
|
|
keys := make([]int, 0, len(m))
|
|
for k := range m {
|
|
keys = append(keys, int(k))
|
|
}
|
|
sort.Ints(keys)
|
|
|
|
for _, id := range keys {
|
|
e := m[int32(id)]
|
|
b = append(b, 1<<3|WireStartGroup)
|
|
b = append(b, 2<<3|WireVarint)
|
|
b = appendVarint(b, uint64(id))
|
|
|
|
if e.value == nil || e.desc == nil {
|
|
// Extension is only in its encoded form.
|
|
msgWithLen := skipVarint(e.enc) // skip old tag, but leave the length varint
|
|
b = append(b, 3<<3|WireBytes)
|
|
b = append(b, msgWithLen...)
|
|
b = append(b, 1<<3|WireEndGroup)
|
|
continue
|
|
}
|
|
|
|
// We don't skip extensions that have an encoded form set,
|
|
// because the extension value may have been mutated after
|
|
// the last time this function was called.
|
|
|
|
ei := u.getExtElemInfo(e.desc)
|
|
v := e.value
|
|
p := toAddrPointer(&v, ei.isptr)
|
|
b, err = ei.marshaler(b, p, 3<<3|WireBytes, deterministic)
|
|
b = append(b, 1<<3|WireEndGroup)
|
|
if err != nil {
|
|
return b, err
|
|
}
|
|
}
|
|
return b, nil
|
|
}
|
|
|
|
// sizeV1Extensions computes the size of encoded data for a V1-API extension field.
|
|
func (u *marshalInfo) sizeV1Extensions(m map[int32]Extension) int {
|
|
if m == nil {
|
|
return 0
|
|
}
|
|
|
|
n := 0
|
|
for _, e := range m {
|
|
if e.value == nil || e.desc == nil {
|
|
// Extension is only in its encoded form.
|
|
n += len(e.enc)
|
|
continue
|
|
}
|
|
|
|
// We don't skip extensions that have an encoded form set,
|
|
// because the extension value may have been mutated after
|
|
// the last time this function was called.
|
|
|
|
ei := u.getExtElemInfo(e.desc)
|
|
v := e.value
|
|
p := toAddrPointer(&v, ei.isptr)
|
|
n += ei.sizer(p, ei.tagsize)
|
|
}
|
|
return n
|
|
}
|
|
|
|
// appendV1Extensions marshals a V1-API extension field to the end of byte slice b.
|
|
func (u *marshalInfo) appendV1Extensions(b []byte, m map[int32]Extension, deterministic bool) ([]byte, error) {
|
|
if m == nil {
|
|
return b, nil
|
|
}
|
|
|
|
// Sort the keys to provide a deterministic encoding.
|
|
keys := make([]int, 0, len(m))
|
|
for k := range m {
|
|
keys = append(keys, int(k))
|
|
}
|
|
sort.Ints(keys)
|
|
|
|
var err error
|
|
for _, k := range keys {
|
|
e := m[int32(k)]
|
|
if e.value == nil || e.desc == nil {
|
|
// Extension is only in its encoded form.
|
|
b = append(b, e.enc...)
|
|
continue
|
|
}
|
|
|
|
// We don't skip extensions that have an encoded form set,
|
|
// because the extension value may have been mutated after
|
|
// the last time this function was called.
|
|
|
|
ei := u.getExtElemInfo(e.desc)
|
|
v := e.value
|
|
p := toAddrPointer(&v, ei.isptr)
|
|
b, err = ei.marshaler(b, p, ei.wiretag, deterministic)
|
|
if err != nil {
|
|
return b, err
|
|
}
|
|
}
|
|
return b, nil
|
|
}
|
|
|
|
// newMarshaler is the interface representing objects that can marshal themselves.
|
|
//
|
|
// This exists to support protoc-gen-go generated messages.
|
|
// The proto package will stop type-asserting to this interface in the future.
|
|
//
|
|
// DO NOT DEPEND ON THIS.
|
|
type newMarshaler interface {
|
|
XXX_Size() int
|
|
XXX_Marshal(b []byte, deterministic bool) ([]byte, error)
|
|
}
|
|
|
|
// Size returns the encoded size of a protocol buffer message.
|
|
// This is the main entry point.
|
|
func Size(pb Message) int {
|
|
if m, ok := pb.(newMarshaler); ok {
|
|
return m.XXX_Size()
|
|
}
|
|
if m, ok := pb.(Marshaler); ok {
|
|
// If the message can marshal itself, let it do it, for compatibility.
|
|
// NOTE: This is not efficient.
|
|
b, _ := m.Marshal()
|
|
return len(b)
|
|
}
|
|
// in case somehow we didn't generate the wrapper
|
|
if pb == nil {
|
|
return 0
|
|
}
|
|
var info InternalMessageInfo
|
|
return info.Size(pb)
|
|
}
|
|
|
|
// Marshal takes a protocol buffer message
|
|
// and encodes it into the wire format, returning the data.
|
|
// This is the main entry point.
|
|
func Marshal(pb Message) ([]byte, error) {
|
|
if m, ok := pb.(newMarshaler); ok {
|
|
siz := m.XXX_Size()
|
|
b := make([]byte, 0, siz)
|
|
return m.XXX_Marshal(b, false)
|
|
}
|
|
if m, ok := pb.(Marshaler); ok {
|
|
// If the message can marshal itself, let it do it, for compatibility.
|
|
// NOTE: This is not efficient.
|
|
return m.Marshal()
|
|
}
|
|
// in case somehow we didn't generate the wrapper
|
|
if pb == nil {
|
|
return nil, ErrNil
|
|
}
|
|
var info InternalMessageInfo
|
|
siz := info.Size(pb)
|
|
b := make([]byte, 0, siz)
|
|
return info.Marshal(b, pb, false)
|
|
}
|
|
|
|
// Marshal takes a protocol buffer message
|
|
// and encodes it into the wire format, writing the result to the
|
|
// Buffer.
|
|
// This is an alternative entry point. It is not necessary to use
|
|
// a Buffer for most applications.
|
|
func (p *Buffer) Marshal(pb Message) error {
|
|
var err error
|
|
if m, ok := pb.(newMarshaler); ok {
|
|
siz := m.XXX_Size()
|
|
p.grow(siz) // make sure buf has enough capacity
|
|
p.buf, err = m.XXX_Marshal(p.buf, p.deterministic)
|
|
return err
|
|
}
|
|
if m, ok := pb.(Marshaler); ok {
|
|
// If the message can marshal itself, let it do it, for compatibility.
|
|
// NOTE: This is not efficient.
|
|
b, err := m.Marshal()
|
|
p.buf = append(p.buf, b...)
|
|
return err
|
|
}
|
|
// in case somehow we didn't generate the wrapper
|
|
if pb == nil {
|
|
return ErrNil
|
|
}
|
|
var info InternalMessageInfo
|
|
siz := info.Size(pb)
|
|
p.grow(siz) // make sure buf has enough capacity
|
|
p.buf, err = info.Marshal(p.buf, pb, p.deterministic)
|
|
return err
|
|
}
|
|
|
|
// grow grows the buffer's capacity, if necessary, to guarantee space for
|
|
// another n bytes. After grow(n), at least n bytes can be written to the
|
|
// buffer without another allocation.
|
|
func (p *Buffer) grow(n int) {
|
|
need := len(p.buf) + n
|
|
if need <= cap(p.buf) {
|
|
return
|
|
}
|
|
newCap := len(p.buf) * 2
|
|
if newCap < need {
|
|
newCap = need
|
|
}
|
|
p.buf = append(make([]byte, 0, newCap), p.buf...)
|
|
}
|