| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101 |
- // Copyright 2019 The Go Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style
- // license that can be found in the LICENSE file.
- package impl
- import (
- "reflect"
- "sort"
- "google.golang.org/protobuf/internal/encoding/wire"
- pref "google.golang.org/protobuf/reflect/protoreflect"
- piface "google.golang.org/protobuf/runtime/protoiface"
- )
- // coderMessageInfo contains per-message information used by the fast-path functions.
- // This is a different type from MessageInfo to keep MessageInfo as general-purpose as
- // possible.
- type coderMessageInfo struct {
- orderedCoderFields []*coderFieldInfo
- sizecacheOffset offset
- extensionOffset offset
- unknownOffset offset
- needsInitCheck bool
- }
- type coderFieldInfo struct {
- funcs pointerCoderFuncs // fast-path per-field functions
- num pref.FieldNumber // field number
- offset offset // struct field offset
- wiretag uint64 // field tag (number + wire type)
- tagsize int // size of the varint-encoded tag
- isPointer bool // true if IsNil may be called on the struct field
- isRequired bool // true if field is required
- }
- func (mi *MessageInfo) makeMethods(t reflect.Type, si structInfo) {
- mi.sizecacheOffset = invalidOffset
- if fx, _ := t.FieldByName("XXX_sizecache"); fx.Type == sizecacheType {
- mi.sizecacheOffset = offsetOf(fx)
- }
- mi.unknownOffset = invalidOffset
- if fx, _ := t.FieldByName("XXX_unrecognized"); fx.Type == unknownFieldsType {
- mi.unknownOffset = offsetOf(fx)
- }
- mi.extensionOffset = invalidOffset
- if fx, _ := t.FieldByName("XXX_InternalExtensions"); fx.Type == extensionFieldsType {
- mi.extensionOffset = offsetOf(fx)
- } else if fx, _ = t.FieldByName("XXX_extensions"); fx.Type == extensionFieldsType {
- mi.extensionOffset = offsetOf(fx)
- }
- for i := 0; i < mi.PBType.Descriptor().Fields().Len(); i++ {
- fd := mi.PBType.Descriptor().Fields().Get(i)
- if fd.ContainingOneof() != nil {
- continue
- }
- fs := si.fieldsByNumber[fd.Number()]
- ft := fs.Type
- var wiretag uint64
- if !fd.IsPacked() {
- wiretag = wire.EncodeTag(fd.Number(), wireTypes[fd.Kind()])
- } else {
- wiretag = wire.EncodeTag(fd.Number(), wire.BytesType)
- }
- mi.orderedCoderFields = append(mi.orderedCoderFields, &coderFieldInfo{
- num: fd.Number(),
- offset: offsetOf(fs),
- wiretag: wiretag,
- tagsize: wire.SizeVarint(wiretag),
- funcs: fieldCoder(fd, ft),
- isPointer: (fd.Cardinality() == pref.Repeated ||
- fd.Kind() == pref.MessageKind ||
- fd.Kind() == pref.GroupKind ||
- fd.Syntax() != pref.Proto3),
- isRequired: fd.Cardinality() == pref.Required,
- })
- }
- for i := 0; i < mi.PBType.Descriptor().Oneofs().Len(); i++ {
- od := mi.PBType.Descriptor().Oneofs().Get(i)
- fs := si.oneofsByName[od.Name()]
- mi.orderedCoderFields = append(mi.orderedCoderFields, &coderFieldInfo{
- num: od.Fields().Get(0).Number(),
- offset: offsetOf(fs),
- funcs: makeOneofFieldCoder(fs, od, si.fieldsByNumber, si.oneofWrappersByNumber),
- isPointer: true,
- })
- }
- sort.Slice(mi.orderedCoderFields, func(i, j int) bool {
- return mi.orderedCoderFields[i].num < mi.orderedCoderFields[j].num
- })
- mi.needsInitCheck = needsInitCheck(mi.PBType)
- mi.methods = piface.Methods{
- Flags: piface.MethodFlagDeterministicMarshal,
- MarshalAppend: mi.marshalAppend,
- Size: mi.size,
- IsInitialized: mi.isInitialized,
- }
- }
|