internal/impl: store extension values as Values

Change the storage type of ExtensionField from interface{} to
protoreflect.Value.

Replace the codec functions operating on interface{}s with ones
operating on Values.

Values are potentially more efficient, since they can represent
non-pointer types without allocation. This also reduces the number of
types used to represent field values.

Additionally, this change lays groundwork for changing the
user-visible representation of repeated extension fields from
*[]T to []T. The storage type for extension fields must support mutation
(thus *[]T currently); changing the storage type to a Value permits this
without the need to introduce yet another view on field values.

Change-Id: Ida336be14112bb940f655236eb58df21bf312525
Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/192218
Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
diff --git a/internal/impl/codec_tables.go b/internal/impl/codec_tables.go
index 3ff4260..31fc412 100644
--- a/internal/impl/codec_tables.go
+++ b/internal/impl/codec_tables.go
@@ -21,12 +21,12 @@
 	isInit    func(p pointer) error
 }
 
-// ifaceCoderFuncs is a set of interface{} encoding functions.
-type ifaceCoderFuncs struct {
-	size      func(ival interface{}, tagsize int, opts marshalOptions) int
-	marshal   func(b []byte, ival interface{}, wiretag uint64, opts marshalOptions) ([]byte, error)
-	unmarshal func(b []byte, ival interface{}, num wire.Number, wtyp wire.Type, opts unmarshalOptions) (interface{}, int, error)
-	isInit    func(ival interface{}) error
+// valueCoderFuncs is a set of protoreflect.Value encoding functions.
+type valueCoderFuncs struct {
+	size      func(v pref.Value, tagsize int, opts marshalOptions) int
+	marshal   func(b []byte, v pref.Value, wiretag uint64, opts marshalOptions) ([]byte, error)
+	unmarshal func(b []byte, v pref.Value, num wire.Number, wtyp wire.Type, opts unmarshalOptions) (pref.Value, int, error)
+	isInit    func(v pref.Value) error
 }
 
 // fieldCoder returns pointer functions for a field, used for operating on
@@ -428,7 +428,7 @@
 
 // encoderFuncsForValue returns interface{} value functions for a field, used for
 // extension values and map encoding.
-func encoderFuncsForValue(fd pref.FieldDescriptor, ft reflect.Type) ifaceCoderFuncs {
+func encoderFuncsForValue(fd pref.FieldDescriptor, ft reflect.Type) valueCoderFuncs {
 	switch {
 	case fd.Cardinality() == pref.Repeated && !fd.IsPacked():
 		if ft.Kind() != reflect.Ptr || ft.Elem().Kind() != reflect.Slice {
@@ -438,78 +438,78 @@
 		switch fd.Kind() {
 		case pref.BoolKind:
 			if ft.Kind() == reflect.Bool {
-				return coderBoolSliceIface
+				return coderBoolSliceValue
 			}
 		case pref.EnumKind:
 			if ft.Kind() == reflect.Int32 {
-				return coderEnumSliceIface
+				return coderEnumSliceValue
 			}
 		case pref.Int32Kind:
 			if ft.Kind() == reflect.Int32 {
-				return coderInt32SliceIface
+				return coderInt32SliceValue
 			}
 		case pref.Sint32Kind:
 			if ft.Kind() == reflect.Int32 {
-				return coderSint32SliceIface
+				return coderSint32SliceValue
 			}
 		case pref.Uint32Kind:
 			if ft.Kind() == reflect.Uint32 {
-				return coderUint32SliceIface
+				return coderUint32SliceValue
 			}
 		case pref.Int64Kind:
 			if ft.Kind() == reflect.Int64 {
-				return coderInt64SliceIface
+				return coderInt64SliceValue
 			}
 		case pref.Sint64Kind:
 			if ft.Kind() == reflect.Int64 {
-				return coderSint64SliceIface
+				return coderSint64SliceValue
 			}
 		case pref.Uint64Kind:
 			if ft.Kind() == reflect.Uint64 {
-				return coderUint64SliceIface
+				return coderUint64SliceValue
 			}
 		case pref.Sfixed32Kind:
 			if ft.Kind() == reflect.Int32 {
-				return coderSfixed32SliceIface
+				return coderSfixed32SliceValue
 			}
 		case pref.Fixed32Kind:
 			if ft.Kind() == reflect.Uint32 {
-				return coderFixed32SliceIface
+				return coderFixed32SliceValue
 			}
 		case pref.FloatKind:
 			if ft.Kind() == reflect.Float32 {
-				return coderFloatSliceIface
+				return coderFloatSliceValue
 			}
 		case pref.Sfixed64Kind:
 			if ft.Kind() == reflect.Int64 {
-				return coderSfixed64SliceIface
+				return coderSfixed64SliceValue
 			}
 		case pref.Fixed64Kind:
 			if ft.Kind() == reflect.Uint64 {
-				return coderFixed64SliceIface
+				return coderFixed64SliceValue
 			}
 		case pref.DoubleKind:
 			if ft.Kind() == reflect.Float64 {
-				return coderDoubleSliceIface
+				return coderDoubleSliceValue
 			}
 		case pref.StringKind:
 			if ft.Kind() == reflect.String {
-				return coderStringSliceIface
+				return coderStringSliceValue
 			}
 			if ft.Kind() == reflect.Slice && ft.Elem().Kind() == reflect.Uint8 {
-				return coderBytesSliceIface
+				return coderBytesSliceValue
 			}
 		case pref.BytesKind:
 			if ft.Kind() == reflect.String {
-				return coderStringSliceIface
+				return coderStringSliceValue
 			}
 			if ft.Kind() == reflect.Slice && ft.Elem().Kind() == reflect.Uint8 {
-				return coderBytesSliceIface
+				return coderBytesSliceValue
 			}
 		case pref.MessageKind:
-			return coderMessageSliceIface
+			return coderMessageSliceValue
 		case pref.GroupKind:
-			return coderGroupSliceIface
+			return coderGroupSliceValue
 		}
 	case fd.Cardinality() == pref.Repeated && fd.IsPacked():
 		if ft.Kind() != reflect.Ptr || ft.Elem().Kind() != reflect.Slice {
@@ -519,143 +519,144 @@
 		switch fd.Kind() {
 		case pref.BoolKind:
 			if ft.Kind() == reflect.Bool {
-				return coderBoolPackedSliceIface
+				return coderBoolPackedSliceValue
 			}
 		case pref.EnumKind:
 			if ft.Kind() == reflect.Int32 {
-				return coderEnumPackedSliceIface
+				return coderEnumPackedSliceValue
 			}
 		case pref.Int32Kind:
 			if ft.Kind() == reflect.Int32 {
-				return coderInt32PackedSliceIface
+				return coderInt32PackedSliceValue
 			}
 		case pref.Sint32Kind:
 			if ft.Kind() == reflect.Int32 {
-				return coderSint32PackedSliceIface
+				return coderSint32PackedSliceValue
 			}
 		case pref.Uint32Kind:
 			if ft.Kind() == reflect.Uint32 {
-				return coderUint32PackedSliceIface
+				return coderUint32PackedSliceValue
 			}
 		case pref.Int64Kind:
 			if ft.Kind() == reflect.Int64 {
-				return coderInt64PackedSliceIface
+				return coderInt64PackedSliceValue
 			}
 		case pref.Sint64Kind:
 			if ft.Kind() == reflect.Int64 {
-				return coderSint64PackedSliceIface
+				return coderSint64PackedSliceValue
 			}
 		case pref.Uint64Kind:
 			if ft.Kind() == reflect.Uint64 {
-				return coderUint64PackedSliceIface
+				return coderUint64PackedSliceValue
 			}
 		case pref.Sfixed32Kind:
 			if ft.Kind() == reflect.Int32 {
-				return coderSfixed32PackedSliceIface
+				return coderSfixed32PackedSliceValue
 			}
 		case pref.Fixed32Kind:
 			if ft.Kind() == reflect.Uint32 {
-				return coderFixed32PackedSliceIface
+				return coderFixed32PackedSliceValue
 			}
 		case pref.FloatKind:
 			if ft.Kind() == reflect.Float32 {
-				return coderFloatPackedSliceIface
+				return coderFloatPackedSliceValue
 			}
 		case pref.Sfixed64Kind:
 			if ft.Kind() == reflect.Int64 {
-				return coderSfixed64PackedSliceIface
+				return coderSfixed64PackedSliceValue
 			}
 		case pref.Fixed64Kind:
 			if ft.Kind() == reflect.Uint64 {
-				return coderFixed64PackedSliceIface
+				return coderFixed64PackedSliceValue
 			}
 		case pref.DoubleKind:
 			if ft.Kind() == reflect.Float64 {
-				return coderDoublePackedSliceIface
+				return coderDoublePackedSliceValue
 			}
 		}
 	default:
 		switch fd.Kind() {
+		default:
 		case pref.BoolKind:
 			if ft.Kind() == reflect.Bool {
-				return coderBoolIface
+				return coderBoolValue
 			}
 		case pref.EnumKind:
 			if ft.Kind() == reflect.Int32 {
-				return coderEnumIface
+				return coderEnumValue
 			}
 		case pref.Int32Kind:
 			if ft.Kind() == reflect.Int32 {
-				return coderInt32Iface
+				return coderInt32Value
 			}
 		case pref.Sint32Kind:
 			if ft.Kind() == reflect.Int32 {
-				return coderSint32Iface
+				return coderSint32Value
 			}
 		case pref.Uint32Kind:
 			if ft.Kind() == reflect.Uint32 {
-				return coderUint32Iface
+				return coderUint32Value
 			}
 		case pref.Int64Kind:
 			if ft.Kind() == reflect.Int64 {
-				return coderInt64Iface
+				return coderInt64Value
 			}
 		case pref.Sint64Kind:
 			if ft.Kind() == reflect.Int64 {
-				return coderSint64Iface
+				return coderSint64Value
 			}
 		case pref.Uint64Kind:
 			if ft.Kind() == reflect.Uint64 {
-				return coderUint64Iface
+				return coderUint64Value
 			}
 		case pref.Sfixed32Kind:
 			if ft.Kind() == reflect.Int32 {
-				return coderSfixed32Iface
+				return coderSfixed32Value
 			}
 		case pref.Fixed32Kind:
 			if ft.Kind() == reflect.Uint32 {
-				return coderFixed32Iface
+				return coderFixed32Value
 			}
 		case pref.FloatKind:
 			if ft.Kind() == reflect.Float32 {
-				return coderFloatIface
+				return coderFloatValue
 			}
 		case pref.Sfixed64Kind:
 			if ft.Kind() == reflect.Int64 {
-				return coderSfixed64Iface
+				return coderSfixed64Value
 			}
 		case pref.Fixed64Kind:
 			if ft.Kind() == reflect.Uint64 {
-				return coderFixed64Iface
+				return coderFixed64Value
 			}
 		case pref.DoubleKind:
 			if ft.Kind() == reflect.Float64 {
-				return coderDoubleIface
+				return coderDoubleValue
 			}
 		case pref.StringKind:
 			if ft.Kind() == reflect.String && strs.EnforceUTF8(fd) {
-				return coderStringIfaceValidateUTF8
+				return coderStringValueValidateUTF8
 			}
 			if ft.Kind() == reflect.String {
-				return coderStringIface
+				return coderStringValue
 			}
 			if ft.Kind() == reflect.Slice && ft.Elem().Kind() == reflect.Uint8 && strs.EnforceUTF8(fd) {
-				return coderBytesIfaceValidateUTF8
+				return coderBytesValueValidateUTF8
 			}
 			if ft.Kind() == reflect.Slice && ft.Elem().Kind() == reflect.Uint8 {
-				return coderBytesIface
+				return coderBytesValue
 			}
 		case pref.BytesKind:
 			if ft.Kind() == reflect.String {
-				return coderStringIface
+				return coderStringValue
 			}
 			if ft.Kind() == reflect.Slice && ft.Elem().Kind() == reflect.Uint8 {
-				return coderBytesIface
+				return coderBytesValue
 			}
 		case pref.MessageKind:
-			return coderMessageIface
+			return coderMessageValue
 		case pref.GroupKind:
-			return makeGroupValueCoder(fd, ft)
+			return coderGroupValue
 		}
 	}
 	panic(fmt.Errorf("invalid type: no encoder for %v %v %v/%v", fd.FullName(), fd.Cardinality(), fd.Kind(), ft))