mirror of
https://github.com/protocolbuffers/protobuf-go.git
synced 2025-01-27 03:35:32 +00:00
reflect/protoreflect: add helper methods to FieldDescriptor
Added API: FieldDescriptor.IsExtension FieldDescriptor.IsList FieldDescriptor.MapKey FieldDescriptor.MapValue FieldDescriptor.ContainingOneof FieldDescriptor.ContainingMessage Deprecated API (to be removed in subsequent CL): FieldDescriptor.Oneof FieldDescriptor.Extendee These methods help cleanup several common usage patterns. Change-Id: I9a3ffabc2edb2173c536509b22f330f98bba7cf3 Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/176977 Reviewed-by: Damien Neil <dneil@google.com>
This commit is contained in:
parent
67c1d9b2c1
commit
ac31a352ca
@ -559,20 +559,21 @@ func fieldGoType(g *protogen.GeneratedFile, field *protogen.Field) (goType strin
|
||||
goType = "[]byte"
|
||||
pointer = false
|
||||
case protoreflect.MessageKind, protoreflect.GroupKind:
|
||||
if field.Desc.IsMap() {
|
||||
keyType, _ := fieldGoType(g, field.Message.Fields[0])
|
||||
valType, _ := fieldGoType(g, field.Message.Fields[1])
|
||||
return fmt.Sprintf("map[%v]%v", keyType, valType), false
|
||||
}
|
||||
goType = "*" + g.QualifiedGoIdent(field.Message.GoIdent)
|
||||
pointer = false
|
||||
}
|
||||
if field.Desc.Cardinality() == protoreflect.Repeated {
|
||||
switch {
|
||||
case field.Desc.IsList():
|
||||
goType = "[]" + goType
|
||||
pointer = false
|
||||
case field.Desc.IsMap():
|
||||
keyType, _ := fieldGoType(g, field.Message.Fields[0])
|
||||
valType, _ := fieldGoType(g, field.Message.Fields[1])
|
||||
return fmt.Sprintf("map[%v]%v", keyType, valType), false
|
||||
}
|
||||
|
||||
// Extension fields always have pointer type, even when defined in a proto3 file.
|
||||
if field.Desc.Syntax() == protoreflect.Proto3 && field.Desc.Extendee() == nil {
|
||||
if field.Desc.Syntax() == protoreflect.Proto3 && !field.Desc.IsExtension() {
|
||||
pointer = false
|
||||
}
|
||||
return goType, pointer
|
||||
@ -587,7 +588,7 @@ func fieldProtobufTag(field *protogen.Field) string {
|
||||
}
|
||||
|
||||
func fieldDefaultValue(g *protogen.GeneratedFile, message *protogen.Message, field *protogen.Field) string {
|
||||
if field.Desc.Cardinality() == protoreflect.Repeated {
|
||||
if field.Desc.IsList() {
|
||||
return "nil"
|
||||
}
|
||||
if field.Desc.HasDefault() {
|
||||
@ -653,7 +654,7 @@ func genExtensions(gen *protogen.Plugin, g *protogen.GeneratedFile, f *fileInfo)
|
||||
g.P("var (")
|
||||
for i, extension := range f.allExtensions {
|
||||
ed := extension.Desc
|
||||
targetName := string(ed.Extendee().FullName())
|
||||
targetName := string(ed.ContainingMessage().FullName())
|
||||
typeName := ed.Kind().String()
|
||||
switch ed.Kind() {
|
||||
case protoreflect.EnumKind:
|
||||
|
@ -49,13 +49,12 @@ func fillMessage(m pref.Message, level int) {
|
||||
for i := 0; i < fieldDescs.Len(); i++ {
|
||||
fd := fieldDescs.Get(i)
|
||||
num := fd.Number()
|
||||
if cardinality := fd.Cardinality(); cardinality == pref.Repeated {
|
||||
if !fd.IsMap() {
|
||||
setList(knownFields.Get(num).List(), fd, level)
|
||||
} else {
|
||||
setMap(knownFields.Get(num).Map(), fd, level)
|
||||
}
|
||||
} else {
|
||||
switch {
|
||||
case fd.IsList():
|
||||
setList(knownFields.Get(num).List(), fd, level)
|
||||
case fd.IsMap():
|
||||
setMap(knownFields.Get(num).Map(), fd, level)
|
||||
default:
|
||||
setScalarField(knownFields, fd, level)
|
||||
}
|
||||
}
|
||||
|
@ -244,14 +244,20 @@ Loop:
|
||||
continue
|
||||
}
|
||||
|
||||
if cardinality := fd.Cardinality(); cardinality == pref.Repeated {
|
||||
// Map or list fields have cardinality of repeated.
|
||||
if err := o.unmarshalRepeated(knownFields, fd); !nerr.Merge(err) {
|
||||
switch {
|
||||
case fd.IsList():
|
||||
list := knownFields.Get(fd.Number()).List()
|
||||
if err := o.unmarshalList(list, fd); !nerr.Merge(err) {
|
||||
return errors.New("%v|%q: %v", fd.FullName(), name, err)
|
||||
}
|
||||
} else {
|
||||
case fd.IsMap():
|
||||
mmap := knownFields.Get(fd.Number()).Map()
|
||||
if err := o.unmarshalMap(mmap, fd); !nerr.Merge(err) {
|
||||
return errors.New("%v|%q: %v", fd.FullName(), name, err)
|
||||
}
|
||||
default:
|
||||
// If field is a oneof, check if it has already been set.
|
||||
if od := fd.Oneof(); od != nil {
|
||||
if od := fd.ContainingOneof(); od != nil {
|
||||
idx := uint64(od.Index())
|
||||
if seenOneofs.Has(idx) {
|
||||
return errors.New("%v: oneof is already set", od.FullName())
|
||||
@ -548,24 +554,6 @@ func unmarshalEnum(jval json.Value, fd pref.FieldDescriptor) (pref.Value, error)
|
||||
return pref.Value{}, unexpectedJSONError{jval}
|
||||
}
|
||||
|
||||
// unmarshalRepeated unmarshals into a repeated field.
|
||||
func (o UnmarshalOptions) unmarshalRepeated(knownFields pref.KnownFields, fd pref.FieldDescriptor) error {
|
||||
var nerr errors.NonFatal
|
||||
num := fd.Number()
|
||||
val := knownFields.Get(num)
|
||||
if !fd.IsMap() {
|
||||
if err := o.unmarshalList(val.List(), fd); !nerr.Merge(err) {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
if err := o.unmarshalMap(val.Map(), fd); !nerr.Merge(err) {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nerr.E
|
||||
}
|
||||
|
||||
// unmarshalList unmarshals into given protoreflect.List.
|
||||
func (o UnmarshalOptions) unmarshalList(list pref.List, fd pref.FieldDescriptor) error {
|
||||
var nerr errors.NonFatal
|
||||
jval, err := o.decoder.Read()
|
||||
@ -610,10 +598,8 @@ func (o UnmarshalOptions) unmarshalList(list pref.List, fd pref.FieldDescriptor)
|
||||
return nerr.E
|
||||
}
|
||||
|
||||
// unmarshalMap unmarshals into given protoreflect.Map.
|
||||
func (o UnmarshalOptions) unmarshalMap(mmap pref.Map, fd pref.FieldDescriptor) error {
|
||||
var nerr errors.NonFatal
|
||||
|
||||
jval, err := o.decoder.Read()
|
||||
if !nerr.Merge(err) {
|
||||
return err
|
||||
@ -622,17 +608,11 @@ func (o UnmarshalOptions) unmarshalMap(mmap pref.Map, fd pref.FieldDescriptor) e
|
||||
return unexpectedJSONError{jval}
|
||||
}
|
||||
|
||||
fields := fd.Message().Fields()
|
||||
keyDesc := fields.ByNumber(1)
|
||||
valDesc := fields.ByNumber(2)
|
||||
|
||||
// Determine ahead whether map entry is a scalar type or a message type in
|
||||
// order to call the appropriate unmarshalMapValue func inside the for loop
|
||||
// below.
|
||||
unmarshalMapValue := func() (pref.Value, error) {
|
||||
return o.unmarshalScalar(valDesc)
|
||||
}
|
||||
switch valDesc.Kind() {
|
||||
var unmarshalMapValue func() (pref.Value, error)
|
||||
switch fd.MapValue().Kind() {
|
||||
case pref.MessageKind, pref.GroupKind:
|
||||
unmarshalMapValue = func() (pref.Value, error) {
|
||||
var nerr errors.NonFatal
|
||||
@ -642,6 +622,10 @@ func (o UnmarshalOptions) unmarshalMap(mmap pref.Map, fd pref.FieldDescriptor) e
|
||||
}
|
||||
return pref.ValueOf(m), nerr.E
|
||||
}
|
||||
default:
|
||||
unmarshalMapValue = func() (pref.Value, error) {
|
||||
return o.unmarshalScalar(fd.MapValue())
|
||||
}
|
||||
}
|
||||
|
||||
Loop:
|
||||
@ -666,7 +650,7 @@ Loop:
|
||||
}
|
||||
|
||||
// Unmarshal field name.
|
||||
pkey, err := unmarshalMapKey(name, keyDesc)
|
||||
pkey, err := unmarshalMapKey(name, fd.MapKey())
|
||||
if !nerr.Merge(err) {
|
||||
return err
|
||||
}
|
||||
|
@ -118,25 +118,14 @@ func (o MarshalOptions) marshalFields(m pref.Message) error {
|
||||
|
||||
// marshalValue marshals the given protoreflect.Value.
|
||||
func (o MarshalOptions) marshalValue(val pref.Value, fd pref.FieldDescriptor) error {
|
||||
var nerr errors.NonFatal
|
||||
if fd.Cardinality() == pref.Repeated {
|
||||
// Map or repeated fields.
|
||||
if fd.IsMap() {
|
||||
if err := o.marshalMap(val.Map(), fd); !nerr.Merge(err) {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
if err := o.marshalList(val.List(), fd); !nerr.Merge(err) {
|
||||
return err
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Required or optional fields.
|
||||
if err := o.marshalSingular(val, fd); !nerr.Merge(err) {
|
||||
return err
|
||||
}
|
||||
switch {
|
||||
case fd.IsList():
|
||||
return o.marshalList(val.List(), fd)
|
||||
case fd.IsMap():
|
||||
return o.marshalMap(val.Map(), fd)
|
||||
default:
|
||||
return o.marshalSingular(val, fd)
|
||||
}
|
||||
return nerr.E
|
||||
}
|
||||
|
||||
// marshalSingular marshals the given non-repeated field value. This includes
|
||||
@ -226,17 +215,13 @@ func (o MarshalOptions) marshalMap(mmap pref.Map, fd pref.FieldDescriptor) error
|
||||
o.encoder.StartObject()
|
||||
defer o.encoder.EndObject()
|
||||
|
||||
msgFields := fd.Message().Fields()
|
||||
keyType := msgFields.ByNumber(1)
|
||||
valType := msgFields.ByNumber(2)
|
||||
|
||||
// Get a sorted list based on keyType first.
|
||||
entries := make([]mapEntry, 0, mmap.Len())
|
||||
mmap.Range(func(key pref.MapKey, val pref.Value) bool {
|
||||
entries = append(entries, mapEntry{key: key, value: val})
|
||||
return true
|
||||
})
|
||||
sortMap(keyType.Kind(), entries)
|
||||
sortMap(fd.MapKey().Kind(), entries)
|
||||
|
||||
// Write out sorted list.
|
||||
var nerr errors.NonFatal
|
||||
@ -244,7 +229,7 @@ func (o MarshalOptions) marshalMap(mmap pref.Map, fd pref.FieldDescriptor) error
|
||||
if err := o.encoder.WriteName(entry.key.String()); !nerr.Merge(err) {
|
||||
return err
|
||||
}
|
||||
if err := o.marshalSingular(entry.value, valType); !nerr.Merge(err) {
|
||||
if err := o.marshalSingular(entry.value, fd.MapValue()); !nerr.Merge(err) {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@ -333,6 +318,6 @@ func isMessageSetExtension(xt pref.ExtensionType) bool {
|
||||
if xd.FullName().Parent() != md.FullName() {
|
||||
return false
|
||||
}
|
||||
xmd, ok := xd.Extendee().(interface{ IsMessageSet() bool })
|
||||
xmd, ok := xd.ContainingMessage().(interface{ IsMessageSet() bool })
|
||||
return ok && xmd.IsMessageSet()
|
||||
}
|
||||
|
@ -159,14 +159,36 @@ func (o UnmarshalOptions) unmarshalMessage(tmsg [][2]text.Value, m pref.Message)
|
||||
return errors.New("%v contains unknown field: %v", messageDesc.FullName(), tkey)
|
||||
}
|
||||
|
||||
if cardinality := fd.Cardinality(); cardinality == pref.Repeated {
|
||||
// Map or list fields have cardinality of repeated.
|
||||
if err := o.unmarshalRepeated(tval, fd, knownFields); !nerr.Merge(err) {
|
||||
switch {
|
||||
case fd.IsList():
|
||||
// If input is not a list, turn it into a list.
|
||||
var items []text.Value
|
||||
if tval.Type() != text.List {
|
||||
items = []text.Value{tval}
|
||||
} else {
|
||||
items = tval.List()
|
||||
}
|
||||
|
||||
list := knownFields.Get(fd.Number()).List()
|
||||
if err := o.unmarshalList(items, fd, list); !nerr.Merge(err) {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
case fd.IsMap():
|
||||
// If input is not a list, turn it into a list.
|
||||
var items []text.Value
|
||||
if tval.Type() != text.List {
|
||||
items = []text.Value{tval}
|
||||
} else {
|
||||
items = tval.List()
|
||||
}
|
||||
|
||||
mmap := knownFields.Get(fd.Number()).Map()
|
||||
if err := o.unmarshalMap(items, fd, mmap); !nerr.Merge(err) {
|
||||
return err
|
||||
}
|
||||
default:
|
||||
// If field is a oneof, check if it has already been set.
|
||||
if od := fd.Oneof(); od != nil {
|
||||
if od := fd.ContainingOneof(); od != nil {
|
||||
idx := uint64(od.Index())
|
||||
if seenOneofs.Has(idx) {
|
||||
return errors.New("oneof %v is already set", od.FullName())
|
||||
@ -232,33 +254,6 @@ func (o UnmarshalOptions) unmarshalSingular(input text.Value, fd pref.FieldDescr
|
||||
return nerr.E
|
||||
}
|
||||
|
||||
// unmarshalRepeated unmarshals given text.Value into a repeated field. Caller should only
|
||||
// call this for cardinality=repeated.
|
||||
func (o UnmarshalOptions) unmarshalRepeated(input text.Value, fd pref.FieldDescriptor, knownFields pref.KnownFields) error {
|
||||
var items []text.Value
|
||||
// If input is not a list, turn it into a list.
|
||||
if input.Type() != text.List {
|
||||
items = []text.Value{input}
|
||||
} else {
|
||||
items = input.List()
|
||||
}
|
||||
|
||||
var nerr errors.NonFatal
|
||||
num := fd.Number()
|
||||
val := knownFields.Get(num)
|
||||
if !fd.IsMap() {
|
||||
if err := o.unmarshalList(items, fd, val.List()); !nerr.Merge(err) {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
if err := o.unmarshalMap(items, fd, val.Map()); !nerr.Merge(err) {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nerr.E
|
||||
}
|
||||
|
||||
// unmarshalScalar converts the given text.Value to a scalar/enum protoreflect.Value specified in
|
||||
// the given FieldDescriptor. Caller should not pass in a FieldDescriptor for a message/group kind.
|
||||
func unmarshalScalar(input text.Value, fd pref.FieldDescriptor) (pref.Value, error) {
|
||||
@ -358,14 +353,11 @@ func (o UnmarshalOptions) unmarshalList(inputList []text.Value, fd pref.FieldDes
|
||||
// unmarshalMap unmarshals given []text.Value into given protoreflect.Map.
|
||||
func (o UnmarshalOptions) unmarshalMap(input []text.Value, fd pref.FieldDescriptor, mmap pref.Map) error {
|
||||
var nerr errors.NonFatal
|
||||
fields := fd.Message().Fields()
|
||||
keyDesc := fields.ByNumber(1)
|
||||
valDesc := fields.ByNumber(2)
|
||||
|
||||
// Determine ahead whether map entry is a scalar type or a message type in order to call the
|
||||
// appropriate unmarshalMapValue func inside the for loop below.
|
||||
unmarshalMapValue := unmarshalMapScalarValue
|
||||
switch valDesc.Kind() {
|
||||
switch fd.MapValue().Kind() {
|
||||
case pref.MessageKind, pref.GroupKind:
|
||||
unmarshalMapValue = o.unmarshalMapMessageValue
|
||||
}
|
||||
@ -378,11 +370,11 @@ func (o UnmarshalOptions) unmarshalMap(input []text.Value, fd pref.FieldDescript
|
||||
if !nerr.Merge(err) {
|
||||
return err
|
||||
}
|
||||
pkey, err := unmarshalMapKey(tkey, keyDesc)
|
||||
pkey, err := unmarshalMapKey(tkey, fd.MapKey())
|
||||
if !nerr.Merge(err) {
|
||||
return err
|
||||
}
|
||||
err = unmarshalMapValue(tval, pkey, valDesc, mmap)
|
||||
err = unmarshalMapValue(tval, pkey, fd.MapValue(), mmap)
|
||||
if !nerr.Merge(err) {
|
||||
return err
|
||||
}
|
||||
|
@ -132,28 +132,26 @@ func (o MarshalOptions) marshalMessage(m pref.Message) (text.Value, error) {
|
||||
func (o MarshalOptions) appendField(msgFields [][2]text.Value, name text.Value, pval pref.Value, fd pref.FieldDescriptor) ([][2]text.Value, error) {
|
||||
var nerr errors.NonFatal
|
||||
|
||||
if fd.Cardinality() == pref.Repeated {
|
||||
// Map or repeated fields.
|
||||
var items []text.Value
|
||||
var err error
|
||||
if fd.IsMap() {
|
||||
items, err = o.marshalMap(pval.Map(), fd)
|
||||
if !nerr.Merge(err) {
|
||||
return msgFields, err
|
||||
}
|
||||
} else {
|
||||
items, err = o.marshalList(pval.List(), fd)
|
||||
if !nerr.Merge(err) {
|
||||
return msgFields, err
|
||||
}
|
||||
switch {
|
||||
case fd.IsList():
|
||||
items, err := o.marshalList(pval.List(), fd)
|
||||
if !nerr.Merge(err) {
|
||||
return msgFields, err
|
||||
}
|
||||
|
||||
// Add each item as key: value field.
|
||||
for _, item := range items {
|
||||
msgFields = append(msgFields, [2]text.Value{name, item})
|
||||
}
|
||||
} else {
|
||||
// Required or optional fields.
|
||||
case fd.IsMap():
|
||||
items, err := o.marshalMap(pval.Map(), fd)
|
||||
if !nerr.Merge(err) {
|
||||
return msgFields, err
|
||||
}
|
||||
|
||||
for _, item := range items {
|
||||
msgFields = append(msgFields, [2]text.Value{name, item})
|
||||
}
|
||||
default:
|
||||
tval, err := o.marshalSingular(pval, fd)
|
||||
if !nerr.Merge(err) {
|
||||
return msgFields, err
|
||||
@ -231,19 +229,16 @@ func (o MarshalOptions) marshalMap(mmap pref.Map, fd pref.FieldDescriptor) ([]te
|
||||
var nerr errors.NonFatal
|
||||
// values is a list of messages.
|
||||
values := make([]text.Value, 0, mmap.Len())
|
||||
msgFields := fd.Message().Fields()
|
||||
keyType := msgFields.ByNumber(1)
|
||||
valType := msgFields.ByNumber(2)
|
||||
|
||||
var err error
|
||||
mapsort.Range(mmap, keyType.Kind(), func(key pref.MapKey, val pref.Value) bool {
|
||||
mapsort.Range(mmap, fd.MapKey().Kind(), func(key pref.MapKey, val pref.Value) bool {
|
||||
var keyTxtVal text.Value
|
||||
keyTxtVal, err = o.marshalSingular(key.Value(), keyType)
|
||||
keyTxtVal, err = o.marshalSingular(key.Value(), fd.MapKey())
|
||||
if !nerr.Merge(err) {
|
||||
return false
|
||||
}
|
||||
var valTxtVal text.Value
|
||||
valTxtVal, err = o.marshalSingular(val, valType)
|
||||
valTxtVal, err = o.marshalSingular(val, fd.MapValue())
|
||||
if !nerr.Merge(err) {
|
||||
return false
|
||||
}
|
||||
@ -314,7 +309,7 @@ func isMessageSetExtension(xt pref.ExtensionType) bool {
|
||||
if xd.FullName().Parent() != md.FullName() {
|
||||
return false
|
||||
}
|
||||
xmd, ok := xd.Extendee().(interface{ IsMessageSet() bool })
|
||||
xmd, ok := xd.ContainingMessage().(interface{ IsMessageSet() bool })
|
||||
return ok && xmd.IsMessageSet()
|
||||
}
|
||||
|
||||
|
@ -175,13 +175,13 @@ func Marshal(fd pref.FieldDescriptor, enumName string) string {
|
||||
// The previous implementation does not tag extension fields as proto3,
|
||||
// even when the field is defined in a proto3 file. Match that behavior
|
||||
// for consistency.
|
||||
if fd.Syntax() == pref.Proto3 && fd.Extendee() == nil {
|
||||
if fd.Syntax() == pref.Proto3 && !fd.IsExtension() {
|
||||
tag = append(tag, "proto3")
|
||||
}
|
||||
if fd.Kind() == pref.EnumKind && enumName != "" {
|
||||
tag = append(tag, "enum="+enumName)
|
||||
}
|
||||
if fd.Oneof() != nil {
|
||||
if fd.ContainingOneof() != nil {
|
||||
tag = append(tag, "oneof")
|
||||
}
|
||||
// This must appear last in the tag, since commas in strings aren't escaped.
|
||||
|
@ -431,23 +431,43 @@ func (md messageDescriptor) Options() pref.ProtoMessage { return md.options()
|
||||
func (fd *fieldDesc) Options() pref.ProtoMessage {
|
||||
return unmarshalOptions(descopts.Field, fd.options)
|
||||
}
|
||||
func (fd *fieldDesc) Number() pref.FieldNumber { return fd.number }
|
||||
func (fd *fieldDesc) Cardinality() pref.Cardinality { return fd.cardinality }
|
||||
func (fd *fieldDesc) Kind() pref.Kind { return fd.kind }
|
||||
func (fd *fieldDesc) HasJSONName() bool { return fd.hasJSONName }
|
||||
func (fd *fieldDesc) JSONName() string { return fd.jsonName }
|
||||
func (fd *fieldDesc) IsPacked() bool { return fd.isPacked }
|
||||
func (fd *fieldDesc) IsWeak() bool { return fd.isWeak }
|
||||
func (fd *fieldDesc) IsMap() bool { return fd.isMap }
|
||||
func (fd *fieldDesc) Number() pref.FieldNumber { return fd.number }
|
||||
func (fd *fieldDesc) Cardinality() pref.Cardinality { return fd.cardinality }
|
||||
func (fd *fieldDesc) Kind() pref.Kind { return fd.kind }
|
||||
func (fd *fieldDesc) HasJSONName() bool { return fd.hasJSONName }
|
||||
func (fd *fieldDesc) JSONName() string { return fd.jsonName }
|
||||
func (fd *fieldDesc) IsPacked() bool { return fd.isPacked }
|
||||
func (fd *fieldDesc) IsExtension() bool { return false }
|
||||
func (fd *fieldDesc) IsWeak() bool { return fd.isWeak }
|
||||
func (fd *fieldDesc) IsList() bool { return fd.cardinality == pref.Repeated && !fd.IsMap() }
|
||||
func (fd *fieldDesc) IsMap() bool { return fd.isMap }
|
||||
func (fd *fieldDesc) MapKey() pref.FieldDescriptor {
|
||||
if !fd.isMap {
|
||||
return nil
|
||||
}
|
||||
return fd.Message().Fields().ByNumber(1)
|
||||
}
|
||||
func (fd *fieldDesc) MapValue() pref.FieldDescriptor {
|
||||
if !fd.isMap {
|
||||
return nil
|
||||
}
|
||||
return fd.Message().Fields().ByNumber(2)
|
||||
}
|
||||
func (fd *fieldDesc) HasDefault() bool { return fd.defVal.has }
|
||||
func (fd *fieldDesc) Default() pref.Value { return fd.defVal.get() }
|
||||
func (fd *fieldDesc) DefaultEnumValue() pref.EnumValueDescriptor { return fd.defVal.enum }
|
||||
func (fd *fieldDesc) Oneof() pref.OneofDescriptor { return fd.oneofType }
|
||||
func (fd *fieldDesc) Extendee() pref.MessageDescriptor { return nil }
|
||||
func (fd *fieldDesc) Enum() pref.EnumDescriptor { return fd.enumType }
|
||||
func (fd *fieldDesc) Message() pref.MessageDescriptor { return fd.messageType }
|
||||
func (fd *fieldDesc) Format(s fmt.State, r rune) { pfmt.FormatDesc(s, r, fd) }
|
||||
func (fd *fieldDesc) ProtoType(pref.FieldDescriptor) {}
|
||||
func (fd *fieldDesc) ContainingOneof() pref.OneofDescriptor { return fd.oneofType }
|
||||
func (fd *fieldDesc) ContainingMessage() pref.MessageDescriptor {
|
||||
return fd.parent.(pref.MessageDescriptor)
|
||||
}
|
||||
func (fd *fieldDesc) Enum() pref.EnumDescriptor { return fd.enumType }
|
||||
func (fd *fieldDesc) Message() pref.MessageDescriptor { return fd.messageType }
|
||||
func (fd *fieldDesc) Format(s fmt.State, r rune) { pfmt.FormatDesc(s, r, fd) }
|
||||
func (fd *fieldDesc) ProtoType(pref.FieldDescriptor) {}
|
||||
|
||||
// TODO: Remove this.
|
||||
func (fd *fieldDesc) Oneof() pref.OneofDescriptor { return fd.oneofType }
|
||||
func (fd *fieldDesc) Extendee() pref.MessageDescriptor { return nil }
|
||||
|
||||
func (od *oneofDesc) Options() pref.ProtoMessage {
|
||||
return unmarshalOptions(descopts.Oneof, od.options)
|
||||
@ -505,13 +525,17 @@ func (xd *extensionDesc) Kind() pref.Kind { return xd
|
||||
func (xd *extensionDesc) HasJSONName() bool { return xd.lazyInit().hasJSONName }
|
||||
func (xd *extensionDesc) JSONName() string { return xd.lazyInit().jsonName }
|
||||
func (xd *extensionDesc) IsPacked() bool { return xd.lazyInit().isPacked }
|
||||
func (xd *extensionDesc) IsExtension() bool { return true }
|
||||
func (xd *extensionDesc) IsWeak() bool { return false }
|
||||
func (xd *extensionDesc) IsList() bool { return xd.Cardinality() == pref.Repeated }
|
||||
func (xd *extensionDesc) IsMap() bool { return false }
|
||||
func (xd *extensionDesc) MapKey() pref.FieldDescriptor { return nil }
|
||||
func (xd *extensionDesc) MapValue() pref.FieldDescriptor { return nil }
|
||||
func (xd *extensionDesc) HasDefault() bool { return xd.lazyInit().defVal.has }
|
||||
func (xd *extensionDesc) Default() pref.Value { return xd.lazyInit().defVal.get() }
|
||||
func (xd *extensionDesc) DefaultEnumValue() pref.EnumValueDescriptor { return xd.lazyInit().defVal.enum }
|
||||
func (xd *extensionDesc) Oneof() pref.OneofDescriptor { return nil }
|
||||
func (xd *extensionDesc) Extendee() pref.MessageDescriptor { return xd.extendedType }
|
||||
func (xd *extensionDesc) ContainingOneof() pref.OneofDescriptor { return nil }
|
||||
func (xd *extensionDesc) ContainingMessage() pref.MessageDescriptor { return xd.extendedType }
|
||||
func (xd *extensionDesc) Enum() pref.EnumDescriptor { return xd.lazyInit().enumType }
|
||||
func (xd *extensionDesc) Message() pref.MessageDescriptor { return xd.lazyInit().messageType }
|
||||
func (xd *extensionDesc) Format(s fmt.State, r rune) { pfmt.FormatDesc(s, r, xd) }
|
||||
@ -531,6 +555,10 @@ func (xd *extensionDesc) ProtoLegacyExtensionDesc() *piface.ExtensionDescV1 {
|
||||
return xd.legacyDesc
|
||||
}
|
||||
|
||||
// TODO: Remove this.
|
||||
func (xd *extensionDesc) Oneof() pref.OneofDescriptor { return nil }
|
||||
func (xd *extensionDesc) Extendee() pref.MessageDescriptor { return xd.extendedType }
|
||||
|
||||
type (
|
||||
serviceDesc struct {
|
||||
baseDesc
|
||||
|
@ -88,7 +88,7 @@ func visitFields(m protoreflect.Message, f func(protoreflect.FieldDescriptor)) {
|
||||
f(field)
|
||||
switch field.Kind() {
|
||||
case protoreflect.MessageKind, protoreflect.GroupKind:
|
||||
if field.Cardinality() == protoreflect.Repeated {
|
||||
if field.IsList() {
|
||||
for i, list := 0, value.List(); i < list.Len(); i++ {
|
||||
visitFields(list.Get(i).Message(), f)
|
||||
}
|
||||
|
@ -64,7 +64,7 @@ func (p legacyExtensionFields) Has(n pref.FieldNumber) bool {
|
||||
}
|
||||
t := extensionTypeFromDesc(x.Desc)
|
||||
d := t.Descriptor()
|
||||
if d.Cardinality() == pref.Repeated {
|
||||
if d.IsList() {
|
||||
return t.ValueOf(x.Value).List().Len() > 0
|
||||
}
|
||||
return true
|
||||
@ -105,7 +105,7 @@ func (p legacyExtensionFields) Clear(n pref.FieldNumber) {
|
||||
}
|
||||
t := extensionTypeFromDesc(x.Desc)
|
||||
d := t.Descriptor()
|
||||
if d.Cardinality() == pref.Repeated {
|
||||
if d.IsList() {
|
||||
t.ValueOf(x.Value).List().Truncate(0)
|
||||
return
|
||||
}
|
||||
@ -153,7 +153,7 @@ func (p legacyExtensionTypes) Len() (n int) {
|
||||
|
||||
func (p legacyExtensionTypes) Register(t pref.ExtensionType) {
|
||||
d := t.Descriptor()
|
||||
if p.mi.PBType.Descriptor().FullName() != d.Extendee().FullName() {
|
||||
if p.mi.PBType.Descriptor().FullName() != d.ContainingMessage().FullName() {
|
||||
panic("extended type mismatch")
|
||||
}
|
||||
if !p.mi.PBType.Descriptor().ExtensionRanges().Has(d.Number()) {
|
||||
@ -164,7 +164,7 @@ func (p legacyExtensionTypes) Register(t pref.ExtensionType) {
|
||||
panic("extension descriptor already registered")
|
||||
}
|
||||
x.Desc = extensionDescFromType(t)
|
||||
if d.Cardinality() == pref.Repeated {
|
||||
if d.IsList() {
|
||||
// If the field is repeated, initialize the entry with an empty list
|
||||
// so that future Get operations can return a mutable and concrete list.
|
||||
x.Value = t.InterfaceOf(t.New())
|
||||
@ -178,7 +178,7 @@ func (p legacyExtensionTypes) Remove(t pref.ExtensionType) {
|
||||
return
|
||||
}
|
||||
x := p.x.Get(d.Number())
|
||||
if d.Cardinality() == pref.Repeated {
|
||||
if d.IsList() {
|
||||
// Treat an empty repeated field as unpopulated.
|
||||
v := reflect.ValueOf(x.Value)
|
||||
if x.Value == nil || v.IsNil() || v.Elem().Len() == 0 {
|
||||
|
@ -685,7 +685,7 @@ func TestExtensionConvert(t *testing.T) {
|
||||
// Ignore New since it a constructor.
|
||||
case "Options":
|
||||
// Ignore descriptor options since protos are not cmperable.
|
||||
case "Oneof", "Extendee", "Enum", "Message":
|
||||
case "ContainingOneof", "ContainingMessage", "Enum", "Message":
|
||||
// Avoid descending into a dependency to avoid a cycle.
|
||||
// Just record the full name if available.
|
||||
//
|
||||
@ -694,6 +694,8 @@ func TestExtensionConvert(t *testing.T) {
|
||||
if !v.IsNil() {
|
||||
out[name] = v.Interface().(pref.Descriptor).FullName()
|
||||
}
|
||||
case "Oneof", "Extendee":
|
||||
// TODO: Remove this.
|
||||
default:
|
||||
out[name] = m.Call(nil)[0].Interface()
|
||||
}
|
||||
|
@ -118,11 +118,11 @@ func (mi *MessageType) makeKnownFieldsFunc(si structInfo) {
|
||||
fs := si.fieldsByNumber[fd.Number()]
|
||||
var fi fieldInfo
|
||||
switch {
|
||||
case fd.Oneof() != nil:
|
||||
fi = fieldInfoForOneof(fd, si.oneofsByName[fd.Oneof().Name()], si.oneofWrappersByNumber[fd.Number()])
|
||||
case fd.ContainingOneof() != nil:
|
||||
fi = fieldInfoForOneof(fd, si.oneofsByName[fd.ContainingOneof().Name()], si.oneofWrappersByNumber[fd.Number()])
|
||||
case fd.IsMap():
|
||||
fi = fieldInfoForMap(fd, fs)
|
||||
case fd.Cardinality() == pref.Repeated:
|
||||
case fd.IsList():
|
||||
fi = fieldInfoForList(fd, fs)
|
||||
case fd.Kind() == pref.MessageKind || fd.Kind() == pref.GroupKind:
|
||||
fi = fieldInfoForMessage(fd, fs)
|
||||
|
@ -90,8 +90,8 @@ func fieldInfoForMap(fd pref.FieldDescriptor, fs reflect.StructField) fieldInfo
|
||||
if ft.Kind() != reflect.Map {
|
||||
panic(fmt.Sprintf("invalid type: got %v, want map kind", ft))
|
||||
}
|
||||
keyConv := pvalue.NewLegacyConverter(ft.Key(), fd.Message().Fields().ByNumber(1).Kind(), legacyWrapper)
|
||||
valConv := pvalue.NewLegacyConverter(ft.Elem(), fd.Message().Fields().ByNumber(2).Kind(), legacyWrapper)
|
||||
keyConv := pvalue.NewLegacyConverter(ft.Key(), fd.MapKey().Kind(), legacyWrapper)
|
||||
valConv := pvalue.NewLegacyConverter(ft.Elem(), fd.MapValue().Kind(), legacyWrapper)
|
||||
fieldOffset := offsetOf(fs)
|
||||
// TODO: Implement unsafe fast path?
|
||||
return fieldInfo{
|
||||
|
@ -65,7 +65,8 @@ func extensionDescFromType(xt pref.ExtensionType) *piface.ExtensionDescV1 {
|
||||
|
||||
// Determine the parent type if possible.
|
||||
var parent piface.MessageV1
|
||||
if mt, _ := preg.GlobalTypes.FindMessageByName(xt.Descriptor().Extendee().FullName()); mt != nil {
|
||||
messageName := xt.Descriptor().ContainingMessage().FullName()
|
||||
if mt, _ := preg.GlobalTypes.FindMessageByName(messageName); mt != nil {
|
||||
// Create a new parent message and unwrap it if possible.
|
||||
mv := mt.New().Interface()
|
||||
t := reflect.TypeOf(mv)
|
||||
|
@ -433,7 +433,7 @@ func TestDescriptor(t *testing.T) {
|
||||
case "HasJSONName":
|
||||
// Ignore this since the semantics of the field has
|
||||
// changed across protoc and protoc-gen-go releases.
|
||||
case "Oneof", "Extendee", "Enum", "Message":
|
||||
case "ContainingOneof", "ContainingMessage", "Enum", "Message":
|
||||
// Avoid descending into a dependency to avoid a cycle.
|
||||
// Just record the full name if available.
|
||||
//
|
||||
@ -442,6 +442,8 @@ func TestDescriptor(t *testing.T) {
|
||||
if !v.IsNil() {
|
||||
out[name] = v.Interface().(pref.Descriptor).FullName()
|
||||
}
|
||||
case "Oneof", "Extendee":
|
||||
// TODO: Remove this.
|
||||
default:
|
||||
out[name] = m.Call(nil)[0].Interface()
|
||||
}
|
||||
|
@ -124,7 +124,7 @@ func (t *goMessage) Format(s fmt.State, r rune) {
|
||||
// The type M is the concrete message type returned by NewMessage,
|
||||
// which is often, but not required to be, a pointer to a named struct type.
|
||||
func GoExtension(xd protoreflect.ExtensionDescriptor, et protoreflect.EnumType, mt protoreflect.MessageType) protoreflect.ExtensionType {
|
||||
if xd.Extendee() == nil {
|
||||
if !xd.IsExtension() {
|
||||
panic("field descriptor does not extend a message")
|
||||
}
|
||||
switch xd.Kind() {
|
||||
|
@ -114,7 +114,7 @@ func (p *oneofFieldsMeta) lazyInit(parent pref.Descriptor) *oneofFields {
|
||||
md, _ := parent.Parent()
|
||||
fs := md.(pref.MessageDescriptor).Fields()
|
||||
for i := 0; i < fs.Len(); i++ {
|
||||
if f := fs.Get(i); od == f.Oneof() {
|
||||
if f := fs.Get(i); od == f.ContainingOneof() {
|
||||
p.typs = append(p.typs, f)
|
||||
}
|
||||
}
|
||||
|
@ -171,21 +171,43 @@ func (t fieldDesc) JSONName() string { return t.f.js.lazyInit(t.f
|
||||
func (t fieldDesc) IsPacked() bool {
|
||||
return isPacked(t.f.IsPacked, t.f.syntax, t.f.Cardinality, t.f.Kind)
|
||||
}
|
||||
func (t fieldDesc) IsWeak() bool { return t.f.IsWeak }
|
||||
func (t fieldDesc) IsExtension() bool { return false }
|
||||
func (t fieldDesc) IsWeak() bool { return t.f.IsWeak }
|
||||
func (t fieldDesc) IsList() bool {
|
||||
return t.f.Cardinality == pref.Repeated && !t.IsMap()
|
||||
}
|
||||
func (t fieldDesc) IsMap() bool {
|
||||
mt := t.Message()
|
||||
return mt != nil && mt.IsMapEntry()
|
||||
}
|
||||
func (t fieldDesc) MapKey() pref.FieldDescriptor {
|
||||
if !t.IsMap() {
|
||||
return nil
|
||||
}
|
||||
return t.Message().Fields().ByNumber(1)
|
||||
}
|
||||
func (t fieldDesc) MapValue() pref.FieldDescriptor {
|
||||
if !t.IsMap() {
|
||||
return nil
|
||||
}
|
||||
return t.Message().Fields().ByNumber(2)
|
||||
}
|
||||
func (t fieldDesc) HasDefault() bool { return t.f.Default.IsValid() }
|
||||
func (t fieldDesc) Default() pref.Value { return t.f.dv.value(t, t.f.Default) }
|
||||
func (t fieldDesc) DefaultEnumValue() pref.EnumValueDescriptor { return t.f.dv.enum(t, t.f.Default) }
|
||||
func (t fieldDesc) Oneof() pref.OneofDescriptor { return t.f.ot.lazyInit(t, t.f.OneofName) }
|
||||
func (t fieldDesc) Extendee() pref.MessageDescriptor { return nil }
|
||||
func (t fieldDesc) Enum() pref.EnumDescriptor { return t.f.et.lazyInit(t, &t.f.EnumType) }
|
||||
func (t fieldDesc) Message() pref.MessageDescriptor { return t.f.mt.lazyInit(t, &t.f.MessageType) }
|
||||
func (t fieldDesc) Format(s fmt.State, r rune) { pfmt.FormatDesc(s, r, t) }
|
||||
func (t fieldDesc) ProtoType(pref.FieldDescriptor) {}
|
||||
func (t fieldDesc) ProtoInternal(pragma.DoNotImplement) {}
|
||||
func (t fieldDesc) ContainingOneof() pref.OneofDescriptor { return t.f.ot.lazyInit(t, t.f.OneofName) }
|
||||
func (t fieldDesc) ContainingMessage() pref.MessageDescriptor {
|
||||
return t.f.parent.(pref.MessageDescriptor)
|
||||
}
|
||||
func (t fieldDesc) Enum() pref.EnumDescriptor { return t.f.et.lazyInit(t, &t.f.EnumType) }
|
||||
func (t fieldDesc) Message() pref.MessageDescriptor { return t.f.mt.lazyInit(t, &t.f.MessageType) }
|
||||
func (t fieldDesc) Format(s fmt.State, r rune) { pfmt.FormatDesc(s, r, t) }
|
||||
func (t fieldDesc) ProtoType(pref.FieldDescriptor) {}
|
||||
func (t fieldDesc) ProtoInternal(pragma.DoNotImplement) {}
|
||||
|
||||
// TODO: Remove this.
|
||||
func (t fieldDesc) Oneof() pref.OneofDescriptor { return t.f.ot.lazyInit(t, t.f.OneofName) }
|
||||
func (t fieldDesc) Extendee() pref.MessageDescriptor { return nil }
|
||||
|
||||
func isPacked(packed OptionalBool, s pref.Syntax, c pref.Cardinality, k pref.Kind) bool {
|
||||
if packed == False || (packed == DefaultBool && s == pref.Proto2) {
|
||||
@ -299,18 +321,28 @@ func (t extensionDesc) IsPacked() bool {
|
||||
// Extensions always use proto2 defaults for packing.
|
||||
return isPacked(t.x.IsPacked, pref.Proto2, t.x.Cardinality, t.x.Kind)
|
||||
}
|
||||
func (t extensionDesc) IsExtension() bool { return true }
|
||||
func (t extensionDesc) IsWeak() bool { return false }
|
||||
func (t extensionDesc) IsList() bool { return t.x.Cardinality == pref.Repeated }
|
||||
func (t extensionDesc) IsMap() bool { return false }
|
||||
func (t extensionDesc) MapKey() pref.FieldDescriptor { return nil }
|
||||
func (t extensionDesc) MapValue() pref.FieldDescriptor { return nil }
|
||||
func (t extensionDesc) HasDefault() bool { return t.x.Default.IsValid() }
|
||||
func (t extensionDesc) Default() pref.Value { return t.x.dv.value(t, t.x.Default) }
|
||||
func (t extensionDesc) DefaultEnumValue() pref.EnumValueDescriptor { return t.x.dv.enum(t, t.x.Default) }
|
||||
func (t extensionDesc) Oneof() pref.OneofDescriptor { return nil }
|
||||
func (t extensionDesc) Extendee() pref.MessageDescriptor { return t.x.xt.lazyInit(t, &t.x.ExtendedType) }
|
||||
func (t extensionDesc) Enum() pref.EnumDescriptor { return t.x.et.lazyInit(t, &t.x.EnumType) }
|
||||
func (t extensionDesc) Message() pref.MessageDescriptor { return t.x.mt.lazyInit(t, &t.x.MessageType) }
|
||||
func (t extensionDesc) Format(s fmt.State, r rune) { pfmt.FormatDesc(s, r, t) }
|
||||
func (t extensionDesc) ProtoType(pref.FieldDescriptor) {}
|
||||
func (t extensionDesc) ProtoInternal(pragma.DoNotImplement) {}
|
||||
func (t extensionDesc) ContainingOneof() pref.OneofDescriptor { return nil }
|
||||
func (t extensionDesc) ContainingMessage() pref.MessageDescriptor {
|
||||
return t.x.xt.lazyInit(t, &t.x.ExtendedType)
|
||||
}
|
||||
func (t extensionDesc) Enum() pref.EnumDescriptor { return t.x.et.lazyInit(t, &t.x.EnumType) }
|
||||
func (t extensionDesc) Message() pref.MessageDescriptor { return t.x.mt.lazyInit(t, &t.x.MessageType) }
|
||||
func (t extensionDesc) Format(s fmt.State, r rune) { pfmt.FormatDesc(s, r, t) }
|
||||
func (t extensionDesc) ProtoType(pref.FieldDescriptor) {}
|
||||
func (t extensionDesc) ProtoInternal(pragma.DoNotImplement) {}
|
||||
|
||||
// TODO: Remove this.
|
||||
func (t extensionDesc) Oneof() pref.OneofDescriptor { return nil }
|
||||
func (t extensionDesc) Extendee() pref.MessageDescriptor { return t.x.xt.lazyInit(t, &t.x.ExtendedType) }
|
||||
|
||||
type enumMeta struct {
|
||||
inheritedMeta
|
||||
|
@ -85,17 +85,25 @@ func (t standaloneExtension) JSONName() string { return "" }
|
||||
func (t standaloneExtension) IsPacked() bool {
|
||||
return isPacked(t.x.IsPacked, pref.Proto2, t.x.Cardinality, t.x.Kind)
|
||||
}
|
||||
func (t standaloneExtension) IsWeak() bool { return false }
|
||||
func (t standaloneExtension) IsMap() bool { return false }
|
||||
func (t standaloneExtension) HasDefault() bool { return t.x.Default.IsValid() }
|
||||
func (t standaloneExtension) Default() pref.Value { return t.x.dv.value(t, t.x.Default) }
|
||||
func (t standaloneExtension) IsExtension() bool { return true }
|
||||
func (t standaloneExtension) IsWeak() bool { return false }
|
||||
func (t standaloneExtension) IsList() bool { return t.x.Cardinality == pref.Repeated }
|
||||
func (t standaloneExtension) IsMap() bool { return false }
|
||||
func (t standaloneExtension) MapKey() pref.FieldDescriptor { return nil }
|
||||
func (t standaloneExtension) MapValue() pref.FieldDescriptor { return nil }
|
||||
func (t standaloneExtension) HasDefault() bool { return t.x.Default.IsValid() }
|
||||
func (t standaloneExtension) Default() pref.Value { return t.x.dv.value(t, t.x.Default) }
|
||||
func (t standaloneExtension) DefaultEnumValue() pref.EnumValueDescriptor {
|
||||
return t.x.dv.enum(t, t.x.Default)
|
||||
}
|
||||
func (t standaloneExtension) Oneof() pref.OneofDescriptor { return nil }
|
||||
func (t standaloneExtension) Extendee() pref.MessageDescriptor { return t.x.ExtendedType }
|
||||
func (t standaloneExtension) Enum() pref.EnumDescriptor { return t.x.EnumType }
|
||||
func (t standaloneExtension) Message() pref.MessageDescriptor { return t.x.MessageType }
|
||||
func (t standaloneExtension) Format(s fmt.State, r rune) { pfmt.FormatDesc(s, r, t) }
|
||||
func (t standaloneExtension) ProtoType(pref.FieldDescriptor) {}
|
||||
func (t standaloneExtension) ProtoInternal(pragma.DoNotImplement) {}
|
||||
func (t standaloneExtension) ContainingOneof() pref.OneofDescriptor { return nil }
|
||||
func (t standaloneExtension) ContainingMessage() pref.MessageDescriptor { return t.x.ExtendedType }
|
||||
func (t standaloneExtension) Enum() pref.EnumDescriptor { return t.x.EnumType }
|
||||
func (t standaloneExtension) Message() pref.MessageDescriptor { return t.x.MessageType }
|
||||
func (t standaloneExtension) Format(s fmt.State, r rune) { pfmt.FormatDesc(s, r, t) }
|
||||
func (t standaloneExtension) ProtoType(pref.FieldDescriptor) {}
|
||||
func (t standaloneExtension) ProtoInternal(pragma.DoNotImplement) {}
|
||||
|
||||
// TODO: Remove this.
|
||||
func (t standaloneExtension) Oneof() pref.OneofDescriptor { return nil }
|
||||
func (t standaloneExtension) Extendee() pref.MessageDescriptor { return t.x.ExtendedType }
|
||||
|
@ -18,6 +18,7 @@ import (
|
||||
scalar "github.com/golang/protobuf/v2/internal/scalar"
|
||||
pdesc "github.com/golang/protobuf/v2/reflect/protodesc"
|
||||
pref "github.com/golang/protobuf/v2/reflect/protoreflect"
|
||||
"github.com/google/go-cmp/cmp"
|
||||
|
||||
descriptorpb "github.com/golang/protobuf/v2/types/descriptor"
|
||||
)
|
||||
@ -391,42 +392,46 @@ func testFileAccessors(t *testing.T, fd pref.FileDescriptor) {
|
||||
"Fields": M{
|
||||
"Len": 2,
|
||||
"ByNumber:1": M{
|
||||
"Parent": M{"FullName": pref.FullName("test.A")},
|
||||
"Index": 0,
|
||||
"Name": pref.Name("key"),
|
||||
"FullName": pref.FullName("test.A.key"),
|
||||
"Number": pref.FieldNumber(1),
|
||||
"Cardinality": pref.Optional,
|
||||
"Kind": pref.StringKind,
|
||||
"Options": &descriptorpb.FieldOptions{Deprecated: scalar.Bool(true)},
|
||||
"HasJSONName": false,
|
||||
"JSONName": "key",
|
||||
"IsPacked": false,
|
||||
"IsMap": false,
|
||||
"IsWeak": false,
|
||||
"Default": "",
|
||||
"Oneof": nil,
|
||||
"Extendee": nil,
|
||||
"Message": nil,
|
||||
"Enum": nil,
|
||||
"Parent": M{"FullName": pref.FullName("test.A")},
|
||||
"Index": 0,
|
||||
"Name": pref.Name("key"),
|
||||
"FullName": pref.FullName("test.A.key"),
|
||||
"Number": pref.FieldNumber(1),
|
||||
"Cardinality": pref.Optional,
|
||||
"Kind": pref.StringKind,
|
||||
"Options": &descriptorpb.FieldOptions{Deprecated: scalar.Bool(true)},
|
||||
"HasJSONName": false,
|
||||
"JSONName": "key",
|
||||
"IsPacked": false,
|
||||
"IsList": false,
|
||||
"IsMap": false,
|
||||
"IsExtension": false,
|
||||
"IsWeak": false,
|
||||
"Default": "",
|
||||
"ContainingOneof": nil,
|
||||
"ContainingMessage": M{"FullName": pref.FullName("test.A")},
|
||||
"Message": nil,
|
||||
"Enum": nil,
|
||||
},
|
||||
"ByNumber:2": M{
|
||||
"Parent": M{"FullName": pref.FullName("test.A")},
|
||||
"Index": 1,
|
||||
"Name": pref.Name("value"),
|
||||
"FullName": pref.FullName("test.A.value"),
|
||||
"Number": pref.FieldNumber(2),
|
||||
"Cardinality": pref.Optional,
|
||||
"Kind": pref.MessageKind,
|
||||
"JSONName": "value",
|
||||
"IsPacked": false,
|
||||
"IsMap": false,
|
||||
"IsWeak": false,
|
||||
"Default": nil,
|
||||
"Oneof": nil,
|
||||
"Extendee": nil,
|
||||
"Message": M{"FullName": pref.FullName("test.B"), "IsPlaceholder": false},
|
||||
"Enum": nil,
|
||||
"Parent": M{"FullName": pref.FullName("test.A")},
|
||||
"Index": 1,
|
||||
"Name": pref.Name("value"),
|
||||
"FullName": pref.FullName("test.A.value"),
|
||||
"Number": pref.FieldNumber(2),
|
||||
"Cardinality": pref.Optional,
|
||||
"Kind": pref.MessageKind,
|
||||
"JSONName": "value",
|
||||
"IsPacked": false,
|
||||
"IsList": false,
|
||||
"IsMap": false,
|
||||
"IsExtension": false,
|
||||
"IsWeak": false,
|
||||
"Default": nil,
|
||||
"ContainingOneof": nil,
|
||||
"ContainingMessage": M{"FullName": pref.FullName("test.A")},
|
||||
"Message": M{"FullName": pref.FullName("test.B"), "IsPlaceholder": false},
|
||||
"Enum": nil,
|
||||
},
|
||||
"ByNumber:3": nil,
|
||||
},
|
||||
@ -444,31 +449,40 @@ func testFileAccessors(t *testing.T, fd pref.FileDescriptor) {
|
||||
"Len": 6,
|
||||
"ByJSONName:field_one": nil,
|
||||
"ByJSONName:fieldOne": M{
|
||||
"Name": pref.Name("field_one"),
|
||||
"Index": 0,
|
||||
"JSONName": "fieldOne",
|
||||
"Default": "hello, \"world!\"\n",
|
||||
"Oneof": M{"Name": pref.Name("O1"), "IsPlaceholder": false},
|
||||
"Name": pref.Name("field_one"),
|
||||
"Index": 0,
|
||||
"JSONName": "fieldOne",
|
||||
"Default": "hello, \"world!\"\n",
|
||||
"ContainingOneof": M{"Name": pref.Name("O1"), "IsPlaceholder": false},
|
||||
"ContainingMessage": M{"FullName": pref.FullName("test.B")},
|
||||
},
|
||||
"ByJSONName:fieldTwo": nil,
|
||||
"ByJSONName:Field2": M{
|
||||
"Name": pref.Name("field_two"),
|
||||
"Index": 1,
|
||||
"HasJSONName": true,
|
||||
"JSONName": "Field2",
|
||||
"Default": pref.EnumNumber(1),
|
||||
"Oneof": M{"Name": pref.Name("O2"), "IsPlaceholder": false},
|
||||
"Name": pref.Name("field_two"),
|
||||
"Index": 1,
|
||||
"HasJSONName": true,
|
||||
"JSONName": "Field2",
|
||||
"Default": pref.EnumNumber(1),
|
||||
"ContainingOneof": M{"Name": pref.Name("O2"), "IsPlaceholder": false},
|
||||
},
|
||||
"ByName:fieldThree": nil,
|
||||
"ByName:field_three": M{
|
||||
"IsMap": false,
|
||||
"Message": M{"FullName": pref.FullName("test.C"), "IsPlaceholder": false},
|
||||
"Oneof": M{"Name": pref.Name("O2"), "IsPlaceholder": false},
|
||||
"IsExtension": false,
|
||||
"IsMap": false,
|
||||
"MapKey": nil,
|
||||
"MapValue": nil,
|
||||
"Message": M{"FullName": pref.FullName("test.C"), "IsPlaceholder": false},
|
||||
"ContainingOneof": M{"Name": pref.Name("O2"), "IsPlaceholder": false},
|
||||
"ContainingMessage": M{"FullName": pref.FullName("test.B")},
|
||||
},
|
||||
"ByNumber:12": nil,
|
||||
"ByNumber:4": M{
|
||||
"Cardinality": pref.Repeated,
|
||||
"IsExtension": false,
|
||||
"IsList": false,
|
||||
"IsMap": true,
|
||||
"MapKey": M{"Kind": pref.StringKind},
|
||||
"MapValue": M{"Kind": pref.MessageKind, "Message": M{"FullName": pref.FullName("test.B")}},
|
||||
"Default": nil,
|
||||
"Message": M{"FullName": pref.FullName("test.A"), "IsPlaceholder": false},
|
||||
},
|
||||
@ -476,12 +490,14 @@ func testFileAccessors(t *testing.T, fd pref.FileDescriptor) {
|
||||
"Cardinality": pref.Repeated,
|
||||
"Kind": pref.Int32Kind,
|
||||
"IsPacked": true,
|
||||
"IsList": true,
|
||||
"IsMap": false,
|
||||
"Default": int32(0),
|
||||
},
|
||||
"ByNumber:6": M{
|
||||
"Cardinality": pref.Required,
|
||||
"Default": []byte(nil),
|
||||
"Oneof": nil,
|
||||
"Cardinality": pref.Required,
|
||||
"Default": []byte(nil),
|
||||
"ContainingOneof": nil,
|
||||
},
|
||||
},
|
||||
"Oneofs": M{
|
||||
@ -601,14 +617,20 @@ func testFileAccessors(t *testing.T, fd pref.FileDescriptor) {
|
||||
"Extensions": M{
|
||||
"Len": 1,
|
||||
"ByName:X": M{
|
||||
"Name": pref.Name("X"),
|
||||
"Number": pref.FieldNumber(1000),
|
||||
"Cardinality": pref.Repeated,
|
||||
"Kind": pref.MessageKind,
|
||||
"IsPacked": false,
|
||||
"Message": M{"FullName": pref.FullName("test.C"), "IsPlaceholder": false},
|
||||
"Extendee": M{"FullName": pref.FullName("test.B"), "IsPlaceholder": false},
|
||||
"Options": &descriptorpb.FieldOptions{Packed: scalar.Bool(true)},
|
||||
"Name": pref.Name("X"),
|
||||
"Number": pref.FieldNumber(1000),
|
||||
"Cardinality": pref.Repeated,
|
||||
"Kind": pref.MessageKind,
|
||||
"IsExtension": true,
|
||||
"IsPacked": false,
|
||||
"IsList": true,
|
||||
"IsMap": false,
|
||||
"MapKey": nil,
|
||||
"MapValue": nil,
|
||||
"ContainingOneof": nil,
|
||||
"ContainingMessage": M{"FullName": pref.FullName("test.B"), "IsPlaceholder": false},
|
||||
"Message": M{"FullName": pref.FullName("test.C"), "IsPlaceholder": false},
|
||||
"Options": &descriptorpb.FieldOptions{Packed: scalar.Bool(true)},
|
||||
},
|
||||
},
|
||||
"Services": M{
|
||||
@ -768,7 +790,8 @@ func testFileFormat(t *testing.T, fd pref.FileDescriptor) {
|
||||
HasJSONName: true
|
||||
JSONName: "Field4"
|
||||
IsMap: true
|
||||
Message: test.A
|
||||
MapKey: string
|
||||
MapValue: test.B
|
||||
}, {
|
||||
Name: field_five
|
||||
Number: 5
|
||||
@ -776,6 +799,7 @@ func testFileFormat(t *testing.T, fd pref.FileDescriptor) {
|
||||
Kind: int32
|
||||
JSONName: "fieldFive"
|
||||
IsPacked: true
|
||||
IsList: true
|
||||
}, {
|
||||
Name: field_six
|
||||
Number: 6
|
||||
@ -821,6 +845,8 @@ func testFileFormat(t *testing.T, fd pref.FileDescriptor) {
|
||||
Number: 1000
|
||||
Cardinality: repeated
|
||||
Kind: message
|
||||
IsExtension: true
|
||||
IsList: true
|
||||
Extendee: test.B
|
||||
Message: test.C
|
||||
}]
|
||||
@ -839,6 +865,8 @@ func testFileFormat(t *testing.T, fd pref.FileDescriptor) {
|
||||
Number: 1000
|
||||
Cardinality: repeated
|
||||
Kind: message
|
||||
IsExtension: true
|
||||
IsList: true
|
||||
Extendee: test.B
|
||||
Message: test.C
|
||||
}]
|
||||
@ -856,8 +884,8 @@ func testFileFormat(t *testing.T, fd pref.FileDescriptor) {
|
||||
tests := []struct{ fmt, want string }{{"%v", compactMultiFormat(want)}, {"%+v", want}}
|
||||
for _, tt := range tests {
|
||||
got := fmt.Sprintf(tt.fmt, fd)
|
||||
if got != tt.want {
|
||||
t.Errorf("fmt.Sprintf(%q, fd):\ngot: %s\nwant: %s", tt.fmt, got, tt.want)
|
||||
if diff := cmp.Diff(got, tt.want); diff != "" {
|
||||
t.Errorf("fmt.Sprintf(%q, fd) mismatch (-got +want):\n%s", tt.fmt, diff)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -23,6 +23,12 @@ func TestDescriptorAccessors(t *testing.T) {
|
||||
|
||||
"DescriptorByName": true, // specific to FileDescriptor
|
||||
"DefaultEnumValue": true, // specific to FieldDescriptor
|
||||
"MapKey": true, // specific to FieldDescriptor
|
||||
"MapValue": true, // specific to FieldDescriptor
|
||||
|
||||
// TODO: Remove this.
|
||||
"Oneof": true, // specific to FieldDescriptor
|
||||
"Extendee": true, // specific to FieldDescriptor
|
||||
|
||||
// TODO: These should be removed or handled.
|
||||
"DescriptorProto": true,
|
||||
|
@ -106,7 +106,7 @@ func formatListOpt(vs list, isRoot, allowMulti bool) string {
|
||||
var descriptorAccessors = map[reflect.Type][]string{
|
||||
reflect.TypeOf((*pref.FileDescriptor)(nil)).Elem(): {"Path", "Package", "Imports", "Messages", "Enums", "Extensions", "Services"},
|
||||
reflect.TypeOf((*pref.MessageDescriptor)(nil)).Elem(): {"IsMapEntry", "Fields", "Oneofs", "ReservedNames", "ReservedRanges", "RequiredNumbers", "ExtensionRanges", "Messages", "Enums", "Extensions"},
|
||||
reflect.TypeOf((*pref.FieldDescriptor)(nil)).Elem(): {"Number", "Cardinality", "Kind", "HasJSONName", "JSONName", "IsPacked", "IsMap", "IsWeak", "HasDefault", "Default", "Oneof", "Extendee", "Message", "Enum"},
|
||||
reflect.TypeOf((*pref.FieldDescriptor)(nil)).Elem(): {"Number", "Cardinality", "Kind", "HasJSONName", "JSONName", "IsPacked", "IsExtension", "IsWeak", "IsList", "IsMap", "MapKey", "MapValue", "HasDefault", "Default", "ContainingOneof", "ContainingMessage", "Message", "Enum"},
|
||||
reflect.TypeOf((*pref.OneofDescriptor)(nil)).Elem(): {"Fields"}, // not directly used; must keep in sync with formatDescOpt
|
||||
reflect.TypeOf((*pref.EnumDescriptor)(nil)).Elem(): {"Values", "ReservedNames", "ReservedRanges"},
|
||||
reflect.TypeOf((*pref.EnumValueDescriptor)(nil)).Elem(): {"Number"},
|
||||
@ -143,7 +143,42 @@ func formatDescOpt(t pref.Descriptor, isRoot, allowMulti bool) string {
|
||||
default:
|
||||
rs.Append(rv, "Name")
|
||||
}
|
||||
if t, ok := t.(pref.OneofDescriptor); ok {
|
||||
switch t := t.(type) {
|
||||
case pref.FieldDescriptor:
|
||||
for _, s := range descriptorAccessors[rt] {
|
||||
switch s {
|
||||
case "MapKey":
|
||||
if k := t.MapKey(); k != nil {
|
||||
rs.recs = append(rs.recs, [2]string{"MapKey", k.Kind().String()})
|
||||
}
|
||||
case "MapValue":
|
||||
if v := t.MapValue(); v != nil {
|
||||
switch v.Kind() {
|
||||
case pref.EnumKind:
|
||||
rs.recs = append(rs.recs, [2]string{"MapValue", string(v.Enum().FullName())})
|
||||
case pref.MessageKind, pref.GroupKind:
|
||||
rs.recs = append(rs.recs, [2]string{"MapValue", string(v.Message().FullName())})
|
||||
default:
|
||||
rs.recs = append(rs.recs, [2]string{"MapValue", v.Kind().String()})
|
||||
}
|
||||
}
|
||||
case "ContainingOneof":
|
||||
if od := t.ContainingOneof(); od != nil {
|
||||
rs.recs = append(rs.recs, [2]string{"Oneof", string(od.Name())})
|
||||
}
|
||||
case "ContainingMessage":
|
||||
if t.IsExtension() {
|
||||
rs.recs = append(rs.recs, [2]string{"Extendee", string(t.ContainingMessage().FullName())})
|
||||
}
|
||||
case "Message":
|
||||
if !t.IsMap() {
|
||||
rs.Append(rv, s)
|
||||
}
|
||||
default:
|
||||
rs.Append(rv, s)
|
||||
}
|
||||
}
|
||||
case pref.OneofDescriptor:
|
||||
var ss []string
|
||||
fs := t.Fields()
|
||||
for i := 0; i < fs.Len(); i++ {
|
||||
@ -152,7 +187,7 @@ func formatDescOpt(t pref.Descriptor, isRoot, allowMulti bool) string {
|
||||
if len(ss) > 0 {
|
||||
rs.recs = append(rs.recs, [2]string{"Fields", "[" + joinStrings(ss, false) + "]"})
|
||||
}
|
||||
} else {
|
||||
default:
|
||||
rs.Append(rv, descriptorAccessors[rt]...)
|
||||
}
|
||||
if rv.MethodByName("GoType").IsValid() {
|
||||
|
@ -105,12 +105,12 @@ func (o UnmarshalOptions) unmarshalMessage(b []byte, m protoreflect.Message) err
|
||||
switch {
|
||||
case fieldDesc == nil:
|
||||
err = errUnknown
|
||||
case fieldDesc.Cardinality() != protoreflect.Repeated:
|
||||
valLen, err = o.unmarshalScalarField(b[tagLen:], wtyp, num, knownFields, fieldDesc)
|
||||
case !fieldDesc.IsMap():
|
||||
case fieldDesc.IsList():
|
||||
valLen, err = o.unmarshalList(b[tagLen:], wtyp, num, knownFields.Get(num).List(), fieldDesc)
|
||||
default:
|
||||
case fieldDesc.IsMap():
|
||||
valLen, err = o.unmarshalMap(b[tagLen:], wtyp, num, knownFields.Get(num).Map(), fieldDesc)
|
||||
default:
|
||||
valLen, err = o.unmarshalScalarField(b[tagLen:], wtyp, num, knownFields, fieldDesc)
|
||||
}
|
||||
if err == errUnknown {
|
||||
valLen = wire.ConsumeFieldValue(num, wtyp, b[tagLen:])
|
||||
@ -140,7 +140,7 @@ func (o UnmarshalOptions) unmarshalScalarField(b []byte, wtyp wire.Type, num wir
|
||||
// TODO: C++ merges into oneofs, while v1 does not.
|
||||
// Evaluate which behavior to pick.
|
||||
var m protoreflect.Message
|
||||
if knownFields.Has(num) && field.Oneof() == nil {
|
||||
if knownFields.Has(num) && field.ContainingOneof() == nil {
|
||||
m = knownFields.Get(num).Message()
|
||||
} else {
|
||||
m = knownFields.NewMessage(num)
|
||||
@ -166,8 +166,8 @@ func (o UnmarshalOptions) unmarshalMap(b []byte, wtyp wire.Type, num wire.Number
|
||||
return 0, wire.ParseError(n)
|
||||
}
|
||||
var (
|
||||
keyField = field.Message().Fields().ByNumber(1)
|
||||
valField = field.Message().Fields().ByNumber(2)
|
||||
keyField = field.MapKey()
|
||||
valField = field.MapValue()
|
||||
key protoreflect.Value
|
||||
val protoreflect.Value
|
||||
haveKey bool
|
||||
|
@ -176,25 +176,52 @@ func (o MarshalOptions) rangeKnown(knownFields protoreflect.KnownFields, f func(
|
||||
}
|
||||
}
|
||||
|
||||
func (o MarshalOptions) marshalField(b []byte, field protoreflect.FieldDescriptor, value protoreflect.Value) ([]byte, error) {
|
||||
num := field.Number()
|
||||
kind := field.Kind()
|
||||
func (o MarshalOptions) marshalField(b []byte, fd protoreflect.FieldDescriptor, value protoreflect.Value) ([]byte, error) {
|
||||
num := fd.Number()
|
||||
kind := fd.Kind()
|
||||
switch {
|
||||
case field.Cardinality() != protoreflect.Repeated:
|
||||
b = wire.AppendTag(b, num, wireTypes[kind])
|
||||
return o.marshalSingular(b, num, field, value)
|
||||
case field.IsMap():
|
||||
return o.marshalMap(b, num, kind, field.Message(), value.Map())
|
||||
case field.IsPacked():
|
||||
return o.marshalPacked(b, num, field, value.List())
|
||||
case fd.IsList():
|
||||
return o.marshalList(b, num, fd, value.List())
|
||||
case fd.IsMap():
|
||||
return o.marshalMap(b, num, fd, value.Map())
|
||||
default:
|
||||
return o.marshalList(b, num, field, value.List())
|
||||
b = wire.AppendTag(b, num, wireTypes[kind])
|
||||
return o.marshalSingular(b, num, fd, value)
|
||||
}
|
||||
}
|
||||
|
||||
func (o MarshalOptions) marshalMap(b []byte, num wire.Number, kind protoreflect.Kind, mdesc protoreflect.MessageDescriptor, mapv protoreflect.Map) ([]byte, error) {
|
||||
keyf := mdesc.Fields().ByNumber(1)
|
||||
valf := mdesc.Fields().ByNumber(2)
|
||||
func (o MarshalOptions) marshalList(b []byte, num wire.Number, fd protoreflect.FieldDescriptor, list protoreflect.List) ([]byte, error) {
|
||||
if fd.IsPacked() {
|
||||
b = wire.AppendTag(b, num, wire.BytesType)
|
||||
b, pos := appendSpeculativeLength(b)
|
||||
var nerr errors.NonFatal
|
||||
for i, llen := 0, list.Len(); i < llen; i++ {
|
||||
var err error
|
||||
b, err = o.marshalSingular(b, num, fd, list.Get(i))
|
||||
if !nerr.Merge(err) {
|
||||
return b, err
|
||||
}
|
||||
}
|
||||
b = finishSpeculativeLength(b, pos)
|
||||
return b, nerr.E
|
||||
}
|
||||
|
||||
kind := fd.Kind()
|
||||
var nerr errors.NonFatal
|
||||
for i, llen := 0, list.Len(); i < llen; i++ {
|
||||
var err error
|
||||
b = wire.AppendTag(b, num, wireTypes[kind])
|
||||
b, err = o.marshalSingular(b, num, fd, list.Get(i))
|
||||
if !nerr.Merge(err) {
|
||||
return b, err
|
||||
}
|
||||
}
|
||||
return b, nerr.E
|
||||
}
|
||||
|
||||
func (o MarshalOptions) marshalMap(b []byte, num wire.Number, fd protoreflect.FieldDescriptor, mapv protoreflect.Map) ([]byte, error) {
|
||||
keyf := fd.MapKey()
|
||||
valf := fd.MapValue()
|
||||
var nerr errors.NonFatal
|
||||
var err error
|
||||
o.rangeMap(mapv, keyf.Kind(), func(key protoreflect.MapKey, value protoreflect.Value) bool {
|
||||
@ -229,35 +256,6 @@ func (o MarshalOptions) rangeMap(mapv protoreflect.Map, kind protoreflect.Kind,
|
||||
mapsort.Range(mapv, kind, f)
|
||||
}
|
||||
|
||||
func (o MarshalOptions) marshalPacked(b []byte, num wire.Number, field protoreflect.FieldDescriptor, list protoreflect.List) ([]byte, error) {
|
||||
b = wire.AppendTag(b, num, wire.BytesType)
|
||||
b, pos := appendSpeculativeLength(b)
|
||||
var nerr errors.NonFatal
|
||||
for i, llen := 0, list.Len(); i < llen; i++ {
|
||||
var err error
|
||||
b, err = o.marshalSingular(b, num, field, list.Get(i))
|
||||
if !nerr.Merge(err) {
|
||||
return b, err
|
||||
}
|
||||
}
|
||||
b = finishSpeculativeLength(b, pos)
|
||||
return b, nerr.E
|
||||
}
|
||||
|
||||
func (o MarshalOptions) marshalList(b []byte, num wire.Number, field protoreflect.FieldDescriptor, list protoreflect.List) ([]byte, error) {
|
||||
kind := field.Kind()
|
||||
var nerr errors.NonFatal
|
||||
for i, llen := 0, list.Len(); i < llen; i++ {
|
||||
var err error
|
||||
b = wire.AppendTag(b, num, wireTypes[kind])
|
||||
b, err = o.marshalSingular(b, num, field, list.Get(i))
|
||||
if !nerr.Merge(err) {
|
||||
return b, err
|
||||
}
|
||||
}
|
||||
return b, nerr.E
|
||||
}
|
||||
|
||||
// When encoding length-prefixed fields, we speculatively set aside some number of bytes
|
||||
// for the length, encode the data, and then encode the length (shifting the data if necessary
|
||||
// to make room).
|
||||
|
@ -98,10 +98,10 @@ func equalMessage(a, b pref.Message) bool {
|
||||
// equalFields compares two fields.
|
||||
func equalFields(fd pref.FieldDescriptor, a, b pref.Value) bool {
|
||||
switch {
|
||||
case fd.IsList():
|
||||
return equalList(fd, a.List(), b.List())
|
||||
case fd.IsMap():
|
||||
return equalMap(fd, a.Map(), b.Map())
|
||||
case fd.Cardinality() == pref.Repeated:
|
||||
return equalList(fd, a.List(), b.List())
|
||||
default:
|
||||
return equalValue(fd, a, b)
|
||||
}
|
||||
@ -109,7 +109,6 @@ func equalFields(fd pref.FieldDescriptor, a, b pref.Value) bool {
|
||||
|
||||
// equalMap compares a map field.
|
||||
func equalMap(fd pref.FieldDescriptor, a, b pref.Map) bool {
|
||||
fdv := fd.Message().Fields().ByNumber(2)
|
||||
alen := a.Len()
|
||||
if alen != b.Len() {
|
||||
return false
|
||||
@ -117,7 +116,7 @@ func equalMap(fd pref.FieldDescriptor, a, b pref.Map) bool {
|
||||
equal := true
|
||||
a.Range(func(k pref.MapKey, va pref.Value) bool {
|
||||
vb := b.Get(k)
|
||||
if !vb.IsValid() || !equalValue(fdv, va, vb) {
|
||||
if !vb.IsValid() || !equalValue(fd.MapValue(), va, vb) {
|
||||
equal = false
|
||||
return false
|
||||
}
|
||||
|
@ -53,20 +53,14 @@ func isInitialized(m pref.Message, stack []interface{}) error {
|
||||
return true
|
||||
}
|
||||
if field.IsMap() {
|
||||
if md.Fields().ByNumber(2).Message() == nil {
|
||||
if field.MapValue().Message() == nil {
|
||||
return true
|
||||
}
|
||||
}
|
||||
// Recurse into the field
|
||||
stack := append(stack, field.Name())
|
||||
switch {
|
||||
case field.IsMap():
|
||||
v.Map().Range(func(key pref.MapKey, v pref.Value) bool {
|
||||
stack := append(stack, "[", key, "].")
|
||||
err = isInitialized(v.Message(), stack)
|
||||
return err == nil
|
||||
})
|
||||
case field.Cardinality() == pref.Repeated:
|
||||
case field.IsList():
|
||||
for i, list := 0, v.List(); i < list.Len(); i++ {
|
||||
stack := append(stack, "[", i, "].")
|
||||
err = isInitialized(list.Get(i).Message(), stack)
|
||||
@ -74,6 +68,12 @@ func isInitialized(m pref.Message, stack []interface{}) error {
|
||||
break
|
||||
}
|
||||
}
|
||||
case field.IsMap():
|
||||
v.Map().Range(func(key pref.MapKey, v pref.Value) bool {
|
||||
stack := append(stack, "[", key, "].")
|
||||
err = isInitialized(v.Message(), stack)
|
||||
return err == nil
|
||||
})
|
||||
default:
|
||||
stack := append(stack, ".")
|
||||
err = isInitialized(v.Message(), stack)
|
||||
|
@ -54,43 +54,38 @@ func sizeMessage(m protoreflect.Message) (size int) {
|
||||
return size
|
||||
}
|
||||
|
||||
func sizeField(field protoreflect.FieldDescriptor, value protoreflect.Value) (size int) {
|
||||
num := field.Number()
|
||||
kind := field.Kind()
|
||||
func sizeField(fd protoreflect.FieldDescriptor, value protoreflect.Value) (size int) {
|
||||
num := fd.Number()
|
||||
switch {
|
||||
case field.Cardinality() != protoreflect.Repeated:
|
||||
return wire.SizeTag(num) + sizeSingular(num, kind, value)
|
||||
case field.IsMap():
|
||||
return sizeMap(num, kind, field.Message(), value.Map())
|
||||
case field.IsPacked():
|
||||
return sizePacked(num, kind, value.List())
|
||||
case fd.IsList():
|
||||
return sizeList(num, fd, value.List())
|
||||
case fd.IsMap():
|
||||
return sizeMap(num, fd, value.Map())
|
||||
default:
|
||||
return sizeList(num, kind, value.List())
|
||||
return wire.SizeTag(num) + sizeSingular(num, fd.Kind(), value)
|
||||
}
|
||||
}
|
||||
|
||||
func sizeMap(num wire.Number, kind protoreflect.Kind, mdesc protoreflect.MessageDescriptor, mapv protoreflect.Map) (size int) {
|
||||
keyf := mdesc.Fields().ByNumber(1)
|
||||
valf := mdesc.Fields().ByNumber(2)
|
||||
func sizeList(num wire.Number, fd protoreflect.FieldDescriptor, list protoreflect.List) (size int) {
|
||||
if fd.IsPacked() {
|
||||
content := 0
|
||||
for i, llen := 0, list.Len(); i < llen; i++ {
|
||||
content += sizeSingular(num, fd.Kind(), list.Get(i))
|
||||
}
|
||||
return wire.SizeTag(num) + wire.SizeBytes(content)
|
||||
}
|
||||
|
||||
for i, llen := 0, list.Len(); i < llen; i++ {
|
||||
size += wire.SizeTag(num) + sizeSingular(num, fd.Kind(), list.Get(i))
|
||||
}
|
||||
return size
|
||||
}
|
||||
|
||||
func sizeMap(num wire.Number, fd protoreflect.FieldDescriptor, mapv protoreflect.Map) (size int) {
|
||||
mapv.Range(func(key protoreflect.MapKey, value protoreflect.Value) bool {
|
||||
size += wire.SizeTag(num)
|
||||
size += wire.SizeBytes(sizeField(keyf, key.Value()) + sizeField(valf, value))
|
||||
size += wire.SizeBytes(sizeField(fd.MapKey(), key.Value()) + sizeField(fd.MapValue(), value))
|
||||
return true
|
||||
})
|
||||
return size
|
||||
}
|
||||
|
||||
func sizePacked(num wire.Number, kind protoreflect.Kind, list protoreflect.List) (size int) {
|
||||
content := 0
|
||||
for i, llen := 0, list.Len(); i < llen; i++ {
|
||||
content += sizeSingular(num, kind, list.Get(i))
|
||||
}
|
||||
return wire.SizeTag(num) + wire.SizeBytes(content)
|
||||
}
|
||||
|
||||
func sizeList(num wire.Number, kind protoreflect.Kind, list protoreflect.List) (size int) {
|
||||
for i, llen := 0, list.Len(); i < llen; i++ {
|
||||
size += wire.SizeTag(num) + sizeSingular(num, kind, list.Get(i))
|
||||
}
|
||||
return size
|
||||
}
|
||||
|
@ -637,9 +637,9 @@ type Field struct {
|
||||
func newField(gen *Plugin, f *File, message *Message, desc protoreflect.FieldDescriptor) *Field {
|
||||
var loc Location
|
||||
switch {
|
||||
case desc.Extendee() != nil && message == nil:
|
||||
case desc.IsExtension() && message == nil:
|
||||
loc = f.location(fieldnum.FileDescriptorProto_Extension, int32(desc.Index()))
|
||||
case desc.Extendee() != nil && message != nil:
|
||||
case desc.IsExtension() && message != nil:
|
||||
loc = message.Location.appendPath(fieldnum.DescriptorProto_Extension, int32(desc.Index()))
|
||||
default:
|
||||
loc = message.Location.appendPath(fieldnum.DescriptorProto_Field, int32(desc.Index()))
|
||||
@ -650,8 +650,8 @@ func newField(gen *Plugin, f *File, message *Message, desc protoreflect.FieldDes
|
||||
Parent: message,
|
||||
Location: loc,
|
||||
}
|
||||
if desc.Oneof() != nil {
|
||||
field.Oneof = message.Oneofs[desc.Oneof().Index()]
|
||||
if desc.ContainingOneof() != nil {
|
||||
field.Oneof = message.Oneofs[desc.ContainingOneof().Index()]
|
||||
}
|
||||
return field
|
||||
}
|
||||
@ -677,8 +677,8 @@ func (field *Field) init(gen *Plugin) error {
|
||||
}
|
||||
field.Enum = enum
|
||||
}
|
||||
if desc.Extendee() != nil {
|
||||
mname := desc.Extendee().FullName()
|
||||
if desc.IsExtension() {
|
||||
mname := desc.ContainingMessage().FullName()
|
||||
message, ok := gen.messagesByName[mname]
|
||||
if !ok {
|
||||
return fmt.Errorf("field %v: no descriptor for type %v", desc.FullName(), mname)
|
||||
|
@ -96,12 +96,14 @@ func ToDescriptorProto(message protoreflect.MessageDescriptor) *descriptorpb.Des
|
||||
// google.protobuf.FieldDescriptorProto.
|
||||
func ToFieldDescriptorProto(field protoreflect.FieldDescriptor) *descriptorpb.FieldDescriptorProto {
|
||||
p := &descriptorpb.FieldDescriptorProto{
|
||||
Name: scalar.String(string(field.Name())),
|
||||
Number: scalar.Int32(int32(field.Number())),
|
||||
Label: descriptorpb.FieldDescriptorProto_Label(field.Cardinality()).Enum(),
|
||||
Type: descriptorpb.FieldDescriptorProto_Type(field.Kind()).Enum(),
|
||||
Extendee: fullNameOf(field.Extendee()),
|
||||
Options: field.Options().(*descriptorpb.FieldOptions),
|
||||
Name: scalar.String(string(field.Name())),
|
||||
Number: scalar.Int32(int32(field.Number())),
|
||||
Label: descriptorpb.FieldDescriptorProto_Label(field.Cardinality()).Enum(),
|
||||
Type: descriptorpb.FieldDescriptorProto_Type(field.Kind()).Enum(),
|
||||
Options: field.Options().(*descriptorpb.FieldOptions),
|
||||
}
|
||||
if field.IsExtension() {
|
||||
p.Extendee = fullNameOf(field.ContainingMessage())
|
||||
}
|
||||
switch field.Kind() {
|
||||
case protoreflect.EnumKind:
|
||||
@ -125,7 +127,7 @@ func ToFieldDescriptorProto(field protoreflect.FieldDescriptor) *descriptorpb.Fi
|
||||
p.DefaultValue = scalar.String(def)
|
||||
}
|
||||
}
|
||||
if oneof := field.Oneof(); oneof != nil {
|
||||
if oneof := field.ContainingOneof(); oneof != nil {
|
||||
p.OneofIndex = scalar.Int32(int32(oneof.Index()))
|
||||
}
|
||||
return p
|
||||
|
@ -285,23 +285,41 @@ type FieldDescriptor interface {
|
||||
// It is usually the camel-cased form of the field name.
|
||||
JSONName() string
|
||||
|
||||
// IsPacked reports whether repeated primitive numeric kinds should be
|
||||
// serialized using a packed encoding.
|
||||
// If true, then it implies Cardinality is Repeated.
|
||||
IsPacked() bool
|
||||
// IsExtension reports whether this is an extension field. If false,
|
||||
// then Parent and ContainingMessage refer to the same message.
|
||||
// Otherwise, ContainingMessage and Parent almost certainly differ.
|
||||
IsExtension() bool
|
||||
|
||||
// IsWeak reports whether this is a weak field, which does not impose a
|
||||
// direct dependency on the target type.
|
||||
// If true, then MessageDescriptor returns a placeholder type.
|
||||
IsWeak() bool
|
||||
|
||||
// IsMap reports whether this field represents a map.
|
||||
// The value type for the associated field is a Map instead of a List.
|
||||
//
|
||||
// If true, it implies that Kind is MessageKind, Cardinality is Repeated,
|
||||
// and MessageDescriptor.IsMapEntry is true.
|
||||
// IsPacked reports whether repeated primitive numeric kinds should be
|
||||
// serialized using a packed encoding.
|
||||
// If true, then it implies Cardinality is Repeated.
|
||||
IsPacked() bool
|
||||
|
||||
// IsList reports whether this field represents a list,
|
||||
// where the value type for the associated field is a List.
|
||||
// It is equivalent to checking whether Cardinality is Repeated and
|
||||
// that IsMap reports false.
|
||||
IsList() bool
|
||||
|
||||
// IsMap reports whether this field represents a map,
|
||||
// where the value type for the associated field is a Map.
|
||||
// It is equivalent to checking whether Cardinality is Repeated,
|
||||
// that the Kind is MessageKind, and that Message.IsMapEntry reports true.
|
||||
IsMap() bool
|
||||
|
||||
// MapKey returns the field descriptor for the key in the map entry.
|
||||
// It returns nil if IsMap reports false.
|
||||
MapKey() FieldDescriptor
|
||||
|
||||
// MapValue returns the field descriptor for the value in the map entry.
|
||||
// It returns nil if IsMap reports false.
|
||||
MapValue() FieldDescriptor
|
||||
|
||||
// HasDefault reports whether this field has a default value.
|
||||
HasDefault() bool
|
||||
|
||||
@ -312,19 +330,26 @@ type FieldDescriptor interface {
|
||||
// The Value type is determined by the Kind.
|
||||
Default() Value
|
||||
|
||||
// DefaultEnumValue returns the EnumValueDescriptor for the default value
|
||||
// DefaultEnumValue returns the enum value descriptor for the default value
|
||||
// of an enum field, and is nil for any other kind of field.
|
||||
DefaultEnumValue() EnumValueDescriptor
|
||||
|
||||
// Oneof is the containing oneof that this field belongs to,
|
||||
// and is nil if this field is not part of a oneof.
|
||||
// TODO: Remove this.
|
||||
// Deprecated: Use ContainingOneof instead.
|
||||
Oneof() OneofDescriptor
|
||||
|
||||
// Extendee returns a message descriptor for the extended message
|
||||
// that this extension field belongs in.
|
||||
// It returns nil if this field is not an extension.
|
||||
// TODO: Remove this.
|
||||
// Deprecated: Use ContainingMessage instead.
|
||||
Extendee() MessageDescriptor
|
||||
|
||||
// ContainingOneof is the containing oneof that this field belongs to,
|
||||
// and is nil if this field is not part of a oneof.
|
||||
ContainingOneof() OneofDescriptor
|
||||
|
||||
// ContainingMessage is the containing message that this field belongs to.
|
||||
// For extension fields, this may not necessarily be the parent message
|
||||
// that the field is declared within.
|
||||
ContainingMessage() MessageDescriptor
|
||||
|
||||
// Enum is the enum descriptor if Kind is EnumKind.
|
||||
// It returns nil for any other Kind.
|
||||
Enum() EnumDescriptor
|
||||
|
@ -381,7 +381,7 @@ typeLoop:
|
||||
// Check for conflicts in extensionsByMessage.
|
||||
if xt, _ := typ.(protoreflect.ExtensionType); xt != nil {
|
||||
field := xt.Descriptor().Number()
|
||||
message := xt.Descriptor().Extendee().FullName()
|
||||
message := xt.Descriptor().ContainingMessage().FullName()
|
||||
if r.extensionsByMessage[message][field] != nil {
|
||||
if firstErr == nil {
|
||||
firstErr = errors.New("extension %v is already registered on message %v", name, message)
|
||||
|
@ -26,10 +26,10 @@ func TestMessage(t testing.TB, message proto.Message) {
|
||||
for i := 0; i < md.Fields().Len(); i++ {
|
||||
fd := md.Fields().Get(i)
|
||||
switch {
|
||||
case fd.IsList():
|
||||
testFieldList(t, m, fd)
|
||||
case fd.IsMap():
|
||||
testFieldMap(t, m, fd)
|
||||
case fd.Cardinality() == pref.Repeated:
|
||||
testFieldList(t, m, fd)
|
||||
case fd.Kind() == pref.FloatKind || fd.Kind() == pref.DoubleKind:
|
||||
testFieldFloat(t, m, fd)
|
||||
}
|
||||
@ -105,7 +105,7 @@ func testField(t testing.TB, m pref.Message, fd pref.FieldDescriptor) {
|
||||
if fd.Cardinality() == pref.Repeated {
|
||||
wantHas = false
|
||||
}
|
||||
if fd.Oneof() != nil {
|
||||
if fd.ContainingOneof() != nil {
|
||||
wantHas = true
|
||||
}
|
||||
}
|
||||
@ -122,12 +122,12 @@ func testField(t testing.TB, m pref.Message, fd pref.FieldDescriptor) {
|
||||
t.Errorf("after clearing %q:\nHas(%v) = %v, want %v", name, num, got, want)
|
||||
}
|
||||
switch {
|
||||
case fd.IsMap():
|
||||
if got := known.Get(num); got.Map().Len() != 0 {
|
||||
case fd.IsList():
|
||||
if got := known.Get(num); got.List().Len() != 0 {
|
||||
t.Errorf("after clearing %q:\nGet(%v) = %v, want empty list", name, num, formatValue(got))
|
||||
}
|
||||
case fd.Cardinality() == pref.Repeated:
|
||||
if got := known.Get(num); got.List().Len() != 0 {
|
||||
case fd.IsMap():
|
||||
if got := known.Get(num); got.Map().Len() != 0 {
|
||||
t.Errorf("after clearing %q:\nGet(%v) = %v, want empty list", name, num, formatValue(got))
|
||||
}
|
||||
default:
|
||||
@ -421,6 +421,16 @@ const (
|
||||
func newValue(m pref.Message, fd pref.FieldDescriptor, n seed, stack []pref.MessageDescriptor) pref.Value {
|
||||
num := fd.Number()
|
||||
switch {
|
||||
case fd.IsList():
|
||||
list := m.New().KnownFields().Get(num).List()
|
||||
if n == 0 {
|
||||
return pref.ValueOf(list)
|
||||
}
|
||||
list.Append(newListElement(fd, list, 0, stack))
|
||||
list.Append(newListElement(fd, list, minVal, stack))
|
||||
list.Append(newListElement(fd, list, maxVal, stack))
|
||||
list.Append(newListElement(fd, list, n, stack))
|
||||
return pref.ValueOf(list)
|
||||
case fd.IsMap():
|
||||
mapv := m.New().KnownFields().Get(num).Map()
|
||||
if n == 0 {
|
||||
@ -431,16 +441,6 @@ func newValue(m pref.Message, fd pref.FieldDescriptor, n seed, stack []pref.Mess
|
||||
mapv.Set(newMapKey(fd, maxVal), newMapValue(fd, mapv, maxVal, stack))
|
||||
mapv.Set(newMapKey(fd, n), newMapValue(fd, mapv, 10*n, stack))
|
||||
return pref.ValueOf(mapv)
|
||||
case fd.Cardinality() == pref.Repeated:
|
||||
list := m.New().KnownFields().Get(num).List()
|
||||
if n == 0 {
|
||||
return pref.ValueOf(list)
|
||||
}
|
||||
list.Append(newListElement(fd, list, 0, stack))
|
||||
list.Append(newListElement(fd, list, minVal, stack))
|
||||
list.Append(newListElement(fd, list, maxVal, stack))
|
||||
list.Append(newListElement(fd, list, n, stack))
|
||||
return pref.ValueOf(list)
|
||||
case fd.Message() != nil:
|
||||
return populateMessage(m.KnownFields().NewMessage(num), n, stack)
|
||||
default:
|
||||
@ -456,12 +456,12 @@ func newListElement(fd pref.FieldDescriptor, list pref.List, n seed, stack []pre
|
||||
}
|
||||
|
||||
func newMapKey(fd pref.FieldDescriptor, n seed) pref.MapKey {
|
||||
kd := fd.Message().Fields().ByNumber(1)
|
||||
kd := fd.MapKey()
|
||||
return newScalarValue(kd, n).MapKey()
|
||||
}
|
||||
|
||||
func newMapValue(fd pref.FieldDescriptor, mapv pref.Map, n seed, stack []pref.MessageDescriptor) pref.Value {
|
||||
vd := fd.Message().Fields().ByNumber(2)
|
||||
vd := fd.MapValue()
|
||||
if vd.Message() == nil {
|
||||
return newScalarValue(vd, n)
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user