codec_message.go raw

   1  // Copyright 2019 The Go Authors. All rights reserved.
   2  // Use of this source code is governed by a BSD-style
   3  // license that can be found in the LICENSE file.
   4  
   5  package impl
   6  
   7  import (
   8  	"fmt"
   9  	"reflect"
  10  	"sort"
  11  
  12  	"google.golang.org/protobuf/encoding/protowire"
  13  	"google.golang.org/protobuf/internal/encoding/messageset"
  14  	"google.golang.org/protobuf/internal/order"
  15  	"google.golang.org/protobuf/reflect/protoreflect"
  16  	"google.golang.org/protobuf/runtime/protoiface"
  17  )
  18  
  19  // coderMessageInfo contains per-message information used by the fast-path functions.
  20  // This is a different type from MessageInfo to keep MessageInfo as general-purpose as
  21  // possible.
  22  type coderMessageInfo struct {
  23  	methods protoiface.Methods
  24  
  25  	orderedCoderFields []*coderFieldInfo
  26  	denseCoderFields   []*coderFieldInfo
  27  	coderFields        map[protowire.Number]*coderFieldInfo
  28  	sizecacheOffset    offset
  29  	unknownOffset      offset
  30  	unknownPtrKind     bool
  31  	extensionOffset    offset
  32  	needsInitCheck     bool
  33  	isMessageSet       bool
  34  	numRequiredFields  uint8
  35  
  36  	lazyOffset     offset
  37  	presenceOffset offset
  38  	presenceSize   presenceSize
  39  }
  40  
  41  type coderFieldInfo struct {
  42  	funcs      pointerCoderFuncs // fast-path per-field functions
  43  	mi         *MessageInfo      // field's message
  44  	ft         reflect.Type
  45  	validation validationInfo           // information used by message validation
  46  	num        protoreflect.FieldNumber // field number
  47  	offset     offset                   // struct field offset
  48  	wiretag    uint64                   // field tag (number + wire type)
  49  	tagsize    int                      // size of the varint-encoded tag
  50  	isPointer  bool                     // true if IsNil may be called on the struct field
  51  	isRequired bool                     // true if field is required
  52  
  53  	isLazy        bool
  54  	presenceIndex uint32
  55  }
  56  
  57  const noPresence = 0xffffffff
  58  
  59  func (mi *MessageInfo) makeCoderMethods(t reflect.Type, si structInfo) {
  60  	mi.sizecacheOffset = invalidOffset
  61  	mi.unknownOffset = invalidOffset
  62  	mi.extensionOffset = invalidOffset
  63  	mi.lazyOffset = invalidOffset
  64  	mi.presenceOffset = si.presenceOffset
  65  
  66  	if si.sizecacheOffset.IsValid() && si.sizecacheType == sizecacheType {
  67  		mi.sizecacheOffset = si.sizecacheOffset
  68  	}
  69  	if si.unknownOffset.IsValid() && (si.unknownType == unknownFieldsAType || si.unknownType == unknownFieldsBType) {
  70  		mi.unknownOffset = si.unknownOffset
  71  		mi.unknownPtrKind = si.unknownType.Kind() == reflect.Ptr
  72  	}
  73  	if si.extensionOffset.IsValid() && si.extensionType == extensionFieldsType {
  74  		mi.extensionOffset = si.extensionOffset
  75  	}
  76  
  77  	mi.coderFields = make(map[protowire.Number]*coderFieldInfo)
  78  	fields := mi.Desc.Fields()
  79  	preallocFields := make([]coderFieldInfo, fields.Len())
  80  	for i := 0; i < fields.Len(); i++ {
  81  		fd := fields.Get(i)
  82  
  83  		fs := si.fieldsByNumber[fd.Number()]
  84  		isOneof := fd.ContainingOneof() != nil && !fd.ContainingOneof().IsSynthetic()
  85  		if isOneof {
  86  			fs = si.oneofsByName[fd.ContainingOneof().Name()]
  87  		}
  88  		ft := fs.Type
  89  		var wiretag uint64
  90  		if !fd.IsPacked() {
  91  			wiretag = protowire.EncodeTag(fd.Number(), wireTypes[fd.Kind()])
  92  		} else {
  93  			wiretag = protowire.EncodeTag(fd.Number(), protowire.BytesType)
  94  		}
  95  		var fieldOffset offset
  96  		var funcs pointerCoderFuncs
  97  		var childMessage *MessageInfo
  98  		switch {
  99  		case ft == nil:
 100  			// This never occurs for generated message types.
 101  			// It implies that a hand-crafted type has missing Go fields
 102  			// for specific protobuf message fields.
 103  			funcs = pointerCoderFuncs{
 104  				size: func(p pointer, f *coderFieldInfo, opts marshalOptions) int {
 105  					return 0
 106  				},
 107  				marshal: func(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) {
 108  					return nil, nil
 109  				},
 110  				unmarshal: func(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (unmarshalOutput, error) {
 111  					panic("missing Go struct field for " + string(fd.FullName()))
 112  				},
 113  				isInit: func(p pointer, f *coderFieldInfo) error {
 114  					panic("missing Go struct field for " + string(fd.FullName()))
 115  				},
 116  				merge: func(dst, src pointer, f *coderFieldInfo, opts mergeOptions) {
 117  					panic("missing Go struct field for " + string(fd.FullName()))
 118  				},
 119  			}
 120  		case isOneof:
 121  			fieldOffset = offsetOf(fs)
 122  		default:
 123  			fieldOffset = offsetOf(fs)
 124  			childMessage, funcs = fieldCoder(fd, ft)
 125  		}
 126  		cf := &preallocFields[i]
 127  		*cf = coderFieldInfo{
 128  			num:        fd.Number(),
 129  			offset:     fieldOffset,
 130  			wiretag:    wiretag,
 131  			ft:         ft,
 132  			tagsize:    protowire.SizeVarint(wiretag),
 133  			funcs:      funcs,
 134  			mi:         childMessage,
 135  			validation: newFieldValidationInfo(mi, si, fd, ft),
 136  			isPointer:  fd.Cardinality() == protoreflect.Repeated || fd.HasPresence(),
 137  			isRequired: fd.Cardinality() == protoreflect.Required,
 138  
 139  			presenceIndex: noPresence,
 140  		}
 141  		mi.orderedCoderFields = append(mi.orderedCoderFields, cf)
 142  		mi.coderFields[cf.num] = cf
 143  	}
 144  	for i, oneofs := 0, mi.Desc.Oneofs(); i < oneofs.Len(); i++ {
 145  		if od := oneofs.Get(i); !od.IsSynthetic() {
 146  			mi.initOneofFieldCoders(od, si)
 147  		}
 148  	}
 149  	if messageset.IsMessageSet(mi.Desc) {
 150  		if !mi.extensionOffset.IsValid() {
 151  			panic(fmt.Sprintf("%v: MessageSet with no extensions field", mi.Desc.FullName()))
 152  		}
 153  		if !mi.unknownOffset.IsValid() {
 154  			panic(fmt.Sprintf("%v: MessageSet with no unknown field", mi.Desc.FullName()))
 155  		}
 156  		mi.isMessageSet = true
 157  	}
 158  	sort.Slice(mi.orderedCoderFields, func(i, j int) bool {
 159  		return mi.orderedCoderFields[i].num < mi.orderedCoderFields[j].num
 160  	})
 161  
 162  	var maxDense protoreflect.FieldNumber
 163  	for _, cf := range mi.orderedCoderFields {
 164  		if cf.num >= 16 && cf.num >= 2*maxDense {
 165  			break
 166  		}
 167  		maxDense = cf.num
 168  	}
 169  	mi.denseCoderFields = make([]*coderFieldInfo, maxDense+1)
 170  	for _, cf := range mi.orderedCoderFields {
 171  		if int(cf.num) >= len(mi.denseCoderFields) {
 172  			break
 173  		}
 174  		mi.denseCoderFields[cf.num] = cf
 175  	}
 176  
 177  	// To preserve compatibility with historic wire output, marshal oneofs last.
 178  	if mi.Desc.Oneofs().Len() > 0 {
 179  		sort.Slice(mi.orderedCoderFields, func(i, j int) bool {
 180  			fi := fields.ByNumber(mi.orderedCoderFields[i].num)
 181  			fj := fields.ByNumber(mi.orderedCoderFields[j].num)
 182  			return order.LegacyFieldOrder(fi, fj)
 183  		})
 184  	}
 185  
 186  	mi.needsInitCheck = needsInitCheck(mi.Desc)
 187  	if mi.methods.Marshal == nil && mi.methods.Size == nil {
 188  		mi.methods.Flags |= protoiface.SupportMarshalDeterministic
 189  		mi.methods.Marshal = mi.marshal
 190  		mi.methods.Size = mi.size
 191  	}
 192  	if mi.methods.Unmarshal == nil {
 193  		mi.methods.Flags |= protoiface.SupportUnmarshalDiscardUnknown
 194  		mi.methods.Unmarshal = mi.unmarshal
 195  	}
 196  	if mi.methods.CheckInitialized == nil {
 197  		mi.methods.CheckInitialized = mi.checkInitialized
 198  	}
 199  	if mi.methods.Merge == nil {
 200  		mi.methods.Merge = mi.merge
 201  	}
 202  	if mi.methods.Equal == nil {
 203  		mi.methods.Equal = equal
 204  	}
 205  }
 206  
 207  // getUnknownBytes returns a *[]byte for the unknown fields.
 208  // It is the caller's responsibility to check whether the pointer is nil.
 209  // This function is specially designed to be inlineable.
 210  func (mi *MessageInfo) getUnknownBytes(p pointer) *[]byte {
 211  	if mi.unknownPtrKind {
 212  		return *p.Apply(mi.unknownOffset).BytesPtr()
 213  	} else {
 214  		return p.Apply(mi.unknownOffset).Bytes()
 215  	}
 216  }
 217  
 218  // mutableUnknownBytes returns a *[]byte for the unknown fields.
 219  // The returned pointer is guaranteed to not be nil.
 220  func (mi *MessageInfo) mutableUnknownBytes(p pointer) *[]byte {
 221  	if mi.unknownPtrKind {
 222  		bp := p.Apply(mi.unknownOffset).BytesPtr()
 223  		if *bp == nil {
 224  			*bp = new([]byte)
 225  		}
 226  		return *bp
 227  	} else {
 228  		return p.Apply(mi.unknownOffset).Bytes()
 229  	}
 230  }
 231