mirror of
https://github.com/hanzoai/metrics.git
synced 2026-10-30 20:03:39 +00:00
719 lines
18 KiB
Go
719 lines
18 KiB
Go
package easyproto
|
|
|
|
import (
|
|
"encoding/binary"
|
|
"math"
|
|
"math/bits"
|
|
"sync"
|
|
)
|
|
|
|
// MarshalerPool is a pool of Marshaler structs.
|
|
type MarshalerPool struct {
|
|
p sync.Pool
|
|
}
|
|
|
|
// Get obtains a Marshaler from the pool.
|
|
//
|
|
// The returned Marshaler can be returned to the pool via Put after it is no longer needed.
|
|
func (mp *MarshalerPool) Get() *Marshaler {
|
|
v := mp.p.Get()
|
|
if v == nil {
|
|
return &Marshaler{}
|
|
}
|
|
return v.(*Marshaler)
|
|
}
|
|
|
|
// Put returns the given m to the pool.
|
|
//
|
|
// m cannot be used after returning to the pool.
|
|
func (mp *MarshalerPool) Put(m *Marshaler) {
|
|
m.Reset()
|
|
mp.p.Put(m)
|
|
}
|
|
|
|
// Marshaler helps marshaling arbitrary protobuf messages.
|
|
//
|
|
// Construct message with Append* functions at MessageMarshaler() and then call Marshal* for marshaling the constructed message.
|
|
//
|
|
// It is unsafe to use a single Marshaler instance from multiple concurrently running goroutines.
|
|
//
|
|
// It is recommended re-cycling Marshaler via MarshalerPool in order to reduce memory allocations.
|
|
type Marshaler struct {
|
|
// mm contains the root MessageMarshaler.
|
|
mm *MessageMarshaler
|
|
|
|
// buf contains temporary data needed for marshaling the protobuf message.
|
|
buf []byte
|
|
|
|
// fs contains fields for the currently marshaled message.
|
|
fs []field
|
|
|
|
// mms contains MessageMarshaler structs for the currently marshaled message.
|
|
mms []MessageMarshaler
|
|
}
|
|
|
|
// MessageMarshaler helps constructing protobuf message for marshaling.
|
|
//
|
|
// MessageMarshaler must be obtained via Marshaler.MessageMarshaler().
|
|
type MessageMarshaler struct {
|
|
// m is the parent Marshaler for the given MessageMarshaler.
|
|
m *Marshaler
|
|
|
|
// tag contains protobuf message tag for the given MessageMarshaler.
|
|
tag uint64
|
|
|
|
// firstFieldIdx contains the index of the first field in the Marshaler.fs, which belongs to MessageMarshaler.
|
|
firstFieldIdx int
|
|
|
|
// lastFieldIdx is the index of the last field in the Marshaler.fs, which belongs to MessageMarshaler.
|
|
lastFieldIdx int
|
|
}
|
|
|
|
func (mm *MessageMarshaler) reset() {
|
|
mm.m = nil
|
|
mm.tag = 0
|
|
mm.firstFieldIdx = -1
|
|
mm.lastFieldIdx = -1
|
|
}
|
|
|
|
type field struct {
|
|
// messageSize is the size of marshaled protobuf message for the given field.
|
|
messageSize uint64
|
|
|
|
// dataStart is the start offset of field data at Marshaler.buf.
|
|
dataStart int
|
|
|
|
// dataEnd is the end offset of field data at Marshaler.buf.
|
|
dataEnd int
|
|
|
|
// nextFieldIdx contains an index of the next field in Marshaler.fs.
|
|
nextFieldIdx int
|
|
|
|
// childMessageMarshalerIdx contains an index of child MessageMarshaler in Marshaler.mms.
|
|
childMessageMarshalerIdx int
|
|
}
|
|
|
|
func (f *field) reset() {
|
|
f.messageSize = 0
|
|
f.dataStart = 0
|
|
f.dataEnd = 0
|
|
f.nextFieldIdx = -1
|
|
f.childMessageMarshalerIdx = -1
|
|
}
|
|
|
|
// Reset resets m, so it can be re-used.
|
|
func (m *Marshaler) Reset() {
|
|
m.mm = nil
|
|
m.buf = m.buf[:0]
|
|
|
|
// There is no need in resetting individual fields, since they are reset in newFieldIndex()
|
|
m.fs = m.fs[:0]
|
|
|
|
// There is no need in resetting individual MessageMarshaler items, since they are reset in newMessageMarshalerIndex()
|
|
m.mms = m.mms[:0]
|
|
}
|
|
|
|
// MarshalWithLen marshals m, appends its length together with the marshaled m to dst and returns the result.
|
|
//
|
|
// I.e. it appends length-delimited protobuf message to dst.
|
|
// The length of the resulting message can be read via UnmarshalMessageLen() function.
|
|
//
|
|
// See also Marshal.
|
|
func (m *Marshaler) MarshalWithLen(dst []byte) []byte {
|
|
if m.mm == nil {
|
|
dst = marshalVarUint64(dst, 0)
|
|
return dst
|
|
}
|
|
if firstFieldIdx := m.mm.firstFieldIdx; firstFieldIdx >= 0 {
|
|
f := &m.fs[firstFieldIdx]
|
|
messageSize := f.initMessageSize(m)
|
|
if cap(dst) == 0 {
|
|
dst = make([]byte, messageSize+10)
|
|
dst = dst[:0]
|
|
}
|
|
dst = marshalVarUint64(dst, messageSize)
|
|
dst = f.marshal(dst, m)
|
|
}
|
|
return dst
|
|
}
|
|
|
|
// Marshal appends marshaled protobuf m to dst and returns the result.
|
|
//
|
|
// The marshaled message can be read via FieldContext.NextField().
|
|
//
|
|
// See also MarshalWithLen.
|
|
func (m *Marshaler) Marshal(dst []byte) []byte {
|
|
if m.mm == nil {
|
|
// Nothing to marshal
|
|
return dst
|
|
}
|
|
if firstFieldIdx := m.mm.firstFieldIdx; firstFieldIdx >= 0 {
|
|
f := &m.fs[firstFieldIdx]
|
|
messageSize := f.initMessageSize(m)
|
|
if cap(dst) == 0 {
|
|
dst = make([]byte, messageSize)
|
|
dst = dst[:0]
|
|
}
|
|
dst = f.marshal(dst, m)
|
|
}
|
|
return dst
|
|
}
|
|
|
|
// MessageMarshaler returns message marshaler for the given m.
|
|
func (m *Marshaler) MessageMarshaler() *MessageMarshaler {
|
|
if mm := m.mm; mm != nil {
|
|
return mm
|
|
}
|
|
idx := m.newMessageMarshalerIndex()
|
|
mm := &m.mms[idx]
|
|
m.mm = mm
|
|
return mm
|
|
}
|
|
|
|
func (m *Marshaler) newMessageMarshalerIndex() int {
|
|
mms := m.mms
|
|
mmsLen := len(mms)
|
|
if cap(mms) > mmsLen {
|
|
mms = mms[:mmsLen+1]
|
|
} else {
|
|
mms = append(mms, MessageMarshaler{})
|
|
}
|
|
m.mms = mms
|
|
mm := &mms[mmsLen]
|
|
mm.reset()
|
|
mm.m = m
|
|
return mmsLen
|
|
}
|
|
|
|
func (m *Marshaler) newFieldIndex() int {
|
|
fs := m.fs
|
|
fsLen := len(fs)
|
|
if cap(fs) > fsLen {
|
|
fs = fs[:fsLen+1]
|
|
} else {
|
|
fs = append(fs, field{})
|
|
}
|
|
m.fs = fs
|
|
fs[fsLen].reset()
|
|
return fsLen
|
|
}
|
|
|
|
// AppendInt32 appends the given int32 value under the given fieldNum to mm.
|
|
func (mm *MessageMarshaler) AppendInt32(fieldNum uint32, i32 int32) {
|
|
mm.AppendUint64(fieldNum, uint64(uint32(i32)))
|
|
}
|
|
|
|
// AppendInt64 appends the given int64 value under the given fieldNum to mm.
|
|
func (mm *MessageMarshaler) AppendInt64(fieldNum uint32, i64 int64) {
|
|
mm.AppendUint64(fieldNum, uint64(i64))
|
|
}
|
|
|
|
// AppendUint32 appends the given uint32 value under the given fieldNum to mm.
|
|
func (mm *MessageMarshaler) AppendUint32(fieldNum, u32 uint32) {
|
|
mm.AppendUint64(fieldNum, uint64(u32))
|
|
}
|
|
|
|
// AppendUint64 appends the given uint64 value under the given fieldNum to mm.
|
|
func (mm *MessageMarshaler) AppendUint64(fieldNum uint32, u64 uint64) {
|
|
tag := makeTag(fieldNum, wireTypeVarint)
|
|
|
|
m := mm.m
|
|
dst := m.buf
|
|
dstLen := len(dst)
|
|
if tag < 0x80 {
|
|
dst = append(dst, byte(tag))
|
|
} else {
|
|
dst = marshalVarUint64(dst, tag)
|
|
}
|
|
dst = marshalVarUint64(dst, u64)
|
|
m.buf = dst
|
|
|
|
mm.appendField(m, dstLen, len(dst))
|
|
}
|
|
|
|
// AppendSint32 appends the given sint32 value under the given fieldNum to mm.
|
|
func (mm *MessageMarshaler) AppendSint32(fieldNum uint32, i32 int32) {
|
|
u64 := uint64(encodeZigZagInt32(i32))
|
|
mm.AppendUint64(fieldNum, u64)
|
|
}
|
|
|
|
// AppendSint64 appends the given sint64 value under the given fieldNum to mm.
|
|
func (mm *MessageMarshaler) AppendSint64(fieldNum uint32, i64 int64) {
|
|
u64 := encodeZigZagInt64(i64)
|
|
mm.AppendUint64(fieldNum, u64)
|
|
}
|
|
|
|
// AppendBool appends the given bool value under the given fieldNum to mm.
|
|
func (mm *MessageMarshaler) AppendBool(fieldNum uint32, v bool) {
|
|
u64 := uint64(0)
|
|
if v {
|
|
u64 = 1
|
|
}
|
|
mm.AppendUint64(fieldNum, u64)
|
|
}
|
|
|
|
// AppendFixed64 appends fixed64 value under the given fieldNum to mm.
|
|
func (mm *MessageMarshaler) AppendFixed64(fieldNum uint32, u64 uint64) {
|
|
tag := makeTag(fieldNum, wireTypeI64)
|
|
|
|
m := mm.m
|
|
dst := m.buf
|
|
dstLen := len(dst)
|
|
if tag < 0x80 {
|
|
dst = append(dst, byte(tag))
|
|
} else {
|
|
dst = marshalVarUint64(dst, tag)
|
|
}
|
|
dst = marshalUint64(dst, u64)
|
|
m.buf = dst
|
|
|
|
mm.appendField(m, dstLen, len(dst))
|
|
}
|
|
|
|
// AppendSfixed64 appends sfixed64 value under the given fieldNum to mm.
|
|
func (mm *MessageMarshaler) AppendSfixed64(fieldNum uint32, i64 int64) {
|
|
mm.AppendFixed64(fieldNum, uint64(i64))
|
|
}
|
|
|
|
// AppendDouble appends double value under the given fieldNum to mm.
|
|
func (mm *MessageMarshaler) AppendDouble(fieldNum uint32, f float64) {
|
|
u64 := math.Float64bits(f)
|
|
mm.AppendFixed64(fieldNum, u64)
|
|
}
|
|
|
|
// AppendString appends string value under the given fieldNum to mm.
|
|
func (mm *MessageMarshaler) AppendString(fieldNum uint32, s string) {
|
|
tag := makeTag(fieldNum, wireTypeLen)
|
|
|
|
m := mm.m
|
|
dst := m.buf
|
|
dstLen := len(dst)
|
|
sLen := len(s)
|
|
if tag < 0x80 && sLen < 0x80 {
|
|
dst = append(dst, byte(tag), byte(sLen))
|
|
} else {
|
|
dst = marshalVarUint64(dst, tag)
|
|
dst = marshalVarUint64(dst, uint64(sLen))
|
|
}
|
|
dst = append(dst, s...)
|
|
m.buf = dst
|
|
|
|
mm.appendField(m, dstLen, len(dst))
|
|
}
|
|
|
|
// AppendBytes appends bytes value under the given fieldNum to mm.
|
|
func (mm *MessageMarshaler) AppendBytes(fieldNum uint32, b []byte) {
|
|
s := unsafeBytesToString(b)
|
|
mm.AppendString(fieldNum, s)
|
|
}
|
|
|
|
// AppendMessage appends protobuf message with the given fieldNum to m.
|
|
//
|
|
// The function returns the MessageMarshaler for constructing the appended message.
|
|
func (mm *MessageMarshaler) AppendMessage(fieldNum uint32) *MessageMarshaler {
|
|
tag := makeTag(fieldNum, wireTypeLen)
|
|
|
|
f := mm.newField()
|
|
m := mm.m
|
|
f.childMessageMarshalerIdx = m.newMessageMarshalerIndex()
|
|
mmChild := &m.mms[f.childMessageMarshalerIdx]
|
|
mmChild.tag = tag
|
|
return mmChild
|
|
}
|
|
|
|
// AppendFixed32 appends fixed32 value under the given fieldNum to mm.
|
|
func (mm *MessageMarshaler) AppendFixed32(fieldNum, u32 uint32) {
|
|
tag := makeTag(fieldNum, wireTypeI32)
|
|
|
|
m := mm.m
|
|
dst := m.buf
|
|
dstLen := len(dst)
|
|
if tag < 0x80 {
|
|
dst = append(dst, byte(tag))
|
|
} else {
|
|
dst = marshalVarUint64(dst, tag)
|
|
}
|
|
dst = marshalUint32(dst, u32)
|
|
m.buf = dst
|
|
|
|
mm.appendField(m, dstLen, len(dst))
|
|
}
|
|
|
|
// AppendSfixed32 appends sfixed32 value under the given fieldNum to mm.
|
|
func (mm *MessageMarshaler) AppendSfixed32(fieldNum uint32, i32 int32) {
|
|
mm.AppendFixed32(fieldNum, uint32(i32))
|
|
}
|
|
|
|
// AppendFloat appends float value under the given fieldNum to mm.
|
|
func (mm *MessageMarshaler) AppendFloat(fieldNum uint32, f float32) {
|
|
u32 := math.Float32bits(f)
|
|
mm.AppendFixed32(fieldNum, u32)
|
|
}
|
|
|
|
// AppendInt32s appends the given int32 values under the given fieldNum to mm.
|
|
func (mm *MessageMarshaler) AppendInt32s(fieldNum uint32, i32s []int32) {
|
|
child := mm.AppendMessage(fieldNum)
|
|
child.appendInt32s(i32s)
|
|
}
|
|
|
|
// AppendInt64s appends the given int64 values under the given fieldNum to mm.
|
|
func (mm *MessageMarshaler) AppendInt64s(fieldNum uint32, i64s []int64) {
|
|
child := mm.AppendMessage(fieldNum)
|
|
child.appendInt64s(i64s)
|
|
}
|
|
|
|
// AppendUint32s appends the given uint32 values under the given fieldNum to mm.
|
|
func (mm *MessageMarshaler) AppendUint32s(fieldNum uint32, u32s []uint32) {
|
|
child := mm.AppendMessage(fieldNum)
|
|
child.appendUint32s(u32s)
|
|
}
|
|
|
|
// AppendUint64s appends the given uint64 values under the given fieldNum to mm.
|
|
func (mm *MessageMarshaler) AppendUint64s(fieldNum uint32, u64s []uint64) {
|
|
child := mm.AppendMessage(fieldNum)
|
|
child.appendUint64s(u64s)
|
|
}
|
|
|
|
// AppendSint32s appends the given sint32 values under the given fieldNum to mm.
|
|
func (mm *MessageMarshaler) AppendSint32s(fieldNum uint32, i32s []int32) {
|
|
child := mm.AppendMessage(fieldNum)
|
|
child.appendSint32s(i32s)
|
|
}
|
|
|
|
// AppendSint64s appends the given sint64 values under the given fieldNum to mm.
|
|
func (mm *MessageMarshaler) AppendSint64s(fieldNum uint32, i64s []int64) {
|
|
child := mm.AppendMessage(fieldNum)
|
|
child.appendSint64s(i64s)
|
|
}
|
|
|
|
// AppendBools appends the given bool values under the given fieldNum to mm.
|
|
func (mm *MessageMarshaler) AppendBools(fieldNum uint32, bs []bool) {
|
|
child := mm.AppendMessage(fieldNum)
|
|
child.appendBools(bs)
|
|
}
|
|
|
|
// AppendFixed64s appends the given fixed64 values under the given fieldNum to mm.
|
|
func (mm *MessageMarshaler) AppendFixed64s(fieldNum uint32, u64s []uint64) {
|
|
child := mm.AppendMessage(fieldNum)
|
|
child.appendFixed64s(u64s)
|
|
}
|
|
|
|
// AppendSfixed64s appends the given sfixed64 values under the given fieldNum to mm.
|
|
func (mm *MessageMarshaler) AppendSfixed64s(fieldNum uint32, i64s []int64) {
|
|
child := mm.AppendMessage(fieldNum)
|
|
child.appendSfixed64s(i64s)
|
|
}
|
|
|
|
// AppendDoubles appends the given double values under the given fieldNum to mm.
|
|
func (mm *MessageMarshaler) AppendDoubles(fieldNum uint32, fs []float64) {
|
|
child := mm.AppendMessage(fieldNum)
|
|
child.appendDoubles(fs)
|
|
}
|
|
|
|
// AppendFixed32s appends the given fixed32 values under the given fieldNum to mm.
|
|
func (mm *MessageMarshaler) AppendFixed32s(fieldNum uint32, u32s []uint32) {
|
|
child := mm.AppendMessage(fieldNum)
|
|
child.appendFixed32s(u32s)
|
|
}
|
|
|
|
// AppendSfixed32s appends the given sfixed32 values under the given fieldNum to mm.
|
|
func (mm *MessageMarshaler) AppendSfixed32s(fieldNum uint32, i32s []int32) {
|
|
child := mm.AppendMessage(fieldNum)
|
|
child.appendSfixed32s(i32s)
|
|
}
|
|
|
|
// AppendFloats appends the given float values under the given fieldNum to mm.
|
|
func (mm *MessageMarshaler) AppendFloats(fieldNum uint32, fs []float32) {
|
|
child := mm.AppendMessage(fieldNum)
|
|
child.appendFloats(fs)
|
|
}
|
|
|
|
func (mm *MessageMarshaler) appendInt32s(i32s []int32) {
|
|
m := mm.m
|
|
dst := m.buf
|
|
dstLen := len(dst)
|
|
for _, i32 := range i32s {
|
|
dst = marshalVarUint64(dst, uint64(uint32(i32)))
|
|
}
|
|
m.buf = dst
|
|
|
|
mm.appendField(m, dstLen, len(dst))
|
|
}
|
|
|
|
func (mm *MessageMarshaler) appendUint32s(u32s []uint32) {
|
|
m := mm.m
|
|
dst := m.buf
|
|
dstLen := len(dst)
|
|
for _, u32 := range u32s {
|
|
dst = marshalVarUint64(dst, uint64(u32))
|
|
}
|
|
m.buf = dst
|
|
|
|
mm.appendField(m, dstLen, len(dst))
|
|
}
|
|
|
|
func (mm *MessageMarshaler) appendSint32s(i32s []int32) {
|
|
m := mm.m
|
|
dst := m.buf
|
|
dstLen := len(dst)
|
|
for _, i32 := range i32s {
|
|
u64 := uint64(encodeZigZagInt32(i32))
|
|
dst = marshalVarUint64(dst, u64)
|
|
}
|
|
m.buf = dst
|
|
|
|
mm.appendField(m, dstLen, len(dst))
|
|
}
|
|
|
|
func (mm *MessageMarshaler) appendInt64s(i64s []int64) {
|
|
m := mm.m
|
|
dst := m.buf
|
|
dstLen := len(dst)
|
|
for _, i64 := range i64s {
|
|
dst = marshalVarUint64(dst, uint64(i64))
|
|
}
|
|
m.buf = dst
|
|
|
|
mm.appendField(m, dstLen, len(dst))
|
|
}
|
|
|
|
func (mm *MessageMarshaler) appendUint64s(u64s []uint64) {
|
|
m := mm.m
|
|
dst := m.buf
|
|
dstLen := len(dst)
|
|
for _, u64 := range u64s {
|
|
dst = marshalVarUint64(dst, u64)
|
|
}
|
|
m.buf = dst
|
|
|
|
mm.appendField(m, dstLen, len(dst))
|
|
}
|
|
|
|
func (mm *MessageMarshaler) appendSint64s(i64s []int64) {
|
|
m := mm.m
|
|
dst := m.buf
|
|
dstLen := len(dst)
|
|
for _, i64 := range i64s {
|
|
u64 := encodeZigZagInt64(i64)
|
|
dst = marshalVarUint64(dst, u64)
|
|
}
|
|
m.buf = dst
|
|
|
|
mm.appendField(m, dstLen, len(dst))
|
|
}
|
|
|
|
func (mm *MessageMarshaler) appendBools(bs []bool) {
|
|
m := mm.m
|
|
dst := m.buf
|
|
dstLen := len(dst)
|
|
for _, b := range bs {
|
|
u64 := uint64(0)
|
|
if b {
|
|
u64 = 1
|
|
}
|
|
dst = marshalVarUint64(dst, u64)
|
|
}
|
|
m.buf = dst
|
|
|
|
mm.appendField(m, dstLen, len(dst))
|
|
}
|
|
|
|
func (mm *MessageMarshaler) appendFixed64s(u64s []uint64) {
|
|
m := mm.m
|
|
dst := m.buf
|
|
dstLen := len(dst)
|
|
for _, u64 := range u64s {
|
|
dst = marshalUint64(dst, u64)
|
|
}
|
|
m.buf = dst
|
|
|
|
mm.appendField(m, dstLen, len(dst))
|
|
}
|
|
|
|
func (mm *MessageMarshaler) appendSfixed64s(i64s []int64) {
|
|
m := mm.m
|
|
dst := m.buf
|
|
dstLen := len(dst)
|
|
for _, i64 := range i64s {
|
|
dst = marshalUint64(dst, uint64(i64))
|
|
}
|
|
m.buf = dst
|
|
|
|
mm.appendField(m, dstLen, len(dst))
|
|
}
|
|
|
|
func (mm *MessageMarshaler) appendFixed32s(u32s []uint32) {
|
|
m := mm.m
|
|
dst := m.buf
|
|
dstLen := len(dst)
|
|
for _, u32 := range u32s {
|
|
dst = marshalUint32(dst, u32)
|
|
}
|
|
m.buf = dst
|
|
|
|
mm.appendField(m, dstLen, len(dst))
|
|
}
|
|
|
|
func (mm *MessageMarshaler) appendSfixed32s(i32s []int32) {
|
|
m := mm.m
|
|
dst := m.buf
|
|
dstLen := len(dst)
|
|
for _, i32 := range i32s {
|
|
dst = marshalUint32(dst, uint32(i32))
|
|
}
|
|
m.buf = dst
|
|
|
|
mm.appendField(m, dstLen, len(dst))
|
|
}
|
|
|
|
func (mm *MessageMarshaler) appendDoubles(fs []float64) {
|
|
m := mm.m
|
|
dst := m.buf
|
|
dstLen := len(dst)
|
|
for _, f := range fs {
|
|
u64 := math.Float64bits(f)
|
|
dst = marshalUint64(dst, u64)
|
|
}
|
|
m.buf = dst
|
|
|
|
mm.appendField(m, dstLen, len(dst))
|
|
}
|
|
|
|
func (mm *MessageMarshaler) appendFloats(fs []float32) {
|
|
m := mm.m
|
|
dst := m.buf
|
|
dstLen := len(dst)
|
|
for _, f := range fs {
|
|
u32 := math.Float32bits(f)
|
|
dst = marshalUint32(dst, u32)
|
|
}
|
|
m.buf = dst
|
|
|
|
mm.appendField(m, dstLen, len(dst))
|
|
}
|
|
|
|
func (mm *MessageMarshaler) appendField(m *Marshaler, dataStart, dataEnd int) {
|
|
if lastFieldIdx := mm.lastFieldIdx; lastFieldIdx >= 0 {
|
|
if f := &m.fs[lastFieldIdx]; f.childMessageMarshalerIdx == -1 && f.dataEnd == dataStart {
|
|
f.dataEnd = dataEnd
|
|
return
|
|
}
|
|
}
|
|
f := mm.newField()
|
|
f.dataStart = dataStart
|
|
f.dataEnd = dataEnd
|
|
}
|
|
|
|
func (mm *MessageMarshaler) newField() *field {
|
|
m := mm.m
|
|
idx := m.newFieldIndex()
|
|
f := &m.fs[idx]
|
|
if lastFieldIdx := mm.lastFieldIdx; lastFieldIdx >= 0 {
|
|
m.fs[lastFieldIdx].nextFieldIdx = idx
|
|
} else {
|
|
mm.firstFieldIdx = idx
|
|
}
|
|
mm.lastFieldIdx = idx
|
|
return f
|
|
}
|
|
|
|
func (f *field) initMessageSize(m *Marshaler) uint64 {
|
|
n := uint64(0)
|
|
for {
|
|
if childMessageMarshalerIdx := f.childMessageMarshalerIdx; childMessageMarshalerIdx < 0 {
|
|
n += uint64(f.dataEnd - f.dataStart)
|
|
} else {
|
|
mmChild := m.mms[childMessageMarshalerIdx]
|
|
if tag := mmChild.tag; tag < 0x80 {
|
|
n++
|
|
} else {
|
|
n += varuintLen(tag)
|
|
}
|
|
messageSize := uint64(0)
|
|
if firstFieldIdx := mmChild.firstFieldIdx; firstFieldIdx >= 0 {
|
|
messageSize = m.fs[firstFieldIdx].initMessageSize(m)
|
|
}
|
|
n += messageSize
|
|
if messageSize < 0x80 {
|
|
n++
|
|
} else {
|
|
n += varuintLen(messageSize)
|
|
}
|
|
f.messageSize = messageSize
|
|
}
|
|
nextFieldIdx := f.nextFieldIdx
|
|
if nextFieldIdx < 0 {
|
|
return n
|
|
}
|
|
f = &m.fs[nextFieldIdx]
|
|
}
|
|
}
|
|
|
|
func (f *field) marshal(dst []byte, m *Marshaler) []byte {
|
|
for {
|
|
if childMessageMarshalerIdx := f.childMessageMarshalerIdx; childMessageMarshalerIdx < 0 {
|
|
data := m.buf[f.dataStart:f.dataEnd]
|
|
dst = append(dst, data...)
|
|
} else {
|
|
mmChild := m.mms[childMessageMarshalerIdx]
|
|
tag := mmChild.tag
|
|
messageSize := f.messageSize
|
|
if tag < 0x80 && messageSize < 0x80 {
|
|
dst = append(dst, byte(tag), byte(messageSize))
|
|
} else {
|
|
dst = marshalVarUint64(dst, mmChild.tag)
|
|
dst = marshalVarUint64(dst, f.messageSize)
|
|
}
|
|
if firstFieldIdx := mmChild.firstFieldIdx; firstFieldIdx >= 0 {
|
|
dst = m.fs[firstFieldIdx].marshal(dst, m)
|
|
}
|
|
}
|
|
nextFieldIdx := f.nextFieldIdx
|
|
if nextFieldIdx < 0 {
|
|
return dst
|
|
}
|
|
f = &m.fs[nextFieldIdx]
|
|
}
|
|
}
|
|
|
|
func marshalUint64(dst []byte, u64 uint64) []byte {
|
|
return binary.LittleEndian.AppendUint64(dst, u64)
|
|
}
|
|
|
|
func marshalUint32(dst []byte, u32 uint32) []byte {
|
|
return binary.LittleEndian.AppendUint32(dst, u32)
|
|
}
|
|
|
|
func marshalVarUint64(dst []byte, u64 uint64) []byte {
|
|
if u64 < 0x80 {
|
|
// Fast path
|
|
dst = append(dst, byte(u64))
|
|
return dst
|
|
}
|
|
for u64 > 0x7f {
|
|
dst = append(dst, 0x80|byte(u64))
|
|
u64 >>= 7
|
|
}
|
|
dst = append(dst, byte(u64))
|
|
return dst
|
|
}
|
|
|
|
func encodeZigZagInt64(i64 int64) uint64 {
|
|
return uint64((i64 << 1) ^ (i64 >> 63))
|
|
}
|
|
|
|
func encodeZigZagInt32(i32 int32) uint32 {
|
|
return uint32((i32 << 1) ^ (i32 >> 31))
|
|
}
|
|
|
|
func makeTag(fieldNum uint32, wt wireType) uint64 {
|
|
return (uint64(fieldNum) << 3) | uint64(wt)
|
|
}
|
|
|
|
// varuintLen returns the number of bytes needed for varuint-encoding of u64.
|
|
//
|
|
// Note that it returns 0 for u64=0, so this case must be handled separately.
|
|
func varuintLen(u64 uint64) uint64 {
|
|
return uint64(((byte(bits.Len64(u64))) + 6) / 7)
|
|
}
|