internal/impl: support legacy unknown extension fields

The unknown fields in legacy messages is split across the XXX_unrecognized
field and also the XXX_InternalExtensions field. Implement support for
wrapping both fields and presenting it as if it were a unified set of
unknown fields.

Change-Id: If274fae2b48962520edd8a640080b6eced747684
Reviewed-on: https://go-review.googlesource.com/c/146517
Reviewed-by: Damien Neil <dneil@google.com>
diff --git a/internal/impl/message.go b/internal/impl/message.go
index 2b0a9ca..a3e4b9d 100644
--- a/internal/impl/message.go
+++ b/internal/impl/message.go
@@ -53,9 +53,8 @@
 		mi.goType = t
 
 		// Derive the message descriptor if unspecified.
-		md := mi.Desc
-		if md == nil {
-			// TODO: derive the message type from the Go struct type
+		if mi.Desc == nil {
+			mi.Desc = loadMessageDesc(t)
 		}
 
 		// Initialize the Go message type wrapper if the Go type does not
@@ -68,7 +67,7 @@
 		// Generated code ensures that this property holds.
 		if _, ok := p.(pref.ProtoMessage); !ok {
 			mi.pbType = ptype.NewGoMessage(&ptype.GoMessage{
-				MessageDescriptor: md,
+				MessageDescriptor: mi.Desc,
 				New: func(pref.MessageType) pref.ProtoMessage {
 					p := reflect.New(t.Elem()).Interface()
 					return (*message)(mi.dataTypeOf(p))
@@ -76,9 +75,9 @@
 			})
 		}
 
-		mi.generateKnownFieldFuncs(t.Elem(), md)
-		mi.generateUnknownFieldFuncs(t.Elem(), md)
-		mi.generateExtensionFieldFuncs(t.Elem(), md)
+		mi.makeKnownFieldsFunc(t.Elem())
+		mi.makeUnknownFieldsFunc(t.Elem())
+		mi.makeExtensionFieldsFunc(t.Elem())
 	})
 
 	// TODO: Remove this check? This API is primarily used by generated code,
@@ -90,14 +89,14 @@
 	}
 }
 
-// generateKnownFieldFuncs generates per-field functions for all operations
+// makeKnownFieldsFunc generates per-field functions for all operations
 // to be performed on each field. It takes in a reflect.Type representing the
 // Go struct, and a protoreflect.MessageDescriptor to match with the fields
 // in the struct.
 //
 // This code assumes that the struct is well-formed and panics if there are
 // any discrepancies.
-func (mi *MessageType) generateKnownFieldFuncs(t reflect.Type, md pref.MessageDescriptor) {
+func (mi *MessageType) makeKnownFieldsFunc(t reflect.Type) {
 	// Generate a mapping of field numbers and names to Go struct field or type.
 	fields := map[pref.FieldNumber]reflect.StructField{}
 	oneofs := map[pref.Name]reflect.StructField{}
@@ -140,8 +139,8 @@
 	}
 
 	mi.fields = map[pref.FieldNumber]*fieldInfo{}
-	for i := 0; i < md.Fields().Len(); i++ {
-		fd := md.Fields().Get(i)
+	for i := 0; i < mi.Desc.Fields().Len(); i++ {
+		fd := mi.Desc.Fields().Get(i)
 		fs := fields[fd.Number()]
 		var fi fieldInfo
 		switch {
@@ -162,8 +161,8 @@
 	}
 }
 
-func (mi *MessageType) generateUnknownFieldFuncs(t reflect.Type, md pref.MessageDescriptor) {
-	if f := generateLegacyUnknownFieldFuncs(t, md); f != nil {
+func (mi *MessageType) makeUnknownFieldsFunc(t reflect.Type) {
+	if f := makeLegacyUnknownFieldsFunc(t); f != nil {
 		mi.unknownFields = f
 		return
 	}
@@ -172,7 +171,7 @@
 	}
 }
 
-func (mi *MessageType) generateExtensionFieldFuncs(t reflect.Type, md pref.MessageDescriptor) {
+func (mi *MessageType) makeExtensionFieldsFunc(t reflect.Type) {
 	// TODO
 	mi.extensionFields = func(*messageDataType) pref.KnownFields {
 		return emptyExtensionFields{}