| // 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, errLater 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 { |
| if ptr.offset(f.field).getPointer().isNil() { |
| // Required field is not set. |
| // We record the error but keep going, to give a complete marshaling. |
| if errLater == nil { |
| errLater = &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 errLater == nil { |
| errLater = &RequiredNotSetError{f.name + "." + err1.field} |
| } |
| continue |
| } |
| if err == errRepeatedHasNil { |
| err = errors.New("proto: repeated field " + f.name + " has nil element") |
| } |
| if err == errInvalidUTF8 { |
| if errLater == nil { |
| fullName := revProtoTypes[reflect.PtrTo(u.typ)] + "." + f.name |
| errLater = &invalidUTF8Error{fullName} |
| } |
| continue |
| } |
| return b, err |
| } |
| } |
| if u.unrecognized.IsValid() { |
| s := *ptr.offset(u.unrecognized).toBytes() |
| b = append(b, s...) |
| } |
| return b, errLater |
| } |
| |
| // 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 |
| validateUTF8 := true |
| for i := 2; i < len(tags); i++ { |
| if tags[i] == "packed" { |
| packed = true |
| } |
| if tags[i] == "proto3" { |
| proto3 = true |
| } |
| } |
| validateUTF8 = validateUTF8 && proto3 |
| |
| 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 validateUTF8 { |
| if pointer { |
| return sizeStringPtr, appendUTF8StringPtr |
| } |
| if slice { |
| return sizeStringSlice, appendUTF8StringSlice |
| } |
| if nozero { |
| return sizeStringValueNoZero, appendUTF8StringValueNoZero |
| } |
| return sizeStringValue, appendUTF8StringValue |
| } |
| 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() |
| 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 |
| } |
| 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 |
| 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 { |
| b = appendVarint(b, wiretag) |
| b = appendVarint(b, uint64(len(v))) |
| b = append(b, v...) |
| } |
| return b, nil |
| } |
| func appendUTF8StringValue(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { |
| var invalidUTF8 bool |
| v := *ptr.toString() |
| if !utf8.ValidString(v) { |
| invalidUTF8 = true |
| } |
| b = appendVarint(b, wiretag) |
| b = appendVarint(b, uint64(len(v))) |
| b = append(b, v...) |
| if invalidUTF8 { |
| return b, errInvalidUTF8 |
| } |
| return b, nil |
| } |
| func appendUTF8StringValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { |
| var invalidUTF8 bool |
| v := *ptr.toString() |
| if v == "" { |
| return b, nil |
| } |
| if !utf8.ValidString(v) { |
| invalidUTF8 = true |
| } |
| b = appendVarint(b, wiretag) |
| b = appendVarint(b, uint64(len(v))) |
| b = append(b, v...) |
| if invalidUTF8 { |
| return b, errInvalidUTF8 |
| } |
| return b, nil |
| } |
| func appendUTF8StringPtr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { |
| var invalidUTF8 bool |
| p := *ptr.toStringPtr() |
| if p == nil { |
| return b, nil |
| } |
| v := *p |
| if !utf8.ValidString(v) { |
| invalidUTF8 = true |
| } |
| b = appendVarint(b, wiretag) |
| b = appendVarint(b, uint64(len(v))) |
| b = append(b, v...) |
| if invalidUTF8 { |
| return b, errInvalidUTF8 |
| } |
| return b, nil |
| } |
| func appendUTF8StringSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { |
| var invalidUTF8 bool |
| s := *ptr.toStringSlice() |
| for _, v := range s { |
| if !utf8.ValidString(v) { |
| invalidUTF8 = true |
| } |
| b = appendVarint(b, wiretag) |
| b = appendVarint(b, uint64(len(v))) |
| b = append(b, v...) |
| } |
| if invalidUTF8 { |
| return b, errInvalidUTF8 |
| } |
| 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 error |
| var nerr nonFatal |
| 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 !nerr.Merge(err) { |
| if err == ErrNil { |
| err = errRepeatedHasNil |
| } |
| return b, err |
| } |
| } |
| return b, nerr.E |
| } |
| } |
| |
| // 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 error |
| var nerr nonFatal |
| 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 !nerr.Merge(err) { |
| if err == ErrNil { |
| err = errRepeatedHasNil |
| } |
| return b, err |
| } |
| } |
| return b, nerr.E |
| } |
| } |
| |
| // 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 |
| |
| // If value is a message with nested maps, calling |
| // valSizer in marshal may be quadratic. We should use |
| // cached version in marshal (but not in size). |
| // If value is not message type, we don't have size cache, |
| // but it cannot be nested either. Just use valSizer. |
| valCachedSizer := valSizer |
| if valIsPtr && valType.Elem().Kind() == reflect.Struct { |
| u := getMarshalInfo(valType.Elem()) |
| valCachedSizer = func(ptr pointer, tagsize int) int { |
| // Same as message sizer, but use cache. |
| p := ptr.getPointer() |
| if p.isNil() { |
| return 0 |
| } |
| siz := u.cachedsize(p) |
| return siz + SizeVarint(uint64(siz)) + tagsize |
| } |
| } |
| 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)) |
| } |
| |
| var nerr nonFatal |
| 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) + valCachedSizer(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 !nerr.Merge(err) { |
| return b, err |
| } |
| b, err = valMarshaler(b, vaddr, valWireTag, deterministic) |
| if err != ErrNil && !nerr.Merge(err) { // allow nil value in map |
| return b, err |
| } |
| } |
| return b, nerr.E |
| } |
| } |
| |
| // 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 |
| var nerr nonFatal |
| |
| // 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 !nerr.Merge(err) { |
| return b, err |
| } |
| } |
| return b, nerr.E |
| } |
| |
| // 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 !nerr.Merge(err) { |
| return b, err |
| } |
| } |
| return b, nerr.E |
| } |
| |
| // 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 |
| var nerr nonFatal |
| |
| // 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 !nerr.Merge(err) { |
| return b, err |
| } |
| b = append(b, 1<<3|WireEndGroup) |
| } |
| return b, nerr.E |
| } |
| |
| // 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 !nerr.Merge(err) { |
| return b, err |
| } |
| } |
| return b, nerr.E |
| } |
| |
| // 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 |
| var nerr nonFatal |
| 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 !nerr.Merge(err) { |
| return b, err |
| } |
| } |
| return b, nerr.E |
| } |
| |
| // 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...) |
| } |