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_extension.go b/internal/impl/codec_extension.go
index 8a999ef..442628e 100644
--- a/internal/impl/codec_extension.go
+++ b/internal/impl/codec_extension.go
@@ -16,7 +16,7 @@
 	wiretag             uint64
 	tagsize             int
 	unmarshalNeedsValue bool
-	funcs               ifaceCoderFuncs
+	funcs               valueCoderFuncs
 }
 
 func (mi *MessageInfo) extensionFieldInfo(xt pref.ExtensionType) *extensionFieldInfo {
@@ -66,60 +66,80 @@
 
 	// value is either the value of GetValue,
 	// or a *lazyExtensionValue that then returns the value of GetValue.
-	value interface{} // TODO: switch to protoreflect.Value
+	value pref.Value
+	lazy  *lazyExtensionValue
 }
 
-func (f ExtensionField) HasType() bool {
-	return f.typ != nil
-}
-func (f ExtensionField) GetType() pref.ExtensionType {
-	return f.typ
-}
-func (f *ExtensionField) SetType(t pref.ExtensionType) {
+// Set sets the type and value of the extension field.
+// This must not be called concurrently.
+func (f *ExtensionField) Set(t pref.ExtensionType, v pref.Value) {
 	f.typ = t
+	f.value = v
 }
 
-// HasValue reports whether a value is set for the extension field.
-// This may be called concurrently.
-func (f ExtensionField) HasValue() bool {
-	return f.value != nil
+// SetLazy sets the type and a value that is to be lazily evaluated upon first use.
+// This must not be called concurrently.
+func (f *ExtensionField) SetLazy(t pref.ExtensionType, fn func() pref.Value) {
+	f.typ = t
+	f.lazy = &lazyExtensionValue{value: fn}
 }
 
-// GetValue returns the concrete value for the extension field.
-// Let the type of Desc.ExtensionType be the "API type" and
-// the type of GetValue be the "storage type".
-// The API type and storage type are the same except:
-//	* for scalars (except []byte), where the API type uses *T,
-//	while the storage type uses T.
-//	* for repeated fields, where the API type uses []T,
-//	while the storage type uses *[]T.
-//
-// The reason for the divergence is so that the storage type more naturally
-// matches what is expected of when retrieving the values through the
-// protobuf reflection APIs.
-//
-// GetValue is only populated if Desc is also populated.
+// Value returns the value of the extension field.
 // This may be called concurrently.
-//
-// TODO: switch interface{} to protoreflect.Value
-func (f ExtensionField) GetValue() interface{} {
-	if f, ok := f.value.(*lazyExtensionValue); ok {
-		return f.GetValue()
+func (f *ExtensionField) Value() pref.Value {
+	if f.lazy != nil {
+		return f.lazy.GetValue()
 	}
 	return f.value
 }
 
-// SetEagerValue sets the current value of the extension.
-// This must not be called concurrently.
-func (f *ExtensionField) SetEagerValue(v interface{}) {
-	f.value = v
+// Type returns the type of the extension field.
+// This may be called concurrently.
+func (f ExtensionField) Type() pref.ExtensionType {
+	return f.typ
 }
 
-// SetLazyValue sets a value that is to be lazily evaluated upon first use.
-// The returned value must not be nil.
-// This must not be called concurrently.
-func (f *ExtensionField) SetLazyValue(v func() interface{}) {
-	f.value = &lazyExtensionValue{value: v}
+// IsSet returns whether the extension field is set.
+// This may be called concurrently.
+func (f ExtensionField) IsSet() bool {
+	return f.typ != nil
+}
+
+// Deprecated: Do not use.
+func (f ExtensionField) HasType() bool {
+	return f.typ != nil
+}
+
+// Deprecated: Do not use.
+func (f ExtensionField) GetType() pref.ExtensionType {
+	return f.typ
+}
+
+// Deprecated: Do not use.
+func (f *ExtensionField) SetType(t pref.ExtensionType) {
+	f.typ = t
+}
+
+// Deprecated: Do not use.
+func (f ExtensionField) HasValue() bool {
+	return f.value.IsValid() || f.lazy != nil
+}
+
+// Deprecated: Do not use.
+func (f ExtensionField) GetValue() interface{} {
+	return f.typ.InterfaceOf(f.Value())
+}
+
+// Deprecated: Do not use.
+func (f *ExtensionField) SetEagerValue(ival interface{}) {
+	f.value = f.typ.ValueOf(ival)
+}
+
+// Deprecated: Do not use.
+func (f *ExtensionField) SetLazyValue(fn func() interface{}) {
+	f.lazy = &lazyExtensionValue{value: func() interface{} {
+		return f.typ.ValueOf(fn())
+	}}
 }
 
 type lazyExtensionValue struct {
@@ -128,14 +148,14 @@
 	value interface{} // either the value itself or a func() interface{}
 }
 
-func (v *lazyExtensionValue) GetValue() interface{} {
+func (v *lazyExtensionValue) GetValue() pref.Value {
 	if atomic.LoadUint32(&v.once) == 0 {
 		v.mu.Lock()
-		if f, ok := v.value.(func() interface{}); ok {
+		if f, ok := v.value.(func() pref.Value); ok {
 			v.value = f()
 		}
 		atomic.StoreUint32(&v.once, 1)
 		v.mu.Unlock()
 	}
-	return v.value
+	return v.value.(pref.Value)
 }