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>
diff --git a/internal/impl/message.go b/internal/impl/message.go
index 29d95e6..8879015 100644
--- a/internal/impl/message.go
+++ b/internal/impl/message.go
@@ -46,44 +46,40 @@
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 @@
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 @@
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)
}
}