mirror of
https://github.com/protocolbuffers/protobuf-go.git
synced 2025-01-06 00:55:51 +00:00
internal/impl: pull out message struct info into a type
Minor refactoring of impl.MessageType initialization: Pull the information gathered about a message struct by makeKnownFieldsFunc out into a struct that we can pass around. At the moment, makeKnownFieldsFunc is the only user of this struct, but this will simplify the table (un)marshaler. Drop the 'specialByName' map indexing XXX_ fields because it currently isn't used anywhere. Change-Id: I992c9f490982a05f3919d7d4e08052e2ab54d44d Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/176220 Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
This commit is contained in:
parent
00a323deed
commit
3eaddf0344
@ -46,44 +46,40 @@ func (mi *MessageType) init() {
|
||||
panic(fmt.Sprintf("got %v, want *struct kind", t))
|
||||
}
|
||||
|
||||
mi.makeKnownFieldsFunc(t.Elem())
|
||||
si := mi.makeStructInfo(t.Elem())
|
||||
mi.makeKnownFieldsFunc(si)
|
||||
mi.makeUnknownFieldsFunc(t.Elem())
|
||||
mi.makeExtensionFieldsFunc(t.Elem())
|
||||
})
|
||||
}
|
||||
|
||||
// makeKnownFieldsFunc generates functions for operations that can be performed
|
||||
// on each protobuf message field. It takes in a reflect.Type representing the
|
||||
// Go struct and matches message fields with struct fields.
|
||||
//
|
||||
// This code assumes that the struct is well-formed and panics if there are
|
||||
// any discrepancies.
|
||||
func (mi *MessageType) makeKnownFieldsFunc(t reflect.Type) {
|
||||
type structInfo struct {
|
||||
fieldsByNumber map[pref.FieldNumber]reflect.StructField
|
||||
oneofsByName map[pref.Name]reflect.StructField
|
||||
oneofWrappersByType map[reflect.Type]pref.FieldNumber
|
||||
oneofWrappersByNumber map[pref.FieldNumber]reflect.Type
|
||||
}
|
||||
|
||||
func (mi *MessageType) makeStructInfo(t reflect.Type) structInfo {
|
||||
// Generate a mapping of field numbers and names to Go struct field or type.
|
||||
var (
|
||||
fieldsByNumber = map[pref.FieldNumber]reflect.StructField{}
|
||||
oneofsByName = map[pref.Name]reflect.StructField{}
|
||||
oneofWrappersByType = map[reflect.Type]pref.FieldNumber{}
|
||||
oneofWrappersByNumber = map[pref.FieldNumber]reflect.Type{}
|
||||
specialByName = map[string]reflect.StructField{}
|
||||
)
|
||||
si := structInfo{
|
||||
fieldsByNumber: map[pref.FieldNumber]reflect.StructField{},
|
||||
oneofsByName: map[pref.Name]reflect.StructField{},
|
||||
oneofWrappersByType: map[reflect.Type]pref.FieldNumber{},
|
||||
oneofWrappersByNumber: map[pref.FieldNumber]reflect.Type{},
|
||||
}
|
||||
fieldLoop:
|
||||
for i := 0; i < t.NumField(); i++ {
|
||||
f := t.Field(i)
|
||||
for _, s := range strings.Split(f.Tag.Get("protobuf"), ",") {
|
||||
if len(s) > 0 && strings.Trim(s, "0123456789") == "" {
|
||||
n, _ := strconv.ParseUint(s, 10, 64)
|
||||
fieldsByNumber[pref.FieldNumber(n)] = f
|
||||
si.fieldsByNumber[pref.FieldNumber(n)] = f
|
||||
continue fieldLoop
|
||||
}
|
||||
}
|
||||
if s := f.Tag.Get("protobuf_oneof"); len(s) > 0 {
|
||||
oneofsByName[pref.Name(s)] = f
|
||||
continue fieldLoop
|
||||
}
|
||||
switch f.Name {
|
||||
case "XXX_weak", "XXX_unrecognized", "XXX_sizecache", "XXX_extensions", "XXX_InternalExtensions":
|
||||
specialByName[f.Name] = f
|
||||
si.oneofsByName[pref.Name(s)] = f
|
||||
continue fieldLoop
|
||||
}
|
||||
}
|
||||
@ -100,21 +96,30 @@ fieldLoop:
|
||||
for _, s := range strings.Split(f.Tag.Get("protobuf"), ",") {
|
||||
if len(s) > 0 && strings.Trim(s, "0123456789") == "" {
|
||||
n, _ := strconv.ParseUint(s, 10, 64)
|
||||
oneofWrappersByType[tf] = pref.FieldNumber(n)
|
||||
oneofWrappersByNumber[pref.FieldNumber(n)] = tf
|
||||
si.oneofWrappersByType[tf] = pref.FieldNumber(n)
|
||||
si.oneofWrappersByNumber[pref.FieldNumber(n)] = tf
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
return si
|
||||
}
|
||||
|
||||
// makeKnownFieldsFunc generates functions for operations that can be performed
|
||||
// on each protobuf message field. It takes in a reflect.Type representing the
|
||||
// Go struct and matches message fields with struct fields.
|
||||
//
|
||||
// This code assumes that the struct is well-formed and panics if there are
|
||||
// any discrepancies.
|
||||
func (mi *MessageType) makeKnownFieldsFunc(si structInfo) {
|
||||
mi.fields = map[pref.FieldNumber]*fieldInfo{}
|
||||
for i := 0; i < mi.PBType.Fields().Len(); i++ {
|
||||
fd := mi.PBType.Fields().Get(i)
|
||||
fs := fieldsByNumber[fd.Number()]
|
||||
fs := si.fieldsByNumber[fd.Number()]
|
||||
var fi fieldInfo
|
||||
switch {
|
||||
case fd.Oneof() != nil:
|
||||
fi = fieldInfoForOneof(fd, oneofsByName[fd.Oneof().Name()], oneofWrappersByNumber[fd.Number()])
|
||||
fi = fieldInfoForOneof(fd, si.oneofsByName[fd.Oneof().Name()], si.oneofWrappersByNumber[fd.Number()])
|
||||
case fd.IsMap():
|
||||
fi = fieldInfoForMap(fd, fs)
|
||||
case fd.Cardinality() == pref.Repeated:
|
||||
@ -130,7 +135,7 @@ fieldLoop:
|
||||
mi.oneofs = map[pref.Name]*oneofInfo{}
|
||||
for i := 0; i < mi.PBType.Oneofs().Len(); i++ {
|
||||
od := mi.PBType.Oneofs().Get(i)
|
||||
mi.oneofs[od.Name()] = makeOneofInfo(od, oneofsByName[od.Name()], oneofWrappersByType)
|
||||
mi.oneofs[od.Name()] = makeOneofInfo(od, si.oneofsByName[od.Name()], si.oneofWrappersByType)
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user