| // 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 [google.golang.org/protobuf/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[any]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[any]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.HasPresence() && !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 any) protoreflect.Value { | |
| // return protoreflect.ValueOf(iv) | |
| // } | |
| // | |
| // func (xt extensionType) InterfaceOf(v protoreflect.Value) any { | |
| // 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[any]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 any) protoreflect.Value { | |
| v := protoreflect.ValueOf(iv) | |
| typecheck(xt.desc, v) | |
| return v | |
| } | |
| func (xt extensionType) InterfaceOf(v protoreflect.Value) any { | |
| typecheck(xt.desc, v) | |
| return v.Interface() | |
| } | |
| func (xt extensionType) IsValidInterface(iv any) 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 | |
| } |