mirror of
https://github.com/protocolbuffers/protobuf-go.git
synced 2025-01-26 18:35:25 +00:00
e14d6b3cdc
Add a new TextName accessor that returns the field name that should be used for the text format. It is usually just the field name, except: 1) it uses the inlined message name for groups, 2) uses the full name surrounded by brackets for extensions, and 3) strips the "message_set_extension" for well-formed extensions to the proto1 MessageSet. We make similar adjustments to the JSONName accessor so that it applies similar semantics for extensions. The two changes simplifies all logic that wants the humanly readable name for a field. Change-Id: I524b6e017fb955146db81819270fe197f8f97980 Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/239838 Reviewed-by: Herbie Ong <herbie@google.com>
259 lines
6.9 KiB
Go
259 lines
6.9 KiB
Go
// Copyright 2020 The Go Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
package protocmp
|
|
|
|
import (
|
|
"reflect"
|
|
"sort"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"google.golang.org/protobuf/internal/genid"
|
|
"google.golang.org/protobuf/proto"
|
|
"google.golang.org/protobuf/reflect/protoreflect"
|
|
"google.golang.org/protobuf/runtime/protoiface"
|
|
)
|
|
|
|
func reflectValueOf(v interface{}) protoreflect.Value {
|
|
switch v := v.(type) {
|
|
case Enum:
|
|
return protoreflect.ValueOfEnum(v.Number())
|
|
case Message:
|
|
return protoreflect.ValueOfMessage(v.ProtoReflect())
|
|
case []byte:
|
|
return protoreflect.ValueOfBytes(v) // avoid overlap with reflect.Slice check below
|
|
default:
|
|
switch rv := reflect.ValueOf(v); {
|
|
case rv.Kind() == reflect.Slice:
|
|
return protoreflect.ValueOfList(reflectList{rv})
|
|
case rv.Kind() == reflect.Map:
|
|
return protoreflect.ValueOfMap(reflectMap{rv})
|
|
default:
|
|
return protoreflect.ValueOf(v)
|
|
}
|
|
}
|
|
}
|
|
|
|
type reflectMessage Message
|
|
|
|
func (m reflectMessage) stringKey(fd protoreflect.FieldDescriptor) string {
|
|
if m.Descriptor() != fd.ContainingMessage() {
|
|
panic("mismatching containing message")
|
|
}
|
|
return fd.TextName()
|
|
}
|
|
|
|
func (m reflectMessage) Descriptor() protoreflect.MessageDescriptor {
|
|
return (Message)(m).Descriptor()
|
|
}
|
|
func (m reflectMessage) Type() protoreflect.MessageType {
|
|
return reflectMessageType{m.Descriptor()}
|
|
}
|
|
func (m reflectMessage) New() protoreflect.Message {
|
|
return m.Type().New()
|
|
}
|
|
func (m reflectMessage) Interface() protoreflect.ProtoMessage {
|
|
return Message(m)
|
|
}
|
|
func (m reflectMessage) Range(f func(fd protoreflect.FieldDescriptor, v protoreflect.Value) bool) {
|
|
// Range over populated known fields.
|
|
fds := m.Descriptor().Fields()
|
|
for i := 0; i < fds.Len(); i++ {
|
|
fd := fds.Get(i)
|
|
if m.Has(fd) && !f(fd, m.Get(fd)) {
|
|
return
|
|
}
|
|
}
|
|
|
|
// Range over populated extension fields.
|
|
for _, xd := range m[messageTypeKey].(messageType).xds {
|
|
if m.Has(xd) && !f(xd, m.Get(xd)) {
|
|
return
|
|
}
|
|
}
|
|
}
|
|
func (m reflectMessage) Has(fd protoreflect.FieldDescriptor) bool {
|
|
_, ok := m[m.stringKey(fd)]
|
|
return ok
|
|
}
|
|
func (m reflectMessage) Clear(protoreflect.FieldDescriptor) {
|
|
panic("invalid mutation of read-only message")
|
|
}
|
|
func (m reflectMessage) Get(fd protoreflect.FieldDescriptor) protoreflect.Value {
|
|
v, ok := m[m.stringKey(fd)]
|
|
if !ok {
|
|
switch {
|
|
case fd.IsList():
|
|
return protoreflect.ValueOfList(reflectList{})
|
|
case fd.IsMap():
|
|
return protoreflect.ValueOfMap(reflectMap{})
|
|
case fd.Message() != nil:
|
|
return protoreflect.ValueOfMessage(reflectMessage{
|
|
messageTypeKey: messageType{md: m.Descriptor()},
|
|
})
|
|
default:
|
|
return fd.Default()
|
|
}
|
|
}
|
|
|
|
// The transformation may leave Any messages in structured form.
|
|
// If so, convert them back to a raw-encoded form.
|
|
if fd.FullName() == genid.Any_Value_field_fullname {
|
|
if m, ok := v.(Message); ok {
|
|
b, err := proto.MarshalOptions{Deterministic: true}.Marshal(m)
|
|
if err != nil {
|
|
panic("BUG: " + err.Error())
|
|
}
|
|
return protoreflect.ValueOfBytes(b)
|
|
}
|
|
}
|
|
|
|
return reflectValueOf(v)
|
|
}
|
|
func (m reflectMessage) Set(protoreflect.FieldDescriptor, protoreflect.Value) {
|
|
panic("invalid mutation of read-only message")
|
|
}
|
|
func (m reflectMessage) Mutable(fd protoreflect.FieldDescriptor) protoreflect.Value {
|
|
panic("invalid mutation of read-only message")
|
|
}
|
|
func (m reflectMessage) NewField(protoreflect.FieldDescriptor) protoreflect.Value {
|
|
panic("not implemented")
|
|
}
|
|
func (m reflectMessage) WhichOneof(od protoreflect.OneofDescriptor) protoreflect.FieldDescriptor {
|
|
if m.Descriptor().Oneofs().ByName(od.Name()) != od {
|
|
panic("oneof descriptor does not belong to this message")
|
|
}
|
|
fds := od.Fields()
|
|
for i := 0; i < fds.Len(); i++ {
|
|
fd := fds.Get(i)
|
|
if _, ok := m[m.stringKey(fd)]; ok {
|
|
return fd
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
func (m reflectMessage) GetUnknown() protoreflect.RawFields {
|
|
var nums []protoreflect.FieldNumber
|
|
for k := range m {
|
|
if len(strings.Trim(k, "0123456789")) == 0 {
|
|
n, _ := strconv.ParseUint(k, 10, 32)
|
|
nums = append(nums, protoreflect.FieldNumber(n))
|
|
}
|
|
}
|
|
sort.Slice(nums, func(i, j int) bool { return nums[i] < nums[j] })
|
|
|
|
var raw protoreflect.RawFields
|
|
for _, num := range nums {
|
|
b, _ := m[strconv.FormatUint(uint64(num), 10)].(protoreflect.RawFields)
|
|
raw = append(raw, b...)
|
|
}
|
|
return raw
|
|
}
|
|
func (m reflectMessage) SetUnknown(protoreflect.RawFields) {
|
|
panic("invalid mutation of read-only message")
|
|
}
|
|
func (m reflectMessage) IsValid() bool {
|
|
invalid, _ := m[messageInvalidKey].(bool)
|
|
return !invalid
|
|
}
|
|
func (m reflectMessage) ProtoMethods() *protoiface.Methods {
|
|
return nil
|
|
}
|
|
|
|
type reflectMessageType struct{ protoreflect.MessageDescriptor }
|
|
|
|
func (t reflectMessageType) New() protoreflect.Message {
|
|
panic("not implemented")
|
|
}
|
|
func (t reflectMessageType) Zero() protoreflect.Message {
|
|
panic("not implemented")
|
|
}
|
|
func (t reflectMessageType) Descriptor() protoreflect.MessageDescriptor {
|
|
return t.MessageDescriptor
|
|
}
|
|
|
|
type reflectList struct{ v reflect.Value }
|
|
|
|
func (ls reflectList) Len() int {
|
|
if !ls.IsValid() {
|
|
return 0
|
|
}
|
|
return ls.v.Len()
|
|
}
|
|
func (ls reflectList) Get(i int) protoreflect.Value {
|
|
return reflectValueOf(ls.v.Index(i).Interface())
|
|
}
|
|
func (ls reflectList) Set(int, protoreflect.Value) {
|
|
panic("invalid mutation of read-only list")
|
|
}
|
|
func (ls reflectList) Append(protoreflect.Value) {
|
|
panic("invalid mutation of read-only list")
|
|
}
|
|
func (ls reflectList) AppendMutable() protoreflect.Value {
|
|
panic("invalid mutation of read-only list")
|
|
}
|
|
func (ls reflectList) Truncate(int) {
|
|
panic("invalid mutation of read-only list")
|
|
}
|
|
func (ls reflectList) NewElement() protoreflect.Value {
|
|
panic("not implemented")
|
|
}
|
|
func (ls reflectList) IsValid() bool {
|
|
return ls.v.IsValid()
|
|
}
|
|
|
|
type reflectMap struct{ v reflect.Value }
|
|
|
|
func (ms reflectMap) Len() int {
|
|
if !ms.IsValid() {
|
|
return 0
|
|
}
|
|
return ms.v.Len()
|
|
}
|
|
func (ms reflectMap) Range(f func(protoreflect.MapKey, protoreflect.Value) bool) {
|
|
if !ms.IsValid() {
|
|
return
|
|
}
|
|
ks := ms.v.MapKeys()
|
|
for _, k := range ks {
|
|
pk := reflectValueOf(k.Interface()).MapKey()
|
|
pv := reflectValueOf(ms.v.MapIndex(k).Interface())
|
|
if !f(pk, pv) {
|
|
return
|
|
}
|
|
}
|
|
}
|
|
func (ms reflectMap) Has(k protoreflect.MapKey) bool {
|
|
if !ms.IsValid() {
|
|
return false
|
|
}
|
|
return ms.v.MapIndex(reflect.ValueOf(k.Interface())).IsValid()
|
|
}
|
|
func (ms reflectMap) Clear(protoreflect.MapKey) {
|
|
panic("invalid mutation of read-only list")
|
|
}
|
|
func (ms reflectMap) Get(k protoreflect.MapKey) protoreflect.Value {
|
|
if !ms.IsValid() {
|
|
return protoreflect.Value{}
|
|
}
|
|
v := ms.v.MapIndex(reflect.ValueOf(k.Interface()))
|
|
if !v.IsValid() {
|
|
return protoreflect.Value{}
|
|
}
|
|
return reflectValueOf(v.Interface())
|
|
}
|
|
func (ms reflectMap) Set(protoreflect.MapKey, protoreflect.Value) {
|
|
panic("invalid mutation of read-only list")
|
|
}
|
|
func (ms reflectMap) Mutable(k protoreflect.MapKey) protoreflect.Value {
|
|
panic("invalid mutation of read-only list")
|
|
}
|
|
func (ms reflectMap) NewValue() protoreflect.Value {
|
|
panic("not implemented")
|
|
}
|
|
func (ms reflectMap) IsValid() bool {
|
|
return ms.v.IsValid()
|
|
}
|