internal/impl: add runtime support for *[]byte unknown representation

This CL adds runtime support for unknown fields to be represented
as *[]byte in addition to the current representation as []byte.
This CL does not change generated code to use *[]byte.

Comparison between using *[]byte and []byte:

• Every message supports unknown fields, so use of []byte
  expands a message size by 24B (for 64-bit systems).
  In contrast, *[]byte only expands a message by 8B.
  This has significant memory implications for small messages.

• If unknown fields are encountered, *[]byte has extra overhead
  allocating the 24B slice header. However, it is assumed
  that messages rarely see any unknown fields at runtime,
  or generally do so for a temporary period of time.

Change-Id: I81935e4ea7394166e61ff4579f76f59fa792dfc9
Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/244937
Reviewed-by: Damien Neil <dneil@google.com>
diff --git a/internal/impl/message_reflect_test.go b/internal/impl/message_reflect_test.go
index 66c2536..96c7e1b 100644
--- a/internal/impl/message_reflect_test.go
+++ b/internal/impl/message_reflect_test.go
@@ -22,6 +22,7 @@
 	pdesc "google.golang.org/protobuf/reflect/protodesc"
 	pref "google.golang.org/protobuf/reflect/protoreflect"
 	"google.golang.org/protobuf/reflect/protoregistry"
+	"google.golang.org/protobuf/testing/protopack"
 
 	proto2_20180125 "google.golang.org/protobuf/internal/testprotos/legacy/proto2_20180125_92554152"
 	testpb "google.golang.org/protobuf/internal/testprotos/test"
@@ -1425,6 +1426,43 @@
 	return strings.Join(ss, ".")
 }
 
+type UnknownFieldsA struct {
+	XXX_unrecognized []byte
+}
+
+var unknownFieldsAType = pimpl.MessageInfo{
+	GoReflectType: reflect.TypeOf(new(UnknownFieldsA)),
+	Desc:          mustMakeMessageDesc("unknown.proto", pref.Proto2, "", `name: "UnknownFieldsA"`, nil),
+}
+
+func (m *UnknownFieldsA) ProtoReflect() pref.Message { return unknownFieldsAType.MessageOf(m) }
+
+type UnknownFieldsB struct {
+	XXX_unrecognized *[]byte
+}
+
+var unknownFieldsBType = pimpl.MessageInfo{
+	GoReflectType: reflect.TypeOf(new(UnknownFieldsB)),
+	Desc:          mustMakeMessageDesc("unknown.proto", pref.Proto2, "", `name: "UnknownFieldsB"`, nil),
+}
+
+func (m *UnknownFieldsB) ProtoReflect() pref.Message { return unknownFieldsBType.MessageOf(m) }
+
+func TestUnknownFields(t *testing.T) {
+	for _, m := range []proto.Message{new(UnknownFieldsA), new(UnknownFieldsB)} {
+		t.Run(reflect.TypeOf(m).Elem().Name(), func(t *testing.T) {
+			want := protopack.Message{
+				protopack.Tag{1, protopack.BytesType}, protopack.String("Hello, world!"),
+			}.Marshal()
+			m.ProtoReflect().SetUnknown(want)
+			got := []byte(m.ProtoReflect().GetUnknown())
+			if diff := cmp.Diff(want, got); diff != "" {
+				t.Errorf("UnknownFields mismatch (-want +got):\n%s", diff)
+			}
+		})
+	}
+}
+
 func TestReset(t *testing.T) {
 	mi := new(testpb.TestAllTypes)