codec_message.go

  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
  5package impl
  6
  7import (
  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.
 22type 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
 41type 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
 57const noPresence = 0xffffffff
 58
 59func (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.
210func (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.
220func (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}