proto, internal/impl: store unknown MessageSet items in non-mset format

In the v1 implementation, unknown MessageSet items are stored in a
message's unknown fields section in non-MessageSet format. For example,
consider a MessageSet containing an item with type_id T and value V.
If the type_id is not resolvable, the item will be placed in the unknown
fields as a bytes-valued field with number T and contents V. This
conversion is then reversed when marshaling a MessageSet containing
unknown fields.

Preserve this behavior in v2.

One consequence of this change is that actual unknown fields in a
MessageSet (any field other than 1) are now discarded. This matches
the previous behavior.

Change-Id: I3d913613f84e0ae82481078dbc91cb25628651cc
Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/205697
Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
diff --git a/internal/impl/encode.go b/internal/impl/encode.go
index d7dc892..cd57998 100644
--- a/internal/impl/encode.go
+++ b/internal/impl/encode.go
@@ -8,6 +8,7 @@
 	"sort"
 	"sync/atomic"
 
+	"google.golang.org/protobuf/internal/flags"
 	proto "google.golang.org/protobuf/proto"
 	pref "google.golang.org/protobuf/reflect/protoreflect"
 	piface "google.golang.org/protobuf/runtime/protoiface"
@@ -69,6 +70,13 @@
 }
 
 func (mi *MessageInfo) sizePointerSlow(p pointer, opts marshalOptions) (size int) {
+	if flags.ProtoLegacy && mi.isMessageSet {
+		size = sizeMessageSet(mi, p, opts)
+		if mi.sizecacheOffset.IsValid() {
+			atomic.StoreInt32(p.Apply(mi.sizecacheOffset).Int32(), int32(size))
+		}
+		return size
+	}
 	if mi.extensionOffset.IsValid() {
 		e := p.Apply(mi.extensionOffset).Extensions()
 		size += mi.sizeExtensions(e, opts)
@@ -109,6 +117,9 @@
 	if p.IsNil() {
 		return b, nil
 	}
+	if flags.ProtoLegacy && mi.isMessageSet {
+		return marshalMessageSet(mi, b, p, opts)
+	}
 	var err error
 	// The old marshaler encodes extensions at beginning.
 	if mi.extensionOffset.IsValid() {
@@ -132,7 +143,7 @@
 			return b, err
 		}
 	}
-	if mi.unknownOffset.IsValid() {
+	if mi.unknownOffset.IsValid() && !mi.isMessageSet {
 		u := *p.Apply(mi.unknownOffset).Bytes()
 		b = append(b, u...)
 	}