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_field.go b/internal/impl/codec_field.go
index af6ce05..5414635 100644
--- a/internal/impl/codec_field.go
+++ b/internal/impl/codec_field.go
@@ -170,32 +170,55 @@
 	return n, nil
 }
 
-func sizeMessageIface(ival interface{}, tagsize int, opts marshalOptions) int {
-	m := Export{}.MessageOf(ival).Interface()
+func sizeMessageValue(v pref.Value, tagsize int, opts marshalOptions) int {
+	m := v.Message().Interface()
 	return sizeMessage(m, tagsize, opts)
 }
 
-func appendMessageIface(b []byte, ival interface{}, wiretag uint64, opts marshalOptions) ([]byte, error) {
-	m := Export{}.MessageOf(ival).Interface()
+func appendMessageValue(b []byte, v pref.Value, wiretag uint64, opts marshalOptions) ([]byte, error) {
+	m := v.Message().Interface()
 	return appendMessage(b, m, wiretag, opts)
 }
 
-func consumeMessageIface(b []byte, ival interface{}, _ wire.Number, wtyp wire.Type, opts unmarshalOptions) (interface{}, int, error) {
-	m := Export{}.MessageOf(ival).Interface()
+func consumeMessageValue(b []byte, v pref.Value, _ wire.Number, wtyp wire.Type, opts unmarshalOptions) (pref.Value, int, error) {
+	m := v.Message().Interface()
 	n, err := consumeMessage(b, m, wtyp, opts)
-	return ival, n, err
+	return v, n, err
 }
 
-func isInitMessageIface(ival interface{}) error {
-	m := Export{}.MessageOf(ival).Interface()
+func isInitMessageValue(v pref.Value) error {
+	m := v.Message().Interface()
 	return proto.IsInitialized(m)
 }
 
-var coderMessageIface = ifaceCoderFuncs{
-	size:      sizeMessageIface,
-	marshal:   appendMessageIface,
-	unmarshal: consumeMessageIface,
-	isInit:    isInitMessageIface,
+var coderMessageValue = valueCoderFuncs{
+	size:      sizeMessageValue,
+	marshal:   appendMessageValue,
+	unmarshal: consumeMessageValue,
+	isInit:    isInitMessageValue,
+}
+
+func sizeGroupValue(v pref.Value, tagsize int, opts marshalOptions) int {
+	m := v.Message().Interface()
+	return sizeGroup(m, tagsize, opts)
+}
+
+func appendGroupValue(b []byte, v pref.Value, wiretag uint64, opts marshalOptions) ([]byte, error) {
+	m := v.Message().Interface()
+	return appendGroup(b, m, wiretag, opts)
+}
+
+func consumeGroupValue(b []byte, v pref.Value, num wire.Number, wtyp wire.Type, opts unmarshalOptions) (pref.Value, int, error) {
+	m := v.Message().Interface()
+	n, err := consumeGroup(b, m, num, wtyp, opts)
+	return v, n, err
+}
+
+var coderGroupValue = valueCoderFuncs{
+	size:      sizeGroupValue,
+	marshal:   appendGroupValue,
+	unmarshal: consumeGroupValue,
+	isInit:    isInitMessageValue,
 }
 
 func makeGroupFieldCoder(fd pref.FieldDescriptor, ft reflect.Type) pointerCoderFuncs {
@@ -283,25 +306,6 @@
 	return n, opts.Options().Unmarshal(b, m)
 }
 
-func makeGroupValueCoder(fd pref.FieldDescriptor, ft reflect.Type) ifaceCoderFuncs {
-	return ifaceCoderFuncs{
-		size: func(ival interface{}, tagsize int, opts marshalOptions) int {
-			m := Export{}.MessageOf(ival).Interface()
-			return sizeGroup(m, tagsize, opts)
-		},
-		marshal: func(b []byte, ival interface{}, wiretag uint64, opts marshalOptions) ([]byte, error) {
-			m := Export{}.MessageOf(ival).Interface()
-			return appendGroup(b, m, wiretag, opts)
-		},
-		unmarshal: func(b []byte, ival interface{}, num wire.Number, wtyp wire.Type, opts unmarshalOptions) (interface{}, int, error) {
-			m := Export{}.MessageOf(ival).Interface()
-			n, err := consumeGroup(b, m, num, wtyp, opts)
-			return ival, n, err
-		},
-		isInit: isInitMessageIface,
-	}
-}
-
 func makeMessageSliceFieldCoder(fd pref.FieldDescriptor, ft reflect.Type) pointerCoderFuncs {
 	if mi := getMessageInfo(ft); mi != nil {
 		return pointerCoderFuncs{
@@ -441,32 +445,116 @@
 
 // Slices of messages
 
-func sizeMessageSliceIface(ival interface{}, tagsize int, opts marshalOptions) int {
-	p := pointerOfIface(ival)
-	return sizeMessageSlice(p, reflect.TypeOf(ival).Elem().Elem(), tagsize, opts)
+func sizeMessageSliceValue(listv pref.Value, tagsize int, opts marshalOptions) int {
+	list := listv.List()
+	n := 0
+	for i, llen := 0, list.Len(); i < llen; i++ {
+		m := list.Get(i).Message().Interface()
+		n += wire.SizeBytes(proto.Size(m)) + tagsize
+	}
+	return n
 }
 
-func appendMessageSliceIface(b []byte, ival interface{}, wiretag uint64, opts marshalOptions) ([]byte, error) {
-	p := pointerOfIface(ival)
-	return appendMessageSlice(b, p, wiretag, reflect.TypeOf(ival).Elem().Elem(), opts)
+func appendMessageSliceValue(b []byte, listv pref.Value, wiretag uint64, opts marshalOptions) ([]byte, error) {
+	list := listv.List()
+	mopts := opts.Options()
+	for i, llen := 0, list.Len(); i < llen; i++ {
+		m := list.Get(i).Message().Interface()
+		b = wire.AppendVarint(b, wiretag)
+		siz := proto.Size(m)
+		b = wire.AppendVarint(b, uint64(siz))
+		var err error
+		b, err = mopts.MarshalAppend(b, m)
+		if err != nil {
+			return b, err
+		}
+	}
+	return b, nil
 }
 
-func consumeMessageSliceIface(b []byte, ival interface{}, _ wire.Number, wtyp wire.Type, opts unmarshalOptions) (interface{}, int, error) {
-	p := pointerOfIface(ival)
-	n, err := consumeMessageSlice(b, p, reflect.TypeOf(ival).Elem().Elem(), wtyp, opts)
-	return ival, n, err
+func consumeMessageSliceValue(b []byte, listv pref.Value, _ wire.Number, wtyp wire.Type, opts unmarshalOptions) (pref.Value, int, error) {
+	list := listv.List()
+	if wtyp != wire.BytesType {
+		return pref.Value{}, 0, errUnknown
+	}
+	v, n := wire.ConsumeBytes(b)
+	if n < 0 {
+		return pref.Value{}, 0, wire.ParseError(n)
+	}
+	m := list.NewElement()
+	if err := opts.Options().Unmarshal(v, m.Message().Interface()); err != nil {
+		return pref.Value{}, 0, err
+	}
+	list.Append(m)
+	return listv, n, nil
 }
 
-func isInitMessageSliceIface(ival interface{}) error {
-	p := pointerOfIface(ival)
-	return isInitMessageSlice(p, reflect.TypeOf(ival).Elem().Elem())
+func isInitMessageSliceValue(listv pref.Value) error {
+	list := listv.List()
+	for i, llen := 0, list.Len(); i < llen; i++ {
+		m := list.Get(i).Message().Interface()
+		if err := proto.IsInitialized(m); err != nil {
+			return err
+		}
+	}
+	return nil
 }
 
-var coderMessageSliceIface = ifaceCoderFuncs{
-	size:      sizeMessageSliceIface,
-	marshal:   appendMessageSliceIface,
-	unmarshal: consumeMessageSliceIface,
-	isInit:    isInitMessageSliceIface,
+var coderMessageSliceValue = valueCoderFuncs{
+	size:      sizeMessageSliceValue,
+	marshal:   appendMessageSliceValue,
+	unmarshal: consumeMessageSliceValue,
+	isInit:    isInitMessageSliceValue,
+}
+
+func sizeGroupSliceValue(listv pref.Value, tagsize int, opts marshalOptions) int {
+	list := listv.List()
+	n := 0
+	for i, llen := 0, list.Len(); i < llen; i++ {
+		m := list.Get(i).Message().Interface()
+		n += 2*tagsize + proto.Size(m)
+	}
+	return n
+}
+
+func appendGroupSliceValue(b []byte, listv pref.Value, wiretag uint64, opts marshalOptions) ([]byte, error) {
+	list := listv.List()
+	mopts := opts.Options()
+	for i, llen := 0, list.Len(); i < llen; i++ {
+		m := list.Get(i).Message().Interface()
+		b = wire.AppendVarint(b, wiretag) // start group
+		var err error
+		b, err = mopts.MarshalAppend(b, m)
+		if err != nil {
+			return b, err
+		}
+		b = wire.AppendVarint(b, wiretag+1) // end group
+	}
+	return b, nil
+}
+
+func consumeGroupSliceValue(b []byte, listv pref.Value, num wire.Number, wtyp wire.Type, opts unmarshalOptions) (pref.Value, int, error) {
+	list := listv.List()
+	if wtyp != wire.StartGroupType {
+		return pref.Value{}, 0, errUnknown
+	}
+	b, n := wire.ConsumeGroup(num, b)
+	if n < 0 {
+		return pref.Value{}, 0, wire.ParseError(n)
+	}
+	m := list.NewElement()
+	if err := opts.Options().Unmarshal(b, m.Message().Interface()); err != nil {
+		return pref.Value{}, 0, err
+	}
+	list.Append(m)
+	return listv, n, nil
+}
+
+var coderGroupSliceValue = valueCoderFuncs{
+	size:      sizeGroupSliceValue,
+	marshal:   appendGroupSliceValue,
+	unmarshal: consumeGroupSliceValue,
+	isInit:    isInitMessageSliceValue,
 }
 
 func makeGroupSliceFieldCoder(fd pref.FieldDescriptor, ft reflect.Type) pointerCoderFuncs {
@@ -581,171 +669,6 @@
 	return n, nil
 }
 
-func sizeGroupSliceIface(ival interface{}, tagsize int, opts marshalOptions) int {
-	p := pointerOfIface(ival)
-	return sizeGroupSlice(p, reflect.TypeOf(ival).Elem().Elem(), tagsize, opts)
-}
-
-func appendGroupSliceIface(b []byte, ival interface{}, wiretag uint64, opts marshalOptions) ([]byte, error) {
-	p := pointerOfIface(ival)
-	return appendGroupSlice(b, p, wiretag, reflect.TypeOf(ival).Elem().Elem(), opts)
-}
-
-func consumeGroupSliceIface(b []byte, ival interface{}, num wire.Number, wtyp wire.Type, opts unmarshalOptions) (interface{}, int, error) {
-	p := pointerOfIface(ival)
-	n, err := consumeGroupSlice(b, p, num, wtyp, reflect.TypeOf(ival).Elem().Elem(), opts)
-	return ival, n, err
-}
-
-var coderGroupSliceIface = ifaceCoderFuncs{
-	size:      sizeGroupSliceIface,
-	marshal:   appendGroupSliceIface,
-	unmarshal: consumeGroupSliceIface,
-	isInit:    isInitMessageSliceIface,
-}
-
-// Enums
-
-func sizeEnumIface(ival interface{}, tagsize int, _ marshalOptions) (n int) {
-	v := reflect.ValueOf(ival).Int()
-	return wire.SizeVarint(uint64(v)) + tagsize
-}
-
-func appendEnumIface(b []byte, ival interface{}, wiretag uint64, _ marshalOptions) ([]byte, error) {
-	v := reflect.ValueOf(ival).Int()
-	b = wire.AppendVarint(b, wiretag)
-	b = wire.AppendVarint(b, uint64(v))
-	return b, nil
-}
-
-func consumeEnumIface(b []byte, ival interface{}, _ wire.Number, wtyp wire.Type, _ unmarshalOptions) (interface{}, int, error) {
-	if wtyp != wire.VarintType {
-		return nil, 0, errUnknown
-	}
-	v, n := wire.ConsumeVarint(b)
-	if n < 0 {
-		return nil, 0, wire.ParseError(n)
-	}
-	rv := reflect.New(reflect.TypeOf(ival)).Elem()
-	rv.SetInt(int64(v))
-	return rv.Interface(), n, nil
-}
-
-var coderEnumIface = ifaceCoderFuncs{
-	size:      sizeEnumIface,
-	marshal:   appendEnumIface,
-	unmarshal: consumeEnumIface,
-}
-
-func sizeEnumSliceIface(ival interface{}, tagsize int, opts marshalOptions) (size int) {
-	return sizeEnumSliceReflect(reflect.ValueOf(ival).Elem(), tagsize, opts)
-}
-
-func sizeEnumSliceReflect(s reflect.Value, tagsize int, _ marshalOptions) (size int) {
-	for i, llen := 0, s.Len(); i < llen; i++ {
-		size += wire.SizeVarint(uint64(s.Index(i).Int())) + tagsize
-	}
-	return size
-}
-
-func appendEnumSliceIface(b []byte, ival interface{}, wiretag uint64, opts marshalOptions) ([]byte, error) {
-	return appendEnumSliceReflect(b, reflect.ValueOf(ival).Elem(), wiretag, opts)
-}
-
-func appendEnumSliceReflect(b []byte, s reflect.Value, wiretag uint64, opts marshalOptions) ([]byte, error) {
-	for i, llen := 0, s.Len(); i < llen; i++ {
-		b = wire.AppendVarint(b, wiretag)
-		b = wire.AppendVarint(b, uint64(s.Index(i).Int()))
-	}
-	return b, nil
-}
-
-func consumeEnumSliceIface(b []byte, ival interface{}, _ wire.Number, wtyp wire.Type, opts unmarshalOptions) (interface{}, int, error) {
-	n, err := consumeEnumSliceReflect(b, reflect.ValueOf(ival), wtyp, opts)
-	return ival, n, err
-}
-
-func consumeEnumSliceReflect(b []byte, s reflect.Value, wtyp wire.Type, _ unmarshalOptions) (n int, err error) {
-	s = s.Elem() // *[]E -> []E
-	if wtyp == wire.BytesType {
-		b, n = wire.ConsumeBytes(b)
-		if n < 0 {
-			return 0, wire.ParseError(n)
-		}
-		for len(b) > 0 {
-			v, n := wire.ConsumeVarint(b)
-			if n < 0 {
-				return 0, wire.ParseError(n)
-			}
-			rv := reflect.New(s.Type().Elem()).Elem()
-			rv.SetInt(int64(v))
-			s.Set(reflect.Append(s, rv))
-			b = b[n:]
-		}
-		return n, nil
-	}
-	if wtyp != wire.VarintType {
-		return 0, errUnknown
-	}
-	v, n := wire.ConsumeVarint(b)
-	if n < 0 {
-		return 0, wire.ParseError(n)
-	}
-	rv := reflect.New(s.Type().Elem()).Elem()
-	rv.SetInt(int64(v))
-	s.Set(reflect.Append(s, rv))
-	return n, nil
-}
-
-var coderEnumSliceIface = ifaceCoderFuncs{
-	size:      sizeEnumSliceIface,
-	marshal:   appendEnumSliceIface,
-	unmarshal: consumeEnumSliceIface,
-}
-
-func sizeEnumPackedSliceIface(ival interface{}, tagsize int, opts marshalOptions) (size int) {
-	return sizeEnumPackedSliceReflect(reflect.ValueOf(ival).Elem(), tagsize, opts)
-}
-
-func sizeEnumPackedSliceReflect(s reflect.Value, tagsize int, _ marshalOptions) (size int) {
-	llen := s.Len()
-	if llen == 0 {
-		return 0
-	}
-	n := 0
-	for i := 0; i < llen; i++ {
-		n += wire.SizeVarint(uint64(s.Index(i).Int()))
-	}
-	return tagsize + wire.SizeBytes(n)
-}
-
-func appendEnumPackedSliceIface(b []byte, ival interface{}, wiretag uint64, opts marshalOptions) ([]byte, error) {
-	return appendEnumPackedSliceReflect(b, reflect.ValueOf(ival).Elem(), wiretag, opts)
-}
-
-func appendEnumPackedSliceReflect(b []byte, s reflect.Value, wiretag uint64, opts marshalOptions) ([]byte, error) {
-	llen := s.Len()
-	if llen == 0 {
-		return b, nil
-	}
-	b = wire.AppendVarint(b, wiretag)
-	n := 0
-	for i := 0; i < llen; i++ {
-		n += wire.SizeVarint(uint64(s.Index(i).Int()))
-	}
-	b = wire.AppendVarint(b, uint64(n))
-	for i := 0; i < llen; i++ {
-		b = wire.AppendVarint(b, uint64(s.Index(i).Int()))
-	}
-	return b, nil
-}
-
-var coderEnumPackedSliceIface = ifaceCoderFuncs{
-	size:      sizeEnumPackedSliceIface,
-	marshal:   appendEnumPackedSliceIface,
-	unmarshal: consumeEnumSliceIface,
-}
-
 func asMessage(v reflect.Value) pref.ProtoMessage {
 	if m, ok := v.Interface().(pref.ProtoMessage); ok {
 		return m