|
@@ -0,0 +1,717 @@
|
|
|
|
+// Copyright 2019 The Go Authors. All rights reserved.
|
|
|
|
+// Use of this source code is governed by a BSD-style
|
|
|
|
+// license that can be found in the LICENSE file.
|
|
|
|
+
|
|
|
|
+// Package dynamicpb creates protocol buffer messages using runtime type information.
|
|
|
|
+package dynamicpb
|
|
|
|
+
|
|
|
|
+import (
|
|
|
|
+ "math"
|
|
|
|
+
|
|
|
|
+ "google.golang.org/protobuf/internal/errors"
|
|
|
|
+ "google.golang.org/protobuf/reflect/protoreflect"
|
|
|
|
+ "google.golang.org/protobuf/runtime/protoiface"
|
|
|
|
+ "google.golang.org/protobuf/runtime/protoimpl"
|
|
|
|
+)
|
|
|
|
+
|
|
|
|
+// enum is a dynamic protoreflect.Enum.
|
|
|
|
+type enum struct {
|
|
|
|
+ num protoreflect.EnumNumber
|
|
|
|
+ typ protoreflect.EnumType
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (e enum) Descriptor() protoreflect.EnumDescriptor { return e.typ.Descriptor() }
|
|
|
|
+func (e enum) Type() protoreflect.EnumType { return e.typ }
|
|
|
|
+func (e enum) Number() protoreflect.EnumNumber { return e.num }
|
|
|
|
+
|
|
|
|
+// enumType is a dynamic protoreflect.EnumType.
|
|
|
|
+type enumType struct {
|
|
|
|
+ desc protoreflect.EnumDescriptor
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// NewEnumType creates a new EnumType with the provided descriptor.
|
|
|
|
+//
|
|
|
|
+// EnumTypes created by this package are equal if their descriptors are equal.
|
|
|
|
+// That is, if ed1 == ed2, then NewEnumType(ed1) == NewEnumType(ed2).
|
|
|
|
+//
|
|
|
|
+// Enum values created by the EnumType are equal if their numbers are equal.
|
|
|
|
+func NewEnumType(desc protoreflect.EnumDescriptor) protoreflect.EnumType {
|
|
|
|
+ return enumType{desc}
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (et enumType) New(n protoreflect.EnumNumber) protoreflect.Enum { return enum{n, et} }
|
|
|
|
+func (et enumType) Descriptor() protoreflect.EnumDescriptor { return et.desc }
|
|
|
|
+
|
|
|
|
+// extensionType is a dynamic protoreflect.ExtensionType.
|
|
|
|
+type extensionType struct {
|
|
|
|
+ desc extensionTypeDescriptor
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// A Message is a dynamically constructed protocol buffer message.
|
|
|
|
+//
|
|
|
|
+// Message implements the proto.Message interface, and may be used with all
|
|
|
|
+// standard proto package functions such as Marshal, Unmarshal, and so forth.
|
|
|
|
+//
|
|
|
|
+// Message also implements the protoreflect.Message interface. See the protoreflect
|
|
|
|
+// package documentation for that interface for how to get and set fields and
|
|
|
|
+// otherwise interact with the contents of a Message.
|
|
|
|
+//
|
|
|
|
+// Reflection API functions which construct messages, such as NewField,
|
|
|
|
+// return new dynamic messages of the appropriate type. Functions which take
|
|
|
|
+// messages, such as Set for a message-value field, will accept any message
|
|
|
|
+// with a compatible type.
|
|
|
|
+//
|
|
|
|
+// Operations which modify a Message are not safe for concurrent use.
|
|
|
|
+type Message struct {
|
|
|
|
+ typ messageType
|
|
|
|
+ known map[protoreflect.FieldNumber]protoreflect.Value
|
|
|
|
+ ext map[protoreflect.FieldNumber]protoreflect.FieldDescriptor
|
|
|
|
+ unknown protoreflect.RawFields
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+var (
|
|
|
|
+ _ protoreflect.Message = (*Message)(nil)
|
|
|
|
+ _ protoreflect.ProtoMessage = (*Message)(nil)
|
|
|
|
+ _ protoiface.MessageV1 = (*Message)(nil)
|
|
|
|
+)
|
|
|
|
+
|
|
|
|
+// NewMessage creates a new message with the provided descriptor.
|
|
|
|
+func NewMessage(desc protoreflect.MessageDescriptor) *Message {
|
|
|
|
+ return &Message{
|
|
|
|
+ typ: messageType{desc},
|
|
|
|
+ known: make(map[protoreflect.FieldNumber]protoreflect.Value),
|
|
|
|
+ ext: make(map[protoreflect.FieldNumber]protoreflect.FieldDescriptor),
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// ProtoMessage implements the legacy message interface.
|
|
|
|
+func (m *Message) ProtoMessage() {}
|
|
|
|
+
|
|
|
|
+// ProtoReflect implements the protoreflect.ProtoMessage interface.
|
|
|
|
+func (m *Message) ProtoReflect() protoreflect.Message {
|
|
|
|
+ return m
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// String returns a string representation of a message.
|
|
|
|
+func (m *Message) String() string {
|
|
|
|
+ return protoimpl.X.MessageStringOf(m)
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// Reset clears the message to be empty, but preserves the dynamic message type.
|
|
|
|
+func (m *Message) Reset() {
|
|
|
|
+ m.known = make(map[protoreflect.FieldNumber]protoreflect.Value)
|
|
|
|
+ m.ext = make(map[protoreflect.FieldNumber]protoreflect.FieldDescriptor)
|
|
|
|
+ m.unknown = nil
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// Descriptor returns the message descriptor.
|
|
|
|
+func (m *Message) Descriptor() protoreflect.MessageDescriptor {
|
|
|
|
+ return m.typ.desc
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// Type returns the message type.
|
|
|
|
+func (m *Message) Type() protoreflect.MessageType {
|
|
|
|
+ return m.typ
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// New returns a newly allocated empty message with the same descriptor.
|
|
|
|
+// See protoreflect.Message for details.
|
|
|
|
+func (m *Message) New() protoreflect.Message {
|
|
|
|
+ return m.Type().New()
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// Interface returns the message.
|
|
|
|
+// See protoreflect.Message for details.
|
|
|
|
+func (m *Message) Interface() protoreflect.ProtoMessage {
|
|
|
|
+ return m
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// ProtoMethods is an internal detail of the protoreflect.Message interface.
|
|
|
|
+// Users should never call this directly.
|
|
|
|
+func (m *Message) ProtoMethods() *protoiface.Methods {
|
|
|
|
+ return nil
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// Range visits every populated field in undefined order.
|
|
|
|
+// See protoreflect.Message for details.
|
|
|
|
+func (m *Message) Range(f func(protoreflect.FieldDescriptor, protoreflect.Value) bool) {
|
|
|
|
+ for num, v := range m.known {
|
|
|
|
+ fd := m.ext[num]
|
|
|
|
+ if fd == nil {
|
|
|
|
+ fd = m.Descriptor().Fields().ByNumber(num)
|
|
|
|
+ }
|
|
|
|
+ if !isSet(fd, v) {
|
|
|
|
+ continue
|
|
|
|
+ }
|
|
|
|
+ if !f(fd, v) {
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// Has reports whether a field is populated.
|
|
|
|
+// See protoreflect.Message for details.
|
|
|
|
+func (m *Message) Has(fd protoreflect.FieldDescriptor) bool {
|
|
|
|
+ m.checkField(fd)
|
|
|
|
+ if fd.IsExtension() && m.ext[fd.Number()] != fd {
|
|
|
|
+ return false
|
|
|
|
+ }
|
|
|
|
+ v, ok := m.known[fd.Number()]
|
|
|
|
+ if !ok {
|
|
|
|
+ return false
|
|
|
|
+ }
|
|
|
|
+ return isSet(fd, v)
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// Clear clears a field.
|
|
|
|
+// See protoreflect.Message for details.
|
|
|
|
+func (m *Message) Clear(fd protoreflect.FieldDescriptor) {
|
|
|
|
+ m.checkField(fd)
|
|
|
|
+ num := fd.Number()
|
|
|
|
+ delete(m.known, num)
|
|
|
|
+ delete(m.ext, num)
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// Get returns the value of a field.
|
|
|
|
+// See protoreflect.Message for details.
|
|
|
|
+func (m *Message) Get(fd protoreflect.FieldDescriptor) protoreflect.Value {
|
|
|
|
+ m.checkField(fd)
|
|
|
|
+ num := fd.Number()
|
|
|
|
+ if fd.IsExtension() {
|
|
|
|
+ if fd != m.ext[num] {
|
|
|
|
+ return fd.(protoreflect.ExtensionTypeDescriptor).Type().Zero()
|
|
|
|
+ }
|
|
|
|
+ return m.known[num]
|
|
|
|
+ }
|
|
|
|
+ if v, ok := m.known[num]; ok {
|
|
|
|
+ switch {
|
|
|
|
+ case fd.IsMap():
|
|
|
|
+ if v.Map().Len() > 0 {
|
|
|
|
+ return v
|
|
|
|
+ }
|
|
|
|
+ case fd.IsList():
|
|
|
|
+ if v.List().Len() > 0 {
|
|
|
|
+ return v
|
|
|
|
+ }
|
|
|
|
+ default:
|
|
|
|
+ return v
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ switch {
|
|
|
|
+ case fd.IsMap():
|
|
|
|
+ return protoreflect.ValueOfMap(&dynamicMap{desc: fd})
|
|
|
|
+ case fd.IsList():
|
|
|
|
+ return protoreflect.ValueOfList(emptyList{desc: fd})
|
|
|
|
+ case fd.Message() != nil:
|
|
|
|
+ return protoreflect.ValueOfMessage(&Message{typ: messageType{fd.Message()}})
|
|
|
|
+ case fd.Kind() == protoreflect.BytesKind:
|
|
|
|
+ return protoreflect.ValueOfBytes(append([]byte(nil), fd.Default().Bytes()...))
|
|
|
|
+ default:
|
|
|
|
+ return fd.Default()
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// Mutable returns a mutable reference to a repeated, map, or message field.
|
|
|
|
+// See protoreflect.Message for details.
|
|
|
|
+func (m *Message) Mutable(fd protoreflect.FieldDescriptor) protoreflect.Value {
|
|
|
|
+ m.checkField(fd)
|
|
|
|
+ if !fd.IsMap() && !fd.IsList() && fd.Message() == nil {
|
|
|
|
+ panic(errors.New("%v: getting mutable reference to non-composite type", fd.FullName()))
|
|
|
|
+ }
|
|
|
|
+ if m.known == nil {
|
|
|
|
+ panic(errors.New("%v: modification of read-only message", fd.FullName()))
|
|
|
|
+ }
|
|
|
|
+ num := fd.Number()
|
|
|
|
+ if fd.IsExtension() {
|
|
|
|
+ if fd != m.ext[num] {
|
|
|
|
+ m.ext[num] = fd
|
|
|
|
+ m.known[num] = fd.(protoreflect.ExtensionTypeDescriptor).Type().New()
|
|
|
|
+ }
|
|
|
|
+ return m.known[num]
|
|
|
|
+ }
|
|
|
|
+ if v, ok := m.known[num]; ok {
|
|
|
|
+ return v
|
|
|
|
+ }
|
|
|
|
+ m.clearOtherOneofFields(fd)
|
|
|
|
+ m.known[num] = m.NewField(fd)
|
|
|
|
+ if fd.IsExtension() {
|
|
|
|
+ m.ext[num] = fd
|
|
|
|
+ }
|
|
|
|
+ return m.known[num]
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// Set stores a value in a field.
|
|
|
|
+// See protoreflect.Message for details.
|
|
|
|
+func (m *Message) Set(fd protoreflect.FieldDescriptor, v protoreflect.Value) {
|
|
|
|
+ m.checkField(fd)
|
|
|
|
+ if m.known == nil {
|
|
|
|
+ panic(errors.New("%v: modification of read-only message", fd.FullName()))
|
|
|
|
+ }
|
|
|
|
+ if fd.IsExtension() {
|
|
|
|
+ isValid := true
|
|
|
|
+ switch {
|
|
|
|
+ case !fd.(protoreflect.ExtensionTypeDescriptor).Type().IsValidValue(v):
|
|
|
|
+ isValid = false
|
|
|
|
+ case fd.IsList():
|
|
|
|
+ isValid = v.List().IsValid()
|
|
|
|
+ case fd.IsMap():
|
|
|
|
+ isValid = v.Map().IsValid()
|
|
|
|
+ case fd.Message() != nil:
|
|
|
|
+ isValid = v.Message().IsValid()
|
|
|
|
+ }
|
|
|
|
+ if !isValid {
|
|
|
|
+ panic(errors.New("%v: assigning invalid type %T", fd.FullName(), v.Interface()))
|
|
|
|
+ }
|
|
|
|
+ m.ext[fd.Number()] = fd
|
|
|
|
+ } else {
|
|
|
|
+ typecheck(fd, v)
|
|
|
|
+ }
|
|
|
|
+ m.clearOtherOneofFields(fd)
|
|
|
|
+ m.known[fd.Number()] = v
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (m *Message) clearOtherOneofFields(fd protoreflect.FieldDescriptor) {
|
|
|
|
+ od := fd.ContainingOneof()
|
|
|
|
+ if od == nil {
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+ num := fd.Number()
|
|
|
|
+ for i := 0; i < od.Fields().Len(); i++ {
|
|
|
|
+ if n := od.Fields().Get(i).Number(); n != num {
|
|
|
|
+ delete(m.known, n)
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// NewField returns a new value for assignable to the field of a given descriptor.
|
|
|
|
+// See protoreflect.Message for details.
|
|
|
|
+func (m *Message) NewField(fd protoreflect.FieldDescriptor) protoreflect.Value {
|
|
|
|
+ m.checkField(fd)
|
|
|
|
+ switch {
|
|
|
|
+ case fd.IsExtension():
|
|
|
|
+ return fd.(protoreflect.ExtensionTypeDescriptor).Type().New()
|
|
|
|
+ case fd.IsMap():
|
|
|
|
+ return protoreflect.ValueOfMap(&dynamicMap{
|
|
|
|
+ desc: fd,
|
|
|
|
+ mapv: make(map[interface{}]protoreflect.Value),
|
|
|
|
+ })
|
|
|
|
+ case fd.IsList():
|
|
|
|
+ return protoreflect.ValueOfList(&dynamicList{desc: fd})
|
|
|
|
+ case fd.Message() != nil:
|
|
|
|
+ return protoreflect.ValueOfMessage(NewMessage(fd.Message()).ProtoReflect())
|
|
|
|
+ default:
|
|
|
|
+ return fd.Default()
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// WhichOneof reports which field in a oneof is populated, returning nil if none are populated.
|
|
|
|
+// See protoreflect.Message for details.
|
|
|
|
+func (m *Message) WhichOneof(od protoreflect.OneofDescriptor) protoreflect.FieldDescriptor {
|
|
|
|
+ for i := 0; i < od.Fields().Len(); i++ {
|
|
|
|
+ fd := od.Fields().Get(i)
|
|
|
|
+ if m.Has(fd) {
|
|
|
|
+ return fd
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ return nil
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// GetUnknown returns the raw unknown fields.
|
|
|
|
+// See protoreflect.Message for details.
|
|
|
|
+func (m *Message) GetUnknown() protoreflect.RawFields {
|
|
|
|
+ return m.unknown
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// SetUnknown sets the raw unknown fields.
|
|
|
|
+// See protoreflect.Message for details.
|
|
|
|
+func (m *Message) SetUnknown(r protoreflect.RawFields) {
|
|
|
|
+ if m.known == nil {
|
|
|
|
+ panic(errors.New("%v: modification of read-only message", m.typ.desc.FullName()))
|
|
|
|
+ }
|
|
|
|
+ m.unknown = r
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// IsValid reports whether the message is valid.
|
|
|
|
+// See protoreflect.Message for details.
|
|
|
|
+func (m *Message) IsValid() bool {
|
|
|
|
+ return m.known != nil
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (m *Message) checkField(fd protoreflect.FieldDescriptor) {
|
|
|
|
+ if fd.IsExtension() && fd.ContainingMessage().FullName() == m.Descriptor().FullName() {
|
|
|
|
+ if _, ok := fd.(protoreflect.ExtensionTypeDescriptor); !ok {
|
|
|
|
+ panic(errors.New("%v: extension field descriptor does not implement ExtensionTypeDescriptor", fd.FullName()))
|
|
|
|
+ }
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+ if fd.Parent() == m.Descriptor() {
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+ fields := m.Descriptor().Fields()
|
|
|
|
+ index := fd.Index()
|
|
|
|
+ if index >= fields.Len() || fields.Get(index) != fd {
|
|
|
|
+ panic(errors.New("%v: field descriptor does not belong to this message", fd.FullName()))
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+type messageType struct {
|
|
|
|
+ desc protoreflect.MessageDescriptor
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// NewMessageType creates a new MessageType with the provided descriptor.
|
|
|
|
+//
|
|
|
|
+// MessageTypes created by this package are equal if their descriptors are equal.
|
|
|
|
+// That is, if md1 == md2, then NewMessageType(md1) == NewMessageType(md2).
|
|
|
|
+func NewMessageType(desc protoreflect.MessageDescriptor) protoreflect.MessageType {
|
|
|
|
+ return messageType{desc}
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (mt messageType) New() protoreflect.Message { return NewMessage(mt.desc) }
|
|
|
|
+func (mt messageType) Zero() protoreflect.Message { return &Message{typ: messageType{mt.desc}} }
|
|
|
|
+func (mt messageType) Descriptor() protoreflect.MessageDescriptor { return mt.desc }
|
|
|
|
+func (mt messageType) Enum(i int) protoreflect.EnumType {
|
|
|
|
+ if ed := mt.desc.Fields().Get(i).Enum(); ed != nil {
|
|
|
|
+ return NewEnumType(ed)
|
|
|
|
+ }
|
|
|
|
+ return nil
|
|
|
|
+}
|
|
|
|
+func (mt messageType) Message(i int) protoreflect.MessageType {
|
|
|
|
+ if md := mt.desc.Fields().Get(i).Message(); md != nil {
|
|
|
|
+ return NewMessageType(md)
|
|
|
|
+ }
|
|
|
|
+ return nil
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+type emptyList struct {
|
|
|
|
+ desc protoreflect.FieldDescriptor
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (x emptyList) Len() int { return 0 }
|
|
|
|
+func (x emptyList) Get(n int) protoreflect.Value { panic(errors.New("out of range")) }
|
|
|
|
+func (x emptyList) Set(n int, v protoreflect.Value) {
|
|
|
|
+ panic(errors.New("modification of immutable list"))
|
|
|
|
+}
|
|
|
|
+func (x emptyList) Append(v protoreflect.Value) { panic(errors.New("modification of immutable list")) }
|
|
|
|
+func (x emptyList) AppendMutable() protoreflect.Value {
|
|
|
|
+ panic(errors.New("modification of immutable list"))
|
|
|
|
+}
|
|
|
|
+func (x emptyList) Truncate(n int) { panic(errors.New("modification of immutable list")) }
|
|
|
|
+func (x emptyList) NewElement() protoreflect.Value { return newListEntry(x.desc) }
|
|
|
|
+func (x emptyList) IsValid() bool { return false }
|
|
|
|
+
|
|
|
|
+type dynamicList struct {
|
|
|
|
+ desc protoreflect.FieldDescriptor
|
|
|
|
+ list []protoreflect.Value
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (x *dynamicList) Len() int {
|
|
|
|
+ return len(x.list)
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (x *dynamicList) Get(n int) protoreflect.Value {
|
|
|
|
+ return x.list[n]
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (x *dynamicList) Set(n int, v protoreflect.Value) {
|
|
|
|
+ typecheckSingular(x.desc, v)
|
|
|
|
+ x.list[n] = v
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (x *dynamicList) Append(v protoreflect.Value) {
|
|
|
|
+ typecheckSingular(x.desc, v)
|
|
|
|
+ x.list = append(x.list, v)
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (x *dynamicList) AppendMutable() protoreflect.Value {
|
|
|
|
+ if x.desc.Message() == nil {
|
|
|
|
+ panic(errors.New("%v: invalid AppendMutable on list with non-message type", x.desc.FullName()))
|
|
|
|
+ }
|
|
|
|
+ v := x.NewElement()
|
|
|
|
+ x.Append(v)
|
|
|
|
+ return v
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (x *dynamicList) Truncate(n int) {
|
|
|
|
+ // Zero truncated elements to avoid keeping data live.
|
|
|
|
+ for i := n; i < len(x.list); i++ {
|
|
|
|
+ x.list[i] = protoreflect.Value{}
|
|
|
|
+ }
|
|
|
|
+ x.list = x.list[:n]
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (x *dynamicList) NewElement() protoreflect.Value {
|
|
|
|
+ return newListEntry(x.desc)
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (x *dynamicList) IsValid() bool {
|
|
|
|
+ return true
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+type dynamicMap struct {
|
|
|
|
+ desc protoreflect.FieldDescriptor
|
|
|
|
+ mapv map[interface{}]protoreflect.Value
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (x *dynamicMap) Get(k protoreflect.MapKey) protoreflect.Value { return x.mapv[k.Interface()] }
|
|
|
|
+func (x *dynamicMap) Set(k protoreflect.MapKey, v protoreflect.Value) {
|
|
|
|
+ typecheckSingular(x.desc.MapKey(), k.Value())
|
|
|
|
+ typecheckSingular(x.desc.MapValue(), v)
|
|
|
|
+ x.mapv[k.Interface()] = v
|
|
|
|
+}
|
|
|
|
+func (x *dynamicMap) Has(k protoreflect.MapKey) bool { return x.Get(k).IsValid() }
|
|
|
|
+func (x *dynamicMap) Clear(k protoreflect.MapKey) { delete(x.mapv, k.Interface()) }
|
|
|
|
+func (x *dynamicMap) Mutable(k protoreflect.MapKey) protoreflect.Value {
|
|
|
|
+ if x.desc.MapValue().Message() == nil {
|
|
|
|
+ panic(errors.New("%v: invalid Mutable on map with non-message value type", x.desc.FullName()))
|
|
|
|
+ }
|
|
|
|
+ v := x.Get(k)
|
|
|
|
+ if !v.IsValid() {
|
|
|
|
+ v = x.NewValue()
|
|
|
|
+ x.Set(k, v)
|
|
|
|
+ }
|
|
|
|
+ return v
|
|
|
|
+}
|
|
|
|
+func (x *dynamicMap) Len() int { return len(x.mapv) }
|
|
|
|
+func (x *dynamicMap) NewValue() protoreflect.Value {
|
|
|
|
+ if md := x.desc.MapValue().Message(); md != nil {
|
|
|
|
+ return protoreflect.ValueOfMessage(NewMessage(md).ProtoReflect())
|
|
|
|
+ }
|
|
|
|
+ return x.desc.MapValue().Default()
|
|
|
|
+}
|
|
|
|
+func (x *dynamicMap) IsValid() bool {
|
|
|
|
+ return x.mapv != nil
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (x *dynamicMap) Range(f func(protoreflect.MapKey, protoreflect.Value) bool) {
|
|
|
|
+ for k, v := range x.mapv {
|
|
|
|
+ if !f(protoreflect.ValueOf(k).MapKey(), v) {
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func isSet(fd protoreflect.FieldDescriptor, v protoreflect.Value) bool {
|
|
|
|
+ switch {
|
|
|
|
+ case fd.IsMap():
|
|
|
|
+ return v.Map().Len() > 0
|
|
|
|
+ case fd.IsList():
|
|
|
|
+ return v.List().Len() > 0
|
|
|
|
+ case fd.ContainingOneof() != nil:
|
|
|
|
+ return true
|
|
|
|
+ case fd.Syntax() == protoreflect.Proto3 && !fd.IsExtension():
|
|
|
|
+ switch fd.Kind() {
|
|
|
|
+ case protoreflect.BoolKind:
|
|
|
|
+ return v.Bool()
|
|
|
|
+ case protoreflect.EnumKind:
|
|
|
|
+ return v.Enum() != 0
|
|
|
|
+ case protoreflect.Int32Kind, protoreflect.Sint32Kind, protoreflect.Int64Kind, protoreflect.Sint64Kind, protoreflect.Sfixed32Kind, protoreflect.Sfixed64Kind:
|
|
|
|
+ return v.Int() != 0
|
|
|
|
+ case protoreflect.Uint32Kind, protoreflect.Uint64Kind, protoreflect.Fixed32Kind, protoreflect.Fixed64Kind:
|
|
|
|
+ return v.Uint() != 0
|
|
|
|
+ case protoreflect.FloatKind, protoreflect.DoubleKind:
|
|
|
|
+ return v.Float() != 0 || math.Signbit(v.Float())
|
|
|
|
+ case protoreflect.StringKind:
|
|
|
|
+ return v.String() != ""
|
|
|
|
+ case protoreflect.BytesKind:
|
|
|
|
+ return len(v.Bytes()) > 0
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ return true
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func typecheck(fd protoreflect.FieldDescriptor, v protoreflect.Value) {
|
|
|
|
+ if err := typeIsValid(fd, v); err != nil {
|
|
|
|
+ panic(err)
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func typeIsValid(fd protoreflect.FieldDescriptor, v protoreflect.Value) error {
|
|
|
|
+ switch {
|
|
|
|
+ case !v.IsValid():
|
|
|
|
+ return errors.New("%v: assigning invalid value", fd.FullName())
|
|
|
|
+ case fd.IsMap():
|
|
|
|
+ if mapv, ok := v.Interface().(*dynamicMap); !ok || mapv.desc != fd || !mapv.IsValid() {
|
|
|
|
+ return errors.New("%v: assigning invalid type %T", fd.FullName(), v.Interface())
|
|
|
|
+ }
|
|
|
|
+ return nil
|
|
|
|
+ case fd.IsList():
|
|
|
|
+ switch list := v.Interface().(type) {
|
|
|
|
+ case *dynamicList:
|
|
|
|
+ if list.desc == fd && list.IsValid() {
|
|
|
|
+ return nil
|
|
|
|
+ }
|
|
|
|
+ case emptyList:
|
|
|
|
+ if list.desc == fd && list.IsValid() {
|
|
|
|
+ return nil
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ return errors.New("%v: assigning invalid type %T", fd.FullName(), v.Interface())
|
|
|
|
+ default:
|
|
|
|
+ return singularTypeIsValid(fd, v)
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func typecheckSingular(fd protoreflect.FieldDescriptor, v protoreflect.Value) {
|
|
|
|
+ if err := singularTypeIsValid(fd, v); err != nil {
|
|
|
|
+ panic(err)
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func singularTypeIsValid(fd protoreflect.FieldDescriptor, v protoreflect.Value) error {
|
|
|
|
+ vi := v.Interface()
|
|
|
|
+ var ok bool
|
|
|
|
+ switch fd.Kind() {
|
|
|
|
+ case protoreflect.BoolKind:
|
|
|
|
+ _, ok = vi.(bool)
|
|
|
|
+ case protoreflect.EnumKind:
|
|
|
|
+ // We could check against the valid set of enum values, but do not.
|
|
|
|
+ _, ok = vi.(protoreflect.EnumNumber)
|
|
|
|
+ case protoreflect.Int32Kind, protoreflect.Sint32Kind, protoreflect.Sfixed32Kind:
|
|
|
|
+ _, ok = vi.(int32)
|
|
|
|
+ case protoreflect.Uint32Kind, protoreflect.Fixed32Kind:
|
|
|
|
+ _, ok = vi.(uint32)
|
|
|
|
+ case protoreflect.Int64Kind, protoreflect.Sint64Kind, protoreflect.Sfixed64Kind:
|
|
|
|
+ _, ok = vi.(int64)
|
|
|
|
+ case protoreflect.Uint64Kind, protoreflect.Fixed64Kind:
|
|
|
|
+ _, ok = vi.(uint64)
|
|
|
|
+ case protoreflect.FloatKind:
|
|
|
|
+ _, ok = vi.(float32)
|
|
|
|
+ case protoreflect.DoubleKind:
|
|
|
|
+ _, ok = vi.(float64)
|
|
|
|
+ case protoreflect.StringKind:
|
|
|
|
+ _, ok = vi.(string)
|
|
|
|
+ case protoreflect.BytesKind:
|
|
|
|
+ _, ok = vi.([]byte)
|
|
|
|
+ case protoreflect.MessageKind, protoreflect.GroupKind:
|
|
|
|
+ var m protoreflect.Message
|
|
|
|
+ m, ok = vi.(protoreflect.Message)
|
|
|
|
+ if ok && m.Descriptor().FullName() != fd.Message().FullName() {
|
|
|
|
+ return errors.New("%v: assigning invalid message type %v", fd.FullName(), m.Descriptor().FullName())
|
|
|
|
+ }
|
|
|
|
+ if dm, ok := vi.(*Message); ok && dm.known == nil {
|
|
|
|
+ return errors.New("%v: assigning invalid zero-value message", fd.FullName())
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ if !ok {
|
|
|
|
+ return errors.New("%v: assigning invalid type %T", fd.FullName(), v.Interface())
|
|
|
|
+ }
|
|
|
|
+ return nil
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func newListEntry(fd protoreflect.FieldDescriptor) protoreflect.Value {
|
|
|
|
+ switch fd.Kind() {
|
|
|
|
+ case protoreflect.BoolKind:
|
|
|
|
+ return protoreflect.ValueOfBool(false)
|
|
|
|
+ case protoreflect.EnumKind:
|
|
|
|
+ return protoreflect.ValueOfEnum(fd.Enum().Values().Get(0).Number())
|
|
|
|
+ case protoreflect.Int32Kind, protoreflect.Sint32Kind, protoreflect.Sfixed32Kind:
|
|
|
|
+ return protoreflect.ValueOfInt32(0)
|
|
|
|
+ case protoreflect.Uint32Kind, protoreflect.Fixed32Kind:
|
|
|
|
+ return protoreflect.ValueOfUint32(0)
|
|
|
|
+ case protoreflect.Int64Kind, protoreflect.Sint64Kind, protoreflect.Sfixed64Kind:
|
|
|
|
+ return protoreflect.ValueOfInt64(0)
|
|
|
|
+ case protoreflect.Uint64Kind, protoreflect.Fixed64Kind:
|
|
|
|
+ return protoreflect.ValueOfUint64(0)
|
|
|
|
+ case protoreflect.FloatKind:
|
|
|
|
+ return protoreflect.ValueOfFloat32(0)
|
|
|
|
+ case protoreflect.DoubleKind:
|
|
|
|
+ return protoreflect.ValueOfFloat64(0)
|
|
|
|
+ case protoreflect.StringKind:
|
|
|
|
+ return protoreflect.ValueOfString("")
|
|
|
|
+ case protoreflect.BytesKind:
|
|
|
|
+ return protoreflect.ValueOfBytes(nil)
|
|
|
|
+ case protoreflect.MessageKind, protoreflect.GroupKind:
|
|
|
|
+ return protoreflect.ValueOfMessage(NewMessage(fd.Message()).ProtoReflect())
|
|
|
|
+ }
|
|
|
|
+ panic(errors.New("%v: unknown kind %v", fd.FullName(), fd.Kind()))
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// NewExtensionType creates a new ExtensionType with the provided descriptor.
|
|
|
|
+//
|
|
|
|
+// Dynamic ExtensionTypes with the same descriptor compare as equal. That is,
|
|
|
|
+// if xd1 == xd2, then NewExtensionType(xd1) == NewExtensionType(xd2).
|
|
|
|
+//
|
|
|
|
+// The InterfaceOf and ValueOf methods of the extension type are defined as:
|
|
|
|
+//
|
|
|
|
+// func (xt extensionType) ValueOf(iv interface{}) protoreflect.Value {
|
|
|
|
+// return protoreflect.ValueOf(iv)
|
|
|
|
+// }
|
|
|
|
+//
|
|
|
|
+// func (xt extensionType) InterfaceOf(v protoreflect.Value) interface{} {
|
|
|
|
+// return v.Interface()
|
|
|
|
+// }
|
|
|
|
+//
|
|
|
|
+// The Go type used by the proto.GetExtension and proto.SetExtension functions
|
|
|
|
+// is determined by these methods, and is therefore equivalent to the Go type
|
|
|
|
+// used to represent a protoreflect.Value. See the protoreflect.Value
|
|
|
|
+// documentation for more details.
|
|
|
|
+func NewExtensionType(desc protoreflect.ExtensionDescriptor) protoreflect.ExtensionType {
|
|
|
|
+ if xt, ok := desc.(protoreflect.ExtensionTypeDescriptor); ok {
|
|
|
|
+ desc = xt.Descriptor()
|
|
|
|
+ }
|
|
|
|
+ return extensionType{extensionTypeDescriptor{desc}}
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (xt extensionType) New() protoreflect.Value {
|
|
|
|
+ switch {
|
|
|
|
+ case xt.desc.IsMap():
|
|
|
|
+ return protoreflect.ValueOfMap(&dynamicMap{
|
|
|
|
+ desc: xt.desc,
|
|
|
|
+ mapv: make(map[interface{}]protoreflect.Value),
|
|
|
|
+ })
|
|
|
|
+ case xt.desc.IsList():
|
|
|
|
+ return protoreflect.ValueOfList(&dynamicList{desc: xt.desc})
|
|
|
|
+ case xt.desc.Message() != nil:
|
|
|
|
+ return protoreflect.ValueOfMessage(NewMessage(xt.desc.Message()))
|
|
|
|
+ default:
|
|
|
|
+ return xt.desc.Default()
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (xt extensionType) Zero() protoreflect.Value {
|
|
|
|
+ switch {
|
|
|
|
+ case xt.desc.IsMap():
|
|
|
|
+ return protoreflect.ValueOfMap(&dynamicMap{desc: xt.desc})
|
|
|
|
+ case xt.desc.Cardinality() == protoreflect.Repeated:
|
|
|
|
+ return protoreflect.ValueOfList(emptyList{desc: xt.desc})
|
|
|
|
+ case xt.desc.Message() != nil:
|
|
|
|
+ return protoreflect.ValueOfMessage(&Message{typ: messageType{xt.desc.Message()}})
|
|
|
|
+ default:
|
|
|
|
+ return xt.desc.Default()
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (xt extensionType) TypeDescriptor() protoreflect.ExtensionTypeDescriptor {
|
|
|
|
+ return xt.desc
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (xt extensionType) ValueOf(iv interface{}) protoreflect.Value {
|
|
|
|
+ v := protoreflect.ValueOf(iv)
|
|
|
|
+ typecheck(xt.desc, v)
|
|
|
|
+ return v
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (xt extensionType) InterfaceOf(v protoreflect.Value) interface{} {
|
|
|
|
+ typecheck(xt.desc, v)
|
|
|
|
+ return v.Interface()
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (xt extensionType) IsValidInterface(iv interface{}) bool {
|
|
|
|
+ return typeIsValid(xt.desc, protoreflect.ValueOf(iv)) == nil
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (xt extensionType) IsValidValue(v protoreflect.Value) bool {
|
|
|
|
+ return typeIsValid(xt.desc, v) == nil
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+type extensionTypeDescriptor struct {
|
|
|
|
+ protoreflect.ExtensionDescriptor
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (xt extensionTypeDescriptor) Type() protoreflect.ExtensionType {
|
|
|
|
+ return extensionType{xt}
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (xt extensionTypeDescriptor) Descriptor() protoreflect.ExtensionDescriptor {
|
|
|
|
+ return xt.ExtensionDescriptor
|
|
|
|
+}
|