2735 lines
90 KiB
Go
2735 lines
90 KiB
Go
|
package dynamic
|
||
|
|
||
|
import (
|
||
|
"bytes"
|
||
|
"compress/gzip"
|
||
|
"errors"
|
||
|
"fmt"
|
||
|
"reflect"
|
||
|
"sort"
|
||
|
"strings"
|
||
|
|
||
|
"github.com/golang/protobuf/proto"
|
||
|
"github.com/golang/protobuf/protoc-gen-go/descriptor"
|
||
|
|
||
|
"github.com/jhump/protoreflect/codec"
|
||
|
"github.com/jhump/protoreflect/desc"
|
||
|
"github.com/jhump/protoreflect/internal"
|
||
|
)
|
||
|
|
||
|
// ErrUnknownTagNumber is an error that is returned when an operation refers
|
||
|
// to an unknown tag number.
|
||
|
var ErrUnknownTagNumber = errors.New("unknown tag number")
|
||
|
|
||
|
// UnknownTagNumberError is the same as ErrUnknownTagNumber.
|
||
|
// Deprecated: use ErrUnknownTagNumber
|
||
|
var UnknownTagNumberError = ErrUnknownTagNumber
|
||
|
|
||
|
// ErrUnknownFieldName is an error that is returned when an operation refers
|
||
|
// to an unknown field name.
|
||
|
var ErrUnknownFieldName = errors.New("unknown field name")
|
||
|
|
||
|
// UnknownFieldNameError is the same as ErrUnknownFieldName.
|
||
|
// Deprecated: use ErrUnknownFieldName
|
||
|
var UnknownFieldNameError = ErrUnknownFieldName
|
||
|
|
||
|
// ErrFieldIsNotMap is an error that is returned when map-related operations
|
||
|
// are attempted with fields that are not maps.
|
||
|
var ErrFieldIsNotMap = errors.New("field is not a map type")
|
||
|
|
||
|
// FieldIsNotMapError is the same as ErrFieldIsNotMap.
|
||
|
// Deprecated: use ErrFieldIsNotMap
|
||
|
var FieldIsNotMapError = ErrFieldIsNotMap
|
||
|
|
||
|
// ErrFieldIsNotRepeated is an error that is returned when repeated field
|
||
|
// operations are attempted with fields that are not repeated.
|
||
|
var ErrFieldIsNotRepeated = errors.New("field is not repeated")
|
||
|
|
||
|
// FieldIsNotRepeatedError is the same as ErrFieldIsNotRepeated.
|
||
|
// Deprecated: use ErrFieldIsNotRepeated
|
||
|
var FieldIsNotRepeatedError = ErrFieldIsNotRepeated
|
||
|
|
||
|
// ErrIndexOutOfRange is an error that is returned when an invalid index is
|
||
|
// provided when access a single element of a repeated field.
|
||
|
var ErrIndexOutOfRange = errors.New("index is out of range")
|
||
|
|
||
|
// IndexOutOfRangeError is the same as ErrIndexOutOfRange.
|
||
|
// Deprecated: use ErrIndexOutOfRange
|
||
|
var IndexOutOfRangeError = ErrIndexOutOfRange
|
||
|
|
||
|
// ErrNumericOverflow is an error returned by operations that encounter a
|
||
|
// numeric value that is too large, for example de-serializing a value into an
|
||
|
// int32 field when the value is larger that can fit into a 32-bit value.
|
||
|
var ErrNumericOverflow = errors.New("numeric value is out of range")
|
||
|
|
||
|
// NumericOverflowError is the same as ErrNumericOverflow.
|
||
|
// Deprecated: use ErrNumericOverflow
|
||
|
var NumericOverflowError = ErrNumericOverflow
|
||
|
|
||
|
var typeOfProtoMessage = reflect.TypeOf((*proto.Message)(nil)).Elem()
|
||
|
var typeOfDynamicMessage = reflect.TypeOf((*Message)(nil))
|
||
|
var typeOfBytes = reflect.TypeOf(([]byte)(nil))
|
||
|
|
||
|
// Message is a dynamic protobuf message. Instead of a generated struct,
|
||
|
// like most protobuf messages, this is a map of field number to values and
|
||
|
// a message descriptor, which is used to validate the field values and
|
||
|
// also to de-serialize messages (from the standard binary format, as well
|
||
|
// as from the text format and from JSON).
|
||
|
type Message struct {
|
||
|
md *desc.MessageDescriptor
|
||
|
er *ExtensionRegistry
|
||
|
mf *MessageFactory
|
||
|
extraFields map[int32]*desc.FieldDescriptor
|
||
|
values map[int32]interface{}
|
||
|
unknownFields map[int32][]UnknownField
|
||
|
}
|
||
|
|
||
|
// UnknownField represents a field that was parsed from the binary wire
|
||
|
// format for a message, but was not a recognized field number. Enough
|
||
|
// information is preserved so that re-serializing the message won't lose
|
||
|
// any of the unrecognized data.
|
||
|
type UnknownField struct {
|
||
|
// Encoding indicates how the unknown field was encoded on the wire. If it
|
||
|
// is proto.WireBytes or proto.WireGroupStart then Contents will be set to
|
||
|
// the raw bytes. If it is proto.WireTypeFixed32 then the data is in the least
|
||
|
// significant 32 bits of Value. Otherwise, the data is in all 64 bits of
|
||
|
// Value.
|
||
|
Encoding int8
|
||
|
Contents []byte
|
||
|
Value uint64
|
||
|
}
|
||
|
|
||
|
// NewMessage creates a new dynamic message for the type represented by the given
|
||
|
// message descriptor. During de-serialization, a default MessageFactory is used to
|
||
|
// instantiate any nested message fields and no extension fields will be parsed. To
|
||
|
// use a custom MessageFactory or ExtensionRegistry, use MessageFactory.NewMessage.
|
||
|
func NewMessage(md *desc.MessageDescriptor) *Message {
|
||
|
return NewMessageWithMessageFactory(md, nil)
|
||
|
}
|
||
|
|
||
|
// NewMessageWithExtensionRegistry creates a new dynamic message for the type
|
||
|
// represented by the given message descriptor. During de-serialization, the given
|
||
|
// ExtensionRegistry is used to parse extension fields and nested messages will be
|
||
|
// instantiated using dynamic.NewMessageFactoryWithExtensionRegistry(er).
|
||
|
func NewMessageWithExtensionRegistry(md *desc.MessageDescriptor, er *ExtensionRegistry) *Message {
|
||
|
mf := NewMessageFactoryWithExtensionRegistry(er)
|
||
|
return NewMessageWithMessageFactory(md, mf)
|
||
|
}
|
||
|
|
||
|
// NewMessageWithMessageFactory creates a new dynamic message for the type
|
||
|
// represented by the given message descriptor. During de-serialization, the given
|
||
|
// MessageFactory is used to instantiate nested messages.
|
||
|
func NewMessageWithMessageFactory(md *desc.MessageDescriptor, mf *MessageFactory) *Message {
|
||
|
var er *ExtensionRegistry
|
||
|
if mf != nil {
|
||
|
er = mf.er
|
||
|
}
|
||
|
return &Message{
|
||
|
md: md,
|
||
|
mf: mf,
|
||
|
er: er,
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// AsDynamicMessage converts the given message to a dynamic message. If the
|
||
|
// given message is dynamic, it is returned. Otherwise, a dynamic message is
|
||
|
// created using NewMessage.
|
||
|
func AsDynamicMessage(msg proto.Message) (*Message, error) {
|
||
|
return AsDynamicMessageWithMessageFactory(msg, nil)
|
||
|
}
|
||
|
|
||
|
// AsDynamicMessageWithExtensionRegistry converts the given message to a dynamic
|
||
|
// message. If the given message is dynamic, it is returned. Otherwise, a
|
||
|
// dynamic message is created using NewMessageWithExtensionRegistry.
|
||
|
func AsDynamicMessageWithExtensionRegistry(msg proto.Message, er *ExtensionRegistry) (*Message, error) {
|
||
|
mf := NewMessageFactoryWithExtensionRegistry(er)
|
||
|
return AsDynamicMessageWithMessageFactory(msg, mf)
|
||
|
}
|
||
|
|
||
|
// AsDynamicMessageWithMessageFactory converts the given message to a dynamic
|
||
|
// message. If the given message is dynamic, it is returned. Otherwise, a
|
||
|
// dynamic message is created using NewMessageWithMessageFactory.
|
||
|
func AsDynamicMessageWithMessageFactory(msg proto.Message, mf *MessageFactory) (*Message, error) {
|
||
|
if dm, ok := msg.(*Message); ok {
|
||
|
return dm, nil
|
||
|
}
|
||
|
md, err := desc.LoadMessageDescriptorForMessage(msg)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
dm := NewMessageWithMessageFactory(md, mf)
|
||
|
err = dm.mergeFrom(msg)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
return dm, nil
|
||
|
}
|
||
|
|
||
|
// GetMessageDescriptor returns a descriptor for this message's type.
|
||
|
func (m *Message) GetMessageDescriptor() *desc.MessageDescriptor {
|
||
|
return m.md
|
||
|
}
|
||
|
|
||
|
// GetKnownFields returns a slice of descriptors for all known fields. The
|
||
|
// fields will not be in any defined order.
|
||
|
func (m *Message) GetKnownFields() []*desc.FieldDescriptor {
|
||
|
if len(m.extraFields) == 0 {
|
||
|
return m.md.GetFields()
|
||
|
}
|
||
|
flds := make([]*desc.FieldDescriptor, len(m.md.GetFields()), len(m.md.GetFields())+len(m.extraFields))
|
||
|
copy(flds, m.md.GetFields())
|
||
|
for _, fld := range m.extraFields {
|
||
|
if !fld.IsExtension() {
|
||
|
flds = append(flds, fld)
|
||
|
}
|
||
|
}
|
||
|
return flds
|
||
|
}
|
||
|
|
||
|
// GetKnownExtensions returns a slice of descriptors for all extensions known by
|
||
|
// the message's extension registry. The fields will not be in any defined order.
|
||
|
func (m *Message) GetKnownExtensions() []*desc.FieldDescriptor {
|
||
|
if !m.md.IsExtendable() {
|
||
|
return nil
|
||
|
}
|
||
|
exts := m.er.AllExtensionsForType(m.md.GetFullyQualifiedName())
|
||
|
for _, fld := range m.extraFields {
|
||
|
if fld.IsExtension() {
|
||
|
exts = append(exts, fld)
|
||
|
}
|
||
|
}
|
||
|
return exts
|
||
|
}
|
||
|
|
||
|
// GetUnknownFields returns a slice of tag numbers for all unknown fields that
|
||
|
// this message contains. The tags will not be in any defined order.
|
||
|
func (m *Message) GetUnknownFields() []int32 {
|
||
|
flds := make([]int32, 0, len(m.unknownFields))
|
||
|
for tag := range m.unknownFields {
|
||
|
flds = append(flds, tag)
|
||
|
}
|
||
|
return flds
|
||
|
}
|
||
|
|
||
|
// Descriptor returns the serialized form of the file descriptor in which the
|
||
|
// message was defined and a path to the message type therein. This mimics the
|
||
|
// method of the same name on message types generated by protoc.
|
||
|
func (m *Message) Descriptor() ([]byte, []int) {
|
||
|
// get encoded file descriptor
|
||
|
b, err := proto.Marshal(m.md.GetFile().AsProto())
|
||
|
if err != nil {
|
||
|
panic(fmt.Sprintf("failed to get encoded descriptor for %s: %v", m.md.GetFile().GetName(), err))
|
||
|
}
|
||
|
var zippedBytes bytes.Buffer
|
||
|
w := gzip.NewWriter(&zippedBytes)
|
||
|
if _, err := w.Write(b); err != nil {
|
||
|
panic(fmt.Sprintf("failed to get encoded descriptor for %s: %v", m.md.GetFile().GetName(), err))
|
||
|
}
|
||
|
if err := w.Close(); err != nil {
|
||
|
panic(fmt.Sprintf("failed to get an encoded descriptor for %s: %v", m.md.GetFile().GetName(), err))
|
||
|
}
|
||
|
|
||
|
// and path to message
|
||
|
path := []int{}
|
||
|
var d desc.Descriptor
|
||
|
name := m.md.GetFullyQualifiedName()
|
||
|
for d = m.md.GetParent(); d != nil; name, d = d.GetFullyQualifiedName(), d.GetParent() {
|
||
|
found := false
|
||
|
switch d := d.(type) {
|
||
|
case (*desc.FileDescriptor):
|
||
|
for i, md := range d.GetMessageTypes() {
|
||
|
if md.GetFullyQualifiedName() == name {
|
||
|
found = true
|
||
|
path = append(path, i)
|
||
|
}
|
||
|
}
|
||
|
case (*desc.MessageDescriptor):
|
||
|
for i, md := range d.GetNestedMessageTypes() {
|
||
|
if md.GetFullyQualifiedName() == name {
|
||
|
found = true
|
||
|
path = append(path, i)
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
if !found {
|
||
|
panic(fmt.Sprintf("failed to compute descriptor path for %s", m.md.GetFullyQualifiedName()))
|
||
|
}
|
||
|
}
|
||
|
// reverse the path
|
||
|
i := 0
|
||
|
j := len(path) - 1
|
||
|
for i < j {
|
||
|
path[i], path[j] = path[j], path[i]
|
||
|
i++
|
||
|
j--
|
||
|
}
|
||
|
|
||
|
return zippedBytes.Bytes(), path
|
||
|
}
|
||
|
|
||
|
// XXX_MessageName returns the fully qualified name of this message's type. This
|
||
|
// allows dynamic messages to be used with proto.MessageName.
|
||
|
func (m *Message) XXX_MessageName() string {
|
||
|
return m.md.GetFullyQualifiedName()
|
||
|
}
|
||
|
|
||
|
// FindFieldDescriptor returns a field descriptor for the given tag number. This
|
||
|
// searches known fields in the descriptor, known fields discovered during calls
|
||
|
// to GetField or SetField, and extension fields known by the message's extension
|
||
|
// registry. It returns nil if the tag is unknown.
|
||
|
func (m *Message) FindFieldDescriptor(tagNumber int32) *desc.FieldDescriptor {
|
||
|
fd := m.md.FindFieldByNumber(tagNumber)
|
||
|
if fd != nil {
|
||
|
return fd
|
||
|
}
|
||
|
fd = m.er.FindExtension(m.md.GetFullyQualifiedName(), tagNumber)
|
||
|
if fd != nil {
|
||
|
return fd
|
||
|
}
|
||
|
return m.extraFields[tagNumber]
|
||
|
}
|
||
|
|
||
|
// FindFieldDescriptorByName returns a field descriptor for the given field
|
||
|
// name. This searches known fields in the descriptor, known fields discovered
|
||
|
// during calls to GetField or SetField, and extension fields known by the
|
||
|
// message's extension registry. It returns nil if the name is unknown. If the
|
||
|
// given name refers to an extension, it should be fully qualified and may be
|
||
|
// optionally enclosed in parentheses or brackets.
|
||
|
func (m *Message) FindFieldDescriptorByName(name string) *desc.FieldDescriptor {
|
||
|
if name == "" {
|
||
|
return nil
|
||
|
}
|
||
|
fd := m.md.FindFieldByName(name)
|
||
|
if fd != nil {
|
||
|
return fd
|
||
|
}
|
||
|
mustBeExt := false
|
||
|
if name[0] == '(' {
|
||
|
if name[len(name)-1] != ')' {
|
||
|
// malformed name
|
||
|
return nil
|
||
|
}
|
||
|
mustBeExt = true
|
||
|
name = name[1 : len(name)-1]
|
||
|
} else if name[0] == '[' {
|
||
|
if name[len(name)-1] != ']' {
|
||
|
// malformed name
|
||
|
return nil
|
||
|
}
|
||
|
mustBeExt = true
|
||
|
name = name[1 : len(name)-1]
|
||
|
}
|
||
|
fd = m.er.FindExtensionByName(m.md.GetFullyQualifiedName(), name)
|
||
|
if fd != nil {
|
||
|
return fd
|
||
|
}
|
||
|
for _, fd := range m.extraFields {
|
||
|
if fd.IsExtension() && name == fd.GetFullyQualifiedName() {
|
||
|
return fd
|
||
|
} else if !mustBeExt && !fd.IsExtension() && name == fd.GetName() {
|
||
|
return fd
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
// FindFieldDescriptorByJSONName returns a field descriptor for the given JSON
|
||
|
// name. This searches known fields in the descriptor, known fields discovered
|
||
|
// during calls to GetField or SetField, and extension fields known by the
|
||
|
// message's extension registry. If no field matches the given JSON name, it
|
||
|
// will fall back to searching field names (e.g. FindFieldDescriptorByName). If
|
||
|
// this also yields no match, nil is returned.
|
||
|
func (m *Message) FindFieldDescriptorByJSONName(name string) *desc.FieldDescriptor {
|
||
|
if name == "" {
|
||
|
return nil
|
||
|
}
|
||
|
fd := m.md.FindFieldByJSONName(name)
|
||
|
if fd != nil {
|
||
|
return fd
|
||
|
}
|
||
|
mustBeExt := false
|
||
|
if name[0] == '(' {
|
||
|
if name[len(name)-1] != ')' {
|
||
|
// malformed name
|
||
|
return nil
|
||
|
}
|
||
|
mustBeExt = true
|
||
|
name = name[1 : len(name)-1]
|
||
|
} else if name[0] == '[' {
|
||
|
if name[len(name)-1] != ']' {
|
||
|
// malformed name
|
||
|
return nil
|
||
|
}
|
||
|
mustBeExt = true
|
||
|
name = name[1 : len(name)-1]
|
||
|
}
|
||
|
fd = m.er.FindExtensionByJSONName(m.md.GetFullyQualifiedName(), name)
|
||
|
if fd != nil {
|
||
|
return fd
|
||
|
}
|
||
|
for _, fd := range m.extraFields {
|
||
|
if fd.IsExtension() && name == fd.GetFullyQualifiedJSONName() {
|
||
|
return fd
|
||
|
} else if !mustBeExt && !fd.IsExtension() && name == fd.GetJSONName() {
|
||
|
return fd
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// try non-JSON names
|
||
|
return m.FindFieldDescriptorByName(name)
|
||
|
}
|
||
|
|
||
|
func (m *Message) checkField(fd *desc.FieldDescriptor) error {
|
||
|
return checkField(fd, m.md)
|
||
|
}
|
||
|
|
||
|
func checkField(fd *desc.FieldDescriptor, md *desc.MessageDescriptor) error {
|
||
|
if fd.GetOwner().GetFullyQualifiedName() != md.GetFullyQualifiedName() {
|
||
|
return fmt.Errorf("given field, %s, is for wrong message type: %s; expecting %s", fd.GetName(), fd.GetOwner().GetFullyQualifiedName(), md.GetFullyQualifiedName())
|
||
|
}
|
||
|
if fd.IsExtension() && !md.IsExtension(fd.GetNumber()) {
|
||
|
return fmt.Errorf("given field, %s, is an extension but is not in message extension range: %v", fd.GetFullyQualifiedName(), md.GetExtensionRanges())
|
||
|
}
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
// GetField returns the value for the given field descriptor. It panics if an
|
||
|
// error is encountered. See TryGetField.
|
||
|
func (m *Message) GetField(fd *desc.FieldDescriptor) interface{} {
|
||
|
if v, err := m.TryGetField(fd); err != nil {
|
||
|
panic(err.Error())
|
||
|
} else {
|
||
|
return v
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// TryGetField returns the value for the given field descriptor. An error is
|
||
|
// returned if the given field descriptor does not belong to the right message
|
||
|
// type.
|
||
|
//
|
||
|
// The Go type of the returned value, for scalar fields, is the same as protoc
|
||
|
// would generate for the field (in a non-dynamic message). The table below
|
||
|
// lists the scalar types and the corresponding Go types.
|
||
|
// +-------------------------+-----------+
|
||
|
// | Declared Type | Go Type |
|
||
|
// +-------------------------+-----------+
|
||
|
// | int32, sint32, sfixed32 | int32 |
|
||
|
// | int64, sint64, sfixed64 | int64 |
|
||
|
// | uint32, fixed32 | uint32 |
|
||
|
// | uint64, fixed64 | uint64 |
|
||
|
// | float | float32 |
|
||
|
// | double | double32 |
|
||
|
// | bool | bool |
|
||
|
// | string | string |
|
||
|
// | bytes | []byte |
|
||
|
// +-------------------------+-----------+
|
||
|
//
|
||
|
// Values for enum fields will always be int32 values. You can use the enum
|
||
|
// descriptor associated with the field to lookup value names with those values.
|
||
|
// Values for message type fields may be an instance of the generated type *or*
|
||
|
// may be another *dynamic.Message that represents the type.
|
||
|
//
|
||
|
// If the given field is a map field, the returned type will be
|
||
|
// map[interface{}]interface{}. The actual concrete types of keys and values is
|
||
|
// as described above. If the given field is a (non-map) repeated field, the
|
||
|
// returned type is always []interface{}; the type of the actual elements is as
|
||
|
// described above.
|
||
|
//
|
||
|
// If this message has no value for the given field, its default value is
|
||
|
// returned. If the message is defined in a file with "proto3" syntax, the
|
||
|
// default is always the zero value for the field. The default value for map and
|
||
|
// repeated fields is a nil map or slice (respectively). For field's whose types
|
||
|
// is a message, the default value is an empty message for "proto2" syntax or a
|
||
|
// nil message for "proto3" syntax. Note that the in the latter case, a non-nil
|
||
|
// interface with a nil pointer is returned, not a nil interface. Also note that
|
||
|
// whether the returned value is an empty message or nil depends on if *this*
|
||
|
// message was defined as "proto3" syntax, not the message type referred to by
|
||
|
// the field's type.
|
||
|
//
|
||
|
// If the given field descriptor is not known (e.g. not present in the message
|
||
|
// descriptor) but corresponds to an unknown field, the unknown value will be
|
||
|
// parsed and become known. The parsed value will be returned, or an error will
|
||
|
// be returned if the unknown value cannot be parsed according to the field
|
||
|
// descriptor's type information.
|
||
|
func (m *Message) TryGetField(fd *desc.FieldDescriptor) (interface{}, error) {
|
||
|
if err := m.checkField(fd); err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
return m.getField(fd)
|
||
|
}
|
||
|
|
||
|
// GetFieldByName returns the value for the field with the given name. It panics
|
||
|
// if an error is encountered. See TryGetFieldByName.
|
||
|
func (m *Message) GetFieldByName(name string) interface{} {
|
||
|
if v, err := m.TryGetFieldByName(name); err != nil {
|
||
|
panic(err.Error())
|
||
|
} else {
|
||
|
return v
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// TryGetFieldByName returns the value for the field with the given name. An
|
||
|
// error is returned if the given name is unknown. If the given name refers to
|
||
|
// an extension field, it should be fully qualified and optionally enclosed in
|
||
|
// parenthesis or brackets.
|
||
|
//
|
||
|
// If this message has no value for the given field, its default value is
|
||
|
// returned. (See TryGetField for more info on types and default field values.)
|
||
|
func (m *Message) TryGetFieldByName(name string) (interface{}, error) {
|
||
|
fd := m.FindFieldDescriptorByName(name)
|
||
|
if fd == nil {
|
||
|
return nil, UnknownFieldNameError
|
||
|
}
|
||
|
return m.getField(fd)
|
||
|
}
|
||
|
|
||
|
// GetFieldByNumber returns the value for the field with the given tag number.
|
||
|
// It panics if an error is encountered. See TryGetFieldByNumber.
|
||
|
func (m *Message) GetFieldByNumber(tagNumber int) interface{} {
|
||
|
if v, err := m.TryGetFieldByNumber(tagNumber); err != nil {
|
||
|
panic(err.Error())
|
||
|
} else {
|
||
|
return v
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// TryGetFieldByNumber returns the value for the field with the given tag
|
||
|
// number. An error is returned if the given tag is unknown.
|
||
|
//
|
||
|
// If this message has no value for the given field, its default value is
|
||
|
// returned. (See TryGetField for more info on types and default field values.)
|
||
|
func (m *Message) TryGetFieldByNumber(tagNumber int) (interface{}, error) {
|
||
|
fd := m.FindFieldDescriptor(int32(tagNumber))
|
||
|
if fd == nil {
|
||
|
return nil, UnknownTagNumberError
|
||
|
}
|
||
|
return m.getField(fd)
|
||
|
}
|
||
|
|
||
|
func (m *Message) getField(fd *desc.FieldDescriptor) (interface{}, error) {
|
||
|
return m.doGetField(fd, false)
|
||
|
}
|
||
|
|
||
|
func (m *Message) doGetField(fd *desc.FieldDescriptor, nilIfAbsent bool) (interface{}, error) {
|
||
|
res := m.values[fd.GetNumber()]
|
||
|
if res == nil {
|
||
|
var err error
|
||
|
if res, err = m.parseUnknownField(fd); err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
if res == nil {
|
||
|
if nilIfAbsent {
|
||
|
return nil, nil
|
||
|
} else {
|
||
|
def := fd.GetDefaultValue()
|
||
|
if def != nil {
|
||
|
return def, nil
|
||
|
}
|
||
|
// GetDefaultValue only returns nil for message types
|
||
|
md := fd.GetMessageType()
|
||
|
if m.md.IsProto3() {
|
||
|
return nilMessage(md), nil
|
||
|
} else {
|
||
|
// for proto2, return default instance of message
|
||
|
return m.mf.NewMessage(md), nil
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
rt := reflect.TypeOf(res)
|
||
|
if rt.Kind() == reflect.Map {
|
||
|
// make defensive copies to prevent caller from storing illegal keys and values
|
||
|
m := res.(map[interface{}]interface{})
|
||
|
res := map[interface{}]interface{}{}
|
||
|
for k, v := range m {
|
||
|
res[k] = v
|
||
|
}
|
||
|
return res, nil
|
||
|
} else if rt.Kind() == reflect.Slice && rt != typeOfBytes {
|
||
|
// make defensive copies to prevent caller from storing illegal elements
|
||
|
sl := res.([]interface{})
|
||
|
res := make([]interface{}, len(sl))
|
||
|
copy(res, sl)
|
||
|
return res, nil
|
||
|
}
|
||
|
return res, nil
|
||
|
}
|
||
|
|
||
|
func nilMessage(md *desc.MessageDescriptor) interface{} {
|
||
|
// try to return a proper nil pointer
|
||
|
msgType := proto.MessageType(md.GetFullyQualifiedName())
|
||
|
if msgType != nil && msgType.Implements(typeOfProtoMessage) {
|
||
|
return reflect.Zero(msgType).Interface().(proto.Message)
|
||
|
}
|
||
|
// fallback to nil dynamic message pointer
|
||
|
return (*Message)(nil)
|
||
|
}
|
||
|
|
||
|
// HasField returns true if this message has a value for the given field. If the
|
||
|
// given field is not valid (e.g. belongs to a different message type), false is
|
||
|
// returned. If this message is defined in a file with "proto3" syntax, this
|
||
|
// will return false even if a field was explicitly assigned its zero value (the
|
||
|
// zero values for a field are intentionally indistinguishable from absent).
|
||
|
func (m *Message) HasField(fd *desc.FieldDescriptor) bool {
|
||
|
if err := m.checkField(fd); err != nil {
|
||
|
return false
|
||
|
}
|
||
|
return m.HasFieldNumber(int(fd.GetNumber()))
|
||
|
}
|
||
|
|
||
|
// HasFieldName returns true if this message has a value for a field with the
|
||
|
// given name. If the given name is unknown, this returns false.
|
||
|
func (m *Message) HasFieldName(name string) bool {
|
||
|
fd := m.FindFieldDescriptorByName(name)
|
||
|
if fd == nil {
|
||
|
return false
|
||
|
}
|
||
|
return m.HasFieldNumber(int(fd.GetNumber()))
|
||
|
}
|
||
|
|
||
|
// HasFieldNumber returns true if this message has a value for a field with the
|
||
|
// given tag number. If the given tag is unknown, this returns false.
|
||
|
func (m *Message) HasFieldNumber(tagNumber int) bool {
|
||
|
if _, ok := m.values[int32(tagNumber)]; ok {
|
||
|
return true
|
||
|
}
|
||
|
_, ok := m.unknownFields[int32(tagNumber)]
|
||
|
return ok
|
||
|
}
|
||
|
|
||
|
// SetField sets the value for the given field descriptor to the given value. It
|
||
|
// panics if an error is encountered. See TrySetField.
|
||
|
func (m *Message) SetField(fd *desc.FieldDescriptor, val interface{}) {
|
||
|
if err := m.TrySetField(fd, val); err != nil {
|
||
|
panic(err.Error())
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// TrySetField sets the value for the given field descriptor to the given value.
|
||
|
// An error is returned if the given field descriptor does not belong to the
|
||
|
// right message type or if the given value is not a correct/compatible type for
|
||
|
// the given field.
|
||
|
//
|
||
|
// The Go type expected for a field is the same as TryGetField would return for
|
||
|
// the field. So message values can be supplied as either the correct generated
|
||
|
// message type or as a *dynamic.Message.
|
||
|
//
|
||
|
// Since it is cumbersome to work with dynamic messages, some concessions are
|
||
|
// made to simplify usage regarding types:
|
||
|
//
|
||
|
// 1. If a numeric type is provided that can be converted *without loss or
|
||
|
// overflow*, it is accepted. This allows for setting int64 fields using int
|
||
|
// or int32 values. Similarly for uint64 with uint and uint32 values and for
|
||
|
// float64 fields with float32 values.
|
||
|
// 2. The value can be a named type, as long as its underlying type is correct.
|
||
|
// 3. Map and repeated fields can be set using any kind of concrete map or
|
||
|
// slice type, as long as the values within are all of the correct type. So
|
||
|
// a field defined as a 'map<string, int32>` can be set using a
|
||
|
// map[string]int32, a map[string]interface{}, or even a
|
||
|
// map[interface{}]interface{}.
|
||
|
// 4. Finally, dynamic code that chooses to not treat maps as a special-case
|
||
|
// find that they can set map fields using a slice where each element is a
|
||
|
// message that matches the implicit map-entry field message type.
|
||
|
//
|
||
|
// If the given field descriptor is not known (e.g. not present in the message
|
||
|
// descriptor) it will become known. Subsequent operations using tag numbers or
|
||
|
// names will be able to resolve the newly-known type. If the message has a
|
||
|
// value for the unknown value, it is cleared, replaced by the given known
|
||
|
// value.
|
||
|
func (m *Message) TrySetField(fd *desc.FieldDescriptor, val interface{}) error {
|
||
|
if err := m.checkField(fd); err != nil {
|
||
|
return err
|
||
|
}
|
||
|
return m.setField(fd, val)
|
||
|
}
|
||
|
|
||
|
// SetFieldByName sets the value for the field with the given name to the given
|
||
|
// value. It panics if an error is encountered. See TrySetFieldByName.
|
||
|
func (m *Message) SetFieldByName(name string, val interface{}) {
|
||
|
if err := m.TrySetFieldByName(name, val); err != nil {
|
||
|
panic(err.Error())
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// TrySetFieldByName sets the value for the field with the given name to the
|
||
|
// given value. An error is returned if the given name is unknown or if the
|
||
|
// given value has an incorrect type. If the given name refers to an extension
|
||
|
// field, it should be fully qualified and optionally enclosed in parenthesis or
|
||
|
// brackets.
|
||
|
//
|
||
|
// (See TrySetField for more info on types.)
|
||
|
func (m *Message) TrySetFieldByName(name string, val interface{}) error {
|
||
|
fd := m.FindFieldDescriptorByName(name)
|
||
|
if fd == nil {
|
||
|
return UnknownFieldNameError
|
||
|
}
|
||
|
return m.setField(fd, val)
|
||
|
}
|
||
|
|
||
|
// SetFieldByNumber sets the value for the field with the given tag number to
|
||
|
// the given value. It panics if an error is encountered. See
|
||
|
// TrySetFieldByNumber.
|
||
|
func (m *Message) SetFieldByNumber(tagNumber int, val interface{}) {
|
||
|
if err := m.TrySetFieldByNumber(tagNumber, val); err != nil {
|
||
|
panic(err.Error())
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// TrySetFieldByNumber sets the value for the field with the given tag number to
|
||
|
// the given value. An error is returned if the given tag is unknown or if the
|
||
|
// given value has an incorrect type.
|
||
|
//
|
||
|
// (See TrySetField for more info on types.)
|
||
|
func (m *Message) TrySetFieldByNumber(tagNumber int, val interface{}) error {
|
||
|
fd := m.FindFieldDescriptor(int32(tagNumber))
|
||
|
if fd == nil {
|
||
|
return UnknownTagNumberError
|
||
|
}
|
||
|
return m.setField(fd, val)
|
||
|
}
|
||
|
|
||
|
func (m *Message) setField(fd *desc.FieldDescriptor, val interface{}) error {
|
||
|
var err error
|
||
|
if val, err = validFieldValue(fd, val); err != nil {
|
||
|
return err
|
||
|
}
|
||
|
m.internalSetField(fd, val)
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
func (m *Message) internalSetField(fd *desc.FieldDescriptor, val interface{}) {
|
||
|
if fd.IsRepeated() {
|
||
|
// Unset fields and zero-length fields are indistinguishable, in both
|
||
|
// proto2 and proto3 syntax
|
||
|
if reflect.ValueOf(val).Len() == 0 {
|
||
|
if m.values != nil {
|
||
|
delete(m.values, fd.GetNumber())
|
||
|
}
|
||
|
return
|
||
|
}
|
||
|
} else if m.md.IsProto3() && fd.GetOneOf() == nil {
|
||
|
// proto3 considers fields that are set to their zero value as unset
|
||
|
// (we already handled repeated fields above)
|
||
|
var equal bool
|
||
|
if b, ok := val.([]byte); ok {
|
||
|
// can't compare slices, so we have to special-case []byte values
|
||
|
equal = ok && bytes.Equal(b, fd.GetDefaultValue().([]byte))
|
||
|
} else {
|
||
|
defVal := fd.GetDefaultValue()
|
||
|
equal = defVal == val
|
||
|
if !equal && defVal == nil {
|
||
|
// above just checks if value is the nil interface,
|
||
|
// but we should also test if the given value is a
|
||
|
// nil pointer
|
||
|
rv := reflect.ValueOf(val)
|
||
|
if rv.Kind() == reflect.Ptr && rv.IsNil() {
|
||
|
equal = true
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
if equal {
|
||
|
if m.values != nil {
|
||
|
delete(m.values, fd.GetNumber())
|
||
|
}
|
||
|
return
|
||
|
}
|
||
|
}
|
||
|
if m.values == nil {
|
||
|
m.values = map[int32]interface{}{}
|
||
|
}
|
||
|
m.values[fd.GetNumber()] = val
|
||
|
// if this field is part of a one-of, make sure all other one-of choices are cleared
|
||
|
od := fd.GetOneOf()
|
||
|
if od != nil {
|
||
|
for _, other := range od.GetChoices() {
|
||
|
if other.GetNumber() != fd.GetNumber() {
|
||
|
delete(m.values, other.GetNumber())
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
// also clear any unknown fields
|
||
|
if m.unknownFields != nil {
|
||
|
delete(m.unknownFields, fd.GetNumber())
|
||
|
}
|
||
|
// and add this field if it was previously unknown
|
||
|
if existing := m.FindFieldDescriptor(fd.GetNumber()); existing == nil {
|
||
|
m.addField(fd)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func (m *Message) addField(fd *desc.FieldDescriptor) {
|
||
|
if m.extraFields == nil {
|
||
|
m.extraFields = map[int32]*desc.FieldDescriptor{}
|
||
|
}
|
||
|
m.extraFields[fd.GetNumber()] = fd
|
||
|
}
|
||
|
|
||
|
// ClearField removes any value for the given field. It panics if an error is
|
||
|
// encountered. See TryClearField.
|
||
|
func (m *Message) ClearField(fd *desc.FieldDescriptor) {
|
||
|
if err := m.TryClearField(fd); err != nil {
|
||
|
panic(err.Error())
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// TryClearField removes any value for the given field. An error is returned if
|
||
|
// the given field descriptor does not belong to the right message type.
|
||
|
func (m *Message) TryClearField(fd *desc.FieldDescriptor) error {
|
||
|
if err := m.checkField(fd); err != nil {
|
||
|
return err
|
||
|
}
|
||
|
m.clearField(fd)
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
// ClearFieldByName removes any value for the field with the given name. It
|
||
|
// panics if an error is encountered. See TryClearFieldByName.
|
||
|
func (m *Message) ClearFieldByName(name string) {
|
||
|
if err := m.TryClearFieldByName(name); err != nil {
|
||
|
panic(err.Error())
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// TryClearFieldByName removes any value for the field with the given name. An
|
||
|
// error is returned if the given name is unknown. If the given name refers to
|
||
|
// an extension field, it should be fully qualified and optionally enclosed in
|
||
|
// parenthesis or brackets.
|
||
|
func (m *Message) TryClearFieldByName(name string) error {
|
||
|
fd := m.FindFieldDescriptorByName(name)
|
||
|
if fd == nil {
|
||
|
return UnknownFieldNameError
|
||
|
}
|
||
|
m.clearField(fd)
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
// ClearFieldByNumber removes any value for the field with the given tag number.
|
||
|
// It panics if an error is encountered. See TryClearFieldByNumber.
|
||
|
func (m *Message) ClearFieldByNumber(tagNumber int) {
|
||
|
if err := m.TryClearFieldByNumber(tagNumber); err != nil {
|
||
|
panic(err.Error())
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// TryClearFieldByNumber removes any value for the field with the given tag
|
||
|
// number. An error is returned if the given tag is unknown.
|
||
|
func (m *Message) TryClearFieldByNumber(tagNumber int) error {
|
||
|
fd := m.FindFieldDescriptor(int32(tagNumber))
|
||
|
if fd == nil {
|
||
|
return UnknownTagNumberError
|
||
|
}
|
||
|
m.clearField(fd)
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
func (m *Message) clearField(fd *desc.FieldDescriptor) {
|
||
|
// clear value
|
||
|
if m.values != nil {
|
||
|
delete(m.values, fd.GetNumber())
|
||
|
}
|
||
|
// also clear any unknown fields
|
||
|
if m.unknownFields != nil {
|
||
|
delete(m.unknownFields, fd.GetNumber())
|
||
|
}
|
||
|
// and add this field if it was previously unknown
|
||
|
if existing := m.FindFieldDescriptor(fd.GetNumber()); existing == nil {
|
||
|
m.addField(fd)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// GetOneOfField returns which of the given one-of's fields is set and the
|
||
|
// corresponding value. It panics if an error is encountered. See
|
||
|
// TryGetOneOfField.
|
||
|
func (m *Message) GetOneOfField(od *desc.OneOfDescriptor) (*desc.FieldDescriptor, interface{}) {
|
||
|
if fd, val, err := m.TryGetOneOfField(od); err != nil {
|
||
|
panic(err.Error())
|
||
|
} else {
|
||
|
return fd, val
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// TryGetOneOfField returns which of the given one-of's fields is set and the
|
||
|
// corresponding value. An error is returned if the given one-of belongs to the
|
||
|
// wrong message type. If the given one-of has no field set, this method will
|
||
|
// return nil, nil.
|
||
|
//
|
||
|
// The type of the value, if one is set, is the same as would be returned by
|
||
|
// TryGetField using the returned field descriptor.
|
||
|
//
|
||
|
// Like with TryGetField, if the given one-of contains any fields that are not
|
||
|
// known (e.g. not present in this message's descriptor), they will become known
|
||
|
// and any unknown value will be parsed (and become a known value on success).
|
||
|
func (m *Message) TryGetOneOfField(od *desc.OneOfDescriptor) (*desc.FieldDescriptor, interface{}, error) {
|
||
|
if od.GetOwner().GetFullyQualifiedName() != m.md.GetFullyQualifiedName() {
|
||
|
return nil, nil, fmt.Errorf("given one-of, %s, is for wrong message type: %s; expecting %s", od.GetName(), od.GetOwner().GetFullyQualifiedName(), m.md.GetFullyQualifiedName())
|
||
|
}
|
||
|
for _, fd := range od.GetChoices() {
|
||
|
val, err := m.doGetField(fd, true)
|
||
|
if err != nil {
|
||
|
return nil, nil, err
|
||
|
}
|
||
|
if val != nil {
|
||
|
return fd, val, nil
|
||
|
}
|
||
|
}
|
||
|
return nil, nil, nil
|
||
|
}
|
||
|
|
||
|
// ClearOneOfField removes any value for any of the given one-of's fields. It
|
||
|
// panics if an error is encountered. See TryClearOneOfField.
|
||
|
func (m *Message) ClearOneOfField(od *desc.OneOfDescriptor) {
|
||
|
if err := m.TryClearOneOfField(od); err != nil {
|
||
|
panic(err.Error())
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// TryClearOneOfField removes any value for any of the given one-of's fields. An
|
||
|
// error is returned if the given one-of descriptor does not belong to the right
|
||
|
// message type.
|
||
|
func (m *Message) TryClearOneOfField(od *desc.OneOfDescriptor) error {
|
||
|
if od.GetOwner().GetFullyQualifiedName() != m.md.GetFullyQualifiedName() {
|
||
|
return fmt.Errorf("given one-of, %s, is for wrong message type: %s; expecting %s", od.GetName(), od.GetOwner().GetFullyQualifiedName(), m.md.GetFullyQualifiedName())
|
||
|
}
|
||
|
for _, fd := range od.GetChoices() {
|
||
|
m.clearField(fd)
|
||
|
}
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
// GetMapField returns the value for the given map field descriptor and given
|
||
|
// key. It panics if an error is encountered. See TryGetMapField.
|
||
|
func (m *Message) GetMapField(fd *desc.FieldDescriptor, key interface{}) interface{} {
|
||
|
if v, err := m.TryGetMapField(fd, key); err != nil {
|
||
|
panic(err.Error())
|
||
|
} else {
|
||
|
return v
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// TryGetMapField returns the value for the given map field descriptor and given
|
||
|
// key. An error is returned if the given field descriptor does not belong to
|
||
|
// the right message type or if it is not a map field.
|
||
|
//
|
||
|
// If the map field does not contain the requested key, this method returns
|
||
|
// nil, nil. The Go type of the value returned mirrors the type that protoc
|
||
|
// would generate for the field. (See TryGetField for more details on types).
|
||
|
//
|
||
|
// If the given field descriptor is not known (e.g. not present in the message
|
||
|
// descriptor) but corresponds to an unknown field, the unknown value will be
|
||
|
// parsed and become known. The parsed value will be searched for the requested
|
||
|
// key and any value returned. An error will be returned if the unknown value
|
||
|
// cannot be parsed according to the field descriptor's type information.
|
||
|
func (m *Message) TryGetMapField(fd *desc.FieldDescriptor, key interface{}) (interface{}, error) {
|
||
|
if err := m.checkField(fd); err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
return m.getMapField(fd, key)
|
||
|
}
|
||
|
|
||
|
// GetMapFieldByName returns the value for the map field with the given name and
|
||
|
// given key. It panics if an error is encountered. See TryGetMapFieldByName.
|
||
|
func (m *Message) GetMapFieldByName(name string, key interface{}) interface{} {
|
||
|
if v, err := m.TryGetMapFieldByName(name, key); err != nil {
|
||
|
panic(err.Error())
|
||
|
} else {
|
||
|
return v
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// TryGetMapFieldByName returns the value for the map field with the given name
|
||
|
// and given key. An error is returned if the given name is unknown or if it
|
||
|
// names a field that is not a map field.
|
||
|
//
|
||
|
// If this message has no value for the given field or the value has no value
|
||
|
// for the requested key, then this method returns nil, nil.
|
||
|
//
|
||
|
// (See TryGetField for more info on types.)
|
||
|
func (m *Message) TryGetMapFieldByName(name string, key interface{}) (interface{}, error) {
|
||
|
fd := m.FindFieldDescriptorByName(name)
|
||
|
if fd == nil {
|
||
|
return nil, UnknownFieldNameError
|
||
|
}
|
||
|
return m.getMapField(fd, key)
|
||
|
}
|
||
|
|
||
|
// GetMapFieldByNumber returns the value for the map field with the given tag
|
||
|
// number and given key. It panics if an error is encountered. See
|
||
|
// TryGetMapFieldByNumber.
|
||
|
func (m *Message) GetMapFieldByNumber(tagNumber int, key interface{}) interface{} {
|
||
|
if v, err := m.TryGetMapFieldByNumber(tagNumber, key); err != nil {
|
||
|
panic(err.Error())
|
||
|
} else {
|
||
|
return v
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// TryGetMapFieldByNumber returns the value for the map field with the given tag
|
||
|
// number and given key. An error is returned if the given tag is unknown or if
|
||
|
// it indicates a field that is not a map field.
|
||
|
//
|
||
|
// If this message has no value for the given field or the value has no value
|
||
|
// for the requested key, then this method returns nil, nil.
|
||
|
//
|
||
|
// (See TryGetField for more info on types.)
|
||
|
func (m *Message) TryGetMapFieldByNumber(tagNumber int, key interface{}) (interface{}, error) {
|
||
|
fd := m.FindFieldDescriptor(int32(tagNumber))
|
||
|
if fd == nil {
|
||
|
return nil, UnknownTagNumberError
|
||
|
}
|
||
|
return m.getMapField(fd, key)
|
||
|
}
|
||
|
|
||
|
func (m *Message) getMapField(fd *desc.FieldDescriptor, key interface{}) (interface{}, error) {
|
||
|
if !fd.IsMap() {
|
||
|
return nil, FieldIsNotMapError
|
||
|
}
|
||
|
kfd := fd.GetMessageType().GetFields()[0]
|
||
|
ki, err := validElementFieldValue(kfd, key, false)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
mp := m.values[fd.GetNumber()]
|
||
|
if mp == nil {
|
||
|
if mp, err = m.parseUnknownField(fd); err != nil {
|
||
|
return nil, err
|
||
|
} else if mp == nil {
|
||
|
return nil, nil
|
||
|
}
|
||
|
}
|
||
|
return mp.(map[interface{}]interface{})[ki], nil
|
||
|
}
|
||
|
|
||
|
// ForEachMapFieldEntry executes the given function for each entry in the map
|
||
|
// value for the given field descriptor. It stops iteration if the function
|
||
|
// returns false. It panics if an error is encountered. See
|
||
|
// TryForEachMapFieldEntry.
|
||
|
func (m *Message) ForEachMapFieldEntry(fd *desc.FieldDescriptor, fn func(key, val interface{}) bool) {
|
||
|
if err := m.TryForEachMapFieldEntry(fd, fn); err != nil {
|
||
|
panic(err.Error())
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// TryForEachMapFieldEntry executes the given function for each entry in the map
|
||
|
// value for the given field descriptor. An error is returned if the given field
|
||
|
// descriptor does not belong to the right message type or if it is not a map
|
||
|
// field.
|
||
|
//
|
||
|
// Iteration ends either when all entries have been examined or when the given
|
||
|
// function returns false. So the function is expected to return true for normal
|
||
|
// iteration and false to break out. If this message has no value for the given
|
||
|
// field, it returns without invoking the given function.
|
||
|
//
|
||
|
// The Go type of the key and value supplied to the function mirrors the type
|
||
|
// that protoc would generate for the field. (See TryGetField for more details
|
||
|
// on types).
|
||
|
//
|
||
|
// If the given field descriptor is not known (e.g. not present in the message
|
||
|
// descriptor) but corresponds to an unknown field, the unknown value will be
|
||
|
// parsed and become known. The parsed value will be searched for the requested
|
||
|
// key and any value returned. An error will be returned if the unknown value
|
||
|
// cannot be parsed according to the field descriptor's type information.
|
||
|
func (m *Message) TryForEachMapFieldEntry(fd *desc.FieldDescriptor, fn func(key, val interface{}) bool) error {
|
||
|
if err := m.checkField(fd); err != nil {
|
||
|
return err
|
||
|
}
|
||
|
return m.forEachMapFieldEntry(fd, fn)
|
||
|
}
|
||
|
|
||
|
// ForEachMapFieldEntryByName executes the given function for each entry in the
|
||
|
// map value for the field with the given name. It stops iteration if the
|
||
|
// function returns false. It panics if an error is encountered. See
|
||
|
// TryForEachMapFieldEntryByName.
|
||
|
func (m *Message) ForEachMapFieldEntryByName(name string, fn func(key, val interface{}) bool) {
|
||
|
if err := m.TryForEachMapFieldEntryByName(name, fn); err != nil {
|
||
|
panic(err.Error())
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// TryForEachMapFieldEntryByName executes the given function for each entry in
|
||
|
// the map value for the field with the given name. It stops iteration if the
|
||
|
// function returns false. An error is returned if the given name is unknown or
|
||
|
// if it names a field that is not a map field.
|
||
|
//
|
||
|
// If this message has no value for the given field, it returns without ever
|
||
|
// invoking the given function.
|
||
|
//
|
||
|
// (See TryGetField for more info on types supplied to the function.)
|
||
|
func (m *Message) TryForEachMapFieldEntryByName(name string, fn func(key, val interface{}) bool) error {
|
||
|
fd := m.FindFieldDescriptorByName(name)
|
||
|
if fd == nil {
|
||
|
return UnknownFieldNameError
|
||
|
}
|
||
|
return m.forEachMapFieldEntry(fd, fn)
|
||
|
}
|
||
|
|
||
|
// ForEachMapFieldEntryByNumber executes the given function for each entry in
|
||
|
// the map value for the field with the given tag number. It stops iteration if
|
||
|
// the function returns false. It panics if an error is encountered. See
|
||
|
// TryForEachMapFieldEntryByNumber.
|
||
|
func (m *Message) ForEachMapFieldEntryByNumber(tagNumber int, fn func(key, val interface{}) bool) {
|
||
|
if err := m.TryForEachMapFieldEntryByNumber(tagNumber, fn); err != nil {
|
||
|
panic(err.Error())
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// TryForEachMapFieldEntryByNumber executes the given function for each entry in
|
||
|
// the map value for the field with the given tag number. It stops iteration if
|
||
|
// the function returns false. An error is returned if the given tag is unknown
|
||
|
// or if it indicates a field that is not a map field.
|
||
|
//
|
||
|
// If this message has no value for the given field, it returns without ever
|
||
|
// invoking the given function.
|
||
|
//
|
||
|
// (See TryGetField for more info on types supplied to the function.)
|
||
|
func (m *Message) TryForEachMapFieldEntryByNumber(tagNumber int, fn func(key, val interface{}) bool) error {
|
||
|
fd := m.FindFieldDescriptor(int32(tagNumber))
|
||
|
if fd == nil {
|
||
|
return UnknownTagNumberError
|
||
|
}
|
||
|
return m.forEachMapFieldEntry(fd, fn)
|
||
|
}
|
||
|
|
||
|
func (m *Message) forEachMapFieldEntry(fd *desc.FieldDescriptor, fn func(key, val interface{}) bool) error {
|
||
|
if !fd.IsMap() {
|
||
|
return FieldIsNotMapError
|
||
|
}
|
||
|
mp := m.values[fd.GetNumber()]
|
||
|
if mp == nil {
|
||
|
if mp, err := m.parseUnknownField(fd); err != nil {
|
||
|
return err
|
||
|
} else if mp == nil {
|
||
|
return nil
|
||
|
}
|
||
|
}
|
||
|
for k, v := range mp.(map[interface{}]interface{}) {
|
||
|
if !fn(k, v) {
|
||
|
break
|
||
|
}
|
||
|
}
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
// PutMapField sets the value for the given map field descriptor and given key
|
||
|
// to the given value. It panics if an error is encountered. See TryPutMapField.
|
||
|
func (m *Message) PutMapField(fd *desc.FieldDescriptor, key interface{}, val interface{}) {
|
||
|
if err := m.TryPutMapField(fd, key, val); err != nil {
|
||
|
panic(err.Error())
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// TryPutMapField sets the value for the given map field descriptor and given
|
||
|
// key to the given value. An error is returned if the given field descriptor
|
||
|
// does not belong to the right message type, if the given field is not a map
|
||
|
// field, or if the given value is not a correct/compatible type for the given
|
||
|
// field.
|
||
|
//
|
||
|
// The Go type expected for a field is the same as required by TrySetField for
|
||
|
// a field with the same type as the map's value type.
|
||
|
//
|
||
|
// If the given field descriptor is not known (e.g. not present in the message
|
||
|
// descriptor) it will become known. Subsequent operations using tag numbers or
|
||
|
// names will be able to resolve the newly-known type. If the message has a
|
||
|
// value for the unknown value, it is cleared, replaced by the given known
|
||
|
// value.
|
||
|
func (m *Message) TryPutMapField(fd *desc.FieldDescriptor, key interface{}, val interface{}) error {
|
||
|
if err := m.checkField(fd); err != nil {
|
||
|
return err
|
||
|
}
|
||
|
return m.putMapField(fd, key, val)
|
||
|
}
|
||
|
|
||
|
// PutMapFieldByName sets the value for the map field with the given name and
|
||
|
// given key to the given value. It panics if an error is encountered. See
|
||
|
// TryPutMapFieldByName.
|
||
|
func (m *Message) PutMapFieldByName(name string, key interface{}, val interface{}) {
|
||
|
if err := m.TryPutMapFieldByName(name, key, val); err != nil {
|
||
|
panic(err.Error())
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// TryPutMapFieldByName sets the value for the map field with the given name and
|
||
|
// the given key to the given value. An error is returned if the given name is
|
||
|
// unknown, if it names a field that is not a map, or if the given value has an
|
||
|
// incorrect type.
|
||
|
//
|
||
|
// (See TrySetField for more info on types.)
|
||
|
func (m *Message) TryPutMapFieldByName(name string, key interface{}, val interface{}) error {
|
||
|
fd := m.FindFieldDescriptorByName(name)
|
||
|
if fd == nil {
|
||
|
return UnknownFieldNameError
|
||
|
}
|
||
|
return m.putMapField(fd, key, val)
|
||
|
}
|
||
|
|
||
|
// PutMapFieldByNumber sets the value for the map field with the given tag
|
||
|
// number and given key to the given value. It panics if an error is
|
||
|
// encountered. See TryPutMapFieldByNumber.
|
||
|
func (m *Message) PutMapFieldByNumber(tagNumber int, key interface{}, val interface{}) {
|
||
|
if err := m.TryPutMapFieldByNumber(tagNumber, key, val); err != nil {
|
||
|
panic(err.Error())
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// TryPutMapFieldByNumber sets the value for the map field with the given tag
|
||
|
// number and the given key to the given value. An error is returned if the
|
||
|
// given tag is unknown, if it indicates a field that is not a map, or if the
|
||
|
// given value has an incorrect type.
|
||
|
//
|
||
|
// (See TrySetField for more info on types.)
|
||
|
func (m *Message) TryPutMapFieldByNumber(tagNumber int, key interface{}, val interface{}) error {
|
||
|
fd := m.FindFieldDescriptor(int32(tagNumber))
|
||
|
if fd == nil {
|
||
|
return UnknownTagNumberError
|
||
|
}
|
||
|
return m.putMapField(fd, key, val)
|
||
|
}
|
||
|
|
||
|
func (m *Message) putMapField(fd *desc.FieldDescriptor, key interface{}, val interface{}) error {
|
||
|
if !fd.IsMap() {
|
||
|
return FieldIsNotMapError
|
||
|
}
|
||
|
kfd := fd.GetMessageType().GetFields()[0]
|
||
|
ki, err := validElementFieldValue(kfd, key, false)
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
vfd := fd.GetMessageType().GetFields()[1]
|
||
|
vi, err := validElementFieldValue(vfd, val, true)
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
mp := m.values[fd.GetNumber()]
|
||
|
if mp == nil {
|
||
|
if mp, err = m.parseUnknownField(fd); err != nil {
|
||
|
return err
|
||
|
} else if mp == nil {
|
||
|
m.internalSetField(fd, map[interface{}]interface{}{ki: vi})
|
||
|
return nil
|
||
|
}
|
||
|
}
|
||
|
mp.(map[interface{}]interface{})[ki] = vi
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
// RemoveMapField changes the value for the given field descriptor by removing
|
||
|
// any value associated with the given key. It panics if an error is
|
||
|
// encountered. See TryRemoveMapField.
|
||
|
func (m *Message) RemoveMapField(fd *desc.FieldDescriptor, key interface{}) {
|
||
|
if err := m.TryRemoveMapField(fd, key); err != nil {
|
||
|
panic(err.Error())
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// TryRemoveMapField changes the value for the given field descriptor by
|
||
|
// removing any value associated with the given key. An error is returned if the
|
||
|
// given field descriptor does not belong to the right message type or if the
|
||
|
// given field is not a map field.
|
||
|
//
|
||
|
// If the given field descriptor is not known (e.g. not present in the message
|
||
|
// descriptor) it will become known. Subsequent operations using tag numbers or
|
||
|
// names will be able to resolve the newly-known type. If the message has a
|
||
|
// value for the unknown value, it is parsed and any value for the given key
|
||
|
// removed.
|
||
|
func (m *Message) TryRemoveMapField(fd *desc.FieldDescriptor, key interface{}) error {
|
||
|
if err := m.checkField(fd); err != nil {
|
||
|
return err
|
||
|
}
|
||
|
return m.removeMapField(fd, key)
|
||
|
}
|
||
|
|
||
|
// RemoveMapFieldByName changes the value for the field with the given name by
|
||
|
// removing any value associated with the given key. It panics if an error is
|
||
|
// encountered. See TryRemoveMapFieldByName.
|
||
|
func (m *Message) RemoveMapFieldByName(name string, key interface{}) {
|
||
|
if err := m.TryRemoveMapFieldByName(name, key); err != nil {
|
||
|
panic(err.Error())
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// TryRemoveMapFieldByName changes the value for the field with the given name
|
||
|
// by removing any value associated with the given key. An error is returned if
|
||
|
// the given name is unknown or if it names a field that is not a map.
|
||
|
func (m *Message) TryRemoveMapFieldByName(name string, key interface{}) error {
|
||
|
fd := m.FindFieldDescriptorByName(name)
|
||
|
if fd == nil {
|
||
|
return UnknownFieldNameError
|
||
|
}
|
||
|
return m.removeMapField(fd, key)
|
||
|
}
|
||
|
|
||
|
// RemoveMapFieldByNumber changes the value for the field with the given tag
|
||
|
// number by removing any value associated with the given key. It panics if an
|
||
|
// error is encountered. See TryRemoveMapFieldByNumber.
|
||
|
func (m *Message) RemoveMapFieldByNumber(tagNumber int, key interface{}) {
|
||
|
if err := m.TryRemoveMapFieldByNumber(tagNumber, key); err != nil {
|
||
|
panic(err.Error())
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// TryRemoveMapFieldByNumber changes the value for the field with the given tag
|
||
|
// number by removing any value associated with the given key. An error is
|
||
|
// returned if the given tag is unknown or if it indicates a field that is not
|
||
|
// a map.
|
||
|
func (m *Message) TryRemoveMapFieldByNumber(tagNumber int, key interface{}) error {
|
||
|
fd := m.FindFieldDescriptor(int32(tagNumber))
|
||
|
if fd == nil {
|
||
|
return UnknownTagNumberError
|
||
|
}
|
||
|
return m.removeMapField(fd, key)
|
||
|
}
|
||
|
|
||
|
func (m *Message) removeMapField(fd *desc.FieldDescriptor, key interface{}) error {
|
||
|
if !fd.IsMap() {
|
||
|
return FieldIsNotMapError
|
||
|
}
|
||
|
kfd := fd.GetMessageType().GetFields()[0]
|
||
|
ki, err := validElementFieldValue(kfd, key, false)
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
mp := m.values[fd.GetNumber()]
|
||
|
if mp == nil {
|
||
|
if mp, err = m.parseUnknownField(fd); err != nil {
|
||
|
return err
|
||
|
} else if mp == nil {
|
||
|
return nil
|
||
|
}
|
||
|
}
|
||
|
res := mp.(map[interface{}]interface{})
|
||
|
delete(res, ki)
|
||
|
if len(res) == 0 {
|
||
|
delete(m.values, fd.GetNumber())
|
||
|
}
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
// FieldLength returns the number of elements in this message for the given
|
||
|
// field descriptor. It panics if an error is encountered. See TryFieldLength.
|
||
|
func (m *Message) FieldLength(fd *desc.FieldDescriptor) int {
|
||
|
l, err := m.TryFieldLength(fd)
|
||
|
if err != nil {
|
||
|
panic(err.Error())
|
||
|
}
|
||
|
return l
|
||
|
}
|
||
|
|
||
|
// TryFieldLength returns the number of elements in this message for the given
|
||
|
// field descriptor. An error is returned if the given field descriptor does not
|
||
|
// belong to the right message type or if it is neither a map field nor a
|
||
|
// repeated field.
|
||
|
func (m *Message) TryFieldLength(fd *desc.FieldDescriptor) (int, error) {
|
||
|
if err := m.checkField(fd); err != nil {
|
||
|
return 0, err
|
||
|
}
|
||
|
return m.fieldLength(fd)
|
||
|
}
|
||
|
|
||
|
// FieldLengthByName returns the number of elements in this message for the
|
||
|
// field with the given name. It panics if an error is encountered. See
|
||
|
// TryFieldLengthByName.
|
||
|
func (m *Message) FieldLengthByName(name string) int {
|
||
|
l, err := m.TryFieldLengthByName(name)
|
||
|
if err != nil {
|
||
|
panic(err.Error())
|
||
|
}
|
||
|
return l
|
||
|
}
|
||
|
|
||
|
// TryFieldLengthByName returns the number of elements in this message for the
|
||
|
// field with the given name. An error is returned if the given name is unknown
|
||
|
// or if the named field is neither a map field nor a repeated field.
|
||
|
func (m *Message) TryFieldLengthByName(name string) (int, error) {
|
||
|
fd := m.FindFieldDescriptorByName(name)
|
||
|
if fd == nil {
|
||
|
return 0, UnknownFieldNameError
|
||
|
}
|
||
|
return m.fieldLength(fd)
|
||
|
}
|
||
|
|
||
|
// FieldLengthByNumber returns the number of elements in this message for the
|
||
|
// field with the given tag number. It panics if an error is encountered. See
|
||
|
// TryFieldLengthByNumber.
|
||
|
func (m *Message) FieldLengthByNumber(tagNumber int32) int {
|
||
|
l, err := m.TryFieldLengthByNumber(tagNumber)
|
||
|
if err != nil {
|
||
|
panic(err.Error())
|
||
|
}
|
||
|
return l
|
||
|
}
|
||
|
|
||
|
// TryFieldLengthByNumber returns the number of elements in this message for the
|
||
|
// field with the given tag number. An error is returned if the given tag is
|
||
|
// unknown or if the named field is neither a map field nor a repeated field.
|
||
|
func (m *Message) TryFieldLengthByNumber(tagNumber int32) (int, error) {
|
||
|
fd := m.FindFieldDescriptor(int32(tagNumber))
|
||
|
if fd == nil {
|
||
|
return 0, UnknownTagNumberError
|
||
|
}
|
||
|
return m.fieldLength(fd)
|
||
|
}
|
||
|
|
||
|
func (m *Message) fieldLength(fd *desc.FieldDescriptor) (int, error) {
|
||
|
if !fd.IsRepeated() {
|
||
|
return 0, FieldIsNotRepeatedError
|
||
|
}
|
||
|
val := m.values[fd.GetNumber()]
|
||
|
if val == nil {
|
||
|
var err error
|
||
|
if val, err = m.parseUnknownField(fd); err != nil {
|
||
|
return 0, err
|
||
|
} else if val == nil {
|
||
|
return 0, nil
|
||
|
}
|
||
|
}
|
||
|
if sl, ok := val.([]interface{}); ok {
|
||
|
return len(sl), nil
|
||
|
} else if mp, ok := val.(map[interface{}]interface{}); ok {
|
||
|
return len(mp), nil
|
||
|
}
|
||
|
return 0, nil
|
||
|
}
|
||
|
|
||
|
// GetRepeatedField returns the value for the given repeated field descriptor at
|
||
|
// the given index. It panics if an error is encountered. See
|
||
|
// TryGetRepeatedField.
|
||
|
func (m *Message) GetRepeatedField(fd *desc.FieldDescriptor, index int) interface{} {
|
||
|
if v, err := m.TryGetRepeatedField(fd, index); err != nil {
|
||
|
panic(err.Error())
|
||
|
} else {
|
||
|
return v
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// TryGetRepeatedField returns the value for the given repeated field descriptor
|
||
|
// at the given index. An error is returned if the given field descriptor does
|
||
|
// not belong to the right message type, if it is not a repeated field, or if
|
||
|
// the given index is out of range (less than zero or greater than or equal to
|
||
|
// the length of the repeated field). Also, even though map fields technically
|
||
|
// are repeated fields, if the given field is a map field an error will result:
|
||
|
// map representation does not lend itself to random access by index.
|
||
|
//
|
||
|
// The Go type of the value returned mirrors the type that protoc would generate
|
||
|
// for the field's element type. (See TryGetField for more details on types).
|
||
|
//
|
||
|
// If the given field descriptor is not known (e.g. not present in the message
|
||
|
// descriptor) but corresponds to an unknown field, the unknown value will be
|
||
|
// parsed and become known. The value at the given index in the parsed value
|
||
|
// will be returned. An error will be returned if the unknown value cannot be
|
||
|
// parsed according to the field descriptor's type information.
|
||
|
func (m *Message) TryGetRepeatedField(fd *desc.FieldDescriptor, index int) (interface{}, error) {
|
||
|
if index < 0 {
|
||
|
return nil, IndexOutOfRangeError
|
||
|
}
|
||
|
if err := m.checkField(fd); err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
return m.getRepeatedField(fd, index)
|
||
|
}
|
||
|
|
||
|
// GetRepeatedFieldByName returns the value for the repeated field with the
|
||
|
// given name at the given index. It panics if an error is encountered. See
|
||
|
// TryGetRepeatedFieldByName.
|
||
|
func (m *Message) GetRepeatedFieldByName(name string, index int) interface{} {
|
||
|
if v, err := m.TryGetRepeatedFieldByName(name, index); err != nil {
|
||
|
panic(err.Error())
|
||
|
} else {
|
||
|
return v
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// TryGetRepeatedFieldByName returns the value for the repeated field with the
|
||
|
// given name at the given index. An error is returned if the given name is
|
||
|
// unknown, if it names a field that is not a repeated field (or is a map
|
||
|
// field), or if the given index is out of range (less than zero or greater
|
||
|
// than or equal to the length of the repeated field).
|
||
|
//
|
||
|
// (See TryGetField for more info on types.)
|
||
|
func (m *Message) TryGetRepeatedFieldByName(name string, index int) (interface{}, error) {
|
||
|
if index < 0 {
|
||
|
return nil, IndexOutOfRangeError
|
||
|
}
|
||
|
fd := m.FindFieldDescriptorByName(name)
|
||
|
if fd == nil {
|
||
|
return nil, UnknownFieldNameError
|
||
|
}
|
||
|
return m.getRepeatedField(fd, index)
|
||
|
}
|
||
|
|
||
|
// GetRepeatedFieldByNumber returns the value for the repeated field with the
|
||
|
// given tag number at the given index. It panics if an error is encountered.
|
||
|
// See TryGetRepeatedFieldByNumber.
|
||
|
func (m *Message) GetRepeatedFieldByNumber(tagNumber int, index int) interface{} {
|
||
|
if v, err := m.TryGetRepeatedFieldByNumber(tagNumber, index); err != nil {
|
||
|
panic(err.Error())
|
||
|
} else {
|
||
|
return v
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// TryGetRepeatedFieldByNumber returns the value for the repeated field with the
|
||
|
// given tag number at the given index. An error is returned if the given tag is
|
||
|
// unknown, if it indicates a field that is not a repeated field (or is a map
|
||
|
// field), or if the given index is out of range (less than zero or greater than
|
||
|
// or equal to the length of the repeated field).
|
||
|
//
|
||
|
// (See TryGetField for more info on types.)
|
||
|
func (m *Message) TryGetRepeatedFieldByNumber(tagNumber int, index int) (interface{}, error) {
|
||
|
if index < 0 {
|
||
|
return nil, IndexOutOfRangeError
|
||
|
}
|
||
|
fd := m.FindFieldDescriptor(int32(tagNumber))
|
||
|
if fd == nil {
|
||
|
return nil, UnknownTagNumberError
|
||
|
}
|
||
|
return m.getRepeatedField(fd, index)
|
||
|
}
|
||
|
|
||
|
func (m *Message) getRepeatedField(fd *desc.FieldDescriptor, index int) (interface{}, error) {
|
||
|
if fd.IsMap() || !fd.IsRepeated() {
|
||
|
return nil, FieldIsNotRepeatedError
|
||
|
}
|
||
|
sl := m.values[fd.GetNumber()]
|
||
|
if sl == nil {
|
||
|
var err error
|
||
|
if sl, err = m.parseUnknownField(fd); err != nil {
|
||
|
return nil, err
|
||
|
} else if sl == nil {
|
||
|
return nil, IndexOutOfRangeError
|
||
|
}
|
||
|
}
|
||
|
res := sl.([]interface{})
|
||
|
if index >= len(res) {
|
||
|
return nil, IndexOutOfRangeError
|
||
|
}
|
||
|
return res[index], nil
|
||
|
}
|
||
|
|
||
|
// AddRepeatedField appends the given value to the given repeated field. It
|
||
|
// panics if an error is encountered. See TryAddRepeatedField.
|
||
|
func (m *Message) AddRepeatedField(fd *desc.FieldDescriptor, val interface{}) {
|
||
|
if err := m.TryAddRepeatedField(fd, val); err != nil {
|
||
|
panic(err.Error())
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// TryAddRepeatedField appends the given value to the given repeated field. An
|
||
|
// error is returned if the given field descriptor does not belong to the right
|
||
|
// message type, if the given field is not repeated, or if the given value is
|
||
|
// not a correct/compatible type for the given field. If the given field is a
|
||
|
// map field, the call will succeed if the given value is an instance of the
|
||
|
// map's entry message type.
|
||
|
//
|
||
|
// The Go type expected for a field is the same as required by TrySetField for
|
||
|
// a non-repeated field of the same type.
|
||
|
//
|
||
|
// If the given field descriptor is not known (e.g. not present in the message
|
||
|
// descriptor) it will become known. Subsequent operations using tag numbers or
|
||
|
// names will be able to resolve the newly-known type. If the message has a
|
||
|
// value for the unknown value, it is parsed and the given value is appended to
|
||
|
// it.
|
||
|
func (m *Message) TryAddRepeatedField(fd *desc.FieldDescriptor, val interface{}) error {
|
||
|
if err := m.checkField(fd); err != nil {
|
||
|
return err
|
||
|
}
|
||
|
return m.addRepeatedField(fd, val)
|
||
|
}
|
||
|
|
||
|
// AddRepeatedFieldByName appends the given value to the repeated field with the
|
||
|
// given name. It panics if an error is encountered. See
|
||
|
// TryAddRepeatedFieldByName.
|
||
|
func (m *Message) AddRepeatedFieldByName(name string, val interface{}) {
|
||
|
if err := m.TryAddRepeatedFieldByName(name, val); err != nil {
|
||
|
panic(err.Error())
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// TryAddRepeatedFieldByName appends the given value to the repeated field with
|
||
|
// the given name. An error is returned if the given name is unknown, if it
|
||
|
// names a field that is not repeated, or if the given value has an incorrect
|
||
|
// type.
|
||
|
//
|
||
|
// (See TrySetField for more info on types.)
|
||
|
func (m *Message) TryAddRepeatedFieldByName(name string, val interface{}) error {
|
||
|
fd := m.FindFieldDescriptorByName(name)
|
||
|
if fd == nil {
|
||
|
return UnknownFieldNameError
|
||
|
}
|
||
|
return m.addRepeatedField(fd, val)
|
||
|
}
|
||
|
|
||
|
// AddRepeatedFieldByNumber appends the given value to the repeated field with
|
||
|
// the given tag number. It panics if an error is encountered. See
|
||
|
// TryAddRepeatedFieldByNumber.
|
||
|
func (m *Message) AddRepeatedFieldByNumber(tagNumber int, val interface{}) {
|
||
|
if err := m.TryAddRepeatedFieldByNumber(tagNumber, val); err != nil {
|
||
|
panic(err.Error())
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// TryAddRepeatedFieldByNumber appends the given value to the repeated field
|
||
|
// with the given tag number. An error is returned if the given tag is unknown,
|
||
|
// if it indicates a field that is not repeated, or if the given value has an
|
||
|
// incorrect type.
|
||
|
//
|
||
|
// (See TrySetField for more info on types.)
|
||
|
func (m *Message) TryAddRepeatedFieldByNumber(tagNumber int, val interface{}) error {
|
||
|
fd := m.FindFieldDescriptor(int32(tagNumber))
|
||
|
if fd == nil {
|
||
|
return UnknownTagNumberError
|
||
|
}
|
||
|
return m.addRepeatedField(fd, val)
|
||
|
}
|
||
|
|
||
|
func (m *Message) addRepeatedField(fd *desc.FieldDescriptor, val interface{}) error {
|
||
|
if !fd.IsRepeated() {
|
||
|
return FieldIsNotRepeatedError
|
||
|
}
|
||
|
val, err := validElementFieldValue(fd, val, false)
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
if fd.IsMap() {
|
||
|
// We're lenient. Just as we allow setting a map field to a slice of entry messages, we also allow
|
||
|
// adding entries one at a time (as if the field were a normal repeated field).
|
||
|
msg := val.(proto.Message)
|
||
|
dm, err := asDynamicMessage(msg, fd.GetMessageType(), m.mf)
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
k, err := dm.TryGetFieldByNumber(1)
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
v, err := dm.TryGetFieldByNumber(2)
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
return m.putMapField(fd, k, v)
|
||
|
}
|
||
|
|
||
|
sl := m.values[fd.GetNumber()]
|
||
|
if sl == nil {
|
||
|
if sl, err = m.parseUnknownField(fd); err != nil {
|
||
|
return err
|
||
|
} else if sl == nil {
|
||
|
sl = []interface{}{}
|
||
|
}
|
||
|
}
|
||
|
res := sl.([]interface{})
|
||
|
res = append(res, val)
|
||
|
m.internalSetField(fd, res)
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
// SetRepeatedField sets the value for the given repeated field descriptor and
|
||
|
// given index to the given value. It panics if an error is encountered. See
|
||
|
// SetRepeatedField.
|
||
|
func (m *Message) SetRepeatedField(fd *desc.FieldDescriptor, index int, val interface{}) {
|
||
|
if err := m.TrySetRepeatedField(fd, index, val); err != nil {
|
||
|
panic(err.Error())
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// TrySetRepeatedField sets the value for the given repeated field descriptor
|
||
|
// and given index to the given value. An error is returned if the given field
|
||
|
// descriptor does not belong to the right message type, if the given field is
|
||
|
// not repeated, or if the given value is not a correct/compatible type for the
|
||
|
// given field. Also, even though map fields technically are repeated fields, if
|
||
|
// the given field is a map field an error will result: map representation does
|
||
|
// not lend itself to random access by index.
|
||
|
//
|
||
|
// The Go type expected for a field is the same as required by TrySetField for
|
||
|
// a non-repeated field of the same type.
|
||
|
//
|
||
|
// If the given field descriptor is not known (e.g. not present in the message
|
||
|
// descriptor) it will become known. Subsequent operations using tag numbers or
|
||
|
// names will be able to resolve the newly-known type. If the message has a
|
||
|
// value for the unknown value, it is parsed and the element at the given index
|
||
|
// is replaced with the given value.
|
||
|
func (m *Message) TrySetRepeatedField(fd *desc.FieldDescriptor, index int, val interface{}) error {
|
||
|
if index < 0 {
|
||
|
return IndexOutOfRangeError
|
||
|
}
|
||
|
if err := m.checkField(fd); err != nil {
|
||
|
return err
|
||
|
}
|
||
|
return m.setRepeatedField(fd, index, val)
|
||
|
}
|
||
|
|
||
|
// SetRepeatedFieldByName sets the value for the repeated field with the given
|
||
|
// name and given index to the given value. It panics if an error is
|
||
|
// encountered. See TrySetRepeatedFieldByName.
|
||
|
func (m *Message) SetRepeatedFieldByName(name string, index int, val interface{}) {
|
||
|
if err := m.TrySetRepeatedFieldByName(name, index, val); err != nil {
|
||
|
panic(err.Error())
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// TrySetRepeatedFieldByName sets the value for the repeated field with the
|
||
|
// given name and the given index to the given value. An error is returned if
|
||
|
// the given name is unknown, if it names a field that is not repeated (or is a
|
||
|
// map field), or if the given value has an incorrect type.
|
||
|
//
|
||
|
// (See TrySetField for more info on types.)
|
||
|
func (m *Message) TrySetRepeatedFieldByName(name string, index int, val interface{}) error {
|
||
|
if index < 0 {
|
||
|
return IndexOutOfRangeError
|
||
|
}
|
||
|
fd := m.FindFieldDescriptorByName(name)
|
||
|
if fd == nil {
|
||
|
return UnknownFieldNameError
|
||
|
}
|
||
|
return m.setRepeatedField(fd, index, val)
|
||
|
}
|
||
|
|
||
|
// SetRepeatedFieldByNumber sets the value for the repeated field with the given
|
||
|
// tag number and given index to the given value. It panics if an error is
|
||
|
// encountered. See TrySetRepeatedFieldByNumber.
|
||
|
func (m *Message) SetRepeatedFieldByNumber(tagNumber int, index int, val interface{}) {
|
||
|
if err := m.TrySetRepeatedFieldByNumber(tagNumber, index, val); err != nil {
|
||
|
panic(err.Error())
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// TrySetRepeatedFieldByNumber sets the value for the repeated field with the
|
||
|
// given tag number and the given index to the given value. An error is returned
|
||
|
// if the given tag is unknown, if it indicates a field that is not repeated (or
|
||
|
// is a map field), or if the given value has an incorrect type.
|
||
|
//
|
||
|
// (See TrySetField for more info on types.)
|
||
|
func (m *Message) TrySetRepeatedFieldByNumber(tagNumber int, index int, val interface{}) error {
|
||
|
if index < 0 {
|
||
|
return IndexOutOfRangeError
|
||
|
}
|
||
|
fd := m.FindFieldDescriptor(int32(tagNumber))
|
||
|
if fd == nil {
|
||
|
return UnknownTagNumberError
|
||
|
}
|
||
|
return m.setRepeatedField(fd, index, val)
|
||
|
}
|
||
|
|
||
|
func (m *Message) setRepeatedField(fd *desc.FieldDescriptor, index int, val interface{}) error {
|
||
|
if fd.IsMap() || !fd.IsRepeated() {
|
||
|
return FieldIsNotRepeatedError
|
||
|
}
|
||
|
val, err := validElementFieldValue(fd, val, false)
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
sl := m.values[fd.GetNumber()]
|
||
|
if sl == nil {
|
||
|
if sl, err = m.parseUnknownField(fd); err != nil {
|
||
|
return err
|
||
|
} else if sl == nil {
|
||
|
return IndexOutOfRangeError
|
||
|
}
|
||
|
}
|
||
|
res := sl.([]interface{})
|
||
|
if index >= len(res) {
|
||
|
return IndexOutOfRangeError
|
||
|
}
|
||
|
res[index] = val
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
// GetUnknownField gets the value(s) for the given unknown tag number. If this
|
||
|
// message has no unknown fields with the given tag, nil is returned.
|
||
|
func (m *Message) GetUnknownField(tagNumber int32) []UnknownField {
|
||
|
if u, ok := m.unknownFields[tagNumber]; ok {
|
||
|
return u
|
||
|
} else {
|
||
|
return nil
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func (m *Message) parseUnknownField(fd *desc.FieldDescriptor) (interface{}, error) {
|
||
|
unks, ok := m.unknownFields[fd.GetNumber()]
|
||
|
if !ok {
|
||
|
return nil, nil
|
||
|
}
|
||
|
var v interface{}
|
||
|
var sl []interface{}
|
||
|
var mp map[interface{}]interface{}
|
||
|
if fd.IsMap() {
|
||
|
mp = map[interface{}]interface{}{}
|
||
|
}
|
||
|
var err error
|
||
|
for _, unk := range unks {
|
||
|
var val interface{}
|
||
|
if unk.Encoding == proto.WireBytes || unk.Encoding == proto.WireStartGroup {
|
||
|
val, err = codec.DecodeLengthDelimitedField(fd, unk.Contents, m.mf)
|
||
|
} else {
|
||
|
val, err = codec.DecodeScalarField(fd, unk.Value)
|
||
|
}
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
if fd.IsMap() {
|
||
|
newEntry := val.(*Message)
|
||
|
kk, err := newEntry.TryGetFieldByNumber(1)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
vv, err := newEntry.TryGetFieldByNumber(2)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
mp[kk] = vv
|
||
|
v = mp
|
||
|
} else if fd.IsRepeated() {
|
||
|
t := reflect.TypeOf(val)
|
||
|
if t.Kind() == reflect.Slice && t != typeOfBytes {
|
||
|
// append slices if we unmarshalled a packed repeated field
|
||
|
newVals := val.([]interface{})
|
||
|
sl = append(sl, newVals...)
|
||
|
} else {
|
||
|
sl = append(sl, val)
|
||
|
}
|
||
|
v = sl
|
||
|
} else {
|
||
|
v = val
|
||
|
}
|
||
|
}
|
||
|
m.internalSetField(fd, v)
|
||
|
return v, nil
|
||
|
}
|
||
|
|
||
|
func validFieldValue(fd *desc.FieldDescriptor, val interface{}) (interface{}, error) {
|
||
|
return validFieldValueForRv(fd, reflect.ValueOf(val))
|
||
|
}
|
||
|
|
||
|
func validFieldValueForRv(fd *desc.FieldDescriptor, val reflect.Value) (interface{}, error) {
|
||
|
if fd.IsMap() && val.Kind() == reflect.Map {
|
||
|
return validFieldValueForMapField(fd, val)
|
||
|
}
|
||
|
|
||
|
if fd.IsRepeated() { // this will also catch map fields where given value was not a map
|
||
|
if val.Kind() != reflect.Array && val.Kind() != reflect.Slice {
|
||
|
if fd.IsMap() {
|
||
|
return nil, fmt.Errorf("value for map field must be a map; instead was %v", val.Type())
|
||
|
} else {
|
||
|
return nil, fmt.Errorf("value for repeated field must be a slice; instead was %v", val.Type())
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if fd.IsMap() {
|
||
|
// value should be a slice of entry messages that we need convert into a map[interface{}]interface{}
|
||
|
m := map[interface{}]interface{}{}
|
||
|
for i := 0; i < val.Len(); i++ {
|
||
|
e, err := validElementFieldValue(fd, val.Index(i).Interface(), false)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
msg := e.(proto.Message)
|
||
|
dm, err := asDynamicMessage(msg, fd.GetMessageType(), nil)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
k, err := dm.TryGetFieldByNumber(1)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
v, err := dm.TryGetFieldByNumber(2)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
m[k] = v
|
||
|
}
|
||
|
return m, nil
|
||
|
}
|
||
|
|
||
|
// make a defensive copy while checking contents (also converts to []interface{})
|
||
|
s := make([]interface{}, val.Len())
|
||
|
for i := 0; i < val.Len(); i++ {
|
||
|
ev := val.Index(i)
|
||
|
if ev.Kind() == reflect.Interface {
|
||
|
// unwrap it
|
||
|
ev = reflect.ValueOf(ev.Interface())
|
||
|
}
|
||
|
e, err := validElementFieldValueForRv(fd, ev, false)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
s[i] = e
|
||
|
}
|
||
|
|
||
|
return s, nil
|
||
|
}
|
||
|
|
||
|
return validElementFieldValueForRv(fd, val, false)
|
||
|
}
|
||
|
|
||
|
func asDynamicMessage(m proto.Message, md *desc.MessageDescriptor, mf *MessageFactory) (*Message, error) {
|
||
|
if dm, ok := m.(*Message); ok {
|
||
|
return dm, nil
|
||
|
}
|
||
|
dm := NewMessageWithMessageFactory(md, mf)
|
||
|
if err := dm.mergeFrom(m); err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
return dm, nil
|
||
|
}
|
||
|
|
||
|
func validElementFieldValue(fd *desc.FieldDescriptor, val interface{}, allowNilMessage bool) (interface{}, error) {
|
||
|
return validElementFieldValueForRv(fd, reflect.ValueOf(val), allowNilMessage)
|
||
|
}
|
||
|
|
||
|
func validElementFieldValueForRv(fd *desc.FieldDescriptor, val reflect.Value, allowNilMessage bool) (interface{}, error) {
|
||
|
t := fd.GetType()
|
||
|
if !val.IsValid() {
|
||
|
return nil, typeError(fd, nil)
|
||
|
}
|
||
|
|
||
|
switch t {
|
||
|
case descriptor.FieldDescriptorProto_TYPE_SFIXED32,
|
||
|
descriptor.FieldDescriptorProto_TYPE_INT32,
|
||
|
descriptor.FieldDescriptorProto_TYPE_SINT32,
|
||
|
descriptor.FieldDescriptorProto_TYPE_ENUM:
|
||
|
return toInt32(reflect.Indirect(val), fd)
|
||
|
|
||
|
case descriptor.FieldDescriptorProto_TYPE_SFIXED64,
|
||
|
descriptor.FieldDescriptorProto_TYPE_INT64,
|
||
|
descriptor.FieldDescriptorProto_TYPE_SINT64:
|
||
|
return toInt64(reflect.Indirect(val), fd)
|
||
|
|
||
|
case descriptor.FieldDescriptorProto_TYPE_FIXED32,
|
||
|
descriptor.FieldDescriptorProto_TYPE_UINT32:
|
||
|
return toUint32(reflect.Indirect(val), fd)
|
||
|
|
||
|
case descriptor.FieldDescriptorProto_TYPE_FIXED64,
|
||
|
descriptor.FieldDescriptorProto_TYPE_UINT64:
|
||
|
return toUint64(reflect.Indirect(val), fd)
|
||
|
|
||
|
case descriptor.FieldDescriptorProto_TYPE_FLOAT:
|
||
|
return toFloat32(reflect.Indirect(val), fd)
|
||
|
|
||
|
case descriptor.FieldDescriptorProto_TYPE_DOUBLE:
|
||
|
return toFloat64(reflect.Indirect(val), fd)
|
||
|
|
||
|
case descriptor.FieldDescriptorProto_TYPE_BOOL:
|
||
|
return toBool(reflect.Indirect(val), fd)
|
||
|
|
||
|
case descriptor.FieldDescriptorProto_TYPE_BYTES:
|
||
|
return toBytes(reflect.Indirect(val), fd)
|
||
|
|
||
|
case descriptor.FieldDescriptorProto_TYPE_STRING:
|
||
|
return toString(reflect.Indirect(val), fd)
|
||
|
|
||
|
case descriptor.FieldDescriptorProto_TYPE_MESSAGE,
|
||
|
descriptor.FieldDescriptorProto_TYPE_GROUP:
|
||
|
m, err := asMessage(val, fd.GetFullyQualifiedName())
|
||
|
// check that message is correct type
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
var msgType string
|
||
|
if dm, ok := m.(*Message); ok {
|
||
|
if allowNilMessage && dm == nil {
|
||
|
// if dm == nil, we'll panic below, so early out if that is allowed
|
||
|
// (only allowed for map values, to indicate an entry w/ no value)
|
||
|
return m, nil
|
||
|
}
|
||
|
msgType = dm.GetMessageDescriptor().GetFullyQualifiedName()
|
||
|
} else {
|
||
|
msgType = proto.MessageName(m)
|
||
|
}
|
||
|
if msgType != fd.GetMessageType().GetFullyQualifiedName() {
|
||
|
return nil, fmt.Errorf("message field %s requires value of type %s; received %s", fd.GetFullyQualifiedName(), fd.GetMessageType().GetFullyQualifiedName(), msgType)
|
||
|
}
|
||
|
return m, nil
|
||
|
|
||
|
default:
|
||
|
return nil, fmt.Errorf("unable to handle unrecognized field type: %v", fd.GetType())
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func toInt32(v reflect.Value, fd *desc.FieldDescriptor) (int32, error) {
|
||
|
if v.Kind() == reflect.Int32 {
|
||
|
return int32(v.Int()), nil
|
||
|
}
|
||
|
return 0, typeError(fd, v.Type())
|
||
|
}
|
||
|
|
||
|
func toUint32(v reflect.Value, fd *desc.FieldDescriptor) (uint32, error) {
|
||
|
if v.Kind() == reflect.Uint32 {
|
||
|
return uint32(v.Uint()), nil
|
||
|
}
|
||
|
return 0, typeError(fd, v.Type())
|
||
|
}
|
||
|
|
||
|
func toFloat32(v reflect.Value, fd *desc.FieldDescriptor) (float32, error) {
|
||
|
if v.Kind() == reflect.Float32 {
|
||
|
return float32(v.Float()), nil
|
||
|
}
|
||
|
return 0, typeError(fd, v.Type())
|
||
|
}
|
||
|
|
||
|
func toInt64(v reflect.Value, fd *desc.FieldDescriptor) (int64, error) {
|
||
|
if v.Kind() == reflect.Int64 || v.Kind() == reflect.Int || v.Kind() == reflect.Int32 {
|
||
|
return v.Int(), nil
|
||
|
}
|
||
|
return 0, typeError(fd, v.Type())
|
||
|
}
|
||
|
|
||
|
func toUint64(v reflect.Value, fd *desc.FieldDescriptor) (uint64, error) {
|
||
|
if v.Kind() == reflect.Uint64 || v.Kind() == reflect.Uint || v.Kind() == reflect.Uint32 {
|
||
|
return v.Uint(), nil
|
||
|
}
|
||
|
return 0, typeError(fd, v.Type())
|
||
|
}
|
||
|
|
||
|
func toFloat64(v reflect.Value, fd *desc.FieldDescriptor) (float64, error) {
|
||
|
if v.Kind() == reflect.Float64 || v.Kind() == reflect.Float32 {
|
||
|
return v.Float(), nil
|
||
|
}
|
||
|
return 0, typeError(fd, v.Type())
|
||
|
}
|
||
|
|
||
|
func toBool(v reflect.Value, fd *desc.FieldDescriptor) (bool, error) {
|
||
|
if v.Kind() == reflect.Bool {
|
||
|
return v.Bool(), nil
|
||
|
}
|
||
|
return false, typeError(fd, v.Type())
|
||
|
}
|
||
|
|
||
|
func toBytes(v reflect.Value, fd *desc.FieldDescriptor) ([]byte, error) {
|
||
|
if v.Kind() == reflect.Slice && v.Type().Elem().Kind() == reflect.Uint8 {
|
||
|
return v.Bytes(), nil
|
||
|
}
|
||
|
return nil, typeError(fd, v.Type())
|
||
|
}
|
||
|
|
||
|
func toString(v reflect.Value, fd *desc.FieldDescriptor) (string, error) {
|
||
|
if v.Kind() == reflect.String {
|
||
|
return v.String(), nil
|
||
|
}
|
||
|
return "", typeError(fd, v.Type())
|
||
|
}
|
||
|
|
||
|
func typeError(fd *desc.FieldDescriptor, t reflect.Type) error {
|
||
|
return fmt.Errorf(
|
||
|
"%s field %s is not compatible with value of type %v",
|
||
|
getTypeString(fd), fd.GetFullyQualifiedName(), t)
|
||
|
}
|
||
|
|
||
|
func getTypeString(fd *desc.FieldDescriptor) string {
|
||
|
return strings.ToLower(fd.GetType().String())
|
||
|
}
|
||
|
|
||
|
func asMessage(v reflect.Value, fieldName string) (proto.Message, error) {
|
||
|
t := v.Type()
|
||
|
// we need a pointer to a struct that implements proto.Message
|
||
|
if t.Kind() != reflect.Ptr || t.Elem().Kind() != reflect.Struct || !t.Implements(typeOfProtoMessage) {
|
||
|
return nil, fmt.Errorf("message field %s requires is not compatible with value of type %v", fieldName, v.Type())
|
||
|
}
|
||
|
return v.Interface().(proto.Message), nil
|
||
|
}
|
||
|
|
||
|
// Reset resets this message to an empty message. It removes all values set in
|
||
|
// the message.
|
||
|
func (m *Message) Reset() {
|
||
|
for k := range m.values {
|
||
|
delete(m.values, k)
|
||
|
}
|
||
|
for k := range m.unknownFields {
|
||
|
delete(m.unknownFields, k)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// String returns this message rendered in compact text format.
|
||
|
func (m *Message) String() string {
|
||
|
b, err := m.MarshalText()
|
||
|
if err != nil {
|
||
|
panic(fmt.Sprintf("Failed to create string representation of message: %s", err.Error()))
|
||
|
}
|
||
|
return string(b)
|
||
|
}
|
||
|
|
||
|
// ProtoMessage is present to satisfy the proto.Message interface.
|
||
|
func (m *Message) ProtoMessage() {
|
||
|
}
|
||
|
|
||
|
// ConvertTo converts this dynamic message into the given message. This is
|
||
|
// shorthand for resetting then merging:
|
||
|
// target.Reset()
|
||
|
// m.MergeInto(target)
|
||
|
func (m *Message) ConvertTo(target proto.Message) error {
|
||
|
if err := m.checkType(target); err != nil {
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
target.Reset()
|
||
|
return m.mergeInto(target, defaultDeterminism)
|
||
|
}
|
||
|
|
||
|
// ConvertToDeterministic converts this dynamic message into the given message.
|
||
|
// It is just like ConvertTo, but it attempts to produce deterministic results.
|
||
|
// That means that if the target is a generated message (not another dynamic
|
||
|
// message) and the current runtime is unaware of any fields or extensions that
|
||
|
// are present in m, they will be serialized into the target's unrecognized
|
||
|
// fields deterministically.
|
||
|
func (m *Message) ConvertToDeterministic(target proto.Message) error {
|
||
|
if err := m.checkType(target); err != nil {
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
target.Reset()
|
||
|
return m.mergeInto(target, true)
|
||
|
}
|
||
|
|
||
|
// ConvertFrom converts the given message into this dynamic message. This is
|
||
|
// shorthand for resetting then merging:
|
||
|
// m.Reset()
|
||
|
// m.MergeFrom(target)
|
||
|
func (m *Message) ConvertFrom(target proto.Message) error {
|
||
|
if err := m.checkType(target); err != nil {
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
m.Reset()
|
||
|
return m.mergeFrom(target)
|
||
|
}
|
||
|
|
||
|
// MergeInto merges this dynamic message into the given message. All field
|
||
|
// values in this message will be set on the given message. For map fields,
|
||
|
// entries are added to the given message (if the given message has existing
|
||
|
// values for like keys, they are overwritten). For slice fields, elements are
|
||
|
// added.
|
||
|
//
|
||
|
// If the given message has a different set of known fields, it is possible for
|
||
|
// some known fields in this message to be represented as unknown fields in the
|
||
|
// given message after merging, and vice versa.
|
||
|
func (m *Message) MergeInto(target proto.Message) error {
|
||
|
if err := m.checkType(target); err != nil {
|
||
|
return err
|
||
|
}
|
||
|
return m.mergeInto(target, defaultDeterminism)
|
||
|
}
|
||
|
|
||
|
// MergeIntoDeterministic merges this dynamic message into the given message.
|
||
|
// It is just like MergeInto, but it attempts to produce deterministic results.
|
||
|
// That means that if the target is a generated message (not another dynamic
|
||
|
// message) and the current runtime is unaware of any fields or extensions that
|
||
|
// are present in m, they will be serialized into the target's unrecognized
|
||
|
// fields deterministically.
|
||
|
func (m *Message) MergeIntoDeterministic(target proto.Message) error {
|
||
|
if err := m.checkType(target); err != nil {
|
||
|
return err
|
||
|
}
|
||
|
return m.mergeInto(target, true)
|
||
|
}
|
||
|
|
||
|
// MergeFrom merges the given message into this dynamic message. All field
|
||
|
// values in the given message will be set on this message. For map fields,
|
||
|
// entries are added to this message (if this message has existing values for
|
||
|
// like keys, they are overwritten). For slice fields, elements are added.
|
||
|
//
|
||
|
// If the given message has a different set of known fields, it is possible for
|
||
|
// some known fields in that message to be represented as unknown fields in this
|
||
|
// message after merging, and vice versa.
|
||
|
func (m *Message) MergeFrom(source proto.Message) error {
|
||
|
if err := m.checkType(source); err != nil {
|
||
|
return err
|
||
|
}
|
||
|
return m.mergeFrom(source)
|
||
|
}
|
||
|
|
||
|
// Merge implements the proto.Merger interface so that dynamic messages are
|
||
|
// compatible with the proto.Merge function. It delegates to MergeFrom but will
|
||
|
// panic on error as the proto.Merger interface doesn't allow for returning an
|
||
|
// error.
|
||
|
//
|
||
|
// Unlike nearly all other methods, this method can work if this message's type
|
||
|
// is not defined (such as instantiating the message without using NewMessage).
|
||
|
// This is strictly so that dynamic message's are compatible with the
|
||
|
// proto.Clone function, which instantiates a new message via reflection (thus
|
||
|
// its message descriptor will not be set) and than calls Merge.
|
||
|
func (m *Message) Merge(source proto.Message) {
|
||
|
if m.md == nil {
|
||
|
// To support proto.Clone, initialize the descriptor from the source.
|
||
|
if dm, ok := source.(*Message); ok {
|
||
|
m.md = dm.md
|
||
|
// also make sure the clone uses the same message factory and
|
||
|
// extensions and also knows about the same extra fields (if any)
|
||
|
m.mf = dm.mf
|
||
|
m.er = dm.er
|
||
|
m.extraFields = dm.extraFields
|
||
|
} else if md, err := desc.LoadMessageDescriptorForMessage(source); err != nil {
|
||
|
panic(err.Error())
|
||
|
} else {
|
||
|
m.md = md
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if err := m.MergeFrom(source); err != nil {
|
||
|
panic(err.Error())
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func (m *Message) checkType(target proto.Message) error {
|
||
|
if dm, ok := target.(*Message); ok {
|
||
|
if dm.md.GetFullyQualifiedName() != m.md.GetFullyQualifiedName() {
|
||
|
return fmt.Errorf("given message has wrong type: %q; expecting %q", dm.md.GetFullyQualifiedName(), m.md.GetFullyQualifiedName())
|
||
|
}
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
msgName := proto.MessageName(target)
|
||
|
if msgName != m.md.GetFullyQualifiedName() {
|
||
|
return fmt.Errorf("given message has wrong type: %q; expecting %q", msgName, m.md.GetFullyQualifiedName())
|
||
|
}
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
func (m *Message) mergeInto(pm proto.Message, deterministic bool) error {
|
||
|
if dm, ok := pm.(*Message); ok {
|
||
|
return dm.mergeFrom(m)
|
||
|
}
|
||
|
|
||
|
target := reflect.ValueOf(pm)
|
||
|
if target.Kind() == reflect.Ptr {
|
||
|
target = target.Elem()
|
||
|
}
|
||
|
|
||
|
// track tags for which the dynamic message has data but the given
|
||
|
// message doesn't know about it
|
||
|
unknownTags := map[int32]struct{}{}
|
||
|
for tag := range m.values {
|
||
|
unknownTags[tag] = struct{}{}
|
||
|
}
|
||
|
|
||
|
// check that we can successfully do the merge
|
||
|
structProps := proto.GetProperties(reflect.TypeOf(pm).Elem())
|
||
|
for _, prop := range structProps.Prop {
|
||
|
if prop.Tag == 0 {
|
||
|
continue // one-of or special field (such as XXX_unrecognized, etc.)
|
||
|
}
|
||
|
tag := int32(prop.Tag)
|
||
|
v, ok := m.values[tag]
|
||
|
if !ok {
|
||
|
continue
|
||
|
}
|
||
|
if unknownTags != nil {
|
||
|
delete(unknownTags, tag)
|
||
|
}
|
||
|
f := target.FieldByName(prop.Name)
|
||
|
ft := f.Type()
|
||
|
val := reflect.ValueOf(v)
|
||
|
if !canConvert(val, ft) {
|
||
|
return fmt.Errorf("cannot convert %v to %v", val.Type(), ft)
|
||
|
}
|
||
|
}
|
||
|
// check one-of fields
|
||
|
for _, oop := range structProps.OneofTypes {
|
||
|
prop := oop.Prop
|
||
|
tag := int32(prop.Tag)
|
||
|
v, ok := m.values[tag]
|
||
|
if !ok {
|
||
|
continue
|
||
|
}
|
||
|
if unknownTags != nil {
|
||
|
delete(unknownTags, tag)
|
||
|
}
|
||
|
stf, ok := oop.Type.Elem().FieldByName(prop.Name)
|
||
|
if !ok {
|
||
|
return fmt.Errorf("one-of field indicates struct field name %s, but type %v has no such field", prop.Name, oop.Type.Elem())
|
||
|
}
|
||
|
ft := stf.Type
|
||
|
val := reflect.ValueOf(v)
|
||
|
if !canConvert(val, ft) {
|
||
|
return fmt.Errorf("cannot convert %v to %v", val.Type(), ft)
|
||
|
}
|
||
|
}
|
||
|
// and check extensions, too
|
||
|
for tag, ext := range proto.RegisteredExtensions(pm) {
|
||
|
v, ok := m.values[tag]
|
||
|
if !ok {
|
||
|
continue
|
||
|
}
|
||
|
if unknownTags != nil {
|
||
|
delete(unknownTags, tag)
|
||
|
}
|
||
|
ft := reflect.TypeOf(ext.ExtensionType)
|
||
|
val := reflect.ValueOf(v)
|
||
|
if !canConvert(val, ft) {
|
||
|
return fmt.Errorf("cannot convert %v to %v", val.Type(), ft)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// now actually perform the merge
|
||
|
for _, prop := range structProps.Prop {
|
||
|
v, ok := m.values[int32(prop.Tag)]
|
||
|
if !ok {
|
||
|
continue
|
||
|
}
|
||
|
f := target.FieldByName(prop.Name)
|
||
|
if err := mergeVal(reflect.ValueOf(v), f, deterministic); err != nil {
|
||
|
return err
|
||
|
}
|
||
|
}
|
||
|
// merge one-ofs
|
||
|
for _, oop := range structProps.OneofTypes {
|
||
|
prop := oop.Prop
|
||
|
tag := int32(prop.Tag)
|
||
|
v, ok := m.values[tag]
|
||
|
if !ok {
|
||
|
continue
|
||
|
}
|
||
|
oov := reflect.New(oop.Type.Elem())
|
||
|
f := oov.Elem().FieldByName(prop.Name)
|
||
|
if err := mergeVal(reflect.ValueOf(v), f, deterministic); err != nil {
|
||
|
return err
|
||
|
}
|
||
|
target.Field(oop.Field).Set(oov)
|
||
|
}
|
||
|
// merge extensions, too
|
||
|
for tag, ext := range proto.RegisteredExtensions(pm) {
|
||
|
v, ok := m.values[tag]
|
||
|
if !ok {
|
||
|
continue
|
||
|
}
|
||
|
e := reflect.New(reflect.TypeOf(ext.ExtensionType)).Elem()
|
||
|
if err := mergeVal(reflect.ValueOf(v), e, deterministic); err != nil {
|
||
|
return err
|
||
|
}
|
||
|
if err := proto.SetExtension(pm, ext, e.Interface()); err != nil {
|
||
|
// shouldn't happen since we already checked that the extension type was compatible above
|
||
|
return err
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// if we have fields that the given message doesn't know about, add to its unknown fields
|
||
|
if len(unknownTags) > 0 {
|
||
|
var b codec.Buffer
|
||
|
b.SetDeterministic(deterministic)
|
||
|
if deterministic {
|
||
|
// if we need to emit things deterministically, sort the
|
||
|
// extensions by their tag number
|
||
|
sortedUnknownTags := make([]int32, 0, len(unknownTags))
|
||
|
for tag := range unknownTags {
|
||
|
sortedUnknownTags = append(sortedUnknownTags, tag)
|
||
|
}
|
||
|
sort.Slice(sortedUnknownTags, func(i, j int) bool {
|
||
|
return sortedUnknownTags[i] < sortedUnknownTags[j]
|
||
|
})
|
||
|
for _, tag := range sortedUnknownTags {
|
||
|
fd := m.FindFieldDescriptor(tag)
|
||
|
if err := b.EncodeFieldValue(fd, m.values[tag]); err != nil {
|
||
|
return err
|
||
|
}
|
||
|
}
|
||
|
} else {
|
||
|
for tag := range unknownTags {
|
||
|
fd := m.FindFieldDescriptor(tag)
|
||
|
if err := b.EncodeFieldValue(fd, m.values[tag]); err != nil {
|
||
|
return err
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal.SetUnrecognized(pm, b.Bytes())
|
||
|
}
|
||
|
|
||
|
// finally, convey unknown fields into the given message by letting it unmarshal them
|
||
|
// (this will append to its unknown fields if not known; if somehow the given message recognizes
|
||
|
// a field even though the dynamic message did not, it will get correctly unmarshalled)
|
||
|
if unknownTags != nil && len(m.unknownFields) > 0 {
|
||
|
var b codec.Buffer
|
||
|
_ = m.marshalUnknownFields(&b)
|
||
|
_ = proto.UnmarshalMerge(b.Bytes(), pm)
|
||
|
}
|
||
|
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
func canConvert(src reflect.Value, target reflect.Type) bool {
|
||
|
if src.Kind() == reflect.Interface {
|
||
|
src = reflect.ValueOf(src.Interface())
|
||
|
}
|
||
|
srcType := src.Type()
|
||
|
// we allow convertible types instead of requiring exact types so that calling
|
||
|
// code can, for example, assign an enum constant to an enum field. In that case,
|
||
|
// one type is the enum type (a sub-type of int32) and the other may be the int32
|
||
|
// type. So we automatically do the conversion in that case.
|
||
|
if srcType.ConvertibleTo(target) {
|
||
|
return true
|
||
|
} else if target.Kind() == reflect.Ptr && srcType.ConvertibleTo(target.Elem()) {
|
||
|
return true
|
||
|
} else if target.Kind() == reflect.Slice {
|
||
|
if srcType.Kind() != reflect.Slice {
|
||
|
return false
|
||
|
}
|
||
|
et := target.Elem()
|
||
|
for i := 0; i < src.Len(); i++ {
|
||
|
if !canConvert(src.Index(i), et) {
|
||
|
return false
|
||
|
}
|
||
|
}
|
||
|
return true
|
||
|
} else if target.Kind() == reflect.Map {
|
||
|
if srcType.Kind() != reflect.Map {
|
||
|
return false
|
||
|
}
|
||
|
return canConvertMap(src, target)
|
||
|
} else if srcType == typeOfDynamicMessage && target.Implements(typeOfProtoMessage) {
|
||
|
z := reflect.Zero(target).Interface()
|
||
|
msgType := proto.MessageName(z.(proto.Message))
|
||
|
return msgType == src.Interface().(*Message).GetMessageDescriptor().GetFullyQualifiedName()
|
||
|
} else {
|
||
|
return false
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func mergeVal(src, target reflect.Value, deterministic bool) error {
|
||
|
if src.Kind() == reflect.Interface && !src.IsNil() {
|
||
|
src = src.Elem()
|
||
|
}
|
||
|
srcType := src.Type()
|
||
|
targetType := target.Type()
|
||
|
if srcType.ConvertibleTo(targetType) {
|
||
|
if targetType.Implements(typeOfProtoMessage) && !target.IsNil() {
|
||
|
Merge(target.Interface().(proto.Message), src.Convert(targetType).Interface().(proto.Message))
|
||
|
} else {
|
||
|
target.Set(src.Convert(targetType))
|
||
|
}
|
||
|
} else if targetType.Kind() == reflect.Ptr && srcType.ConvertibleTo(targetType.Elem()) {
|
||
|
if !src.CanAddr() {
|
||
|
target.Set(reflect.New(targetType.Elem()))
|
||
|
target.Elem().Set(src.Convert(targetType.Elem()))
|
||
|
} else {
|
||
|
target.Set(src.Addr().Convert(targetType))
|
||
|
}
|
||
|
} else if targetType.Kind() == reflect.Slice {
|
||
|
l := target.Len()
|
||
|
newL := l + src.Len()
|
||
|
if target.Cap() < newL {
|
||
|
// expand capacity of the slice and copy
|
||
|
newSl := reflect.MakeSlice(targetType, newL, newL)
|
||
|
for i := 0; i < target.Len(); i++ {
|
||
|
newSl.Index(i).Set(target.Index(i))
|
||
|
}
|
||
|
target.Set(newSl)
|
||
|
} else {
|
||
|
target.SetLen(newL)
|
||
|
}
|
||
|
for i := 0; i < src.Len(); i++ {
|
||
|
dest := target.Index(l + i)
|
||
|
if dest.Kind() == reflect.Ptr {
|
||
|
dest.Set(reflect.New(dest.Type().Elem()))
|
||
|
}
|
||
|
if err := mergeVal(src.Index(i), dest, deterministic); err != nil {
|
||
|
return err
|
||
|
}
|
||
|
}
|
||
|
} else if targetType.Kind() == reflect.Map {
|
||
|
return mergeMapVal(src, target, targetType, deterministic)
|
||
|
} else if srcType == typeOfDynamicMessage && targetType.Implements(typeOfProtoMessage) {
|
||
|
dm := src.Interface().(*Message)
|
||
|
if target.IsNil() {
|
||
|
target.Set(reflect.New(targetType.Elem()))
|
||
|
}
|
||
|
m := target.Interface().(proto.Message)
|
||
|
if err := dm.mergeInto(m, deterministic); err != nil {
|
||
|
return err
|
||
|
}
|
||
|
} else {
|
||
|
return fmt.Errorf("cannot convert %v to %v", srcType, targetType)
|
||
|
}
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
func (m *Message) mergeFrom(pm proto.Message) error {
|
||
|
if dm, ok := pm.(*Message); ok {
|
||
|
// if given message is also a dynamic message, we merge differently
|
||
|
for tag, v := range dm.values {
|
||
|
fd := m.FindFieldDescriptor(tag)
|
||
|
if fd == nil {
|
||
|
fd = dm.FindFieldDescriptor(tag)
|
||
|
}
|
||
|
if err := mergeField(m, fd, v); err != nil {
|
||
|
return err
|
||
|
}
|
||
|
}
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
pmrv := reflect.ValueOf(pm)
|
||
|
if pmrv.IsNil() {
|
||
|
// nil is an empty message, so nothing to do
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
// check that we can successfully do the merge
|
||
|
src := pmrv.Elem()
|
||
|
values := map[*desc.FieldDescriptor]interface{}{}
|
||
|
props := proto.GetProperties(reflect.TypeOf(pm).Elem())
|
||
|
if props == nil {
|
||
|
return fmt.Errorf("could not determine message properties to merge for %v", reflect.TypeOf(pm).Elem())
|
||
|
}
|
||
|
|
||
|
// regular fields
|
||
|
for _, prop := range props.Prop {
|
||
|
if prop.Tag == 0 {
|
||
|
continue // one-of or special field (such as XXX_unrecognized, etc.)
|
||
|
}
|
||
|
fd := m.FindFieldDescriptor(int32(prop.Tag))
|
||
|
if fd == nil {
|
||
|
// Our descriptor has different fields than this message object. So
|
||
|
// try to reflect on the message object's fields.
|
||
|
md, err := desc.LoadMessageDescriptorForMessage(pm)
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
fd = md.FindFieldByNumber(int32(prop.Tag))
|
||
|
if fd == nil {
|
||
|
return fmt.Errorf("message descriptor %q did not contain field for tag %d (%q)", md.GetFullyQualifiedName(), prop.Tag, prop.Name)
|
||
|
}
|
||
|
}
|
||
|
rv := src.FieldByName(prop.Name)
|
||
|
if (rv.Kind() == reflect.Ptr || rv.Kind() == reflect.Slice) && rv.IsNil() {
|
||
|
continue
|
||
|
}
|
||
|
if v, err := validFieldValueForRv(fd, rv); err != nil {
|
||
|
return err
|
||
|
} else {
|
||
|
values[fd] = v
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// one-of fields
|
||
|
for _, oop := range props.OneofTypes {
|
||
|
oov := src.Field(oop.Field).Elem()
|
||
|
if !oov.IsValid() || oov.Type() != oop.Type {
|
||
|
// this field is unset (in other words, one-of message field is not currently set to this option)
|
||
|
continue
|
||
|
}
|
||
|
prop := oop.Prop
|
||
|
rv := oov.Elem().FieldByName(prop.Name)
|
||
|
fd := m.FindFieldDescriptor(int32(prop.Tag))
|
||
|
if fd == nil {
|
||
|
// Our descriptor has different fields than this message object. So
|
||
|
// try to reflect on the message object's fields.
|
||
|
md, err := desc.LoadMessageDescriptorForMessage(pm)
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
fd = md.FindFieldByNumber(int32(prop.Tag))
|
||
|
if fd == nil {
|
||
|
return fmt.Errorf("message descriptor %q did not contain field for tag %d (%q in one-of %q)", md.GetFullyQualifiedName(), prop.Tag, prop.Name, src.Type().Field(oop.Field).Name)
|
||
|
}
|
||
|
}
|
||
|
if v, err := validFieldValueForRv(fd, rv); err != nil {
|
||
|
return err
|
||
|
} else {
|
||
|
values[fd] = v
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// extension fields
|
||
|
rexts, _ := proto.ExtensionDescs(pm)
|
||
|
for _, ed := range rexts {
|
||
|
v, _ := proto.GetExtension(pm, ed)
|
||
|
if v == nil {
|
||
|
continue
|
||
|
}
|
||
|
if ed.ExtensionType == nil {
|
||
|
// unrecognized extension: we'll handle that below when we
|
||
|
// handle other unrecognized fields
|
||
|
continue
|
||
|
}
|
||
|
fd := m.er.FindExtension(m.md.GetFullyQualifiedName(), ed.Field)
|
||
|
if fd == nil {
|
||
|
var err error
|
||
|
if fd, err = desc.LoadFieldDescriptorForExtension(ed); err != nil {
|
||
|
return err
|
||
|
}
|
||
|
}
|
||
|
if v, err := validFieldValue(fd, v); err != nil {
|
||
|
return err
|
||
|
} else {
|
||
|
values[fd] = v
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// now actually perform the merge
|
||
|
for fd, v := range values {
|
||
|
if err := mergeField(m, fd, v); err != nil {
|
||
|
return err
|
||
|
}
|
||
|
}
|
||
|
|
||
|
data := internal.GetUnrecognized(pm)
|
||
|
if len(data) > 0 {
|
||
|
// ignore any error returned: pulling in unknown fields is best-effort
|
||
|
_ = m.UnmarshalMerge(data)
|
||
|
}
|
||
|
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
// Validate checks that all required fields are present. It returns an error if any are absent.
|
||
|
func (m *Message) Validate() error {
|
||
|
missingFields := m.findMissingFields()
|
||
|
if len(missingFields) == 0 {
|
||
|
return nil
|
||
|
}
|
||
|
return fmt.Errorf("some required fields missing: %v", strings.Join(missingFields, ", "))
|
||
|
}
|
||
|
|
||
|
func (m *Message) findMissingFields() []string {
|
||
|
if m.md.IsProto3() {
|
||
|
// proto3 does not allow required fields
|
||
|
return nil
|
||
|
}
|
||
|
var missingFields []string
|
||
|
for _, fd := range m.md.GetFields() {
|
||
|
if fd.IsRequired() {
|
||
|
if _, ok := m.values[fd.GetNumber()]; !ok {
|
||
|
missingFields = append(missingFields, fd.GetName())
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
return missingFields
|
||
|
}
|
||
|
|
||
|
// ValidateRecursive checks that all required fields are present and also
|
||
|
// recursively validates all fields who are also messages. It returns an error
|
||
|
// if any required fields, in this message or nested within, are absent.
|
||
|
func (m *Message) ValidateRecursive() error {
|
||
|
return m.validateRecursive("")
|
||
|
}
|
||
|
|
||
|
func (m *Message) validateRecursive(prefix string) error {
|
||
|
if missingFields := m.findMissingFields(); len(missingFields) > 0 {
|
||
|
for i := range missingFields {
|
||
|
missingFields[i] = fmt.Sprintf("%s%s", prefix, missingFields[i])
|
||
|
}
|
||
|
return fmt.Errorf("some required fields missing: %v", strings.Join(missingFields, ", "))
|
||
|
}
|
||
|
|
||
|
for tag, fld := range m.values {
|
||
|
fd := m.FindFieldDescriptor(tag)
|
||
|
var chprefix string
|
||
|
var md *desc.MessageDescriptor
|
||
|
checkMsg := func(pm proto.Message) error {
|
||
|
var dm *Message
|
||
|
if d, ok := pm.(*Message); ok {
|
||
|
dm = d
|
||
|
} else if pm != nil {
|
||
|
dm = m.mf.NewDynamicMessage(md)
|
||
|
if err := dm.ConvertFrom(pm); err != nil {
|
||
|
return nil
|
||
|
}
|
||
|
}
|
||
|
if dm == nil {
|
||
|
return nil
|
||
|
}
|
||
|
if err := dm.validateRecursive(chprefix); err != nil {
|
||
|
return err
|
||
|
}
|
||
|
return nil
|
||
|
}
|
||
|
isMap := fd.IsMap()
|
||
|
if isMap && fd.GetMapValueType().GetMessageType() != nil {
|
||
|
md = fd.GetMapValueType().GetMessageType()
|
||
|
mp := fld.(map[interface{}]interface{})
|
||
|
for k, v := range mp {
|
||
|
chprefix = fmt.Sprintf("%s%s[%v].", prefix, getName(fd), k)
|
||
|
if err := checkMsg(v.(proto.Message)); err != nil {
|
||
|
return err
|
||
|
}
|
||
|
}
|
||
|
} else if !isMap && fd.GetMessageType() != nil {
|
||
|
md = fd.GetMessageType()
|
||
|
if fd.IsRepeated() {
|
||
|
sl := fld.([]interface{})
|
||
|
for i, v := range sl {
|
||
|
chprefix = fmt.Sprintf("%s%s[%d].", prefix, getName(fd), i)
|
||
|
if err := checkMsg(v.(proto.Message)); err != nil {
|
||
|
return err
|
||
|
}
|
||
|
}
|
||
|
} else {
|
||
|
chprefix = fmt.Sprintf("%s%s.", prefix, getName(fd))
|
||
|
if err := checkMsg(fld.(proto.Message)); err != nil {
|
||
|
return err
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
func getName(fd *desc.FieldDescriptor) string {
|
||
|
if fd.IsExtension() {
|
||
|
return fmt.Sprintf("(%s)", fd.GetFullyQualifiedName())
|
||
|
} else {
|
||
|
return fd.GetName()
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// knownFieldTags return tags of present and recognized fields, in sorted order.
|
||
|
func (m *Message) knownFieldTags() []int {
|
||
|
if len(m.values) == 0 {
|
||
|
return []int(nil)
|
||
|
}
|
||
|
|
||
|
keys := make([]int, len(m.values))
|
||
|
i := 0
|
||
|
for k := range m.values {
|
||
|
keys[i] = int(k)
|
||
|
i++
|
||
|
}
|
||
|
|
||
|
sort.Ints(keys)
|
||
|
return keys
|
||
|
}
|
||
|
|
||
|
// allKnownFieldTags return tags of present and recognized fields, including
|
||
|
// those that are unset, in sorted order. This only includes extensions that are
|
||
|
// present. Known but not-present extensions are not included in the returned
|
||
|
// set of tags.
|
||
|
func (m *Message) allKnownFieldTags() []int {
|
||
|
fds := m.md.GetFields()
|
||
|
keys := make([]int, 0, len(fds)+len(m.extraFields))
|
||
|
|
||
|
for k := range m.values {
|
||
|
keys = append(keys, int(k))
|
||
|
}
|
||
|
|
||
|
// also include known fields that are not present
|
||
|
for _, fd := range fds {
|
||
|
if _, ok := m.values[fd.GetNumber()]; !ok {
|
||
|
keys = append(keys, int(fd.GetNumber()))
|
||
|
}
|
||
|
}
|
||
|
for _, fd := range m.extraFields {
|
||
|
if !fd.IsExtension() { // skip extensions that are not present
|
||
|
if _, ok := m.values[fd.GetNumber()]; !ok {
|
||
|
keys = append(keys, int(fd.GetNumber()))
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
sort.Ints(keys)
|
||
|
return keys
|
||
|
}
|
||
|
|
||
|
// unknownFieldTags return tags of present but unrecognized fields, in sorted order.
|
||
|
func (m *Message) unknownFieldTags() []int {
|
||
|
if len(m.unknownFields) == 0 {
|
||
|
return []int(nil)
|
||
|
}
|
||
|
keys := make([]int, len(m.unknownFields))
|
||
|
i := 0
|
||
|
for k := range m.unknownFields {
|
||
|
keys[i] = int(k)
|
||
|
i++
|
||
|
}
|
||
|
sort.Ints(keys)
|
||
|
return keys
|
||
|
}
|