// 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" pref "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" ) // 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[pref.FieldNumber]pref.Value ext map[pref.FieldNumber]pref.FieldDescriptor unknown pref.RawFields } // NewMessage creates a new message with the provided descriptor. func NewMessage(desc pref.MessageDescriptor) *Message { return &Message{ typ: messageType{desc}, known: make(map[pref.FieldNumber]pref.Value), ext: make(map[pref.FieldNumber]pref.FieldDescriptor), } } // ProtoReflect implements the protoreflect.ProtoMessage interface. func (m *Message) ProtoReflect() pref.Message { return m } // String returns a string representation of a message. func (m *Message) String() string { return protoimpl.X.MessageStringOf(m) } // Descriptor returns the message descriptor. func (m *Message) Descriptor() pref.MessageDescriptor { return m.typ.desc } // Type returns the message type. func (m *Message) Type() pref.MessageType { return m.typ } // New returns a newly allocated empty message with the same descriptor. // See protoreflect.Message for details. func (m *Message) New() pref.Message { return m.Type().New() } // Interface returns the message. // See protoreflect.Message for details. func (m *Message) Interface() pref.ProtoMessage { return m } // Range visits every populated field in undefined order. // See protoreflect.Message for details. func (m *Message) Range(f func(pref.FieldDescriptor, pref.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 } } } // Range reports whether a field is populated. // See protoreflect.Message for details. func (m *Message) Has(fd pref.FieldDescriptor) bool { m.checkField(fd) if fd.IsExtension() { return m.ext[fd.Number()] == fd } 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 pref.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 pref.FieldDescriptor) pref.Value { m.checkField(fd) num := fd.Number() if fd.IsExtension() { if fd != m.ext[num] { return fd.(pref.ExtensionTypeDescriptor).Type().Zero() } return m.known[num] } if v, ok := m.known[num]; ok { return v } switch { case fd.IsMap(): return pref.ValueOfMap(&dynamicMap{desc: fd}) case fd.IsList(): return pref.ValueOfList(emptyList{desc: fd}) case fd.Message() != nil: return pref.ValueOfMessage(&Message{typ: messageType{fd.Message()}}) case fd.Kind() == pref.BytesKind: return pref.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 pref.FieldDescriptor) pref.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.(pref.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 pref.FieldDescriptor, v pref.Value) { m.checkField(fd) if m.known == nil { panic(errors.New("%v: modification of read-only message", fd.FullName())) } if fd.IsExtension() { if !fd.(pref.ExtensionTypeDescriptor).Type().IsValidValue(v) { 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 pref.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 pref.FieldDescriptor) pref.Value { m.checkField(fd) switch { case fd.IsExtension(): return fd.(pref.ExtensionTypeDescriptor).Type().New() case fd.IsMap(): return pref.ValueOfMap(&dynamicMap{ desc: fd, mapv: make(map[interface{}]pref.Value), }) case fd.IsList(): return pref.ValueOfList(&dynamicList{desc: fd}) case fd.Message() != nil: return pref.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 pref.OneofDescriptor) pref.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() pref.RawFields { return m.unknown } // SetUnknown sets the raw unknown fields. // See protoreflect.Message for details. func (m *Message) SetUnknown(r pref.RawFields) { if m.known == nil { panic(errors.New("%v: modification of read-only message", m.typ.desc.FullName())) } m.unknown = r } func (m *Message) checkField(fd pref.FieldDescriptor) { if fd.IsExtension() && fd.ContainingMessage().FullName() == m.Descriptor().FullName() { if _, ok := fd.(pref.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 pref.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 pref.MessageDescriptor) pref.MessageType { return messageType{desc} } func (mt messageType) New() pref.Message { return NewMessage(mt.desc) } func (mt messageType) Zero() pref.Message { return NewMessage(mt.desc) } func (mt messageType) Descriptor() pref.MessageDescriptor { return mt.desc } type emptyList struct { desc pref.FieldDescriptor } func (x emptyList) Len() int { return 0 } func (x emptyList) Get(n int) pref.Value { panic(errors.New("out of range")) } func (x emptyList) Set(n int, v pref.Value) { panic(errors.New("modification of immutable list")) } func (x emptyList) Append(v pref.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() pref.Value { return newListEntry(x.desc) } type dynamicList struct { desc pref.FieldDescriptor list []pref.Value } func (x *dynamicList) Len() int { return len(x.list) } func (x *dynamicList) Get(n int) pref.Value { return x.list[n] } func (x *dynamicList) Set(n int, v pref.Value) { typecheckSingular(x.desc, v) x.list[n] = v } func (x *dynamicList) Append(v pref.Value) { typecheckSingular(x.desc, v) x.list = append(x.list, 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] = pref.Value{} } x.list = x.list[:n] } func (x *dynamicList) NewElement() pref.Value { return newListEntry(x.desc) } type dynamicMap struct { desc pref.FieldDescriptor mapv map[interface{}]pref.Value } func (x *dynamicMap) Get(k pref.MapKey) pref.Value { return x.mapv[k.Interface()] } func (x *dynamicMap) Set(k pref.MapKey, v pref.Value) { typecheckSingular(x.desc.MapKey(), k.Value()) typecheckSingular(x.desc.MapValue(), v) x.mapv[k.Interface()] = v } func (x *dynamicMap) Has(k pref.MapKey) bool { return x.Get(k).IsValid() } func (x *dynamicMap) Clear(k pref.MapKey) { delete(x.mapv, k.Interface()) } func (x *dynamicMap) Len() int { return len(x.mapv) } func (x *dynamicMap) NewValue() pref.Value { if md := x.desc.MapValue().Message(); md != nil { return pref.ValueOfMessage(NewMessage(md).ProtoReflect()) } return x.desc.MapValue().Default() } func (x *dynamicMap) Range(f func(pref.MapKey, pref.Value) bool) { for k, v := range x.mapv { if !f(pref.ValueOf(k).MapKey(), v) { return } } } func isSet(fd pref.FieldDescriptor, v pref.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() == pref.Proto3: switch fd.Kind() { case pref.BoolKind: return v.Bool() case pref.EnumKind: return v.Enum() != 0 case pref.Int32Kind, pref.Sint32Kind, pref.Int64Kind, pref.Sint64Kind, pref.Sfixed32Kind, pref.Sfixed64Kind: return v.Int() != 0 case pref.Uint32Kind, pref.Uint64Kind, pref.Fixed32Kind, pref.Fixed64Kind: return v.Uint() != 0 case pref.FloatKind, pref.DoubleKind: return v.Float() != 0 || math.Signbit(v.Float()) case pref.StringKind: return v.String() != "" case pref.BytesKind: return len(v.Bytes()) > 0 } } return true } func typecheck(fd pref.FieldDescriptor, v pref.Value) { if err := typeIsValid(fd, v); err != nil { panic(err) } } func typeIsValid(fd pref.FieldDescriptor, v pref.Value) error { switch { case fd.IsMap(): if mapv, ok := v.Interface().(*dynamicMap); !ok || mapv.desc != fd { 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 { return nil } case emptyList: if list.desc == fd { return nil } } return errors.New("%v: assigning invalid type %T", fd.FullName(), v.Interface()) default: return singularTypeIsValid(fd, v) } } func typecheckSingular(fd pref.FieldDescriptor, v pref.Value) { if err := singularTypeIsValid(fd, v); err != nil { panic(err) } } func singularTypeIsValid(fd pref.FieldDescriptor, v pref.Value) error { vi := v.Interface() var ok bool switch fd.Kind() { case pref.BoolKind: _, ok = vi.(bool) case pref.EnumKind: // We could check against the valid set of enum values, but do not. _, ok = vi.(pref.EnumNumber) case pref.Int32Kind, pref.Sint32Kind, pref.Sfixed32Kind: _, ok = vi.(int32) case pref.Uint32Kind, pref.Fixed32Kind: _, ok = vi.(uint32) case pref.Int64Kind, pref.Sint64Kind, pref.Sfixed64Kind: _, ok = vi.(int64) case pref.Uint64Kind, pref.Fixed64Kind: _, ok = vi.(uint64) case pref.FloatKind: _, ok = vi.(float32) case pref.DoubleKind: _, ok = vi.(float64) case pref.StringKind: _, ok = vi.(string) case pref.BytesKind: _, ok = vi.([]byte) case pref.MessageKind, pref.GroupKind: var m pref.Message m, ok = vi.(pref.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 pref.FieldDescriptor) pref.Value { switch fd.Kind() { case pref.BoolKind: return pref.ValueOfBool(false) case pref.EnumKind: return pref.ValueOfEnum(fd.Enum().Values().Get(0).Number()) case pref.Int32Kind, pref.Sint32Kind, pref.Sfixed32Kind: return pref.ValueOfInt32(0) case pref.Uint32Kind, pref.Fixed32Kind: return pref.ValueOfUint32(0) case pref.Int64Kind, pref.Sint64Kind, pref.Sfixed64Kind: return pref.ValueOfInt64(0) case pref.Uint64Kind, pref.Fixed64Kind: return pref.ValueOfUint64(0) case pref.FloatKind: return pref.ValueOfFloat32(0) case pref.DoubleKind: return pref.ValueOfFloat64(0) case pref.StringKind: return pref.ValueOfString("") case pref.BytesKind: return pref.ValueOfBytes(nil) case pref.MessageKind, pref.GroupKind: return pref.ValueOfMessage(NewMessage(fd.Message()).ProtoReflect()) } panic(errors.New("%v: unknown kind %v", fd.FullName(), fd.Kind())) } // extensionType is a dynamic protoreflect.ExtensionType. type extensionType struct { desc extensionTypeDescriptor } // 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 pref.ExtensionDescriptor) pref.ExtensionType { if xt, ok := desc.(pref.ExtensionTypeDescriptor); ok { desc = xt.Descriptor() } return extensionType{extensionTypeDescriptor{desc}} } func (xt extensionType) New() pref.Value { switch { case xt.desc.IsMap(): return pref.ValueOfMap(&dynamicMap{ desc: xt.desc, mapv: make(map[interface{}]pref.Value), }) case xt.desc.IsList(): return pref.ValueOfList(&dynamicList{desc: xt.desc}) case xt.desc.Message() != nil: return pref.ValueOfMessage(NewMessage(xt.desc.Message())) default: return xt.desc.Default() } } func (xt extensionType) Zero() pref.Value { switch { case xt.desc.IsMap(): return pref.ValueOfMap(&dynamicMap{desc: xt.desc}) case xt.desc.Cardinality() == pref.Repeated: return pref.ValueOfList(emptyList{desc: xt.desc}) case xt.desc.Message() != nil: return pref.ValueOfMessage(&Message{typ: messageType{xt.desc.Message()}}) default: return xt.desc.Default() } } func (xt extensionType) TypeDescriptor() pref.ExtensionTypeDescriptor { return xt.desc } func (xt extensionType) ValueOf(iv interface{}) pref.Value { v := pref.ValueOf(iv) typecheck(xt.desc, v) return v } func (xt extensionType) InterfaceOf(v pref.Value) interface{} { typecheck(xt.desc, v) return v.Interface() } func (xt extensionType) IsValidInterface(iv interface{}) bool { return typeIsValid(xt.desc, pref.ValueOf(iv)) == nil } func (xt extensionType) IsValidValue(v pref.Value) bool { return typeIsValid(xt.desc, v) == nil } type extensionTypeDescriptor struct { pref.ExtensionDescriptor } func (xt extensionTypeDescriptor) Type() pref.ExtensionType { return extensionType{xt} } func (xt extensionTypeDescriptor) Descriptor() pref.ExtensionDescriptor { return xt.ExtensionDescriptor }