reflect/prototype: initial commit

Add the prototype package which provides constructors for
protoreflect.{Enum,Message,Extension}Type.

Switch all usages of the internal/prototype equivalent to the new package.
Switch all custom implementions of {Enum,Message}Type to the new package.

Change-Id: Ia9dae6fed4f2b90e55c123627044a7faf098c4b1
Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/178438
Reviewed-by: Damien Neil <dneil@google.com>
diff --git a/internal/impl/message_field.go b/internal/impl/message_field.go
index 72f4523..a69d2c8 100644
--- a/internal/impl/message_field.go
+++ b/internal/impl/message_field.go
@@ -42,7 +42,7 @@
 	if !reflect.PtrTo(ot).Implements(ft) {
 		panic(fmt.Sprintf("invalid type: %v does not implement %v", ot, ft))
 	}
-	conv := pvalue.NewLegacyConverter(ot.Field(0).Type, fd.Kind(), legacyWrapper)
+	conv := newConverter(ot.Field(0).Type, fd.Kind())
 	fieldOffset := offsetOf(fs)
 	// TODO: Implement unsafe fast path?
 	return fieldInfo{
@@ -86,12 +86,9 @@
 			}
 			rv.Set(reflect.Zero(rv.Type()))
 		},
-		newMessage: func() pref.Message {
-			// This is only valid for messages and panics for other kinds.
-			return conv.MessageType.New()
-		},
-		offset:    fieldOffset,
-		isPointer: true,
+		newMessage: conv.NewMessage,
+		offset:     fieldOffset,
+		isPointer:  true,
 	}
 }
 
@@ -100,8 +97,8 @@
 	if ft.Kind() != reflect.Map {
 		panic(fmt.Sprintf("invalid type: got %v, want map kind", ft))
 	}
-	keyConv := pvalue.NewLegacyConverter(ft.Key(), fd.MapKey().Kind(), legacyWrapper)
-	valConv := pvalue.NewLegacyConverter(ft.Elem(), fd.MapValue().Kind(), legacyWrapper)
+	keyConv := newConverter(ft.Key(), fd.MapKey().Kind())
+	valConv := newConverter(ft.Elem(), fd.MapValue().Kind())
 	wiretag := wire.EncodeTag(fd.Number(), wireTypes[fd.Kind()])
 	fieldOffset := offsetOf(fs)
 	// TODO: Implement unsafe fast path?
@@ -142,7 +139,7 @@
 	if ft.Kind() != reflect.Slice {
 		panic(fmt.Sprintf("invalid type: got %v, want slice kind", ft))
 	}
-	conv := pvalue.NewLegacyConverter(ft.Elem(), fd.Kind(), legacyWrapper)
+	conv := newConverter(ft.Elem(), fd.Kind())
 	var wiretag uint64
 	if !fd.IsPacked() {
 		wiretag = wire.EncodeTag(fd.Number(), wireTypes[fd.Kind()])
@@ -197,7 +194,7 @@
 			ft = ft.Elem()
 		}
 	}
-	conv := pvalue.NewLegacyConverter(ft, fd.Kind(), legacyWrapper)
+	conv := newConverter(ft, fd.Kind())
 	fieldOffset := offsetOf(fs)
 	wiretag := wire.EncodeTag(fd.Number(), wireTypes[fd.Kind()])
 	// TODO: Implement unsafe fast path?
@@ -267,7 +264,7 @@
 
 func fieldInfoForMessage(fd pref.FieldDescriptor, fs reflect.StructField) fieldInfo {
 	ft := fs.Type
-	conv := pvalue.NewLegacyConverter(ft, fd.Kind(), legacyWrapper)
+	conv := newConverter(ft, fd.Kind())
 	fieldOffset := offsetOf(fs)
 	// TODO: Implement unsafe fast path?
 	wiretag := wire.EncodeTag(fd.Number(), wireTypes[fd.Kind()])
@@ -300,14 +297,12 @@
 			rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem()
 			rv.Set(reflect.Zero(rv.Type()))
 		},
-		newMessage: func() pref.Message {
-			return conv.MessageType.New()
-		},
-		funcs:     fieldCoder(fd, ft),
-		offset:    fieldOffset,
-		isPointer: true,
-		wiretag:   wiretag,
-		tagsize:   wire.SizeVarint(wiretag),
+		newMessage: conv.NewMessage,
+		funcs:      fieldCoder(fd, ft),
+		offset:     fieldOffset,
+		isPointer:  true,
+		wiretag:    wiretag,
+		tagsize:    wire.SizeVarint(wiretag),
 	}
 }
 
@@ -342,3 +337,10 @@
 		},
 	}
 }
+
+func newConverter(t reflect.Type, k pref.Kind) pvalue.Converter {
+	if legacyWrapper != nil {
+		return legacyWrapper.NewConverter(t, k)
+	}
+	return pvalue.NewConverter(t, k)
+}