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)
 	}
 }