2019-06-20 17:12:23 +00:00
|
|
|
// 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 (
|
2019-06-19 22:22:13 +00:00
|
|
|
"fmt"
|
2019-06-20 17:12:23 +00:00
|
|
|
"reflect"
|
|
|
|
"sort"
|
2019-08-13 22:36:08 +00:00
|
|
|
"sync"
|
2019-06-20 17:12:23 +00:00
|
|
|
|
2019-06-19 22:22:13 +00:00
|
|
|
"google.golang.org/protobuf/internal/encoding/messageset"
|
2019-06-20 17:12:23 +00:00
|
|
|
"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 {
|
2019-08-13 22:36:08 +00:00
|
|
|
methods piface.Methods
|
|
|
|
|
2019-06-20 17:12:23 +00:00
|
|
|
orderedCoderFields []*coderFieldInfo
|
2019-06-27 17:54:42 +00:00
|
|
|
denseCoderFields []*coderFieldInfo
|
|
|
|
coderFields map[wire.Number]*coderFieldInfo
|
2019-06-20 17:12:23 +00:00
|
|
|
sizecacheOffset offset
|
|
|
|
unknownOffset offset
|
2019-07-06 20:05:11 +00:00
|
|
|
extensionOffset offset
|
2019-06-20 17:12:23 +00:00
|
|
|
needsInitCheck bool
|
2019-08-13 22:36:08 +00:00
|
|
|
|
|
|
|
extensionFieldInfosMu sync.RWMutex
|
|
|
|
extensionFieldInfos map[pref.ExtensionType]*extensionFieldInfo
|
2019-06-20 17:12:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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
|
|
|
|
}
|
|
|
|
|
2019-08-13 22:36:08 +00:00
|
|
|
func (mi *MessageInfo) makeCoderMethods(t reflect.Type, si structInfo) {
|
2019-07-06 20:02:14 +00:00
|
|
|
mi.sizecacheOffset = si.sizecacheOffset
|
|
|
|
mi.unknownOffset = si.unknownOffset
|
|
|
|
mi.extensionOffset = si.extensionOffset
|
2019-06-20 17:12:23 +00:00
|
|
|
|
2019-06-27 17:54:42 +00:00
|
|
|
mi.coderFields = make(map[wire.Number]*coderFieldInfo)
|
2019-08-06 22:43:25 +00:00
|
|
|
fields := mi.Desc.Fields()
|
2019-08-02 23:58:08 +00:00
|
|
|
for i := 0; i < fields.Len(); i++ {
|
|
|
|
fd := fields.Get(i)
|
2019-06-20 17:12:23 +00:00
|
|
|
|
|
|
|
fs := si.fieldsByNumber[fd.Number()]
|
2019-06-27 17:54:42 +00:00
|
|
|
if fd.ContainingOneof() != nil {
|
|
|
|
fs = si.oneofsByName[fd.ContainingOneof().Name()]
|
|
|
|
}
|
2019-06-20 17:12:23 +00:00
|
|
|
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)
|
|
|
|
}
|
2019-06-27 17:54:42 +00:00
|
|
|
var funcs pointerCoderFuncs
|
|
|
|
if fd.ContainingOneof() != nil {
|
|
|
|
funcs = makeOneofFieldCoder(si, fd)
|
|
|
|
} else {
|
|
|
|
funcs = fieldCoder(fd, ft)
|
|
|
|
}
|
|
|
|
cf := &coderFieldInfo{
|
2019-06-20 17:12:23 +00:00
|
|
|
num: fd.Number(),
|
2019-07-06 20:05:11 +00:00
|
|
|
offset: offsetOf(fs, mi.Exporter),
|
2019-06-20 17:12:23 +00:00
|
|
|
wiretag: wiretag,
|
|
|
|
tagsize: wire.SizeVarint(wiretag),
|
2019-06-27 17:54:42 +00:00
|
|
|
funcs: funcs,
|
2019-06-20 17:12:23 +00:00
|
|
|
isPointer: (fd.Cardinality() == pref.Repeated ||
|
|
|
|
fd.Kind() == pref.MessageKind ||
|
|
|
|
fd.Kind() == pref.GroupKind ||
|
|
|
|
fd.Syntax() != pref.Proto3),
|
|
|
|
isRequired: fd.Cardinality() == pref.Required,
|
2019-06-27 17:54:42 +00:00
|
|
|
}
|
|
|
|
mi.orderedCoderFields = append(mi.orderedCoderFields, cf)
|
|
|
|
mi.coderFields[cf.num] = cf
|
2019-06-20 17:12:23 +00:00
|
|
|
}
|
2019-08-06 22:43:25 +00:00
|
|
|
if messageset.IsMessageSet(mi.Desc) {
|
2019-06-19 22:22:13 +00:00
|
|
|
if !mi.extensionOffset.IsValid() {
|
2019-08-06 22:43:25 +00:00
|
|
|
panic(fmt.Sprintf("%v: MessageSet with no extensions field", mi.Desc.FullName()))
|
2019-06-19 22:22:13 +00:00
|
|
|
}
|
|
|
|
cf := &coderFieldInfo{
|
|
|
|
num: messageset.FieldItem,
|
|
|
|
offset: si.extensionOffset,
|
|
|
|
isPointer: true,
|
|
|
|
funcs: makeMessageSetFieldCoder(mi),
|
|
|
|
}
|
|
|
|
mi.orderedCoderFields = append(mi.orderedCoderFields, cf)
|
|
|
|
mi.coderFields[cf.num] = cf
|
|
|
|
// Invalidate the extension offset, since the field codec handles extensions.
|
|
|
|
mi.extensionOffset = invalidOffset
|
|
|
|
}
|
2019-06-20 17:12:23 +00:00
|
|
|
sort.Slice(mi.orderedCoderFields, func(i, j int) bool {
|
|
|
|
return mi.orderedCoderFields[i].num < mi.orderedCoderFields[j].num
|
|
|
|
})
|
|
|
|
|
2019-06-27 17:54:42 +00:00
|
|
|
var maxDense pref.FieldNumber
|
|
|
|
for _, cf := range mi.orderedCoderFields {
|
|
|
|
if cf.num >= 16 && cf.num >= 2*maxDense {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
maxDense = cf.num
|
|
|
|
}
|
|
|
|
mi.denseCoderFields = make([]*coderFieldInfo, maxDense+1)
|
|
|
|
for _, cf := range mi.orderedCoderFields {
|
|
|
|
if int(cf.num) > len(mi.denseCoderFields) {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
mi.denseCoderFields[cf.num] = cf
|
|
|
|
}
|
|
|
|
|
2019-08-06 22:43:25 +00:00
|
|
|
mi.needsInitCheck = needsInitCheck(mi.Desc)
|
2019-06-20 17:12:23 +00:00
|
|
|
mi.methods = piface.Methods{
|
2019-07-12 20:37:59 +00:00
|
|
|
Flags: piface.SupportMarshalDeterministic | piface.SupportUnmarshalDiscardUnknown,
|
2019-06-20 17:12:23 +00:00
|
|
|
MarshalAppend: mi.marshalAppend,
|
2019-06-27 17:54:42 +00:00
|
|
|
Unmarshal: mi.unmarshal,
|
2019-06-20 17:12:23 +00:00
|
|
|
Size: mi.size,
|
|
|
|
IsInitialized: mi.isInitialized,
|
|
|
|
}
|
|
|
|
}
|