From ba23aa55b2e4b6f58b46b7628d644f20a1dd0a06 Mon Sep 17 00:00:00 2001
From: Damien Neil <dneil@google.com>
Date: Fri, 7 Dec 2018 14:38:17 -0800
Subject: [PATCH] proto: wire decoding support

Add proto.Unmarshal.

Test cases all produce identical results to the v1 unmarshaller.

Change-Id: I42259266018a14e88a650c5d83a043cb17a3a15d
Reviewed-on: https://go-review.googlesource.com/c/153918
Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
---
 internal/cmd/generate-types/main.go  |    3 +
 internal/cmd/generate-types/proto.go |  210 ++
 internal/testprotos/test/test.pb.go  | 2667 ++++++++++++++++++++++++++
 internal/testprotos/test/test.proto  |  147 ++
 proto/decode.go                      |  191 ++
 proto/decode_gen.go                  |  591 ++++++
 proto/decode_test.go                 |  749 ++++++++
 regenerate.bash                      |    3 +
 8 files changed, 4561 insertions(+)
 create mode 100644 internal/cmd/generate-types/proto.go
 create mode 100644 internal/testprotos/test/test.pb.go
 create mode 100644 internal/testprotos/test/test.proto
 create mode 100644 proto/decode.go
 create mode 100644 proto/decode_gen.go
 create mode 100644 proto/decode_test.go

diff --git a/internal/cmd/generate-types/main.go b/internal/cmd/generate-types/main.go
index d062e0bf..0fa526da 100644
--- a/internal/cmd/generate-types/main.go
+++ b/internal/cmd/generate-types/main.go
@@ -26,6 +26,7 @@ var run = flag.Bool("execute", false, "Write generated files to destination.")
 func main() {
 	flag.Parse()
 	chdirRoot()
+	writeSource("proto/decode_gen.go", generateProtoDecode())
 	writeSource("reflect/prototype/protofile_list_gen.go", generateListTypes())
 }
 
@@ -198,8 +199,10 @@ func writeSource(file, src string) {
 	var imports []string
 	for _, pkg := range []string{
 		"fmt",
+		"math",
 		"sync",
 		"",
+		"github.com/golang/protobuf/v2/internal/encoding/wire",
 		"github.com/golang/protobuf/v2/internal/pragma",
 		"github.com/golang/protobuf/v2/internal/typefmt",
 		"github.com/golang/protobuf/v2/reflect/protoreflect",
diff --git a/internal/cmd/generate-types/proto.go b/internal/cmd/generate-types/proto.go
new file mode 100644
index 00000000..dc71b3f4
--- /dev/null
+++ b/internal/cmd/generate-types/proto.go
@@ -0,0 +1,210 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import "text/template"
+
+type WireType string
+
+const (
+	WireVarint  WireType = "Varint"
+	WireFixed32 WireType = "Fixed32"
+	WireFixed64 WireType = "Fixed64"
+	WireBytes   WireType = "Bytes"
+	WireGroup   WireType = "Group"
+)
+
+func (w WireType) Expr() Expr {
+	if w == WireGroup {
+		return "wire.StartGroupType"
+	}
+	return "wire." + Expr(w) + "Type"
+}
+
+func (w WireType) Packable() bool {
+	return w == WireVarint || w == WireFixed32 || w == WireFixed64
+}
+
+type ProtoKind struct {
+	Name     string
+	WireType WireType
+	ToValue  Expr
+}
+
+func (k ProtoKind) Expr() Expr {
+	return "protoreflect." + Expr(k.Name) + "Kind"
+}
+
+var ProtoKinds = []ProtoKind{
+	{
+		Name:     "Bool",
+		WireType: WireVarint,
+		ToValue:  "wire.DecodeBool(v)",
+	},
+	{
+		Name:     "Enum",
+		WireType: WireVarint,
+		ToValue:  "protoreflect.EnumNumber(v)",
+	},
+	{
+		Name:     "Int32",
+		WireType: WireVarint,
+		ToValue:  "int32(v)",
+	},
+	{
+		Name:     "Sint32",
+		WireType: WireVarint,
+		ToValue:  "int32(wire.DecodeZigZag(v & math.MaxUint32))",
+	},
+	{
+		Name:     "Uint32",
+		WireType: WireVarint,
+		ToValue:  "uint32(v)",
+	},
+	{
+		Name:     "Int64",
+		WireType: WireVarint,
+		ToValue:  "int64(v)",
+	},
+	{
+		Name:     "Sint64",
+		WireType: WireVarint,
+		ToValue:  "wire.DecodeZigZag(v)",
+	},
+	{
+		Name:     "Uint64",
+		WireType: WireVarint,
+		ToValue:  "v",
+	},
+	{
+		Name:     "Sfixed32",
+		WireType: WireFixed32,
+		ToValue:  "int32(v)",
+	},
+	{
+		Name:     "Fixed32",
+		WireType: WireFixed32,
+		ToValue:  "uint32(v)",
+	},
+	{
+		Name:     "Float",
+		WireType: WireFixed32,
+		ToValue:  "math.Float32frombits(uint32(v))",
+	},
+	{
+		Name:     "Sfixed64",
+		WireType: WireFixed64,
+		ToValue:  "int64(v)",
+	},
+	{
+		Name:     "Fixed64",
+		WireType: WireFixed64,
+		ToValue:  "v",
+	},
+	{
+		Name:     "Double",
+		WireType: WireFixed64,
+		ToValue:  "math.Float64frombits(v)",
+	},
+	{
+		Name:     "String",
+		WireType: WireBytes,
+		ToValue:  "string(v)",
+	},
+	{
+		Name:     "Bytes",
+		WireType: WireBytes,
+		ToValue:  "append(([]byte)(nil), v...)",
+	},
+	{
+		Name:     "Message",
+		WireType: WireBytes,
+		ToValue:  "v",
+	},
+	{
+		Name:     "Group",
+		WireType: WireGroup,
+		ToValue:  "v",
+	},
+}
+
+func generateProtoDecode() string {
+	return mustExecute(protoDecodeTemplate, ProtoKinds)
+}
+
+var protoDecodeTemplate = template.Must(template.New("").Parse(`
+// unmarshalScalar decodes a value of the given kind.
+//
+// Message values are decoded into a []byte which aliases the input data.
+func (o UnmarshalOptions) unmarshalScalar(b []byte, wtyp wire.Type, num wire.Number, kind protoreflect.Kind) (val protoreflect.Value, n int, err error) {
+	switch kind {
+	{{- range .}}
+	case {{.Expr}}:
+		if wtyp != {{.WireType.Expr}} {
+			return val, 0, errUnknown
+		}
+		{{if (eq .WireType "Group") -}}
+		v, n := wire.ConsumeGroup(num, b)
+		{{- else -}}
+		v, n := wire.Consume{{.WireType}}(b)
+		{{- end}}
+		if n < 0 {
+			return val, 0, wire.ParseError(n)
+		}
+		return protoreflect.ValueOf({{.ToValue}}), n, nil
+	{{- end}}
+	default:
+		return val, 0, errUnknown
+	}
+}
+
+func (o UnmarshalOptions) unmarshalList(b []byte, wtyp wire.Type, num wire.Number, list protoreflect.List, kind protoreflect.Kind) (n int, err error) {
+	switch kind {
+	{{- range .}}
+	case {{.Expr}}:
+		{{- if .WireType.Packable}}
+		if wtyp == wire.BytesType {
+			buf, n := wire.ConsumeBytes(b)
+			if n < 0 {
+				return 0, wire.ParseError(n)
+			}
+			for len(buf) > 0 {
+				v, n := wire.Consume{{.WireType}}(buf)
+				if n < 0 {
+					return 0, wire.ParseError(n)
+				}
+				buf = buf[n:]
+				list.Append(protoreflect.ValueOf({{.ToValue}}))
+			}
+			return n, nil
+		}
+		{{- end}}
+		if wtyp != {{.WireType.Expr}} {
+			return 0, errUnknown
+		}
+		{{if (eq .WireType "Group") -}}
+		v, n := wire.ConsumeGroup(num, b)
+		{{- else -}}
+		v, n := wire.Consume{{.WireType}}(b)
+		{{- end}}
+		if n < 0 {
+			return 0, wire.ParseError(n)
+		}
+		{{if or (eq .Name "Message") (eq .Name "Group") -}}
+		m := list.NewMessage().ProtoReflect()
+		if err := o.unmarshalMessage(v, m); err != nil {
+			return 0, err
+		}
+		list.Append(protoreflect.ValueOf(m))
+		{{- else -}}
+		list.Append(protoreflect.ValueOf({{.ToValue}}))
+		{{- end}}
+		return n, nil
+	{{- end}}
+	default:
+		return 0, errUnknown
+	}
+}
+`))
diff --git a/internal/testprotos/test/test.pb.go b/internal/testprotos/test/test.pb.go
new file mode 100644
index 00000000..8311d81c
--- /dev/null
+++ b/internal/testprotos/test/test.pb.go
@@ -0,0 +1,2667 @@
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// source: test.proto
+
+package testpb
+
+import (
+	proto "github.com/golang/protobuf/proto"
+	protoreflect "github.com/golang/protobuf/v2/reflect/protoreflect"
+	prototype "github.com/golang/protobuf/v2/reflect/prototype"
+	protoimpl "github.com/golang/protobuf/v2/runtime/protoimpl"
+)
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the proto package it is being compiled against.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
+
+type TestAllTypes_NestedEnum int32
+
+const (
+	TestAllTypes_FOO TestAllTypes_NestedEnum = 0
+	TestAllTypes_BAR TestAllTypes_NestedEnum = 1
+	TestAllTypes_BAZ TestAllTypes_NestedEnum = 2
+	TestAllTypes_NEG TestAllTypes_NestedEnum = -1
+)
+
+type xxx_TestAllTypes_NestedEnum TestAllTypes_NestedEnum
+
+func (e TestAllTypes_NestedEnum) ProtoReflect() protoreflect.Enum {
+	return (xxx_TestAllTypes_NestedEnum)(e)
+}
+func (e xxx_TestAllTypes_NestedEnum) Type() protoreflect.EnumType {
+	return xxx_Test_ProtoFile_EnumTypes[0]
+}
+func (e xxx_TestAllTypes_NestedEnum) Number() protoreflect.EnumNumber {
+	return protoreflect.EnumNumber(e)
+}
+
+var TestAllTypes_NestedEnum_name = map[int32]string{
+	0:  "FOO",
+	1:  "BAR",
+	2:  "BAZ",
+	-1: "NEG",
+}
+
+var TestAllTypes_NestedEnum_value = map[string]int32{
+	"FOO": 0,
+	"BAR": 1,
+	"BAZ": 2,
+	"NEG": -1,
+}
+
+func (x TestAllTypes_NestedEnum) Enum() *TestAllTypes_NestedEnum {
+	p := new(TestAllTypes_NestedEnum)
+	*p = x
+	return p
+}
+
+func (x TestAllTypes_NestedEnum) String() string {
+	return proto.EnumName(TestAllTypes_NestedEnum_name, int32(x))
+}
+
+func (x *TestAllTypes_NestedEnum) UnmarshalJSON(data []byte) error {
+	value, err := proto.UnmarshalJSONEnum(TestAllTypes_NestedEnum_value, data, "TestAllTypes_NestedEnum")
+	if err != nil {
+		return err
+	}
+	*x = TestAllTypes_NestedEnum(value)
+	return nil
+}
+
+func (TestAllTypes_NestedEnum) EnumDescriptor() ([]byte, []int) {
+	return fileDescriptor_c161fcfdc0c3ff1e, []int{0, 0}
+}
+
+type TestAllTypes struct {
+	OptionalInt32          *int32                                 `protobuf:"varint,1,opt,name=optional_int32,json=optionalInt32" json:"optional_int32,omitempty"`
+	OptionalInt64          *int64                                 `protobuf:"varint,2,opt,name=optional_int64,json=optionalInt64" json:"optional_int64,omitempty"`
+	OptionalUint32         *uint32                                `protobuf:"varint,3,opt,name=optional_uint32,json=optionalUint32" json:"optional_uint32,omitempty"`
+	OptionalUint64         *uint64                                `protobuf:"varint,4,opt,name=optional_uint64,json=optionalUint64" json:"optional_uint64,omitempty"`
+	OptionalSint32         *int32                                 `protobuf:"zigzag32,5,opt,name=optional_sint32,json=optionalSint32" json:"optional_sint32,omitempty"`
+	OptionalSint64         *int64                                 `protobuf:"zigzag64,6,opt,name=optional_sint64,json=optionalSint64" json:"optional_sint64,omitempty"`
+	OptionalFixed32        *uint32                                `protobuf:"fixed32,7,opt,name=optional_fixed32,json=optionalFixed32" json:"optional_fixed32,omitempty"`
+	OptionalFixed64        *uint64                                `protobuf:"fixed64,8,opt,name=optional_fixed64,json=optionalFixed64" json:"optional_fixed64,omitempty"`
+	OptionalSfixed32       *int32                                 `protobuf:"fixed32,9,opt,name=optional_sfixed32,json=optionalSfixed32" json:"optional_sfixed32,omitempty"`
+	OptionalSfixed64       *int64                                 `protobuf:"fixed64,10,opt,name=optional_sfixed64,json=optionalSfixed64" json:"optional_sfixed64,omitempty"`
+	OptionalFloat          *float32                               `protobuf:"fixed32,11,opt,name=optional_float,json=optionalFloat" json:"optional_float,omitempty"`
+	OptionalDouble         *float64                               `protobuf:"fixed64,12,opt,name=optional_double,json=optionalDouble" json:"optional_double,omitempty"`
+	OptionalBool           *bool                                  `protobuf:"varint,13,opt,name=optional_bool,json=optionalBool" json:"optional_bool,omitempty"`
+	OptionalString         *string                                `protobuf:"bytes,14,opt,name=optional_string,json=optionalString" json:"optional_string,omitempty"`
+	OptionalBytes          []byte                                 `protobuf:"bytes,15,opt,name=optional_bytes,json=optionalBytes" json:"optional_bytes,omitempty"`
+	Optionalgroup          *TestAllTypes_OptionalGroup            `protobuf:"group,16,opt,name=OptionalGroup,json=optionalgroup" json:"optionalgroup,omitempty"`
+	OptionalNestedMessage  *TestAllTypes_NestedMessage            `protobuf:"bytes,18,opt,name=optional_nested_message,json=optionalNestedMessage" json:"optional_nested_message,omitempty"`
+	OptionalNestedEnum     *TestAllTypes_NestedEnum               `protobuf:"varint,21,opt,name=optional_nested_enum,json=optionalNestedEnum,enum=goproto.proto.test.TestAllTypes_NestedEnum" json:"optional_nested_enum,omitempty"`
+	RepeatedInt32          []int32                                `protobuf:"varint,31,rep,name=repeated_int32,json=repeatedInt32" json:"repeated_int32,omitempty"`
+	RepeatedInt64          []int64                                `protobuf:"varint,32,rep,name=repeated_int64,json=repeatedInt64" json:"repeated_int64,omitempty"`
+	RepeatedUint32         []uint32                               `protobuf:"varint,33,rep,name=repeated_uint32,json=repeatedUint32" json:"repeated_uint32,omitempty"`
+	RepeatedUint64         []uint64                               `protobuf:"varint,34,rep,name=repeated_uint64,json=repeatedUint64" json:"repeated_uint64,omitempty"`
+	RepeatedSint32         []int32                                `protobuf:"zigzag32,35,rep,name=repeated_sint32,json=repeatedSint32" json:"repeated_sint32,omitempty"`
+	RepeatedSint64         []int64                                `protobuf:"zigzag64,36,rep,name=repeated_sint64,json=repeatedSint64" json:"repeated_sint64,omitempty"`
+	RepeatedFixed32        []uint32                               `protobuf:"fixed32,37,rep,name=repeated_fixed32,json=repeatedFixed32" json:"repeated_fixed32,omitempty"`
+	RepeatedFixed64        []uint64                               `protobuf:"fixed64,38,rep,name=repeated_fixed64,json=repeatedFixed64" json:"repeated_fixed64,omitempty"`
+	RepeatedSfixed32       []int32                                `protobuf:"fixed32,39,rep,name=repeated_sfixed32,json=repeatedSfixed32" json:"repeated_sfixed32,omitempty"`
+	RepeatedSfixed64       []int64                                `protobuf:"fixed64,40,rep,name=repeated_sfixed64,json=repeatedSfixed64" json:"repeated_sfixed64,omitempty"`
+	RepeatedFloat          []float32                              `protobuf:"fixed32,41,rep,name=repeated_float,json=repeatedFloat" json:"repeated_float,omitempty"`
+	RepeatedDouble         []float64                              `protobuf:"fixed64,42,rep,name=repeated_double,json=repeatedDouble" json:"repeated_double,omitempty"`
+	RepeatedBool           []bool                                 `protobuf:"varint,43,rep,name=repeated_bool,json=repeatedBool" json:"repeated_bool,omitempty"`
+	RepeatedString         []string                               `protobuf:"bytes,44,rep,name=repeated_string,json=repeatedString" json:"repeated_string,omitempty"`
+	RepeatedBytes          [][]byte                               `protobuf:"bytes,45,rep,name=repeated_bytes,json=repeatedBytes" json:"repeated_bytes,omitempty"`
+	Repeatedgroup          []*TestAllTypes_RepeatedGroup          `protobuf:"group,46,rep,name=RepeatedGroup,json=repeatedgroup" json:"repeatedgroup,omitempty"`
+	RepeatedNestedMessage  []*TestAllTypes_NestedMessage          `protobuf:"bytes,48,rep,name=repeated_nested_message,json=repeatedNestedMessage" json:"repeated_nested_message,omitempty"`
+	RepeatedNestedEnum     []TestAllTypes_NestedEnum              `protobuf:"varint,51,rep,name=repeated_nested_enum,json=repeatedNestedEnum,enum=goproto.proto.test.TestAllTypes_NestedEnum" json:"repeated_nested_enum,omitempty"`
+	MapInt32Int32          map[int32]int32                        `protobuf:"bytes,56,rep,name=map_int32_int32,json=mapInt32Int32" json:"map_int32_int32,omitempty" protobuf_key:"varint,1,opt,name=key" protobuf_val:"varint,2,opt,name=value"`
+	MapInt64Int64          map[int64]int64                        `protobuf:"bytes,57,rep,name=map_int64_int64,json=mapInt64Int64" json:"map_int64_int64,omitempty" protobuf_key:"varint,1,opt,name=key" protobuf_val:"varint,2,opt,name=value"`
+	MapUint32Uint32        map[uint32]uint32                      `protobuf:"bytes,58,rep,name=map_uint32_uint32,json=mapUint32Uint32" json:"map_uint32_uint32,omitempty" protobuf_key:"varint,1,opt,name=key" protobuf_val:"varint,2,opt,name=value"`
+	MapUint64Uint64        map[uint64]uint64                      `protobuf:"bytes,59,rep,name=map_uint64_uint64,json=mapUint64Uint64" json:"map_uint64_uint64,omitempty" protobuf_key:"varint,1,opt,name=key" protobuf_val:"varint,2,opt,name=value"`
+	MapSint32Sint32        map[int32]int32                        `protobuf:"bytes,60,rep,name=map_sint32_sint32,json=mapSint32Sint32" json:"map_sint32_sint32,omitempty" protobuf_key:"zigzag32,1,opt,name=key" protobuf_val:"zigzag32,2,opt,name=value"`
+	MapSint64Sint64        map[int64]int64                        `protobuf:"bytes,61,rep,name=map_sint64_sint64,json=mapSint64Sint64" json:"map_sint64_sint64,omitempty" protobuf_key:"zigzag64,1,opt,name=key" protobuf_val:"zigzag64,2,opt,name=value"`
+	MapFixed32Fixed32      map[uint32]uint32                      `protobuf:"bytes,62,rep,name=map_fixed32_fixed32,json=mapFixed32Fixed32" json:"map_fixed32_fixed32,omitempty" protobuf_key:"fixed32,1,opt,name=key" protobuf_val:"fixed32,2,opt,name=value"`
+	MapFixed64Fixed64      map[uint64]uint64                      `protobuf:"bytes,63,rep,name=map_fixed64_fixed64,json=mapFixed64Fixed64" json:"map_fixed64_fixed64,omitempty" protobuf_key:"fixed64,1,opt,name=key" protobuf_val:"fixed64,2,opt,name=value"`
+	MapSfixed32Sfixed32    map[int32]int32                        `protobuf:"bytes,64,rep,name=map_sfixed32_sfixed32,json=mapSfixed32Sfixed32" json:"map_sfixed32_sfixed32,omitempty" protobuf_key:"fixed32,1,opt,name=key" protobuf_val:"fixed32,2,opt,name=value"`
+	MapSfixed64Sfixed64    map[int64]int64                        `protobuf:"bytes,65,rep,name=map_sfixed64_sfixed64,json=mapSfixed64Sfixed64" json:"map_sfixed64_sfixed64,omitempty" protobuf_key:"fixed64,1,opt,name=key" protobuf_val:"fixed64,2,opt,name=value"`
+	MapInt32Float          map[int32]float32                      `protobuf:"bytes,66,rep,name=map_int32_float,json=mapInt32Float" json:"map_int32_float,omitempty" protobuf_key:"varint,1,opt,name=key" protobuf_val:"fixed32,2,opt,name=value"`
+	MapInt32Double         map[int32]float64                      `protobuf:"bytes,67,rep,name=map_int32_double,json=mapInt32Double" json:"map_int32_double,omitempty" protobuf_key:"varint,1,opt,name=key" protobuf_val:"fixed64,2,opt,name=value"`
+	MapBoolBool            map[bool]bool                          `protobuf:"bytes,68,rep,name=map_bool_bool,json=mapBoolBool" json:"map_bool_bool,omitempty" protobuf_key:"varint,1,opt,name=key" protobuf_val:"varint,2,opt,name=value"`
+	MapStringString        map[string]string                      `protobuf:"bytes,69,rep,name=map_string_string,json=mapStringString" json:"map_string_string,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"`
+	MapStringBytes         map[string][]byte                      `protobuf:"bytes,70,rep,name=map_string_bytes,json=mapStringBytes" json:"map_string_bytes,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"`
+	MapStringNestedMessage map[string]*TestAllTypes_NestedMessage `protobuf:"bytes,71,rep,name=map_string_nested_message,json=mapStringNestedMessage" json:"map_string_nested_message,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"`
+	MapStringNestedEnum    map[string]TestAllTypes_NestedEnum     `protobuf:"bytes,73,rep,name=map_string_nested_enum,json=mapStringNestedEnum" json:"map_string_nested_enum,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"varint,2,opt,name=value,enum=goproto.proto.test.TestAllTypes_NestedEnum"`
+	// Types that are valid to be assigned to OneofField:
+	//	*TestAllTypes_OneofUint32
+	//	*TestAllTypes_OneofNestedMessage
+	//	*TestAllTypes_OneofString
+	//	*TestAllTypes_OneofBytes
+	//	*TestAllTypes_OneofBool
+	//	*TestAllTypes_OneofUint64
+	//	*TestAllTypes_OneofFloat
+	//	*TestAllTypes_OneofDouble
+	//	*TestAllTypes_OneofEnum
+	OneofField           isTestAllTypes_OneofField `protobuf_oneof:"oneof_field"`
+	XXX_NoUnkeyedLiteral struct{}                  `json:"-"`
+	XXX_unrecognized     []byte                    `json:"-"`
+	XXX_sizecache        int32                     `json:"-"`
+}
+
+type xxx_TestAllTypes struct{ m *TestAllTypes }
+
+func (m *TestAllTypes) ProtoReflect() protoreflect.Message {
+	return xxx_TestAllTypes{m}
+}
+func (m xxx_TestAllTypes) Type() protoreflect.MessageType {
+	return xxx_Test_ProtoFile_MessageTypes[0].Type
+}
+func (m xxx_TestAllTypes) KnownFields() protoreflect.KnownFields {
+	return xxx_Test_ProtoFile_MessageTypes[0].KnownFieldsOf(m.m)
+}
+func (m xxx_TestAllTypes) UnknownFields() protoreflect.UnknownFields {
+	return xxx_Test_ProtoFile_MessageTypes[0].UnknownFieldsOf(m.m)
+}
+func (m xxx_TestAllTypes) Interface() protoreflect.ProtoMessage {
+	return m.m
+}
+
+func (m *TestAllTypes) Reset()         { *m = TestAllTypes{} }
+func (m *TestAllTypes) String() string { return proto.CompactTextString(m) }
+func (*TestAllTypes) ProtoMessage()    {}
+func (*TestAllTypes) Descriptor() ([]byte, []int) {
+	return fileDescriptor_c161fcfdc0c3ff1e, []int{0}
+}
+
+func (m *TestAllTypes) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_TestAllTypes.Unmarshal(m, b)
+}
+func (m *TestAllTypes) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_TestAllTypes.Marshal(b, m, deterministic)
+}
+func (m *TestAllTypes) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_TestAllTypes.Merge(m, src)
+}
+func (m *TestAllTypes) XXX_Size() int {
+	return xxx_messageInfo_TestAllTypes.Size(m)
+}
+func (m *TestAllTypes) XXX_DiscardUnknown() {
+	xxx_messageInfo_TestAllTypes.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_TestAllTypes proto.InternalMessageInfo
+
+func (m *TestAllTypes) GetOptionalInt32() int32 {
+	if m != nil && m.OptionalInt32 != nil {
+		return *m.OptionalInt32
+	}
+	return 0
+}
+
+func (m *TestAllTypes) GetOptionalInt64() int64 {
+	if m != nil && m.OptionalInt64 != nil {
+		return *m.OptionalInt64
+	}
+	return 0
+}
+
+func (m *TestAllTypes) GetOptionalUint32() uint32 {
+	if m != nil && m.OptionalUint32 != nil {
+		return *m.OptionalUint32
+	}
+	return 0
+}
+
+func (m *TestAllTypes) GetOptionalUint64() uint64 {
+	if m != nil && m.OptionalUint64 != nil {
+		return *m.OptionalUint64
+	}
+	return 0
+}
+
+func (m *TestAllTypes) GetOptionalSint32() int32 {
+	if m != nil && m.OptionalSint32 != nil {
+		return *m.OptionalSint32
+	}
+	return 0
+}
+
+func (m *TestAllTypes) GetOptionalSint64() int64 {
+	if m != nil && m.OptionalSint64 != nil {
+		return *m.OptionalSint64
+	}
+	return 0
+}
+
+func (m *TestAllTypes) GetOptionalFixed32() uint32 {
+	if m != nil && m.OptionalFixed32 != nil {
+		return *m.OptionalFixed32
+	}
+	return 0
+}
+
+func (m *TestAllTypes) GetOptionalFixed64() uint64 {
+	if m != nil && m.OptionalFixed64 != nil {
+		return *m.OptionalFixed64
+	}
+	return 0
+}
+
+func (m *TestAllTypes) GetOptionalSfixed32() int32 {
+	if m != nil && m.OptionalSfixed32 != nil {
+		return *m.OptionalSfixed32
+	}
+	return 0
+}
+
+func (m *TestAllTypes) GetOptionalSfixed64() int64 {
+	if m != nil && m.OptionalSfixed64 != nil {
+		return *m.OptionalSfixed64
+	}
+	return 0
+}
+
+func (m *TestAllTypes) GetOptionalFloat() float32 {
+	if m != nil && m.OptionalFloat != nil {
+		return *m.OptionalFloat
+	}
+	return 0
+}
+
+func (m *TestAllTypes) GetOptionalDouble() float64 {
+	if m != nil && m.OptionalDouble != nil {
+		return *m.OptionalDouble
+	}
+	return 0
+}
+
+func (m *TestAllTypes) GetOptionalBool() bool {
+	if m != nil && m.OptionalBool != nil {
+		return *m.OptionalBool
+	}
+	return false
+}
+
+func (m *TestAllTypes) GetOptionalString() string {
+	if m != nil && m.OptionalString != nil {
+		return *m.OptionalString
+	}
+	return ""
+}
+
+func (m *TestAllTypes) GetOptionalBytes() []byte {
+	if m != nil {
+		return m.OptionalBytes
+	}
+	return nil
+}
+
+func (m *TestAllTypes) GetOptionalgroup() *TestAllTypes_OptionalGroup {
+	if m != nil {
+		return m.Optionalgroup
+	}
+	return nil
+}
+
+func (m *TestAllTypes) GetOptionalNestedMessage() *TestAllTypes_NestedMessage {
+	if m != nil {
+		return m.OptionalNestedMessage
+	}
+	return nil
+}
+
+func (m *TestAllTypes) GetOptionalNestedEnum() TestAllTypes_NestedEnum {
+	if m != nil && m.OptionalNestedEnum != nil {
+		return *m.OptionalNestedEnum
+	}
+	return TestAllTypes_FOO
+}
+
+func (m *TestAllTypes) GetRepeatedInt32() []int32 {
+	if m != nil {
+		return m.RepeatedInt32
+	}
+	return nil
+}
+
+func (m *TestAllTypes) GetRepeatedInt64() []int64 {
+	if m != nil {
+		return m.RepeatedInt64
+	}
+	return nil
+}
+
+func (m *TestAllTypes) GetRepeatedUint32() []uint32 {
+	if m != nil {
+		return m.RepeatedUint32
+	}
+	return nil
+}
+
+func (m *TestAllTypes) GetRepeatedUint64() []uint64 {
+	if m != nil {
+		return m.RepeatedUint64
+	}
+	return nil
+}
+
+func (m *TestAllTypes) GetRepeatedSint32() []int32 {
+	if m != nil {
+		return m.RepeatedSint32
+	}
+	return nil
+}
+
+func (m *TestAllTypes) GetRepeatedSint64() []int64 {
+	if m != nil {
+		return m.RepeatedSint64
+	}
+	return nil
+}
+
+func (m *TestAllTypes) GetRepeatedFixed32() []uint32 {
+	if m != nil {
+		return m.RepeatedFixed32
+	}
+	return nil
+}
+
+func (m *TestAllTypes) GetRepeatedFixed64() []uint64 {
+	if m != nil {
+		return m.RepeatedFixed64
+	}
+	return nil
+}
+
+func (m *TestAllTypes) GetRepeatedSfixed32() []int32 {
+	if m != nil {
+		return m.RepeatedSfixed32
+	}
+	return nil
+}
+
+func (m *TestAllTypes) GetRepeatedSfixed64() []int64 {
+	if m != nil {
+		return m.RepeatedSfixed64
+	}
+	return nil
+}
+
+func (m *TestAllTypes) GetRepeatedFloat() []float32 {
+	if m != nil {
+		return m.RepeatedFloat
+	}
+	return nil
+}
+
+func (m *TestAllTypes) GetRepeatedDouble() []float64 {
+	if m != nil {
+		return m.RepeatedDouble
+	}
+	return nil
+}
+
+func (m *TestAllTypes) GetRepeatedBool() []bool {
+	if m != nil {
+		return m.RepeatedBool
+	}
+	return nil
+}
+
+func (m *TestAllTypes) GetRepeatedString() []string {
+	if m != nil {
+		return m.RepeatedString
+	}
+	return nil
+}
+
+func (m *TestAllTypes) GetRepeatedBytes() [][]byte {
+	if m != nil {
+		return m.RepeatedBytes
+	}
+	return nil
+}
+
+func (m *TestAllTypes) GetRepeatedgroup() []*TestAllTypes_RepeatedGroup {
+	if m != nil {
+		return m.Repeatedgroup
+	}
+	return nil
+}
+
+func (m *TestAllTypes) GetRepeatedNestedMessage() []*TestAllTypes_NestedMessage {
+	if m != nil {
+		return m.RepeatedNestedMessage
+	}
+	return nil
+}
+
+func (m *TestAllTypes) GetRepeatedNestedEnum() []TestAllTypes_NestedEnum {
+	if m != nil {
+		return m.RepeatedNestedEnum
+	}
+	return nil
+}
+
+func (m *TestAllTypes) GetMapInt32Int32() map[int32]int32 {
+	if m != nil {
+		return m.MapInt32Int32
+	}
+	return nil
+}
+
+func (m *TestAllTypes) GetMapInt64Int64() map[int64]int64 {
+	if m != nil {
+		return m.MapInt64Int64
+	}
+	return nil
+}
+
+func (m *TestAllTypes) GetMapUint32Uint32() map[uint32]uint32 {
+	if m != nil {
+		return m.MapUint32Uint32
+	}
+	return nil
+}
+
+func (m *TestAllTypes) GetMapUint64Uint64() map[uint64]uint64 {
+	if m != nil {
+		return m.MapUint64Uint64
+	}
+	return nil
+}
+
+func (m *TestAllTypes) GetMapSint32Sint32() map[int32]int32 {
+	if m != nil {
+		return m.MapSint32Sint32
+	}
+	return nil
+}
+
+func (m *TestAllTypes) GetMapSint64Sint64() map[int64]int64 {
+	if m != nil {
+		return m.MapSint64Sint64
+	}
+	return nil
+}
+
+func (m *TestAllTypes) GetMapFixed32Fixed32() map[uint32]uint32 {
+	if m != nil {
+		return m.MapFixed32Fixed32
+	}
+	return nil
+}
+
+func (m *TestAllTypes) GetMapFixed64Fixed64() map[uint64]uint64 {
+	if m != nil {
+		return m.MapFixed64Fixed64
+	}
+	return nil
+}
+
+func (m *TestAllTypes) GetMapSfixed32Sfixed32() map[int32]int32 {
+	if m != nil {
+		return m.MapSfixed32Sfixed32
+	}
+	return nil
+}
+
+func (m *TestAllTypes) GetMapSfixed64Sfixed64() map[int64]int64 {
+	if m != nil {
+		return m.MapSfixed64Sfixed64
+	}
+	return nil
+}
+
+func (m *TestAllTypes) GetMapInt32Float() map[int32]float32 {
+	if m != nil {
+		return m.MapInt32Float
+	}
+	return nil
+}
+
+func (m *TestAllTypes) GetMapInt32Double() map[int32]float64 {
+	if m != nil {
+		return m.MapInt32Double
+	}
+	return nil
+}
+
+func (m *TestAllTypes) GetMapBoolBool() map[bool]bool {
+	if m != nil {
+		return m.MapBoolBool
+	}
+	return nil
+}
+
+func (m *TestAllTypes) GetMapStringString() map[string]string {
+	if m != nil {
+		return m.MapStringString
+	}
+	return nil
+}
+
+func (m *TestAllTypes) GetMapStringBytes() map[string][]byte {
+	if m != nil {
+		return m.MapStringBytes
+	}
+	return nil
+}
+
+func (m *TestAllTypes) GetMapStringNestedMessage() map[string]*TestAllTypes_NestedMessage {
+	if m != nil {
+		return m.MapStringNestedMessage
+	}
+	return nil
+}
+
+func (m *TestAllTypes) GetMapStringNestedEnum() map[string]TestAllTypes_NestedEnum {
+	if m != nil {
+		return m.MapStringNestedEnum
+	}
+	return nil
+}
+
+type isTestAllTypes_OneofField interface {
+	isTestAllTypes_OneofField()
+}
+
+type TestAllTypes_OneofUint32 struct {
+	OneofUint32 uint32 `protobuf:"varint,111,opt,name=oneof_uint32,json=oneofUint32,oneof"`
+}
+
+type TestAllTypes_OneofNestedMessage struct {
+	OneofNestedMessage *TestAllTypes_NestedMessage `protobuf:"bytes,112,opt,name=oneof_nested_message,json=oneofNestedMessage,oneof"`
+}
+
+type TestAllTypes_OneofString struct {
+	OneofString string `protobuf:"bytes,113,opt,name=oneof_string,json=oneofString,oneof"`
+}
+
+type TestAllTypes_OneofBytes struct {
+	OneofBytes []byte `protobuf:"bytes,114,opt,name=oneof_bytes,json=oneofBytes,oneof"`
+}
+
+type TestAllTypes_OneofBool struct {
+	OneofBool bool `protobuf:"varint,115,opt,name=oneof_bool,json=oneofBool,oneof"`
+}
+
+type TestAllTypes_OneofUint64 struct {
+	OneofUint64 uint64 `protobuf:"varint,116,opt,name=oneof_uint64,json=oneofUint64,oneof"`
+}
+
+type TestAllTypes_OneofFloat struct {
+	OneofFloat float32 `protobuf:"fixed32,117,opt,name=oneof_float,json=oneofFloat,oneof"`
+}
+
+type TestAllTypes_OneofDouble struct {
+	OneofDouble float64 `protobuf:"fixed64,118,opt,name=oneof_double,json=oneofDouble,oneof"`
+}
+
+type TestAllTypes_OneofEnum struct {
+	OneofEnum TestAllTypes_NestedEnum `protobuf:"varint,119,opt,name=oneof_enum,json=oneofEnum,enum=goproto.proto.test.TestAllTypes_NestedEnum,oneof"`
+}
+
+func (*TestAllTypes_OneofUint32) isTestAllTypes_OneofField() {}
+
+func (*TestAllTypes_OneofNestedMessage) isTestAllTypes_OneofField() {}
+
+func (*TestAllTypes_OneofString) isTestAllTypes_OneofField() {}
+
+func (*TestAllTypes_OneofBytes) isTestAllTypes_OneofField() {}
+
+func (*TestAllTypes_OneofBool) isTestAllTypes_OneofField() {}
+
+func (*TestAllTypes_OneofUint64) isTestAllTypes_OneofField() {}
+
+func (*TestAllTypes_OneofFloat) isTestAllTypes_OneofField() {}
+
+func (*TestAllTypes_OneofDouble) isTestAllTypes_OneofField() {}
+
+func (*TestAllTypes_OneofEnum) isTestAllTypes_OneofField() {}
+
+func (m *TestAllTypes) GetOneofField() isTestAllTypes_OneofField {
+	if m != nil {
+		return m.OneofField
+	}
+	return nil
+}
+
+func (m *TestAllTypes) GetOneofUint32() uint32 {
+	if x, ok := m.GetOneofField().(*TestAllTypes_OneofUint32); ok {
+		return x.OneofUint32
+	}
+	return 0
+}
+
+func (m *TestAllTypes) GetOneofNestedMessage() *TestAllTypes_NestedMessage {
+	if x, ok := m.GetOneofField().(*TestAllTypes_OneofNestedMessage); ok {
+		return x.OneofNestedMessage
+	}
+	return nil
+}
+
+func (m *TestAllTypes) GetOneofString() string {
+	if x, ok := m.GetOneofField().(*TestAllTypes_OneofString); ok {
+		return x.OneofString
+	}
+	return ""
+}
+
+func (m *TestAllTypes) GetOneofBytes() []byte {
+	if x, ok := m.GetOneofField().(*TestAllTypes_OneofBytes); ok {
+		return x.OneofBytes
+	}
+	return nil
+}
+
+func (m *TestAllTypes) GetOneofBool() bool {
+	if x, ok := m.GetOneofField().(*TestAllTypes_OneofBool); ok {
+		return x.OneofBool
+	}
+	return false
+}
+
+func (m *TestAllTypes) GetOneofUint64() uint64 {
+	if x, ok := m.GetOneofField().(*TestAllTypes_OneofUint64); ok {
+		return x.OneofUint64
+	}
+	return 0
+}
+
+func (m *TestAllTypes) GetOneofFloat() float32 {
+	if x, ok := m.GetOneofField().(*TestAllTypes_OneofFloat); ok {
+		return x.OneofFloat
+	}
+	return 0
+}
+
+func (m *TestAllTypes) GetOneofDouble() float64 {
+	if x, ok := m.GetOneofField().(*TestAllTypes_OneofDouble); ok {
+		return x.OneofDouble
+	}
+	return 0
+}
+
+func (m *TestAllTypes) GetOneofEnum() TestAllTypes_NestedEnum {
+	if x, ok := m.GetOneofField().(*TestAllTypes_OneofEnum); ok {
+		return x.OneofEnum
+	}
+	return TestAllTypes_FOO
+}
+
+// XXX_OneofWrappers is for the internal use of the proto package.
+func (*TestAllTypes) XXX_OneofWrappers() []interface{} {
+	return []interface{}{
+		(*TestAllTypes_OneofUint32)(nil),
+		(*TestAllTypes_OneofNestedMessage)(nil),
+		(*TestAllTypes_OneofString)(nil),
+		(*TestAllTypes_OneofBytes)(nil),
+		(*TestAllTypes_OneofBool)(nil),
+		(*TestAllTypes_OneofUint64)(nil),
+		(*TestAllTypes_OneofFloat)(nil),
+		(*TestAllTypes_OneofDouble)(nil),
+		(*TestAllTypes_OneofEnum)(nil),
+	}
+}
+
+type TestAllExtensions struct {
+	XXX_NoUnkeyedLiteral         struct{} `json:"-"`
+	proto.XXX_InternalExtensions `json:"-"`
+	XXX_unrecognized             []byte `json:"-"`
+	XXX_sizecache                int32  `json:"-"`
+}
+
+type xxx_TestAllExtensions struct{ m *TestAllExtensions }
+
+func (m *TestAllExtensions) ProtoReflect() protoreflect.Message {
+	return xxx_TestAllExtensions{m}
+}
+func (m xxx_TestAllExtensions) Type() protoreflect.MessageType {
+	return xxx_Test_ProtoFile_MessageTypes[1].Type
+}
+func (m xxx_TestAllExtensions) KnownFields() protoreflect.KnownFields {
+	return xxx_Test_ProtoFile_MessageTypes[1].KnownFieldsOf(m.m)
+}
+func (m xxx_TestAllExtensions) UnknownFields() protoreflect.UnknownFields {
+	return xxx_Test_ProtoFile_MessageTypes[1].UnknownFieldsOf(m.m)
+}
+func (m xxx_TestAllExtensions) Interface() protoreflect.ProtoMessage {
+	return m.m
+}
+
+func (m *TestAllExtensions) Reset()         { *m = TestAllExtensions{} }
+func (m *TestAllExtensions) String() string { return proto.CompactTextString(m) }
+func (*TestAllExtensions) ProtoMessage()    {}
+func (*TestAllExtensions) Descriptor() ([]byte, []int) {
+	return fileDescriptor_c161fcfdc0c3ff1e, []int{1}
+}
+
+var extRange_TestAllExtensions = []proto.ExtensionRange{
+	{Start: 1, End: 536870911},
+}
+
+func (*TestAllExtensions) ExtensionRangeArray() []proto.ExtensionRange {
+	return extRange_TestAllExtensions
+}
+
+func (m *TestAllExtensions) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_TestAllExtensions.Unmarshal(m, b)
+}
+func (m *TestAllExtensions) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_TestAllExtensions.Marshal(b, m, deterministic)
+}
+func (m *TestAllExtensions) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_TestAllExtensions.Merge(m, src)
+}
+func (m *TestAllExtensions) XXX_Size() int {
+	return xxx_messageInfo_TestAllExtensions.Size(m)
+}
+func (m *TestAllExtensions) XXX_DiscardUnknown() {
+	xxx_messageInfo_TestAllExtensions.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_TestAllExtensions proto.InternalMessageInfo
+
+type OptionalGroupExtension struct {
+	A                    *int32   `protobuf:"varint,17,opt,name=a" json:"a,omitempty"`
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+type xxx_OptionalGroupExtension struct{ m *OptionalGroupExtension }
+
+func (m *OptionalGroupExtension) ProtoReflect() protoreflect.Message {
+	return xxx_OptionalGroupExtension{m}
+}
+func (m xxx_OptionalGroupExtension) Type() protoreflect.MessageType {
+	return xxx_Test_ProtoFile_MessageTypes[2].Type
+}
+func (m xxx_OptionalGroupExtension) KnownFields() protoreflect.KnownFields {
+	return xxx_Test_ProtoFile_MessageTypes[2].KnownFieldsOf(m.m)
+}
+func (m xxx_OptionalGroupExtension) UnknownFields() protoreflect.UnknownFields {
+	return xxx_Test_ProtoFile_MessageTypes[2].UnknownFieldsOf(m.m)
+}
+func (m xxx_OptionalGroupExtension) Interface() protoreflect.ProtoMessage {
+	return m.m
+}
+
+func (m *OptionalGroupExtension) Reset()         { *m = OptionalGroupExtension{} }
+func (m *OptionalGroupExtension) String() string { return proto.CompactTextString(m) }
+func (*OptionalGroupExtension) ProtoMessage()    {}
+func (*OptionalGroupExtension) Descriptor() ([]byte, []int) {
+	return fileDescriptor_c161fcfdc0c3ff1e, []int{2}
+}
+
+func (m *OptionalGroupExtension) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_OptionalGroupExtension.Unmarshal(m, b)
+}
+func (m *OptionalGroupExtension) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_OptionalGroupExtension.Marshal(b, m, deterministic)
+}
+func (m *OptionalGroupExtension) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_OptionalGroupExtension.Merge(m, src)
+}
+func (m *OptionalGroupExtension) XXX_Size() int {
+	return xxx_messageInfo_OptionalGroupExtension.Size(m)
+}
+func (m *OptionalGroupExtension) XXX_DiscardUnknown() {
+	xxx_messageInfo_OptionalGroupExtension.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_OptionalGroupExtension proto.InternalMessageInfo
+
+func (m *OptionalGroupExtension) GetA() int32 {
+	if m != nil && m.A != nil {
+		return *m.A
+	}
+	return 0
+}
+
+type RepeatedGroupExtension struct {
+	A                    *int32   `protobuf:"varint,47,opt,name=a" json:"a,omitempty"`
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+type xxx_RepeatedGroupExtension struct{ m *RepeatedGroupExtension }
+
+func (m *RepeatedGroupExtension) ProtoReflect() protoreflect.Message {
+	return xxx_RepeatedGroupExtension{m}
+}
+func (m xxx_RepeatedGroupExtension) Type() protoreflect.MessageType {
+	return xxx_Test_ProtoFile_MessageTypes[3].Type
+}
+func (m xxx_RepeatedGroupExtension) KnownFields() protoreflect.KnownFields {
+	return xxx_Test_ProtoFile_MessageTypes[3].KnownFieldsOf(m.m)
+}
+func (m xxx_RepeatedGroupExtension) UnknownFields() protoreflect.UnknownFields {
+	return xxx_Test_ProtoFile_MessageTypes[3].UnknownFieldsOf(m.m)
+}
+func (m xxx_RepeatedGroupExtension) Interface() protoreflect.ProtoMessage {
+	return m.m
+}
+
+func (m *RepeatedGroupExtension) Reset()         { *m = RepeatedGroupExtension{} }
+func (m *RepeatedGroupExtension) String() string { return proto.CompactTextString(m) }
+func (*RepeatedGroupExtension) ProtoMessage()    {}
+func (*RepeatedGroupExtension) Descriptor() ([]byte, []int) {
+	return fileDescriptor_c161fcfdc0c3ff1e, []int{3}
+}
+
+func (m *RepeatedGroupExtension) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_RepeatedGroupExtension.Unmarshal(m, b)
+}
+func (m *RepeatedGroupExtension) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_RepeatedGroupExtension.Marshal(b, m, deterministic)
+}
+func (m *RepeatedGroupExtension) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_RepeatedGroupExtension.Merge(m, src)
+}
+func (m *RepeatedGroupExtension) XXX_Size() int {
+	return xxx_messageInfo_RepeatedGroupExtension.Size(m)
+}
+func (m *RepeatedGroupExtension) XXX_DiscardUnknown() {
+	xxx_messageInfo_RepeatedGroupExtension.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_RepeatedGroupExtension proto.InternalMessageInfo
+
+func (m *RepeatedGroupExtension) GetA() int32 {
+	if m != nil && m.A != nil {
+		return *m.A
+	}
+	return 0
+}
+
+type TestAllTypes_NestedMessage struct {
+	A                    *int32        `protobuf:"varint,1,opt,name=a" json:"a,omitempty"`
+	Corecursive          *TestAllTypes `protobuf:"bytes,2,opt,name=corecursive" json:"corecursive,omitempty"`
+	XXX_NoUnkeyedLiteral struct{}      `json:"-"`
+	XXX_unrecognized     []byte        `json:"-"`
+	XXX_sizecache        int32         `json:"-"`
+}
+
+type xxx_TestAllTypes_NestedMessage struct{ m *TestAllTypes_NestedMessage }
+
+func (m *TestAllTypes_NestedMessage) ProtoReflect() protoreflect.Message {
+	return xxx_TestAllTypes_NestedMessage{m}
+}
+func (m xxx_TestAllTypes_NestedMessage) Type() protoreflect.MessageType {
+	return xxx_Test_ProtoFile_MessageTypes[4].Type
+}
+func (m xxx_TestAllTypes_NestedMessage) KnownFields() protoreflect.KnownFields {
+	return xxx_Test_ProtoFile_MessageTypes[4].KnownFieldsOf(m.m)
+}
+func (m xxx_TestAllTypes_NestedMessage) UnknownFields() protoreflect.UnknownFields {
+	return xxx_Test_ProtoFile_MessageTypes[4].UnknownFieldsOf(m.m)
+}
+func (m xxx_TestAllTypes_NestedMessage) Interface() protoreflect.ProtoMessage {
+	return m.m
+}
+
+func (m *TestAllTypes_NestedMessage) Reset()         { *m = TestAllTypes_NestedMessage{} }
+func (m *TestAllTypes_NestedMessage) String() string { return proto.CompactTextString(m) }
+func (*TestAllTypes_NestedMessage) ProtoMessage()    {}
+func (*TestAllTypes_NestedMessage) Descriptor() ([]byte, []int) {
+	return fileDescriptor_c161fcfdc0c3ff1e, []int{0, 0}
+}
+
+func (m *TestAllTypes_NestedMessage) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_TestAllTypes_NestedMessage.Unmarshal(m, b)
+}
+func (m *TestAllTypes_NestedMessage) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_TestAllTypes_NestedMessage.Marshal(b, m, deterministic)
+}
+func (m *TestAllTypes_NestedMessage) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_TestAllTypes_NestedMessage.Merge(m, src)
+}
+func (m *TestAllTypes_NestedMessage) XXX_Size() int {
+	return xxx_messageInfo_TestAllTypes_NestedMessage.Size(m)
+}
+func (m *TestAllTypes_NestedMessage) XXX_DiscardUnknown() {
+	xxx_messageInfo_TestAllTypes_NestedMessage.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_TestAllTypes_NestedMessage proto.InternalMessageInfo
+
+func (m *TestAllTypes_NestedMessage) GetA() int32 {
+	if m != nil && m.A != nil {
+		return *m.A
+	}
+	return 0
+}
+
+func (m *TestAllTypes_NestedMessage) GetCorecursive() *TestAllTypes {
+	if m != nil {
+		return m.Corecursive
+	}
+	return nil
+}
+
+type TestAllTypes_OptionalGroup struct {
+	A                    *int32   `protobuf:"varint,17,opt,name=a" json:"a,omitempty"`
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+type xxx_TestAllTypes_OptionalGroup struct{ m *TestAllTypes_OptionalGroup }
+
+func (m *TestAllTypes_OptionalGroup) ProtoReflect() protoreflect.Message {
+	return xxx_TestAllTypes_OptionalGroup{m}
+}
+func (m xxx_TestAllTypes_OptionalGroup) Type() protoreflect.MessageType {
+	return xxx_Test_ProtoFile_MessageTypes[5].Type
+}
+func (m xxx_TestAllTypes_OptionalGroup) KnownFields() protoreflect.KnownFields {
+	return xxx_Test_ProtoFile_MessageTypes[5].KnownFieldsOf(m.m)
+}
+func (m xxx_TestAllTypes_OptionalGroup) UnknownFields() protoreflect.UnknownFields {
+	return xxx_Test_ProtoFile_MessageTypes[5].UnknownFieldsOf(m.m)
+}
+func (m xxx_TestAllTypes_OptionalGroup) Interface() protoreflect.ProtoMessage {
+	return m.m
+}
+
+func (m *TestAllTypes_OptionalGroup) Reset()         { *m = TestAllTypes_OptionalGroup{} }
+func (m *TestAllTypes_OptionalGroup) String() string { return proto.CompactTextString(m) }
+func (*TestAllTypes_OptionalGroup) ProtoMessage()    {}
+func (*TestAllTypes_OptionalGroup) Descriptor() ([]byte, []int) {
+	return fileDescriptor_c161fcfdc0c3ff1e, []int{0, 1}
+}
+
+func (m *TestAllTypes_OptionalGroup) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_TestAllTypes_OptionalGroup.Unmarshal(m, b)
+}
+func (m *TestAllTypes_OptionalGroup) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_TestAllTypes_OptionalGroup.Marshal(b, m, deterministic)
+}
+func (m *TestAllTypes_OptionalGroup) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_TestAllTypes_OptionalGroup.Merge(m, src)
+}
+func (m *TestAllTypes_OptionalGroup) XXX_Size() int {
+	return xxx_messageInfo_TestAllTypes_OptionalGroup.Size(m)
+}
+func (m *TestAllTypes_OptionalGroup) XXX_DiscardUnknown() {
+	xxx_messageInfo_TestAllTypes_OptionalGroup.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_TestAllTypes_OptionalGroup proto.InternalMessageInfo
+
+func (m *TestAllTypes_OptionalGroup) GetA() int32 {
+	if m != nil && m.A != nil {
+		return *m.A
+	}
+	return 0
+}
+
+type TestAllTypes_RepeatedGroup struct {
+	A                    *int32   `protobuf:"varint,47,opt,name=a" json:"a,omitempty"`
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+type xxx_TestAllTypes_RepeatedGroup struct{ m *TestAllTypes_RepeatedGroup }
+
+func (m *TestAllTypes_RepeatedGroup) ProtoReflect() protoreflect.Message {
+	return xxx_TestAllTypes_RepeatedGroup{m}
+}
+func (m xxx_TestAllTypes_RepeatedGroup) Type() protoreflect.MessageType {
+	return xxx_Test_ProtoFile_MessageTypes[6].Type
+}
+func (m xxx_TestAllTypes_RepeatedGroup) KnownFields() protoreflect.KnownFields {
+	return xxx_Test_ProtoFile_MessageTypes[6].KnownFieldsOf(m.m)
+}
+func (m xxx_TestAllTypes_RepeatedGroup) UnknownFields() protoreflect.UnknownFields {
+	return xxx_Test_ProtoFile_MessageTypes[6].UnknownFieldsOf(m.m)
+}
+func (m xxx_TestAllTypes_RepeatedGroup) Interface() protoreflect.ProtoMessage {
+	return m.m
+}
+
+func (m *TestAllTypes_RepeatedGroup) Reset()         { *m = TestAllTypes_RepeatedGroup{} }
+func (m *TestAllTypes_RepeatedGroup) String() string { return proto.CompactTextString(m) }
+func (*TestAllTypes_RepeatedGroup) ProtoMessage()    {}
+func (*TestAllTypes_RepeatedGroup) Descriptor() ([]byte, []int) {
+	return fileDescriptor_c161fcfdc0c3ff1e, []int{0, 2}
+}
+
+func (m *TestAllTypes_RepeatedGroup) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_TestAllTypes_RepeatedGroup.Unmarshal(m, b)
+}
+func (m *TestAllTypes_RepeatedGroup) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_TestAllTypes_RepeatedGroup.Marshal(b, m, deterministic)
+}
+func (m *TestAllTypes_RepeatedGroup) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_TestAllTypes_RepeatedGroup.Merge(m, src)
+}
+func (m *TestAllTypes_RepeatedGroup) XXX_Size() int {
+	return xxx_messageInfo_TestAllTypes_RepeatedGroup.Size(m)
+}
+func (m *TestAllTypes_RepeatedGroup) XXX_DiscardUnknown() {
+	xxx_messageInfo_TestAllTypes_RepeatedGroup.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_TestAllTypes_RepeatedGroup proto.InternalMessageInfo
+
+func (m *TestAllTypes_RepeatedGroup) GetA() int32 {
+	if m != nil && m.A != nil {
+		return *m.A
+	}
+	return 0
+}
+
+var E_OptionalInt32Extension = &proto.ExtensionDesc{
+	ExtendedType:  (*TestAllExtensions)(nil),
+	ExtensionType: (*int32)(nil),
+	Field:         1,
+	Name:          "goproto.proto.test.optional_int32_extension",
+	Tag:           "varint,1,opt,name=optional_int32_extension",
+	Filename:      "test.proto",
+}
+
+var E_OptionalInt64Extension = &proto.ExtensionDesc{
+	ExtendedType:  (*TestAllExtensions)(nil),
+	ExtensionType: (*int64)(nil),
+	Field:         2,
+	Name:          "goproto.proto.test.optional_int64_extension",
+	Tag:           "varint,2,opt,name=optional_int64_extension",
+	Filename:      "test.proto",
+}
+
+var E_OptionalUint32Extension = &proto.ExtensionDesc{
+	ExtendedType:  (*TestAllExtensions)(nil),
+	ExtensionType: (*uint32)(nil),
+	Field:         3,
+	Name:          "goproto.proto.test.optional_uint32_extension",
+	Tag:           "varint,3,opt,name=optional_uint32_extension",
+	Filename:      "test.proto",
+}
+
+var E_OptionalUint64Extension = &proto.ExtensionDesc{
+	ExtendedType:  (*TestAllExtensions)(nil),
+	ExtensionType: (*uint64)(nil),
+	Field:         4,
+	Name:          "goproto.proto.test.optional_uint64_extension",
+	Tag:           "varint,4,opt,name=optional_uint64_extension",
+	Filename:      "test.proto",
+}
+
+var E_OptionalSint32Extension = &proto.ExtensionDesc{
+	ExtendedType:  (*TestAllExtensions)(nil),
+	ExtensionType: (*int32)(nil),
+	Field:         5,
+	Name:          "goproto.proto.test.optional_sint32_extension",
+	Tag:           "zigzag32,5,opt,name=optional_sint32_extension",
+	Filename:      "test.proto",
+}
+
+var E_OptionalSint64Extension = &proto.ExtensionDesc{
+	ExtendedType:  (*TestAllExtensions)(nil),
+	ExtensionType: (*int64)(nil),
+	Field:         6,
+	Name:          "goproto.proto.test.optional_sint64_extension",
+	Tag:           "zigzag64,6,opt,name=optional_sint64_extension",
+	Filename:      "test.proto",
+}
+
+var E_OptionalFixed32Extension = &proto.ExtensionDesc{
+	ExtendedType:  (*TestAllExtensions)(nil),
+	ExtensionType: (*uint32)(nil),
+	Field:         7,
+	Name:          "goproto.proto.test.optional_fixed32_extension",
+	Tag:           "fixed32,7,opt,name=optional_fixed32_extension",
+	Filename:      "test.proto",
+}
+
+var E_OptionalFixed64Extension = &proto.ExtensionDesc{
+	ExtendedType:  (*TestAllExtensions)(nil),
+	ExtensionType: (*uint64)(nil),
+	Field:         8,
+	Name:          "goproto.proto.test.optional_fixed64_extension",
+	Tag:           "fixed64,8,opt,name=optional_fixed64_extension",
+	Filename:      "test.proto",
+}
+
+var E_OptionalSfixed32Extension = &proto.ExtensionDesc{
+	ExtendedType:  (*TestAllExtensions)(nil),
+	ExtensionType: (*int32)(nil),
+	Field:         9,
+	Name:          "goproto.proto.test.optional_sfixed32_extension",
+	Tag:           "fixed32,9,opt,name=optional_sfixed32_extension",
+	Filename:      "test.proto",
+}
+
+var E_OptionalSfixed64Extension = &proto.ExtensionDesc{
+	ExtendedType:  (*TestAllExtensions)(nil),
+	ExtensionType: (*int64)(nil),
+	Field:         10,
+	Name:          "goproto.proto.test.optional_sfixed64_extension",
+	Tag:           "fixed64,10,opt,name=optional_sfixed64_extension",
+	Filename:      "test.proto",
+}
+
+var E_OptionalFloatExtension = &proto.ExtensionDesc{
+	ExtendedType:  (*TestAllExtensions)(nil),
+	ExtensionType: (*float32)(nil),
+	Field:         11,
+	Name:          "goproto.proto.test.optional_float_extension",
+	Tag:           "fixed32,11,opt,name=optional_float_extension",
+	Filename:      "test.proto",
+}
+
+var E_OptionalDoubleExtension = &proto.ExtensionDesc{
+	ExtendedType:  (*TestAllExtensions)(nil),
+	ExtensionType: (*float64)(nil),
+	Field:         12,
+	Name:          "goproto.proto.test.optional_double_extension",
+	Tag:           "fixed64,12,opt,name=optional_double_extension",
+	Filename:      "test.proto",
+}
+
+var E_OptionalBoolExtension = &proto.ExtensionDesc{
+	ExtendedType:  (*TestAllExtensions)(nil),
+	ExtensionType: (*bool)(nil),
+	Field:         13,
+	Name:          "goproto.proto.test.optional_bool_extension",
+	Tag:           "varint,13,opt,name=optional_bool_extension",
+	Filename:      "test.proto",
+}
+
+var E_OptionalStringExtension = &proto.ExtensionDesc{
+	ExtendedType:  (*TestAllExtensions)(nil),
+	ExtensionType: (*string)(nil),
+	Field:         14,
+	Name:          "goproto.proto.test.optional_string_extension",
+	Tag:           "bytes,14,opt,name=optional_string_extension",
+	Filename:      "test.proto",
+}
+
+var E_OptionalBytesExtension = &proto.ExtensionDesc{
+	ExtendedType:  (*TestAllExtensions)(nil),
+	ExtensionType: ([]byte)(nil),
+	Field:         15,
+	Name:          "goproto.proto.test.optional_bytes_extension",
+	Tag:           "bytes,15,opt,name=optional_bytes_extension",
+	Filename:      "test.proto",
+}
+
+var E_OptionalgroupExtension = &proto.ExtensionDesc{
+	ExtendedType:  (*TestAllExtensions)(nil),
+	ExtensionType: (*OptionalGroupExtension)(nil),
+	Field:         16,
+	Name:          "goproto.proto.test.optionalgroup_extension",
+	Tag:           "group,16,opt,name=OptionalGroup_extension",
+	Filename:      "test.proto",
+}
+
+var E_OptionalNestedMessageExtension = &proto.ExtensionDesc{
+	ExtendedType:  (*TestAllExtensions)(nil),
+	ExtensionType: (*TestAllTypes_NestedMessage)(nil),
+	Field:         18,
+	Name:          "goproto.proto.test.optional_nested_message_extension",
+	Tag:           "bytes,18,opt,name=optional_nested_message_extension",
+	Filename:      "test.proto",
+}
+
+var E_OptionalNestedEnumExtension = &proto.ExtensionDesc{
+	ExtendedType:  (*TestAllExtensions)(nil),
+	ExtensionType: (*TestAllTypes_NestedEnum)(nil),
+	Field:         21,
+	Name:          "goproto.proto.test.optional_nested_enum_extension",
+	Tag:           "varint,21,opt,name=optional_nested_enum_extension,enum=goproto.proto.test.TestAllTypes_NestedEnum",
+	Filename:      "test.proto",
+}
+
+var E_RepeatedInt32Extension = &proto.ExtensionDesc{
+	ExtendedType:  (*TestAllExtensions)(nil),
+	ExtensionType: ([]int32)(nil),
+	Field:         31,
+	Name:          "goproto.proto.test.repeated_int32_extension",
+	Tag:           "varint,31,rep,name=repeated_int32_extension",
+	Filename:      "test.proto",
+}
+
+var E_RepeatedInt64Extension = &proto.ExtensionDesc{
+	ExtendedType:  (*TestAllExtensions)(nil),
+	ExtensionType: ([]int64)(nil),
+	Field:         32,
+	Name:          "goproto.proto.test.repeated_int64_extension",
+	Tag:           "varint,32,rep,name=repeated_int64_extension",
+	Filename:      "test.proto",
+}
+
+var E_RepeatedUint32Extension = &proto.ExtensionDesc{
+	ExtendedType:  (*TestAllExtensions)(nil),
+	ExtensionType: ([]uint32)(nil),
+	Field:         33,
+	Name:          "goproto.proto.test.repeated_uint32_extension",
+	Tag:           "varint,33,rep,name=repeated_uint32_extension",
+	Filename:      "test.proto",
+}
+
+var E_RepeatedUint64Extension = &proto.ExtensionDesc{
+	ExtendedType:  (*TestAllExtensions)(nil),
+	ExtensionType: ([]uint64)(nil),
+	Field:         34,
+	Name:          "goproto.proto.test.repeated_uint64_extension",
+	Tag:           "varint,34,rep,name=repeated_uint64_extension",
+	Filename:      "test.proto",
+}
+
+var E_RepeatedSint32Extension = &proto.ExtensionDesc{
+	ExtendedType:  (*TestAllExtensions)(nil),
+	ExtensionType: ([]int32)(nil),
+	Field:         35,
+	Name:          "goproto.proto.test.repeated_sint32_extension",
+	Tag:           "zigzag32,35,rep,name=repeated_sint32_extension",
+	Filename:      "test.proto",
+}
+
+var E_RepeatedSint64Extension = &proto.ExtensionDesc{
+	ExtendedType:  (*TestAllExtensions)(nil),
+	ExtensionType: ([]int64)(nil),
+	Field:         36,
+	Name:          "goproto.proto.test.repeated_sint64_extension",
+	Tag:           "zigzag64,36,rep,name=repeated_sint64_extension",
+	Filename:      "test.proto",
+}
+
+var E_RepeatedFixed32Extension = &proto.ExtensionDesc{
+	ExtendedType:  (*TestAllExtensions)(nil),
+	ExtensionType: ([]uint32)(nil),
+	Field:         37,
+	Name:          "goproto.proto.test.repeated_fixed32_extension",
+	Tag:           "fixed32,37,rep,name=repeated_fixed32_extension",
+	Filename:      "test.proto",
+}
+
+var E_RepeatedFixed64Extension = &proto.ExtensionDesc{
+	ExtendedType:  (*TestAllExtensions)(nil),
+	ExtensionType: ([]uint64)(nil),
+	Field:         38,
+	Name:          "goproto.proto.test.repeated_fixed64_extension",
+	Tag:           "fixed64,38,rep,name=repeated_fixed64_extension",
+	Filename:      "test.proto",
+}
+
+var E_RepeatedSfixed32Extension = &proto.ExtensionDesc{
+	ExtendedType:  (*TestAllExtensions)(nil),
+	ExtensionType: ([]int32)(nil),
+	Field:         39,
+	Name:          "goproto.proto.test.repeated_sfixed32_extension",
+	Tag:           "fixed32,39,rep,name=repeated_sfixed32_extension",
+	Filename:      "test.proto",
+}
+
+var E_RepeatedSfixed64Extension = &proto.ExtensionDesc{
+	ExtendedType:  (*TestAllExtensions)(nil),
+	ExtensionType: ([]int64)(nil),
+	Field:         40,
+	Name:          "goproto.proto.test.repeated_sfixed64_extension",
+	Tag:           "fixed64,40,rep,name=repeated_sfixed64_extension",
+	Filename:      "test.proto",
+}
+
+var E_RepeatedFloatExtension = &proto.ExtensionDesc{
+	ExtendedType:  (*TestAllExtensions)(nil),
+	ExtensionType: ([]float32)(nil),
+	Field:         41,
+	Name:          "goproto.proto.test.repeated_float_extension",
+	Tag:           "fixed32,41,rep,name=repeated_float_extension",
+	Filename:      "test.proto",
+}
+
+var E_RepeatedDoubleExtension = &proto.ExtensionDesc{
+	ExtendedType:  (*TestAllExtensions)(nil),
+	ExtensionType: ([]float64)(nil),
+	Field:         42,
+	Name:          "goproto.proto.test.repeated_double_extension",
+	Tag:           "fixed64,42,rep,name=repeated_double_extension",
+	Filename:      "test.proto",
+}
+
+var E_RepeatedBoolExtension = &proto.ExtensionDesc{
+	ExtendedType:  (*TestAllExtensions)(nil),
+	ExtensionType: ([]bool)(nil),
+	Field:         43,
+	Name:          "goproto.proto.test.repeated_bool_extension",
+	Tag:           "varint,43,rep,name=repeated_bool_extension",
+	Filename:      "test.proto",
+}
+
+var E_RepeatedStringExtension = &proto.ExtensionDesc{
+	ExtendedType:  (*TestAllExtensions)(nil),
+	ExtensionType: ([]string)(nil),
+	Field:         44,
+	Name:          "goproto.proto.test.repeated_string_extension",
+	Tag:           "bytes,44,rep,name=repeated_string_extension",
+	Filename:      "test.proto",
+}
+
+var E_RepeatedBytesExtension = &proto.ExtensionDesc{
+	ExtendedType:  (*TestAllExtensions)(nil),
+	ExtensionType: ([][]byte)(nil),
+	Field:         45,
+	Name:          "goproto.proto.test.repeated_bytes_extension",
+	Tag:           "bytes,45,rep,name=repeated_bytes_extension",
+	Filename:      "test.proto",
+}
+
+var E_RepeatedgroupExtension = &proto.ExtensionDesc{
+	ExtendedType:  (*TestAllExtensions)(nil),
+	ExtensionType: ([]*RepeatedGroupExtension)(nil),
+	Field:         46,
+	Name:          "goproto.proto.test.repeatedgroup_extension",
+	Tag:           "group,46,rep,name=RepeatedGroup_extension",
+	Filename:      "test.proto",
+}
+
+var E_RepeatedNestedMessageExtension = &proto.ExtensionDesc{
+	ExtendedType:  (*TestAllExtensions)(nil),
+	ExtensionType: ([]*TestAllTypes_NestedMessage)(nil),
+	Field:         48,
+	Name:          "goproto.proto.test.repeated_nested_message_extension",
+	Tag:           "bytes,48,rep,name=repeated_nested_message_extension",
+	Filename:      "test.proto",
+}
+
+var E_RepeatedNestedEnumExtension = &proto.ExtensionDesc{
+	ExtendedType:  (*TestAllExtensions)(nil),
+	ExtensionType: ([]TestAllTypes_NestedEnum)(nil),
+	Field:         51,
+	Name:          "goproto.proto.test.repeated_nested_enum_extension",
+	Tag:           "varint,51,rep,name=repeated_nested_enum_extension,enum=goproto.proto.test.TestAllTypes_NestedEnum",
+	Filename:      "test.proto",
+}
+
+func init() {
+	proto.RegisterFile("test.proto", fileDescriptor_c161fcfdc0c3ff1e)
+	proto.RegisterEnum("goproto.proto.test.TestAllTypes_NestedEnum", TestAllTypes_NestedEnum_name, TestAllTypes_NestedEnum_value)
+	proto.RegisterType((*TestAllTypes)(nil), "goproto.proto.test.TestAllTypes")
+	proto.RegisterMapType((map[bool]bool)(nil), "goproto.proto.test.TestAllTypes.MapBoolBoolEntry")
+	proto.RegisterMapType((map[uint32]uint32)(nil), "goproto.proto.test.TestAllTypes.MapFixed32Fixed32Entry")
+	proto.RegisterMapType((map[uint64]uint64)(nil), "goproto.proto.test.TestAllTypes.MapFixed64Fixed64Entry")
+	proto.RegisterMapType((map[int32]float64)(nil), "goproto.proto.test.TestAllTypes.MapInt32DoubleEntry")
+	proto.RegisterMapType((map[int32]float32)(nil), "goproto.proto.test.TestAllTypes.MapInt32FloatEntry")
+	proto.RegisterMapType((map[int32]int32)(nil), "goproto.proto.test.TestAllTypes.MapInt32Int32Entry")
+	proto.RegisterMapType((map[int64]int64)(nil), "goproto.proto.test.TestAllTypes.MapInt64Int64Entry")
+	proto.RegisterMapType((map[int32]int32)(nil), "goproto.proto.test.TestAllTypes.MapSfixed32Sfixed32Entry")
+	proto.RegisterMapType((map[int64]int64)(nil), "goproto.proto.test.TestAllTypes.MapSfixed64Sfixed64Entry")
+	proto.RegisterMapType((map[int32]int32)(nil), "goproto.proto.test.TestAllTypes.MapSint32Sint32Entry")
+	proto.RegisterMapType((map[int64]int64)(nil), "goproto.proto.test.TestAllTypes.MapSint64Sint64Entry")
+	proto.RegisterMapType((map[string][]byte)(nil), "goproto.proto.test.TestAllTypes.MapStringBytesEntry")
+	proto.RegisterMapType((map[string]TestAllTypes_NestedEnum)(nil), "goproto.proto.test.TestAllTypes.MapStringNestedEnumEntry")
+	proto.RegisterMapType((map[string]*TestAllTypes_NestedMessage)(nil), "goproto.proto.test.TestAllTypes.MapStringNestedMessageEntry")
+	proto.RegisterMapType((map[string]string)(nil), "goproto.proto.test.TestAllTypes.MapStringStringEntry")
+	proto.RegisterMapType((map[uint32]uint32)(nil), "goproto.proto.test.TestAllTypes.MapUint32Uint32Entry")
+	proto.RegisterMapType((map[uint64]uint64)(nil), "goproto.proto.test.TestAllTypes.MapUint64Uint64Entry")
+	proto.RegisterType((*TestAllExtensions)(nil), "goproto.proto.test.TestAllExtensions")
+	proto.RegisterType((*OptionalGroupExtension)(nil), "goproto.proto.test.OptionalGroup_extension")
+	proto.RegisterType((*RepeatedGroupExtension)(nil), "goproto.proto.test.RepeatedGroup_extension")
+	proto.RegisterType((*TestAllTypes_NestedMessage)(nil), "goproto.proto.test.TestAllTypes.NestedMessage")
+	proto.RegisterType((*TestAllTypes_OptionalGroup)(nil), "goproto.proto.test.TestAllTypes.OptionalGroup")
+	proto.RegisterType((*TestAllTypes_RepeatedGroup)(nil), "goproto.proto.test.TestAllTypes.RepeatedGroup")
+	proto.RegisterExtension(E_OptionalInt32Extension)
+	proto.RegisterExtension(E_OptionalInt64Extension)
+	proto.RegisterExtension(E_OptionalUint32Extension)
+	proto.RegisterExtension(E_OptionalUint64Extension)
+	proto.RegisterExtension(E_OptionalSint32Extension)
+	proto.RegisterExtension(E_OptionalSint64Extension)
+	proto.RegisterExtension(E_OptionalFixed32Extension)
+	proto.RegisterExtension(E_OptionalFixed64Extension)
+	proto.RegisterExtension(E_OptionalSfixed32Extension)
+	proto.RegisterExtension(E_OptionalSfixed64Extension)
+	proto.RegisterExtension(E_OptionalFloatExtension)
+	proto.RegisterExtension(E_OptionalDoubleExtension)
+	proto.RegisterExtension(E_OptionalBoolExtension)
+	proto.RegisterExtension(E_OptionalStringExtension)
+	proto.RegisterExtension(E_OptionalBytesExtension)
+	proto.RegisterExtension(E_OptionalgroupExtension)
+	proto.RegisterExtension(E_OptionalNestedMessageExtension)
+	proto.RegisterExtension(E_OptionalNestedEnumExtension)
+	proto.RegisterExtension(E_RepeatedInt32Extension)
+	proto.RegisterExtension(E_RepeatedInt64Extension)
+	proto.RegisterExtension(E_RepeatedUint32Extension)
+	proto.RegisterExtension(E_RepeatedUint64Extension)
+	proto.RegisterExtension(E_RepeatedSint32Extension)
+	proto.RegisterExtension(E_RepeatedSint64Extension)
+	proto.RegisterExtension(E_RepeatedFixed32Extension)
+	proto.RegisterExtension(E_RepeatedFixed64Extension)
+	proto.RegisterExtension(E_RepeatedSfixed32Extension)
+	proto.RegisterExtension(E_RepeatedSfixed64Extension)
+	proto.RegisterExtension(E_RepeatedFloatExtension)
+	proto.RegisterExtension(E_RepeatedDoubleExtension)
+	proto.RegisterExtension(E_RepeatedBoolExtension)
+	proto.RegisterExtension(E_RepeatedStringExtension)
+	proto.RegisterExtension(E_RepeatedBytesExtension)
+	proto.RegisterExtension(E_RepeatedgroupExtension)
+	proto.RegisterExtension(E_RepeatedNestedMessageExtension)
+	proto.RegisterExtension(E_RepeatedNestedEnumExtension)
+}
+
+var fileDescriptor_c161fcfdc0c3ff1e = []byte{
+	// 2008 bytes of a gzipped FileDescriptorProto
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x59, 0x6d, 0x53, 0xdb, 0xca,
+	0x15, 0x46, 0x88, 0xd7, 0x05, 0x83, 0x51, 0xc0, 0x16, 0x61, 0x92, 0x6c, 0x48, 0xd3, 0x28, 0x24,
+	0x35, 0x2d, 0xa8, 0x6a, 0x92, 0xa6, 0x69, 0x70, 0x81, 0x90, 0x99, 0x26, 0x99, 0x11, 0xc9, 0x97,
+	0x74, 0x52, 0xc6, 0x80, 0x70, 0x3d, 0xb5, 0x2d, 0xd7, 0x2f, 0x24, 0x7c, 0xe3, 0x7b, 0x7f, 0xc0,
+	0xfd, 0x7a, 0x7f, 0xd2, 0xfd, 0x47, 0xf7, 0xce, 0xee, 0xd1, 0xae, 0xf6, 0xac, 0xd7, 0x60, 0x29,
+	0x33, 0x31, 0xf6, 0xd1, 0xd1, 0xf3, 0xec, 0xae, 0xf6, 0xd9, 0xa3, 0xdd, 0x87, 0x90, 0x7e, 0xd4,
+	0xeb, 0x57, 0x3a, 0xdd, 0xb8, 0x1f, 0x3b, 0x4e, 0x3d, 0xe6, 0x5f, 0xe0, 0x67, 0x85, 0x5d, 0xd9,
+	0xfc, 0x65, 0x8b, 0x2c, 0x7e, 0x8e, 0x7a, 0xfd, 0xbd, 0x66, 0xf3, 0xf3, 0x55, 0x27, 0xea, 0x39,
+	0x8f, 0xc9, 0x52, 0xdc, 0xe9, 0x37, 0xe2, 0x76, 0xad, 0x79, 0xd2, 0x68, 0xf7, 0x77, 0x77, 0x5c,
+	0x8b, 0x5a, 0xde, 0x74, 0x58, 0x10, 0xd1, 0xf7, 0x2c, 0xa8, 0xa7, 0x05, 0xbe, 0x3b, 0x49, 0x2d,
+	0xcf, 0x46, 0x69, 0x81, 0xef, 0x3c, 0x21, 0xcb, 0x32, 0x6d, 0x00, 0x70, 0x36, 0xb5, 0xbc, 0x42,
+	0x28, 0xef, 0xfe, 0xc2, 0xa3, 0x43, 0x89, 0x81, 0xef, 0x4e, 0x51, 0xcb, 0x9b, 0xc2, 0x89, 0x1a,
+	0x62, 0x0f, 0x10, 0xa7, 0xa9, 0xe5, 0xad, 0xa4, 0x89, 0xc7, 0xc3, 0x88, 0x3d, 0x40, 0x9c, 0xa1,
+	0x96, 0xe7, 0xe0, 0xc4, 0xc0, 0x77, 0x9e, 0x92, 0xa2, 0x4c, 0xbc, 0x68, 0xfc, 0x88, 0xce, 0x77,
+	0x77, 0xdc, 0x59, 0x6a, 0x79, 0xb3, 0xa1, 0x04, 0x38, 0x84, 0xf0, 0x70, 0x6a, 0xe0, 0xbb, 0x73,
+	0xd4, 0xf2, 0x66, 0xb4, 0xd4, 0xc0, 0x77, 0x9e, 0x91, 0x95, 0x94, 0x5e, 0xc0, 0xce, 0x53, 0xcb,
+	0x5b, 0x0e, 0x25, 0xc6, 0x71, 0x12, 0x37, 0x24, 0x07, 0xbe, 0x4b, 0xa8, 0xe5, 0x15, 0xf5, 0xe4,
+	0xc0, 0x47, 0x43, 0x7f, 0xd1, 0x8c, 0x6b, 0x7d, 0x77, 0x81, 0x5a, 0xde, 0x64, 0x3a, 0xf4, 0x87,
+	0x2c, 0x88, 0xfa, 0x7f, 0x1e, 0x0f, 0x4e, 0x9b, 0x91, 0xbb, 0x48, 0x2d, 0xcf, 0x4a, 0xfb, 0xbf,
+	0xcf, 0xa3, 0xce, 0x23, 0x22, 0xef, 0x3c, 0x39, 0x8d, 0xe3, 0xa6, 0x5b, 0xa0, 0x96, 0x37, 0x17,
+	0x2e, 0x8a, 0x60, 0x35, 0x8e, 0x9b, 0x78, 0x34, 0xfb, 0xdd, 0x46, 0xbb, 0xee, 0x2e, 0x51, 0xcb,
+	0x9b, 0x57, 0x46, 0x93, 0x47, 0x51, 0xeb, 0x4e, 0xaf, 0xfa, 0x51, 0xcf, 0x5d, 0xa6, 0x96, 0xb7,
+	0x98, 0xb6, 0xae, 0xca, 0x82, 0xce, 0xe7, 0x94, 0xb4, 0xde, 0x8d, 0x07, 0x1d, 0xb7, 0x48, 0x2d,
+	0x8f, 0xec, 0x54, 0x2a, 0xc3, 0x73, 0xb4, 0xa2, 0xce, 0xcf, 0xca, 0xa7, 0xe4, 0xae, 0x77, 0xec,
+	0xae, 0x10, 0x83, 0x38, 0x17, 0xa4, 0x2c, 0xc9, 0xdb, 0x51, 0xaf, 0x1f, 0x9d, 0x9f, 0xb4, 0xa2,
+	0x5e, 0xaf, 0x56, 0x8f, 0x5c, 0x87, 0x5a, 0xde, 0xc2, 0x18, 0xf8, 0x1f, 0xf9, 0x6d, 0x1f, 0xe0,
+	0xae, 0x70, 0x4d, 0xc0, 0xa1, 0xb0, 0xf3, 0x8d, 0xac, 0xea, 0x3c, 0x51, 0x7b, 0xd0, 0x72, 0xd7,
+	0xa8, 0xe5, 0x2d, 0xed, 0x3c, 0x1b, 0x93, 0xe4, 0xa0, 0x3d, 0x68, 0x85, 0x0e, 0x66, 0x60, 0x31,
+	0x36, 0x86, 0xdd, 0xa8, 0x13, 0xd5, 0x18, 0x2e, 0x4c, 0xf1, 0x07, 0xd4, 0x66, 0x1a, 0x14, 0x51,
+	0xa9, 0x41, 0x35, 0x2d, 0xf0, 0x5d, 0x4a, 0x6d, 0xa6, 0x41, 0x25, 0x0d, 0x14, 0x23, 0xd3, 0x12,
+	0x0d, 0x3e, 0xa4, 0x36, 0xd3, 0xa0, 0x08, 0xa7, 0x1a, 0x44, 0x89, 0x81, 0xef, 0x6e, 0x52, 0x9b,
+	0x69, 0x50, 0x4d, 0xd4, 0x10, 0x13, 0x0d, 0x3e, 0xa2, 0x36, 0xd3, 0xa0, 0x08, 0x1f, 0x0f, 0x23,
+	0x26, 0x1a, 0xfc, 0x1d, 0xb5, 0x99, 0x06, 0xd5, 0x44, 0xd0, 0xa0, 0x4c, 0x14, 0x62, 0x79, 0x4c,
+	0x6d, 0xa6, 0x41, 0x11, 0x57, 0x34, 0x88, 0x53, 0x03, 0xdf, 0xfd, 0x3d, 0xb5, 0x99, 0x06, 0x51,
+	0x2a, 0x68, 0x30, 0xa5, 0x17, 0xb0, 0x4f, 0xa8, 0xcd, 0x34, 0x28, 0x1b, 0xa0, 0x68, 0x50, 0x4b,
+	0x0e, 0x7c, 0xd7, 0xa3, 0x36, 0xd3, 0x20, 0x4e, 0x06, 0x0d, 0xa6, 0x8d, 0xe0, 0x1a, 0x7c, 0x4a,
+	0x6d, 0xa6, 0x41, 0xd9, 0x04, 0xa1, 0x41, 0x99, 0x96, 0x68, 0x70, 0x8b, 0xda, 0x4c, 0x83, 0x22,
+	0x9c, 0x6a, 0x50, 0x26, 0x72, 0x0d, 0x3e, 0xa3, 0x36, 0xd3, 0xa0, 0x08, 0x0a, 0x0d, 0xa6, 0x2d,
+	0x04, 0x0d, 0x3e, 0xa7, 0x36, 0xd3, 0xa0, 0x6c, 0x9f, 0xd4, 0x60, 0x8a, 0xc6, 0x35, 0xf8, 0x07,
+	0x6a, 0x33, 0x0d, 0x4a, 0x38, 0xa1, 0x41, 0x11, 0x00, 0x0d, 0x56, 0xa8, 0x3d, 0x96, 0x06, 0xc3,
+	0xe4, 0xae, 0x44, 0x83, 0x08, 0x84, 0x69, 0x50, 0x92, 0x6b, 0x1a, 0xfc, 0x23, 0xb5, 0xf3, 0x68,
+	0x50, 0xc0, 0x0d, 0x69, 0x50, 0xe7, 0xe1, 0x1a, 0xdc, 0xa5, 0x76, 0x66, 0x0d, 0x62, 0x06, 0xae,
+	0xc1, 0x7f, 0x91, 0xe5, 0x56, 0xad, 0x03, 0xf2, 0x4b, 0x44, 0xf8, 0x82, 0x37, 0x7f, 0xf7, 0x56,
+	0xe4, 0x0f, 0xb5, 0x0e, 0x17, 0x28, 0xff, 0x38, 0x68, 0xf7, 0xbb, 0x57, 0x61, 0xa1, 0xa5, 0xc6,
+	0x14, 0xf0, 0xc0, 0x4f, 0xa4, 0xfb, 0x32, 0x13, 0x78, 0xe0, 0xf3, 0x0f, 0x04, 0x9e, 0xc4, 0x9c,
+	0x1a, 0x59, 0x61, 0xe0, 0x20, 0x75, 0xa1, 0xf8, 0x57, 0x1c, 0xfe, 0xcf, 0xe3, 0xc0, 0xc3, 0x6a,
+	0x00, 0x9f, 0x40, 0xc0, 0x1a, 0xab, 0x46, 0x55, 0x8a, 0xc0, 0x17, 0x6b, 0xc5, 0x5f, 0xb3, 0x51,
+	0x04, 0x3e, 0x7c, 0x62, 0x0a, 0x11, 0x15, 0x14, 0xb0, 0xbc, 0x88, 0x55, 0xe6, 0xf5, 0xf8, 0x14,
+	0xb0, 0x02, 0x1d, 0x6b, 0xbd, 0x50, 0xa3, 0x2a, 0x45, 0xe0, 0x8b, 0xf5, 0xe9, 0x6f, 0xd9, 0x28,
+	0x02, 0xff, 0x58, 0xeb, 0x85, 0x1a, 0x75, 0xea, 0xe4, 0x0e, 0xa3, 0x48, 0xd6, 0x18, 0xb9, 0xb4,
+	0xbd, 0xe1, 0x24, 0x7f, 0x19, 0x87, 0x24, 0x59, 0xf6, 0x92, 0x3f, 0x40, 0xc3, 0x9a, 0x8d, 0xe3,
+	0x88, 0x28, 0xf0, 0xe5, 0xc2, 0xf8, 0xf7, 0x8c, 0x44, 0x81, 0x9f, 0xfc, 0xd1, 0x88, 0x64, 0xdc,
+	0x69, 0x91, 0x35, 0x3e, 0x68, 0xa2, 0x4b, 0x72, 0x5d, 0x7d, 0xcb, 0xa9, 0x5e, 0x8e, 0x35, 0x70,
+	0xc9, 0x3d, 0xe2, 0x2f, 0x90, 0xb1, 0x0e, 0xe8, 0x57, 0x30, 0x1d, 0x7b, 0x4a, 0xa2, 0x67, 0x7b,
+	0x59, 0xe9, 0x02, 0x5f, 0xfc, 0xd5, 0xe9, 0xd2, 0x2b, 0x58, 0xf5, 0xb0, 0xb0, 0x57, 0x33, 0xaa,
+	0x9e, 0xaf, 0xfc, 0x9a, 0xea, 0xa1, 0x1a, 0xfc, 0x9b, 0x14, 0x53, 0xf0, 0xa4, 0x1c, 0xfc, 0x83,
+	0xa3, 0xfb, 0x63, 0xa3, 0x43, 0xbd, 0x00, 0xf8, 0xa5, 0x16, 0x0a, 0x3a, 0x5f, 0x08, 0x23, 0xe4,
+	0xf5, 0x03, 0x8a, 0xc8, 0x3e, 0x07, 0xff, 0xd3, 0x38, 0xe0, 0xac, 0xc0, 0xb0, 0xff, 0x80, 0xbc,
+	0xd0, 0x4a, 0x23, 0x52, 0x26, 0xbc, 0xb6, 0x88, 0xc2, 0x73, 0x90, 0x41, 0x26, 0xfc, 0x0e, 0xf8,
+	0x54, 0x64, 0xa2, 0x44, 0xc5, 0xc8, 0x24, 0x14, 0x50, 0xb2, 0x0e, 0xc7, 0x1f, 0x19, 0x40, 0xe1,
+	0x45, 0x2d, 0x1d, 0x19, 0x25, 0xe8, 0x7c, 0x27, 0xeb, 0x0a, 0xbe, 0x56, 0x95, 0xde, 0x71, 0xa2,
+	0xd7, 0xe3, 0x13, 0xa1, 0x3a, 0x04, 0x84, 0xa5, 0x96, 0xf1, 0xa2, 0xd3, 0x26, 0xa5, 0x61, 0x62,
+	0x5e, 0xa6, 0xde, 0x67, 0x98, 0xbf, 0x0a, 0x30, 0xab, 0x4d, 0xca, 0xfc, 0xd5, 0xae, 0x38, 0x8f,
+	0xc8, 0x62, 0xdc, 0x8e, 0xe2, 0x0b, 0xb1, 0xec, 0xc7, 0x6c, 0xb3, 0x75, 0x34, 0x11, 0x2e, 0xf0,
+	0x68, 0xb2, 0x7a, 0x9f, 0x92, 0x55, 0x48, 0xd2, 0x06, 0xa2, 0x93, 0xe7, 0x15, 0xf9, 0x68, 0x22,
+	0x74, 0x38, 0x1a, 0xee, 0xb8, 0x6c, 0x48, 0x32, 0x5f, 0xfe, 0xc7, 0x36, 0x0b, 0xb2, 0x21, 0xc9,
+	0x63, 0x7f, 0x48, 0xe0, 0x67, 0xf2, 0xc4, 0xbb, 0x6c, 0xa3, 0x70, 0x34, 0x11, 0x12, 0x1e, 0x84,
+	0x27, 0xf7, 0x80, 0x90, 0x24, 0x85, 0x4d, 0xe8, 0x1e, 0xdb, 0x99, 0x1c, 0x4d, 0x84, 0xf3, 0x90,
+	0xc1, 0x66, 0x27, 0xea, 0x71, 0xe0, 0xbb, 0x7d, 0xb6, 0x6b, 0x44, 0x3d, 0x0e, 0xfc, 0x94, 0x08,
+	0x24, 0x3d, 0x60, 0xfb, 0x25, 0x49, 0x04, 0xe2, 0x94, 0x38, 0x89, 0x30, 0x2f, 0xd9, 0x5e, 0x49,
+	0xe2, 0x24, 0x0a, 0xfb, 0xa7, 0x68, 0x0d, 0x7f, 0x84, 0xdf, 0x33, 0xbf, 0xed, 0xcb, 0xa6, 0xb3,
+	0x1f, 0x77, 0x6b, 0xa4, 0x80, 0x07, 0x6d, 0x91, 0x58, 0xb5, 0x64, 0xbb, 0x6d, 0xd5, 0x9c, 0x2a,
+	0x59, 0x38, 0x8b, 0xbb, 0xd1, 0xd9, 0xa0, 0xdb, 0x6b, 0x5c, 0x46, 0x7c, 0x7f, 0xbd, 0xb0, 0x43,
+	0x6f, 0x63, 0x0b, 0xd5, 0x9b, 0xee, 0xde, 0x23, 0x05, 0xb4, 0x61, 0x02, 0x8a, 0x95, 0x84, 0x82,
+	0x5d, 0x46, 0xef, 0x72, 0x70, 0x79, 0x5b, 0x5c, 0x7e, 0x4b, 0x9c, 0xe1, 0x77, 0x19, 0xa7, 0x48,
+	0xec, 0xff, 0x46, 0x57, 0x49, 0x3b, 0xd9, 0x57, 0x67, 0x95, 0x4c, 0x5f, 0xd6, 0x9a, 0x03, 0x68,
+	0xe3, 0x74, 0x08, 0x3f, 0x5e, 0x4d, 0xbe, 0xb0, 0x52, 0x04, 0xf5, 0x85, 0x45, 0x45, 0xb0, 0x0d,
+	0x08, 0xb6, 0x8a, 0x50, 0x25, 0xab, 0xa6, 0x77, 0x12, 0x15, 0xa3, 0x60, 0xc0, 0x28, 0x98, 0x31,
+	0xd0, 0x4b, 0x87, 0x8a, 0x31, 0x65, 0xc0, 0x98, 0x1a, 0xc6, 0x18, 0x7a, 0xab, 0x50, 0x31, 0x56,
+	0x0c, 0x18, 0x2b, 0x66, 0x0c, 0xf4, 0xda, 0xa0, 0x62, 0x38, 0x06, 0x0c, 0x47, 0xc5, 0xd8, 0x27,
+	0x25, 0xf3, 0x5b, 0x81, 0x8a, 0x32, 0x6b, 0x40, 0x99, 0x1d, 0x81, 0x82, 0x4b, 0xbe, 0x8a, 0x32,
+	0x63, 0x40, 0x99, 0x51, 0x51, 0x0e, 0x89, 0x3b, 0xaa, 0x9a, 0xab, 0x38, 0xcb, 0x06, 0x9c, 0xe5,
+	0x51, 0x38, 0x5a, 0x99, 0x56, 0x71, 0x8a, 0x06, 0x9c, 0xa2, 0x71, 0xb6, 0xa9, 0x55, 0xf8, 0xb6,
+	0xf9, 0x3a, 0xa9, 0x22, 0xec, 0x91, 0x3b, 0x86, 0x4a, 0x7b, 0x1b, 0x84, 0xa5, 0x42, 0xbc, 0x21,
+	0x45, 0xbd, 0x9e, 0xaa, 0xf7, 0xcf, 0x19, 0xee, 0x9f, 0x33, 0x4c, 0x12, 0xbd, 0x68, 0xaa, 0x18,
+	0xf3, 0x06, 0x8c, 0xf9, 0xe1, 0x6e, 0xe8, 0x65, 0xf1, 0x36, 0x88, 0x45, 0x15, 0xe2, 0x8a, 0x6c,
+	0xdc, 0x50, 0xf0, 0x0c, 0x50, 0xfb, 0x2a, 0x54, 0xf6, 0x5d, 0x9e, 0x42, 0xdd, 0x83, 0xe9, 0x60,
+	0xaa, 0x7a, 0x06, 0xde, 0x3d, 0x95, 0x37, 0xe3, 0xc6, 0x2f, 0x25, 0xdd, 0x7c, 0x49, 0x88, 0x52,
+	0x47, 0x67, 0x89, 0x7d, 0xf8, 0xe9, 0x53, 0x71, 0x82, 0x7d, 0xa9, 0xee, 0x85, 0x45, 0x0b, 0xbe,
+	0x7c, 0x2d, 0x4e, 0xb2, 0x16, 0x7c, 0x3c, 0x78, 0x57, 0xfc, 0x55, 0xfc, 0xb3, 0xaa, 0x05, 0x59,
+	0x5d, 0x1a, 0x51, 0xf3, 0x7c, 0xf3, 0x1e, 0x59, 0x49, 0xf8, 0x0e, 0x7e, 0xf4, 0xa3, 0x76, 0xaf,
+	0x11, 0xb7, 0x7b, 0x5b, 0x73, 0x73, 0x56, 0xf1, 0xfa, 0xfa, 0xfa, 0x7a, 0x72, 0xf3, 0x09, 0x29,
+	0xa3, 0x25, 0xf9, 0x24, 0x12, 0x59, 0x78, 0x71, 0x66, 0x89, 0x68, 0x71, 0xd6, 0x13, 0xc5, 0x32,
+	0xfd, 0xea, 0x84, 0xb8, 0xf8, 0xc8, 0x56, 0xc9, 0x7c, 0x7c, 0xc3, 0x70, 0xa4, 0xcd, 0x4b, 0x66,
+	0x76, 0x09, 0x9d, 0xf1, 0xca, 0xcb, 0x3a, 0x41, 0xe0, 0x67, 0x27, 0x80, 0x75, 0xbd, 0x84, 0x4e,
+	0x87, 0x53, 0x82, 0x1a, 0x59, 0xd7, 0x8e, 0x89, 0xb3, 0x33, 0xc0, 0xb9, 0x72, 0x19, 0x9f, 0x2b,
+	0x8f, 0xa6, 0xc8, 0xd3, 0x09, 0x38, 0x91, 0x2e, 0xe3, 0x13, 0x69, 0x33, 0x45, 0x2f, 0x67, 0x2f,
+	0xe0, 0x2c, 0xbb, 0x8c, 0xcf, 0xb2, 0x47, 0x53, 0xe4, 0xe9, 0x05, 0x9c, 0x82, 0x97, 0xf1, 0x29,
+	0x78, 0x4a, 0x71, 0x46, 0xee, 0xea, 0xc7, 0xe1, 0xd9, 0x39, 0xe0, 0xfc, 0xdc, 0xd5, 0xce, 0xcf,
+	0x6f, 0x20, 0xc9, 0xd3, 0x11, 0x38, 0x79, 0x77, 0xb5, 0x93, 0xf7, 0x94, 0x24, 0x22, 0x1b, 0x43,
+	0x47, 0xf0, 0xd9, 0x59, 0xe0, 0xcc, 0x7e, 0x5d, 0x3f, 0xb3, 0xbf, 0x89, 0x26, 0x4f, 0x67, 0xe0,
+	0xb4, 0x7f, 0x5d, 0x3f, 0xed, 0x37, 0x8b, 0x90, 0xbf, 0xc6, 0x66, 0xe7, 0x00, 0x9f, 0xa0, 0x84,
+	0x7c, 0x02, 0xf3, 0xdc, 0x82, 0x97, 0xe0, 0xec, 0x0c, 0xe0, 0x30, 0x94, 0xb1, 0xc3, 0x90, 0x52,
+	0x7c, 0x53, 0xce, 0xe7, 0xf9, 0x36, 0x35, 0x33, 0x01, 0x78, 0x13, 0x6b, 0xaa, 0x37, 0x31, 0x42,
+	0x1d, 0xb0, 0xe5, 0xca, 0x4c, 0x00, 0xae, 0x46, 0x19, 0xbb, 0x1a, 0xe6, 0xa7, 0xc0, 0x77, 0x2d,
+	0xd9, 0x19, 0xc0, 0x0f, 0x29, 0x21, 0x3f, 0x24, 0x25, 0xf8, 0xbf, 0x95, 0x8e, 0x51, 0x5d, 0x5b,
+	0xf6, 0xc7, 0x24, 0x00, 0x2b, 0xc5, 0x58, 0x08, 0x47, 0x54, 0x9e, 0xb4, 0x35, 0x9c, 0x32, 0x6d,
+	0xcd, 0xcf, 0x16, 0x79, 0x38, 0xc2, 0x51, 0xc9, 0xde, 0xae, 0x7c, 0x16, 0xcc, 0x7d, 0xa3, 0x05,
+	0x93, 0x36, 0xf1, 0x27, 0x8b, 0xdc, 0x37, 0x99, 0x31, 0xd9, 0xdb, 0x97, 0xc3, 0xbd, 0xd9, 0x18,
+	0x76, 0x6f, 0xd0, 0x5c, 0xc1, 0x36, 0x4e, 0xf6, 0x26, 0x81, 0xef, 0x53, 0x42, 0xbe, 0xcf, 0x48,
+	0x82, 0x3c, 0xcb, 0x0e, 0x38, 0x46, 0x25, 0xe4, 0x18, 0x21, 0x41, 0x69, 0xd6, 0x51, 0x76, 0x06,
+	0xf0, 0x9a, 0xca, 0xd8, 0x6b, 0x1a, 0x4d, 0x91, 0xa7, 0x13, 0xe0, 0x52, 0x95, 0xb1, 0x4b, 0x65,
+	0xa6, 0xc8, 0x5b, 0x97, 0xc1, 0xdf, 0x2a, 0x63, 0x7f, 0x6b, 0x34, 0x45, 0x9e, 0x5e, 0x80, 0x33,
+	0x56, 0xc6, 0xce, 0x18, 0x2a, 0x99, 0xba, 0x45, 0x96, 0x9d, 0x03, 0x3c, 0x35, 0x57, 0xf3, 0xd4,
+	0x6e, 0x20, 0xc9, 0xd3, 0x11, 0x70, 0xe3, 0x5c, 0xcd, 0x8d, 0x43, 0x05, 0x73, 0xc8, 0x96, 0xcb,
+	0xce, 0x02, 0x3e, 0xde, 0xba, 0xee, 0xe3, 0xdd, 0x44, 0x93, 0xa7, 0x33, 0xe0, 0x00, 0xae, 0xeb,
+	0x0e, 0xa0, 0x59, 0x84, 0x39, 0xeb, 0x32, 0x78, 0x87, 0x25, 0xe4, 0x1d, 0x9a, 0xe7, 0x56, 0xde,
+	0xba, 0x0c, 0xae, 0x63, 0x19, 0xbb, 0x8e, 0xa8, 0x2e, 0x23, 0xfb, 0x31, 0x3b, 0x01, 0xf8, 0x95,
+	0x6b, 0xaa, 0x5f, 0x39, 0x42, 0x1d, 0x39, 0xeb, 0x32, 0x38, 0x9d, 0x65, 0xec, 0x74, 0x9a, 0x9f,
+	0x42, 0xce, 0xba, 0x0c, 0x1e, 0x69, 0x09, 0x79, 0xa4, 0xb8, 0x2e, 0x23, 0xa3, 0x33, 0x3b, 0x01,
+	0xd8, 0xab, 0xc6, 0xfa, 0x32, 0x62, 0xa3, 0x97, 0xb6, 0xc6, 0x50, 0x97, 0x47, 0xb8, 0xac, 0xd9,
+	0xdb, 0x95, 0xcf, 0x96, 0xbd, 0x6f, 0xb4, 0x65, 0x71, 0x5d, 0x36, 0x19, 0xb4, 0xd9, 0xdb, 0x97,
+	0xc3, 0xd1, 0xdd, 0x18, 0x76, 0x74, 0x25, 0x60, 0xf5, 0xf9, 0xd7, 0xad, 0x7a, 0xa3, 0xff, 0x9f,
+	0xc1, 0x69, 0xe5, 0x2c, 0x6e, 0x6d, 0xd7, 0xe3, 0x66, 0xad, 0x5d, 0xdf, 0xe6, 0xa0, 0xa7, 0x83,
+	0x8b, 0xed, 0xcb, 0x1d, 0xf8, 0xbe, 0xcd, 0x08, 0x3a, 0xa7, 0xbf, 0x05, 0x00, 0x00, 0xff, 0xff,
+	0x98, 0xed, 0x53, 0x5d, 0x42, 0x25, 0x00, 0x00,
+}
+
+func init() {
+	xxx_Test_ProtoFile_FileDesc.Messages = xxx_Test_ProtoFile_MessageDescs[0:4]
+	xxx_Test_ProtoFile_MessageDescs[0].Enums = xxx_Test_ProtoFile_EnumDescs[0:1]
+	xxx_Test_ProtoFile_MessageDescs[0].Messages = xxx_Test_ProtoFile_MessageDescs[4:24]
+	xxx_Test_ProtoFile_MessageDescs[0].Fields[15].MessageType = xxx_Test_ProtoFile_MessageTypes[5].Type
+	xxx_Test_ProtoFile_MessageDescs[0].Fields[16].MessageType = xxx_Test_ProtoFile_MessageTypes[4].Type
+	xxx_Test_ProtoFile_MessageDescs[0].Fields[17].EnumType = xxx_Test_ProtoFile_EnumTypes[0]
+	xxx_Test_ProtoFile_MessageDescs[0].Fields[33].MessageType = xxx_Test_ProtoFile_MessageTypes[6].Type
+	xxx_Test_ProtoFile_MessageDescs[0].Fields[34].MessageType = xxx_Test_ProtoFile_MessageTypes[4].Type
+	xxx_Test_ProtoFile_MessageDescs[0].Fields[35].EnumType = xxx_Test_ProtoFile_EnumTypes[0]
+	xxx_Test_ProtoFile_MessageDescs[0].Fields[36].MessageType = xxx_Test_ProtoFile_MessageDescs[7].Reference()
+	xxx_Test_ProtoFile_MessageDescs[0].Fields[37].MessageType = xxx_Test_ProtoFile_MessageDescs[8].Reference()
+	xxx_Test_ProtoFile_MessageDescs[0].Fields[38].MessageType = xxx_Test_ProtoFile_MessageDescs[9].Reference()
+	xxx_Test_ProtoFile_MessageDescs[0].Fields[39].MessageType = xxx_Test_ProtoFile_MessageDescs[10].Reference()
+	xxx_Test_ProtoFile_MessageDescs[0].Fields[40].MessageType = xxx_Test_ProtoFile_MessageDescs[11].Reference()
+	xxx_Test_ProtoFile_MessageDescs[0].Fields[41].MessageType = xxx_Test_ProtoFile_MessageDescs[12].Reference()
+	xxx_Test_ProtoFile_MessageDescs[0].Fields[42].MessageType = xxx_Test_ProtoFile_MessageDescs[13].Reference()
+	xxx_Test_ProtoFile_MessageDescs[0].Fields[43].MessageType = xxx_Test_ProtoFile_MessageDescs[14].Reference()
+	xxx_Test_ProtoFile_MessageDescs[0].Fields[44].MessageType = xxx_Test_ProtoFile_MessageDescs[15].Reference()
+	xxx_Test_ProtoFile_MessageDescs[0].Fields[45].MessageType = xxx_Test_ProtoFile_MessageDescs[16].Reference()
+	xxx_Test_ProtoFile_MessageDescs[0].Fields[46].MessageType = xxx_Test_ProtoFile_MessageDescs[17].Reference()
+	xxx_Test_ProtoFile_MessageDescs[0].Fields[47].MessageType = xxx_Test_ProtoFile_MessageDescs[18].Reference()
+	xxx_Test_ProtoFile_MessageDescs[0].Fields[48].MessageType = xxx_Test_ProtoFile_MessageDescs[19].Reference()
+	xxx_Test_ProtoFile_MessageDescs[0].Fields[49].MessageType = xxx_Test_ProtoFile_MessageDescs[20].Reference()
+	xxx_Test_ProtoFile_MessageDescs[0].Fields[50].MessageType = xxx_Test_ProtoFile_MessageDescs[21].Reference()
+	xxx_Test_ProtoFile_MessageDescs[0].Fields[51].MessageType = xxx_Test_ProtoFile_MessageDescs[22].Reference()
+	xxx_Test_ProtoFile_MessageDescs[0].Fields[52].MessageType = xxx_Test_ProtoFile_MessageDescs[23].Reference()
+	xxx_Test_ProtoFile_MessageDescs[0].Fields[54].MessageType = xxx_Test_ProtoFile_MessageTypes[4].Type
+	xxx_Test_ProtoFile_MessageDescs[0].Fields[61].EnumType = xxx_Test_ProtoFile_EnumTypes[0]
+	xxx_Test_ProtoFile_MessageDescs[4].Fields[1].MessageType = xxx_Test_ProtoFile_MessageTypes[0].Type
+	xxx_Test_ProtoFile_MessageDescs[22].Fields[1].MessageType = xxx_Test_ProtoFile_MessageTypes[4].Type
+	xxx_Test_ProtoFile_MessageDescs[23].Fields[1].EnumType = xxx_Test_ProtoFile_EnumTypes[0]
+	var err error
+	Test_ProtoFile, err = prototype.NewFile(&xxx_Test_ProtoFile_FileDesc)
+	if err != nil {
+		panic(err)
+	}
+}
+
+const _ = protoimpl.EnforceVersion(protoimpl.Version - 0)
+
+var Test_ProtoFile protoreflect.FileDescriptor
+
+var xxx_Test_ProtoFile_FileDesc = prototype.File{
+	Syntax:  protoreflect.Proto2,
+	Path:    "test.proto",
+	Package: "goproto.proto.test",
+}
+var xxx_Test_ProtoFile_EnumTypes = [1]protoreflect.EnumType{
+	prototype.GoEnum(
+		xxx_Test_ProtoFile_EnumDescs[0].Reference(),
+		func(_ protoreflect.EnumType, n protoreflect.EnumNumber) protoreflect.ProtoEnum {
+			return TestAllTypes_NestedEnum(n)
+		},
+	),
+}
+var xxx_Test_ProtoFile_EnumDescs = [1]prototype.Enum{
+	{
+		Name: "NestedEnum",
+		Values: []prototype.EnumValue{
+			{Name: "FOO", Number: 0},
+			{Name: "BAR", Number: 1},
+			{Name: "BAZ", Number: 2},
+			{Name: "NEG", Number: -1},
+		},
+	},
+}
+var xxx_Test_ProtoFile_MessageTypes = [24]protoimpl.MessageType{
+	{Type: prototype.GoMessage(
+		xxx_Test_ProtoFile_MessageDescs[0].Reference(),
+		func(protoreflect.MessageType) protoreflect.ProtoMessage {
+			return new(TestAllTypes)
+		},
+	)},
+	{Type: prototype.GoMessage(
+		xxx_Test_ProtoFile_MessageDescs[1].Reference(),
+		func(protoreflect.MessageType) protoreflect.ProtoMessage {
+			return new(TestAllExtensions)
+		},
+	)},
+	{Type: prototype.GoMessage(
+		xxx_Test_ProtoFile_MessageDescs[2].Reference(),
+		func(protoreflect.MessageType) protoreflect.ProtoMessage {
+			return new(OptionalGroupExtension)
+		},
+	)},
+	{Type: prototype.GoMessage(
+		xxx_Test_ProtoFile_MessageDescs[3].Reference(),
+		func(protoreflect.MessageType) protoreflect.ProtoMessage {
+			return new(RepeatedGroupExtension)
+		},
+	)},
+	{Type: prototype.GoMessage(
+		xxx_Test_ProtoFile_MessageDescs[4].Reference(),
+		func(protoreflect.MessageType) protoreflect.ProtoMessage {
+			return new(TestAllTypes_NestedMessage)
+		},
+	)},
+	{Type: prototype.GoMessage(
+		xxx_Test_ProtoFile_MessageDescs[5].Reference(),
+		func(protoreflect.MessageType) protoreflect.ProtoMessage {
+			return new(TestAllTypes_OptionalGroup)
+		},
+	)},
+	{Type: prototype.GoMessage(
+		xxx_Test_ProtoFile_MessageDescs[6].Reference(),
+		func(protoreflect.MessageType) protoreflect.ProtoMessage {
+			return new(TestAllTypes_RepeatedGroup)
+		},
+	)},
+	{ /* no message type for TestAllTypes_MapInt32Int32Entry */ },
+	{ /* no message type for TestAllTypes_MapInt64Int64Entry */ },
+	{ /* no message type for TestAllTypes_MapUint32Uint32Entry */ },
+	{ /* no message type for TestAllTypes_MapUint64Uint64Entry */ },
+	{ /* no message type for TestAllTypes_MapSint32Sint32Entry */ },
+	{ /* no message type for TestAllTypes_MapSint64Sint64Entry */ },
+	{ /* no message type for TestAllTypes_MapFixed32Fixed32Entry */ },
+	{ /* no message type for TestAllTypes_MapFixed64Fixed64Entry */ },
+	{ /* no message type for TestAllTypes_MapSfixed32Sfixed32Entry */ },
+	{ /* no message type for TestAllTypes_MapSfixed64Sfixed64Entry */ },
+	{ /* no message type for TestAllTypes_MapInt32FloatEntry */ },
+	{ /* no message type for TestAllTypes_MapInt32DoubleEntry */ },
+	{ /* no message type for TestAllTypes_MapBoolBoolEntry */ },
+	{ /* no message type for TestAllTypes_MapStringStringEntry */ },
+	{ /* no message type for TestAllTypes_MapStringBytesEntry */ },
+	{ /* no message type for TestAllTypes_MapStringNestedMessageEntry */ },
+	{ /* no message type for TestAllTypes_MapStringNestedEnumEntry */ },
+}
+var xxx_Test_ProtoFile_MessageDescs = [24]prototype.Message{
+	{
+		Name: "TestAllTypes",
+		Fields: []prototype.Field{
+			{
+				Name:        "optional_int32",
+				Number:      1,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.Int32Kind,
+				JSONName:    "optionalInt32",
+				IsPacked:    prototype.False,
+			},
+			{
+				Name:        "optional_int64",
+				Number:      2,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.Int64Kind,
+				JSONName:    "optionalInt64",
+				IsPacked:    prototype.False,
+			},
+			{
+				Name:        "optional_uint32",
+				Number:      3,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.Uint32Kind,
+				JSONName:    "optionalUint32",
+				IsPacked:    prototype.False,
+			},
+			{
+				Name:        "optional_uint64",
+				Number:      4,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.Uint64Kind,
+				JSONName:    "optionalUint64",
+				IsPacked:    prototype.False,
+			},
+			{
+				Name:        "optional_sint32",
+				Number:      5,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.Sint32Kind,
+				JSONName:    "optionalSint32",
+				IsPacked:    prototype.False,
+			},
+			{
+				Name:        "optional_sint64",
+				Number:      6,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.Sint64Kind,
+				JSONName:    "optionalSint64",
+				IsPacked:    prototype.False,
+			},
+			{
+				Name:        "optional_fixed32",
+				Number:      7,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.Fixed32Kind,
+				JSONName:    "optionalFixed32",
+				IsPacked:    prototype.False,
+			},
+			{
+				Name:        "optional_fixed64",
+				Number:      8,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.Fixed64Kind,
+				JSONName:    "optionalFixed64",
+				IsPacked:    prototype.False,
+			},
+			{
+				Name:        "optional_sfixed32",
+				Number:      9,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.Sfixed32Kind,
+				JSONName:    "optionalSfixed32",
+				IsPacked:    prototype.False,
+			},
+			{
+				Name:        "optional_sfixed64",
+				Number:      10,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.Sfixed64Kind,
+				JSONName:    "optionalSfixed64",
+				IsPacked:    prototype.False,
+			},
+			{
+				Name:        "optional_float",
+				Number:      11,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.FloatKind,
+				JSONName:    "optionalFloat",
+				IsPacked:    prototype.False,
+			},
+			{
+				Name:        "optional_double",
+				Number:      12,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.DoubleKind,
+				JSONName:    "optionalDouble",
+				IsPacked:    prototype.False,
+			},
+			{
+				Name:        "optional_bool",
+				Number:      13,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.BoolKind,
+				JSONName:    "optionalBool",
+				IsPacked:    prototype.False,
+			},
+			{
+				Name:        "optional_string",
+				Number:      14,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.StringKind,
+				JSONName:    "optionalString",
+				IsPacked:    prototype.False,
+			},
+			{
+				Name:        "optional_bytes",
+				Number:      15,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.BytesKind,
+				JSONName:    "optionalBytes",
+				IsPacked:    prototype.False,
+			},
+			{
+				Name:        "optionalgroup",
+				Number:      16,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.GroupKind,
+				JSONName:    "optionalgroup",
+				IsPacked:    prototype.False,
+			},
+			{
+				Name:        "optional_nested_message",
+				Number:      18,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.MessageKind,
+				JSONName:    "optionalNestedMessage",
+				IsPacked:    prototype.False,
+			},
+			{
+				Name:        "optional_nested_enum",
+				Number:      21,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.EnumKind,
+				JSONName:    "optionalNestedEnum",
+				IsPacked:    prototype.False,
+			},
+			{
+				Name:        "repeated_int32",
+				Number:      31,
+				Cardinality: protoreflect.Repeated,
+				Kind:        protoreflect.Int32Kind,
+				JSONName:    "repeatedInt32",
+				IsPacked:    prototype.False,
+			},
+			{
+				Name:        "repeated_int64",
+				Number:      32,
+				Cardinality: protoreflect.Repeated,
+				Kind:        protoreflect.Int64Kind,
+				JSONName:    "repeatedInt64",
+				IsPacked:    prototype.False,
+			},
+			{
+				Name:        "repeated_uint32",
+				Number:      33,
+				Cardinality: protoreflect.Repeated,
+				Kind:        protoreflect.Uint32Kind,
+				JSONName:    "repeatedUint32",
+				IsPacked:    prototype.False,
+			},
+			{
+				Name:        "repeated_uint64",
+				Number:      34,
+				Cardinality: protoreflect.Repeated,
+				Kind:        protoreflect.Uint64Kind,
+				JSONName:    "repeatedUint64",
+				IsPacked:    prototype.False,
+			},
+			{
+				Name:        "repeated_sint32",
+				Number:      35,
+				Cardinality: protoreflect.Repeated,
+				Kind:        protoreflect.Sint32Kind,
+				JSONName:    "repeatedSint32",
+				IsPacked:    prototype.False,
+			},
+			{
+				Name:        "repeated_sint64",
+				Number:      36,
+				Cardinality: protoreflect.Repeated,
+				Kind:        protoreflect.Sint64Kind,
+				JSONName:    "repeatedSint64",
+				IsPacked:    prototype.False,
+			},
+			{
+				Name:        "repeated_fixed32",
+				Number:      37,
+				Cardinality: protoreflect.Repeated,
+				Kind:        protoreflect.Fixed32Kind,
+				JSONName:    "repeatedFixed32",
+				IsPacked:    prototype.False,
+			},
+			{
+				Name:        "repeated_fixed64",
+				Number:      38,
+				Cardinality: protoreflect.Repeated,
+				Kind:        protoreflect.Fixed64Kind,
+				JSONName:    "repeatedFixed64",
+				IsPacked:    prototype.False,
+			},
+			{
+				Name:        "repeated_sfixed32",
+				Number:      39,
+				Cardinality: protoreflect.Repeated,
+				Kind:        protoreflect.Sfixed32Kind,
+				JSONName:    "repeatedSfixed32",
+				IsPacked:    prototype.False,
+			},
+			{
+				Name:        "repeated_sfixed64",
+				Number:      40,
+				Cardinality: protoreflect.Repeated,
+				Kind:        protoreflect.Sfixed64Kind,
+				JSONName:    "repeatedSfixed64",
+				IsPacked:    prototype.False,
+			},
+			{
+				Name:        "repeated_float",
+				Number:      41,
+				Cardinality: protoreflect.Repeated,
+				Kind:        protoreflect.FloatKind,
+				JSONName:    "repeatedFloat",
+				IsPacked:    prototype.False,
+			},
+			{
+				Name:        "repeated_double",
+				Number:      42,
+				Cardinality: protoreflect.Repeated,
+				Kind:        protoreflect.DoubleKind,
+				JSONName:    "repeatedDouble",
+				IsPacked:    prototype.False,
+			},
+			{
+				Name:        "repeated_bool",
+				Number:      43,
+				Cardinality: protoreflect.Repeated,
+				Kind:        protoreflect.BoolKind,
+				JSONName:    "repeatedBool",
+				IsPacked:    prototype.False,
+			},
+			{
+				Name:        "repeated_string",
+				Number:      44,
+				Cardinality: protoreflect.Repeated,
+				Kind:        protoreflect.StringKind,
+				JSONName:    "repeatedString",
+				IsPacked:    prototype.False,
+			},
+			{
+				Name:        "repeated_bytes",
+				Number:      45,
+				Cardinality: protoreflect.Repeated,
+				Kind:        protoreflect.BytesKind,
+				JSONName:    "repeatedBytes",
+				IsPacked:    prototype.False,
+			},
+			{
+				Name:        "repeatedgroup",
+				Number:      46,
+				Cardinality: protoreflect.Repeated,
+				Kind:        protoreflect.GroupKind,
+				JSONName:    "repeatedgroup",
+				IsPacked:    prototype.False,
+			},
+			{
+				Name:        "repeated_nested_message",
+				Number:      48,
+				Cardinality: protoreflect.Repeated,
+				Kind:        protoreflect.MessageKind,
+				JSONName:    "repeatedNestedMessage",
+				IsPacked:    prototype.False,
+			},
+			{
+				Name:        "repeated_nested_enum",
+				Number:      51,
+				Cardinality: protoreflect.Repeated,
+				Kind:        protoreflect.EnumKind,
+				JSONName:    "repeatedNestedEnum",
+				IsPacked:    prototype.False,
+			},
+			{
+				Name:        "map_int32_int32",
+				Number:      56,
+				Cardinality: protoreflect.Repeated,
+				Kind:        protoreflect.MessageKind,
+				JSONName:    "mapInt32Int32",
+				IsPacked:    prototype.False,
+			},
+			{
+				Name:        "map_int64_int64",
+				Number:      57,
+				Cardinality: protoreflect.Repeated,
+				Kind:        protoreflect.MessageKind,
+				JSONName:    "mapInt64Int64",
+				IsPacked:    prototype.False,
+			},
+			{
+				Name:        "map_uint32_uint32",
+				Number:      58,
+				Cardinality: protoreflect.Repeated,
+				Kind:        protoreflect.MessageKind,
+				JSONName:    "mapUint32Uint32",
+				IsPacked:    prototype.False,
+			},
+			{
+				Name:        "map_uint64_uint64",
+				Number:      59,
+				Cardinality: protoreflect.Repeated,
+				Kind:        protoreflect.MessageKind,
+				JSONName:    "mapUint64Uint64",
+				IsPacked:    prototype.False,
+			},
+			{
+				Name:        "map_sint32_sint32",
+				Number:      60,
+				Cardinality: protoreflect.Repeated,
+				Kind:        protoreflect.MessageKind,
+				JSONName:    "mapSint32Sint32",
+				IsPacked:    prototype.False,
+			},
+			{
+				Name:        "map_sint64_sint64",
+				Number:      61,
+				Cardinality: protoreflect.Repeated,
+				Kind:        protoreflect.MessageKind,
+				JSONName:    "mapSint64Sint64",
+				IsPacked:    prototype.False,
+			},
+			{
+				Name:        "map_fixed32_fixed32",
+				Number:      62,
+				Cardinality: protoreflect.Repeated,
+				Kind:        protoreflect.MessageKind,
+				JSONName:    "mapFixed32Fixed32",
+				IsPacked:    prototype.False,
+			},
+			{
+				Name:        "map_fixed64_fixed64",
+				Number:      63,
+				Cardinality: protoreflect.Repeated,
+				Kind:        protoreflect.MessageKind,
+				JSONName:    "mapFixed64Fixed64",
+				IsPacked:    prototype.False,
+			},
+			{
+				Name:        "map_sfixed32_sfixed32",
+				Number:      64,
+				Cardinality: protoreflect.Repeated,
+				Kind:        protoreflect.MessageKind,
+				JSONName:    "mapSfixed32Sfixed32",
+				IsPacked:    prototype.False,
+			},
+			{
+				Name:        "map_sfixed64_sfixed64",
+				Number:      65,
+				Cardinality: protoreflect.Repeated,
+				Kind:        protoreflect.MessageKind,
+				JSONName:    "mapSfixed64Sfixed64",
+				IsPacked:    prototype.False,
+			},
+			{
+				Name:        "map_int32_float",
+				Number:      66,
+				Cardinality: protoreflect.Repeated,
+				Kind:        protoreflect.MessageKind,
+				JSONName:    "mapInt32Float",
+				IsPacked:    prototype.False,
+			},
+			{
+				Name:        "map_int32_double",
+				Number:      67,
+				Cardinality: protoreflect.Repeated,
+				Kind:        protoreflect.MessageKind,
+				JSONName:    "mapInt32Double",
+				IsPacked:    prototype.False,
+			},
+			{
+				Name:        "map_bool_bool",
+				Number:      68,
+				Cardinality: protoreflect.Repeated,
+				Kind:        protoreflect.MessageKind,
+				JSONName:    "mapBoolBool",
+				IsPacked:    prototype.False,
+			},
+			{
+				Name:        "map_string_string",
+				Number:      69,
+				Cardinality: protoreflect.Repeated,
+				Kind:        protoreflect.MessageKind,
+				JSONName:    "mapStringString",
+				IsPacked:    prototype.False,
+			},
+			{
+				Name:        "map_string_bytes",
+				Number:      70,
+				Cardinality: protoreflect.Repeated,
+				Kind:        protoreflect.MessageKind,
+				JSONName:    "mapStringBytes",
+				IsPacked:    prototype.False,
+			},
+			{
+				Name:        "map_string_nested_message",
+				Number:      71,
+				Cardinality: protoreflect.Repeated,
+				Kind:        protoreflect.MessageKind,
+				JSONName:    "mapStringNestedMessage",
+				IsPacked:    prototype.False,
+			},
+			{
+				Name:        "map_string_nested_enum",
+				Number:      73,
+				Cardinality: protoreflect.Repeated,
+				Kind:        protoreflect.MessageKind,
+				JSONName:    "mapStringNestedEnum",
+				IsPacked:    prototype.False,
+			},
+			{
+				Name:        "oneof_uint32",
+				Number:      111,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.Uint32Kind,
+				JSONName:    "oneofUint32",
+				OneofName:   "oneof_field",
+				IsPacked:    prototype.False,
+			},
+			{
+				Name:        "oneof_nested_message",
+				Number:      112,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.MessageKind,
+				JSONName:    "oneofNestedMessage",
+				OneofName:   "oneof_field",
+				IsPacked:    prototype.False,
+			},
+			{
+				Name:        "oneof_string",
+				Number:      113,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.StringKind,
+				JSONName:    "oneofString",
+				OneofName:   "oneof_field",
+				IsPacked:    prototype.False,
+			},
+			{
+				Name:        "oneof_bytes",
+				Number:      114,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.BytesKind,
+				JSONName:    "oneofBytes",
+				OneofName:   "oneof_field",
+				IsPacked:    prototype.False,
+			},
+			{
+				Name:        "oneof_bool",
+				Number:      115,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.BoolKind,
+				JSONName:    "oneofBool",
+				OneofName:   "oneof_field",
+				IsPacked:    prototype.False,
+			},
+			{
+				Name:        "oneof_uint64",
+				Number:      116,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.Uint64Kind,
+				JSONName:    "oneofUint64",
+				OneofName:   "oneof_field",
+				IsPacked:    prototype.False,
+			},
+			{
+				Name:        "oneof_float",
+				Number:      117,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.FloatKind,
+				JSONName:    "oneofFloat",
+				OneofName:   "oneof_field",
+				IsPacked:    prototype.False,
+			},
+			{
+				Name:        "oneof_double",
+				Number:      118,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.DoubleKind,
+				JSONName:    "oneofDouble",
+				OneofName:   "oneof_field",
+				IsPacked:    prototype.False,
+			},
+			{
+				Name:        "oneof_enum",
+				Number:      119,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.EnumKind,
+				JSONName:    "oneofEnum",
+				OneofName:   "oneof_field",
+				IsPacked:    prototype.False,
+			},
+		},
+		Oneofs: []prototype.Oneof{
+			{Name: "oneof_field"},
+		},
+	},
+	{
+		Name:            "TestAllExtensions",
+		ExtensionRanges: [][2]protoreflect.FieldNumber{{1, 536870912}},
+	},
+	{
+		Name: "OptionalGroup_extension",
+		Fields: []prototype.Field{
+			{
+				Name:        "a",
+				Number:      17,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.Int32Kind,
+				JSONName:    "a",
+				IsPacked:    prototype.False,
+			},
+		},
+	},
+	{
+		Name: "RepeatedGroup_extension",
+		Fields: []prototype.Field{
+			{
+				Name:        "a",
+				Number:      47,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.Int32Kind,
+				JSONName:    "a",
+				IsPacked:    prototype.False,
+			},
+		},
+	},
+	{
+		Name: "NestedMessage",
+		Fields: []prototype.Field{
+			{
+				Name:        "a",
+				Number:      1,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.Int32Kind,
+				JSONName:    "a",
+				IsPacked:    prototype.False,
+			},
+			{
+				Name:        "corecursive",
+				Number:      2,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.MessageKind,
+				JSONName:    "corecursive",
+				IsPacked:    prototype.False,
+			},
+		},
+	},
+	{
+		Name: "OptionalGroup",
+		Fields: []prototype.Field{
+			{
+				Name:        "a",
+				Number:      17,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.Int32Kind,
+				JSONName:    "a",
+				IsPacked:    prototype.False,
+			},
+		},
+	},
+	{
+		Name: "RepeatedGroup",
+		Fields: []prototype.Field{
+			{
+				Name:        "a",
+				Number:      47,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.Int32Kind,
+				JSONName:    "a",
+				IsPacked:    prototype.False,
+			},
+		},
+	},
+	{
+		Name: "MapInt32Int32Entry",
+		Fields: []prototype.Field{
+			{
+				Name:        "key",
+				Number:      1,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.Int32Kind,
+				JSONName:    "key",
+				IsPacked:    prototype.False,
+			},
+			{
+				Name:        "value",
+				Number:      2,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.Int32Kind,
+				JSONName:    "value",
+				IsPacked:    prototype.False,
+			},
+		},
+		IsMapEntry: true,
+	},
+	{
+		Name: "MapInt64Int64Entry",
+		Fields: []prototype.Field{
+			{
+				Name:        "key",
+				Number:      1,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.Int64Kind,
+				JSONName:    "key",
+				IsPacked:    prototype.False,
+			},
+			{
+				Name:        "value",
+				Number:      2,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.Int64Kind,
+				JSONName:    "value",
+				IsPacked:    prototype.False,
+			},
+		},
+		IsMapEntry: true,
+	},
+	{
+		Name: "MapUint32Uint32Entry",
+		Fields: []prototype.Field{
+			{
+				Name:        "key",
+				Number:      1,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.Uint32Kind,
+				JSONName:    "key",
+				IsPacked:    prototype.False,
+			},
+			{
+				Name:        "value",
+				Number:      2,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.Uint32Kind,
+				JSONName:    "value",
+				IsPacked:    prototype.False,
+			},
+		},
+		IsMapEntry: true,
+	},
+	{
+		Name: "MapUint64Uint64Entry",
+		Fields: []prototype.Field{
+			{
+				Name:        "key",
+				Number:      1,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.Uint64Kind,
+				JSONName:    "key",
+				IsPacked:    prototype.False,
+			},
+			{
+				Name:        "value",
+				Number:      2,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.Uint64Kind,
+				JSONName:    "value",
+				IsPacked:    prototype.False,
+			},
+		},
+		IsMapEntry: true,
+	},
+	{
+		Name: "MapSint32Sint32Entry",
+		Fields: []prototype.Field{
+			{
+				Name:        "key",
+				Number:      1,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.Sint32Kind,
+				JSONName:    "key",
+				IsPacked:    prototype.False,
+			},
+			{
+				Name:        "value",
+				Number:      2,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.Sint32Kind,
+				JSONName:    "value",
+				IsPacked:    prototype.False,
+			},
+		},
+		IsMapEntry: true,
+	},
+	{
+		Name: "MapSint64Sint64Entry",
+		Fields: []prototype.Field{
+			{
+				Name:        "key",
+				Number:      1,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.Sint64Kind,
+				JSONName:    "key",
+				IsPacked:    prototype.False,
+			},
+			{
+				Name:        "value",
+				Number:      2,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.Sint64Kind,
+				JSONName:    "value",
+				IsPacked:    prototype.False,
+			},
+		},
+		IsMapEntry: true,
+	},
+	{
+		Name: "MapFixed32Fixed32Entry",
+		Fields: []prototype.Field{
+			{
+				Name:        "key",
+				Number:      1,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.Fixed32Kind,
+				JSONName:    "key",
+				IsPacked:    prototype.False,
+			},
+			{
+				Name:        "value",
+				Number:      2,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.Fixed32Kind,
+				JSONName:    "value",
+				IsPacked:    prototype.False,
+			},
+		},
+		IsMapEntry: true,
+	},
+	{
+		Name: "MapFixed64Fixed64Entry",
+		Fields: []prototype.Field{
+			{
+				Name:        "key",
+				Number:      1,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.Fixed64Kind,
+				JSONName:    "key",
+				IsPacked:    prototype.False,
+			},
+			{
+				Name:        "value",
+				Number:      2,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.Fixed64Kind,
+				JSONName:    "value",
+				IsPacked:    prototype.False,
+			},
+		},
+		IsMapEntry: true,
+	},
+	{
+		Name: "MapSfixed32Sfixed32Entry",
+		Fields: []prototype.Field{
+			{
+				Name:        "key",
+				Number:      1,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.Sfixed32Kind,
+				JSONName:    "key",
+				IsPacked:    prototype.False,
+			},
+			{
+				Name:        "value",
+				Number:      2,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.Sfixed32Kind,
+				JSONName:    "value",
+				IsPacked:    prototype.False,
+			},
+		},
+		IsMapEntry: true,
+	},
+	{
+		Name: "MapSfixed64Sfixed64Entry",
+		Fields: []prototype.Field{
+			{
+				Name:        "key",
+				Number:      1,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.Sfixed64Kind,
+				JSONName:    "key",
+				IsPacked:    prototype.False,
+			},
+			{
+				Name:        "value",
+				Number:      2,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.Sfixed64Kind,
+				JSONName:    "value",
+				IsPacked:    prototype.False,
+			},
+		},
+		IsMapEntry: true,
+	},
+	{
+		Name: "MapInt32FloatEntry",
+		Fields: []prototype.Field{
+			{
+				Name:        "key",
+				Number:      1,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.Int32Kind,
+				JSONName:    "key",
+				IsPacked:    prototype.False,
+			},
+			{
+				Name:        "value",
+				Number:      2,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.FloatKind,
+				JSONName:    "value",
+				IsPacked:    prototype.False,
+			},
+		},
+		IsMapEntry: true,
+	},
+	{
+		Name: "MapInt32DoubleEntry",
+		Fields: []prototype.Field{
+			{
+				Name:        "key",
+				Number:      1,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.Int32Kind,
+				JSONName:    "key",
+				IsPacked:    prototype.False,
+			},
+			{
+				Name:        "value",
+				Number:      2,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.DoubleKind,
+				JSONName:    "value",
+				IsPacked:    prototype.False,
+			},
+		},
+		IsMapEntry: true,
+	},
+	{
+		Name: "MapBoolBoolEntry",
+		Fields: []prototype.Field{
+			{
+				Name:        "key",
+				Number:      1,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.BoolKind,
+				JSONName:    "key",
+				IsPacked:    prototype.False,
+			},
+			{
+				Name:        "value",
+				Number:      2,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.BoolKind,
+				JSONName:    "value",
+				IsPacked:    prototype.False,
+			},
+		},
+		IsMapEntry: true,
+	},
+	{
+		Name: "MapStringStringEntry",
+		Fields: []prototype.Field{
+			{
+				Name:        "key",
+				Number:      1,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.StringKind,
+				JSONName:    "key",
+				IsPacked:    prototype.False,
+			},
+			{
+				Name:        "value",
+				Number:      2,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.StringKind,
+				JSONName:    "value",
+				IsPacked:    prototype.False,
+			},
+		},
+		IsMapEntry: true,
+	},
+	{
+		Name: "MapStringBytesEntry",
+		Fields: []prototype.Field{
+			{
+				Name:        "key",
+				Number:      1,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.StringKind,
+				JSONName:    "key",
+				IsPacked:    prototype.False,
+			},
+			{
+				Name:        "value",
+				Number:      2,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.BytesKind,
+				JSONName:    "value",
+				IsPacked:    prototype.False,
+			},
+		},
+		IsMapEntry: true,
+	},
+	{
+		Name: "MapStringNestedMessageEntry",
+		Fields: []prototype.Field{
+			{
+				Name:        "key",
+				Number:      1,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.StringKind,
+				JSONName:    "key",
+				IsPacked:    prototype.False,
+			},
+			{
+				Name:        "value",
+				Number:      2,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.MessageKind,
+				JSONName:    "value",
+				IsPacked:    prototype.False,
+			},
+		},
+		IsMapEntry: true,
+	},
+	{
+		Name: "MapStringNestedEnumEntry",
+		Fields: []prototype.Field{
+			{
+				Name:        "key",
+				Number:      1,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.StringKind,
+				JSONName:    "key",
+				IsPacked:    prototype.False,
+			},
+			{
+				Name:        "value",
+				Number:      2,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.EnumKind,
+				JSONName:    "value",
+				IsPacked:    prototype.False,
+			},
+		},
+		IsMapEntry: true,
+	},
+}
diff --git a/internal/testprotos/test/test.proto b/internal/testprotos/test/test.proto
new file mode 100644
index 00000000..fcb4174f
--- /dev/null
+++ b/internal/testprotos/test/test.proto
@@ -0,0 +1,147 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+syntax = "proto2";
+
+package goproto.proto.test;
+
+option go_package = "github.com/golang/protobuf/v2/proto/testpb";
+
+message TestAllTypes {
+  message NestedMessage {
+    optional int32 a = 1;
+    optional TestAllTypes corecursive = 2;
+  }
+
+  enum NestedEnum {
+    FOO = 0;
+    BAR = 1;
+    BAZ = 2;
+    NEG = -1;  // Intentionally negative.
+  }
+
+  optional int32         optional_int32    =  1;
+  optional int64         optional_int64    =  2;
+  optional uint32        optional_uint32   =  3;
+  optional uint64        optional_uint64   =  4;
+  optional sint32        optional_sint32   =  5;
+  optional sint64        optional_sint64   =  6;
+  optional fixed32       optional_fixed32  =  7;
+  optional fixed64       optional_fixed64  =  8;
+  optional sfixed32      optional_sfixed32 =  9;
+  optional sfixed64      optional_sfixed64 = 10;
+  optional float         optional_float    = 11;
+  optional double        optional_double   = 12;
+  optional bool          optional_bool     = 13;
+  optional string        optional_string   = 14;
+  optional bytes         optional_bytes    = 15;
+  optional group OptionalGroup = 16 {
+    optional int32 a = 17;
+  }
+  optional NestedMessage optional_nested_message = 18;
+  optional NestedEnum    optional_nested_enum    = 21;
+
+  repeated int32         repeated_int32    = 31;
+  repeated int64         repeated_int64    = 32;
+  repeated uint32        repeated_uint32   = 33;
+  repeated uint64        repeated_uint64   = 34;
+  repeated sint32        repeated_sint32   = 35;
+  repeated sint64        repeated_sint64   = 36;
+  repeated fixed32       repeated_fixed32  = 37;
+  repeated fixed64       repeated_fixed64  = 38;
+  repeated sfixed32      repeated_sfixed32 = 39;
+  repeated sfixed64      repeated_sfixed64 = 40;
+  repeated float         repeated_float    = 41;
+  repeated double        repeated_double   = 42;
+  repeated bool          repeated_bool     = 43;
+  repeated string        repeated_string   = 44;
+  repeated bytes         repeated_bytes    = 45;
+  repeated group RepeatedGroup = 46 {
+    optional int32 a = 47;
+  }
+  repeated NestedMessage repeated_nested_message = 48;
+  repeated NestedEnum    repeated_nested_enum    = 51;
+
+  map <   int32, int32>         map_int32_int32           = 56;
+  map <   int64, int64>         map_int64_int64           = 57;
+  map <  uint32, uint32>        map_uint32_uint32         = 58;
+  map <  uint64, uint64>        map_uint64_uint64         = 59;
+  map <  sint32, sint32>        map_sint32_sint32         = 60;
+  map <  sint64, sint64>        map_sint64_sint64         = 61;
+  map < fixed32, fixed32>       map_fixed32_fixed32       = 62;
+  map < fixed64, fixed64>       map_fixed64_fixed64       = 63;
+  map <sfixed32, sfixed32>      map_sfixed32_sfixed32     = 64;
+  map <sfixed64, sfixed64>      map_sfixed64_sfixed64     = 65;
+  map <   int32, float>         map_int32_float           = 66;
+  map <   int32, double>        map_int32_double          = 67;
+  map <    bool, bool>          map_bool_bool             = 68;
+  map <  string, string>        map_string_string         = 69;
+  map <  string, bytes>         map_string_bytes          = 70;
+  map <  string, NestedMessage> map_string_nested_message = 71;
+  map <  string, NestedEnum>    map_string_nested_enum    = 73;
+
+  oneof oneof_field {
+    uint32        oneof_uint32         = 111;
+    NestedMessage oneof_nested_message = 112;
+    string        oneof_string         = 113;
+    bytes         oneof_bytes          = 114;
+    bool          oneof_bool           = 115;
+    uint64        oneof_uint64         = 116;
+    float         oneof_float          = 117;
+    double        oneof_double         = 118;
+    NestedEnum    oneof_enum           = 119;
+  }
+}
+
+message TestAllExtensions {
+  extensions 1 to max;
+}
+
+extend TestAllExtensions {
+  optional int32    optional_int32_extension    =  1;
+  optional int64    optional_int64_extension    =  2;
+  optional uint32   optional_uint32_extension   =  3;
+  optional uint64   optional_uint64_extension   =  4;
+  optional sint32   optional_sint32_extension   =  5;
+  optional sint64   optional_sint64_extension   =  6;
+  optional fixed32  optional_fixed32_extension  =  7;
+  optional fixed64  optional_fixed64_extension  =  8;
+  optional sfixed32 optional_sfixed32_extension =  9;
+  optional sfixed64 optional_sfixed64_extension = 10;
+  optional float    optional_float_extension    = 11;
+  optional double   optional_double_extension   = 12;
+  optional bool     optional_bool_extension     = 13;
+  optional string   optional_string_extension   = 14;
+  optional bytes    optional_bytes_extension    = 15;
+
+  optional group OptionalGroup_extension = 16 {
+    optional int32 a = 17;
+  }
+
+  optional TestAllTypes.NestedMessage optional_nested_message_extension = 18;
+  optional TestAllTypes.NestedEnum optional_nested_enum_extension = 21;
+
+  repeated int32    repeated_int32_extension    = 31;
+  repeated int64    repeated_int64_extension    = 32;
+  repeated uint32   repeated_uint32_extension   = 33;
+  repeated uint64   repeated_uint64_extension   = 34;
+  repeated sint32   repeated_sint32_extension   = 35;
+  repeated sint64   repeated_sint64_extension   = 36;
+  repeated fixed32  repeated_fixed32_extension  = 37;
+  repeated fixed64  repeated_fixed64_extension  = 38;
+  repeated sfixed32 repeated_sfixed32_extension = 39;
+  repeated sfixed64 repeated_sfixed64_extension = 40;
+  repeated float    repeated_float_extension    = 41;
+  repeated double   repeated_double_extension   = 42;
+  repeated bool     repeated_bool_extension     = 43;
+  repeated string   repeated_string_extension   = 44;
+  repeated bytes    repeated_bytes_extension    = 45;
+
+  repeated group RepeatedGroup_extension = 46 {
+    optional int32 a = 47;
+  }
+
+  repeated TestAllTypes.NestedMessage repeated_nested_message_extension = 48;
+  repeated TestAllTypes.NestedEnum repeated_nested_enum_extension = 51;
+}
diff --git a/proto/decode.go b/proto/decode.go
new file mode 100644
index 00000000..4af5f162
--- /dev/null
+++ b/proto/decode.go
@@ -0,0 +1,191 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style.
+// license that can be found in the LICENSE file.
+
+package proto
+
+import (
+	"errors"
+
+	"github.com/golang/protobuf/v2/internal/encoding/wire"
+	"github.com/golang/protobuf/v2/internal/pragma"
+	"github.com/golang/protobuf/v2/reflect/protoreflect"
+)
+
+// UnmarshalOptions configures the unmarshaler.
+//
+// Example usage:
+//   err := UnmarshalOptions{DiscardUnknown: true}.Unmarshal(b, m)
+type UnmarshalOptions struct {
+	// If DiscardUnknown is set, unknown fields are ignored.
+	DiscardUnknown bool
+
+	pragma.NoUnkeyedLiterals
+}
+
+// Unmarshal parses the wire-format message in b and places the result in m.
+func Unmarshal(b []byte, m Message) error {
+	return UnmarshalOptions{}.Unmarshal(b, m)
+}
+
+// Unmarshal parses the wire-format message in b and places the result in m.
+func (o UnmarshalOptions) Unmarshal(b []byte, m Message) error {
+	// TODO: Reset m?
+	return o.unmarshalMessage(b, m.ProtoReflect())
+}
+
+func (o UnmarshalOptions) unmarshalMessage(b []byte, m protoreflect.Message) error {
+	messageType := m.Type()
+	fieldTypes := messageType.Fields()
+	knownFields := m.KnownFields()
+	unknownFields := m.UnknownFields()
+	for len(b) > 0 {
+		// Parse the tag (field number and wire type).
+		num, wtyp, tagLen := wire.ConsumeTag(b)
+		if tagLen < 0 {
+			return wire.ParseError(tagLen)
+		}
+
+		// Parse the field value.
+		fieldType := fieldTypes.ByNumber(num)
+		var err error
+		var valLen int
+		switch {
+		case fieldType == nil:
+			err = errUnknown
+		case fieldType.Cardinality() != protoreflect.Repeated:
+			valLen, err = o.unmarshalScalarField(b[tagLen:], wtyp, num, knownFields, fieldType)
+		case !fieldType.IsMap():
+			valLen, err = o.unmarshalList(b[tagLen:], wtyp, num, knownFields.Get(num).List(), fieldType.Kind())
+		default:
+			valLen, err = o.unmarshalMap(b[tagLen:], wtyp, num, knownFields.Get(num).Map(), fieldType)
+		}
+		if err == errUnknown {
+			valLen = wire.ConsumeFieldValue(num, wtyp, b[tagLen:])
+			if valLen < 0 {
+				return wire.ParseError(valLen)
+			}
+			unknownFields.Set(num, append(unknownFields.Get(num), b[:tagLen+valLen]...))
+		} else if err != nil {
+			return err
+		}
+		b = b[tagLen+valLen:]
+	}
+	// TODO: required field checks
+	return nil
+}
+
+func (o UnmarshalOptions) unmarshalScalarField(b []byte, wtyp wire.Type, num wire.Number, knownFields protoreflect.KnownFields, field protoreflect.FieldDescriptor) (n int, err error) {
+	v, n, err := o.unmarshalScalar(b, wtyp, num, field.Kind())
+	if err != nil {
+		return 0, err
+	}
+	switch field.Kind() {
+	case protoreflect.GroupKind, protoreflect.MessageKind:
+		// Messages are merged with any existing message value,
+		// unless the message is part of a oneof.
+		//
+		// TODO: C++ merges into oneofs, while v1 does not.
+		// Evaluate which behavior to pick.
+		var m protoreflect.Message
+		if knownFields.Has(num) && field.OneofType() == nil {
+			m = knownFields.Get(num).Message()
+		} else {
+			m = knownFields.NewMessage(num).ProtoReflect()
+			knownFields.Set(num, protoreflect.ValueOf(m))
+		}
+		if err := o.unmarshalMessage(v.Bytes(), m); err != nil {
+			return 0, err
+		}
+	default:
+		// Non-message scalars replace the previous value.
+		knownFields.Set(num, v)
+	}
+	return n, nil
+}
+
+func (o UnmarshalOptions) unmarshalMap(b []byte, wtyp wire.Type, num wire.Number, mapv protoreflect.Map, field protoreflect.FieldDescriptor) (n int, err error) {
+	if wtyp != wire.BytesType {
+		return 0, errUnknown
+	}
+	b, n = wire.ConsumeBytes(b)
+	if n < 0 {
+		return 0, wire.ParseError(n)
+	}
+	var (
+		keyField = field.MessageType().Fields().ByNumber(1)
+		valField = field.MessageType().Fields().ByNumber(2)
+		key      protoreflect.Value
+		val      protoreflect.Value
+		haveKey  bool
+		haveVal  bool
+	)
+	switch valField.Kind() {
+	case protoreflect.GroupKind, protoreflect.MessageKind:
+		val = protoreflect.ValueOf(mapv.NewMessage().ProtoReflect())
+	}
+	// Map entries are represented as a two-element message with fields
+	// containing the key and value.
+	for len(b) > 0 {
+		num, wtyp, n := wire.ConsumeTag(b)
+		if n < 0 {
+			return 0, wire.ParseError(n)
+		}
+		b = b[n:]
+		err = errUnknown
+		switch num {
+		case 1:
+			key, n, err = o.unmarshalScalar(b, wtyp, num, keyField.Kind())
+			if err != nil {
+				break
+			}
+			haveKey = true
+		case 2:
+			var v protoreflect.Value
+			v, n, err = o.unmarshalScalar(b, wtyp, num, valField.Kind())
+			if err != nil {
+				break
+			}
+			switch valField.Kind() {
+			case protoreflect.GroupKind, protoreflect.MessageKind:
+				if err := o.unmarshalMessage(v.Bytes(), val.Message()); err != nil {
+					return 0, err
+				}
+			default:
+				val = v
+			}
+			haveVal = true
+		}
+		if err == errUnknown {
+			n = wire.ConsumeFieldValue(num, wtyp, b)
+			if n < 0 {
+				return 0, wire.ParseError(n)
+			}
+		} else if err != nil {
+			return 0, err
+		}
+		b = b[n:]
+	}
+	// Every map entry should have entries for key and value, but this is not strictly required.
+	if !haveKey {
+		key = keyField.Default()
+	}
+	if !haveVal {
+		switch valField.Kind() {
+		case protoreflect.GroupKind, protoreflect.MessageKind:
+			// Trigger required field checks by unmarshaling an empty message.
+			if err := o.unmarshalMessage(nil, val.Message()); err != nil {
+				return 0, err
+			}
+		default:
+			val = valField.Default()
+		}
+	}
+	mapv.Set(key.MapKey(), val)
+	return n, nil
+}
+
+// errUnknown is used internally to indicate fields which should be added
+// to the unknown field set of a message. It is never returned from an exported
+// function.
+var errUnknown = errors.New("unknown")
diff --git a/proto/decode_gen.go b/proto/decode_gen.go
new file mode 100644
index 00000000..130876f9
--- /dev/null
+++ b/proto/decode_gen.go
@@ -0,0 +1,591 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style.
+// license that can be found in the LICENSE file.
+
+// Code generated by generate-types. DO NOT EDIT.
+
+package proto
+
+import (
+	"math"
+
+	"github.com/golang/protobuf/v2/internal/encoding/wire"
+	"github.com/golang/protobuf/v2/reflect/protoreflect"
+)
+
+// unmarshalScalar decodes a value of the given kind.
+//
+// Message values are decoded into a []byte which aliases the input data.
+func (o UnmarshalOptions) unmarshalScalar(b []byte, wtyp wire.Type, num wire.Number, kind protoreflect.Kind) (val protoreflect.Value, n int, err error) {
+	switch kind {
+	case protoreflect.BoolKind:
+		if wtyp != wire.VarintType {
+			return val, 0, errUnknown
+		}
+		v, n := wire.ConsumeVarint(b)
+		if n < 0 {
+			return val, 0, wire.ParseError(n)
+		}
+		return protoreflect.ValueOf(wire.DecodeBool(v)), n, nil
+	case protoreflect.EnumKind:
+		if wtyp != wire.VarintType {
+			return val, 0, errUnknown
+		}
+		v, n := wire.ConsumeVarint(b)
+		if n < 0 {
+			return val, 0, wire.ParseError(n)
+		}
+		return protoreflect.ValueOf(protoreflect.EnumNumber(v)), n, nil
+	case protoreflect.Int32Kind:
+		if wtyp != wire.VarintType {
+			return val, 0, errUnknown
+		}
+		v, n := wire.ConsumeVarint(b)
+		if n < 0 {
+			return val, 0, wire.ParseError(n)
+		}
+		return protoreflect.ValueOf(int32(v)), n, nil
+	case protoreflect.Sint32Kind:
+		if wtyp != wire.VarintType {
+			return val, 0, errUnknown
+		}
+		v, n := wire.ConsumeVarint(b)
+		if n < 0 {
+			return val, 0, wire.ParseError(n)
+		}
+		return protoreflect.ValueOf(int32(wire.DecodeZigZag(v & math.MaxUint32))), n, nil
+	case protoreflect.Uint32Kind:
+		if wtyp != wire.VarintType {
+			return val, 0, errUnknown
+		}
+		v, n := wire.ConsumeVarint(b)
+		if n < 0 {
+			return val, 0, wire.ParseError(n)
+		}
+		return protoreflect.ValueOf(uint32(v)), n, nil
+	case protoreflect.Int64Kind:
+		if wtyp != wire.VarintType {
+			return val, 0, errUnknown
+		}
+		v, n := wire.ConsumeVarint(b)
+		if n < 0 {
+			return val, 0, wire.ParseError(n)
+		}
+		return protoreflect.ValueOf(int64(v)), n, nil
+	case protoreflect.Sint64Kind:
+		if wtyp != wire.VarintType {
+			return val, 0, errUnknown
+		}
+		v, n := wire.ConsumeVarint(b)
+		if n < 0 {
+			return val, 0, wire.ParseError(n)
+		}
+		return protoreflect.ValueOf(wire.DecodeZigZag(v)), n, nil
+	case protoreflect.Uint64Kind:
+		if wtyp != wire.VarintType {
+			return val, 0, errUnknown
+		}
+		v, n := wire.ConsumeVarint(b)
+		if n < 0 {
+			return val, 0, wire.ParseError(n)
+		}
+		return protoreflect.ValueOf(v), n, nil
+	case protoreflect.Sfixed32Kind:
+		if wtyp != wire.Fixed32Type {
+			return val, 0, errUnknown
+		}
+		v, n := wire.ConsumeFixed32(b)
+		if n < 0 {
+			return val, 0, wire.ParseError(n)
+		}
+		return protoreflect.ValueOf(int32(v)), n, nil
+	case protoreflect.Fixed32Kind:
+		if wtyp != wire.Fixed32Type {
+			return val, 0, errUnknown
+		}
+		v, n := wire.ConsumeFixed32(b)
+		if n < 0 {
+			return val, 0, wire.ParseError(n)
+		}
+		return protoreflect.ValueOf(uint32(v)), n, nil
+	case protoreflect.FloatKind:
+		if wtyp != wire.Fixed32Type {
+			return val, 0, errUnknown
+		}
+		v, n := wire.ConsumeFixed32(b)
+		if n < 0 {
+			return val, 0, wire.ParseError(n)
+		}
+		return protoreflect.ValueOf(math.Float32frombits(uint32(v))), n, nil
+	case protoreflect.Sfixed64Kind:
+		if wtyp != wire.Fixed64Type {
+			return val, 0, errUnknown
+		}
+		v, n := wire.ConsumeFixed64(b)
+		if n < 0 {
+			return val, 0, wire.ParseError(n)
+		}
+		return protoreflect.ValueOf(int64(v)), n, nil
+	case protoreflect.Fixed64Kind:
+		if wtyp != wire.Fixed64Type {
+			return val, 0, errUnknown
+		}
+		v, n := wire.ConsumeFixed64(b)
+		if n < 0 {
+			return val, 0, wire.ParseError(n)
+		}
+		return protoreflect.ValueOf(v), n, nil
+	case protoreflect.DoubleKind:
+		if wtyp != wire.Fixed64Type {
+			return val, 0, errUnknown
+		}
+		v, n := wire.ConsumeFixed64(b)
+		if n < 0 {
+			return val, 0, wire.ParseError(n)
+		}
+		return protoreflect.ValueOf(math.Float64frombits(v)), n, nil
+	case protoreflect.StringKind:
+		if wtyp != wire.BytesType {
+			return val, 0, errUnknown
+		}
+		v, n := wire.ConsumeBytes(b)
+		if n < 0 {
+			return val, 0, wire.ParseError(n)
+		}
+		return protoreflect.ValueOf(string(v)), n, nil
+	case protoreflect.BytesKind:
+		if wtyp != wire.BytesType {
+			return val, 0, errUnknown
+		}
+		v, n := wire.ConsumeBytes(b)
+		if n < 0 {
+			return val, 0, wire.ParseError(n)
+		}
+		return protoreflect.ValueOf(append(([]byte)(nil), v...)), n, nil
+	case protoreflect.MessageKind:
+		if wtyp != wire.BytesType {
+			return val, 0, errUnknown
+		}
+		v, n := wire.ConsumeBytes(b)
+		if n < 0 {
+			return val, 0, wire.ParseError(n)
+		}
+		return protoreflect.ValueOf(v), n, nil
+	case protoreflect.GroupKind:
+		if wtyp != wire.StartGroupType {
+			return val, 0, errUnknown
+		}
+		v, n := wire.ConsumeGroup(num, b)
+		if n < 0 {
+			return val, 0, wire.ParseError(n)
+		}
+		return protoreflect.ValueOf(v), n, nil
+	default:
+		return val, 0, errUnknown
+	}
+}
+
+func (o UnmarshalOptions) unmarshalList(b []byte, wtyp wire.Type, num wire.Number, list protoreflect.List, kind protoreflect.Kind) (n int, err error) {
+	switch kind {
+	case protoreflect.BoolKind:
+		if wtyp == wire.BytesType {
+			buf, n := wire.ConsumeBytes(b)
+			if n < 0 {
+				return 0, wire.ParseError(n)
+			}
+			for len(buf) > 0 {
+				v, n := wire.ConsumeVarint(buf)
+				if n < 0 {
+					return 0, wire.ParseError(n)
+				}
+				buf = buf[n:]
+				list.Append(protoreflect.ValueOf(wire.DecodeBool(v)))
+			}
+			return n, nil
+		}
+		if wtyp != wire.VarintType {
+			return 0, errUnknown
+		}
+		v, n := wire.ConsumeVarint(b)
+		if n < 0 {
+			return 0, wire.ParseError(n)
+		}
+		list.Append(protoreflect.ValueOf(wire.DecodeBool(v)))
+		return n, nil
+	case protoreflect.EnumKind:
+		if wtyp == wire.BytesType {
+			buf, n := wire.ConsumeBytes(b)
+			if n < 0 {
+				return 0, wire.ParseError(n)
+			}
+			for len(buf) > 0 {
+				v, n := wire.ConsumeVarint(buf)
+				if n < 0 {
+					return 0, wire.ParseError(n)
+				}
+				buf = buf[n:]
+				list.Append(protoreflect.ValueOf(protoreflect.EnumNumber(v)))
+			}
+			return n, nil
+		}
+		if wtyp != wire.VarintType {
+			return 0, errUnknown
+		}
+		v, n := wire.ConsumeVarint(b)
+		if n < 0 {
+			return 0, wire.ParseError(n)
+		}
+		list.Append(protoreflect.ValueOf(protoreflect.EnumNumber(v)))
+		return n, nil
+	case protoreflect.Int32Kind:
+		if wtyp == wire.BytesType {
+			buf, n := wire.ConsumeBytes(b)
+			if n < 0 {
+				return 0, wire.ParseError(n)
+			}
+			for len(buf) > 0 {
+				v, n := wire.ConsumeVarint(buf)
+				if n < 0 {
+					return 0, wire.ParseError(n)
+				}
+				buf = buf[n:]
+				list.Append(protoreflect.ValueOf(int32(v)))
+			}
+			return n, nil
+		}
+		if wtyp != wire.VarintType {
+			return 0, errUnknown
+		}
+		v, n := wire.ConsumeVarint(b)
+		if n < 0 {
+			return 0, wire.ParseError(n)
+		}
+		list.Append(protoreflect.ValueOf(int32(v)))
+		return n, nil
+	case protoreflect.Sint32Kind:
+		if wtyp == wire.BytesType {
+			buf, n := wire.ConsumeBytes(b)
+			if n < 0 {
+				return 0, wire.ParseError(n)
+			}
+			for len(buf) > 0 {
+				v, n := wire.ConsumeVarint(buf)
+				if n < 0 {
+					return 0, wire.ParseError(n)
+				}
+				buf = buf[n:]
+				list.Append(protoreflect.ValueOf(int32(wire.DecodeZigZag(v & math.MaxUint32))))
+			}
+			return n, nil
+		}
+		if wtyp != wire.VarintType {
+			return 0, errUnknown
+		}
+		v, n := wire.ConsumeVarint(b)
+		if n < 0 {
+			return 0, wire.ParseError(n)
+		}
+		list.Append(protoreflect.ValueOf(int32(wire.DecodeZigZag(v & math.MaxUint32))))
+		return n, nil
+	case protoreflect.Uint32Kind:
+		if wtyp == wire.BytesType {
+			buf, n := wire.ConsumeBytes(b)
+			if n < 0 {
+				return 0, wire.ParseError(n)
+			}
+			for len(buf) > 0 {
+				v, n := wire.ConsumeVarint(buf)
+				if n < 0 {
+					return 0, wire.ParseError(n)
+				}
+				buf = buf[n:]
+				list.Append(protoreflect.ValueOf(uint32(v)))
+			}
+			return n, nil
+		}
+		if wtyp != wire.VarintType {
+			return 0, errUnknown
+		}
+		v, n := wire.ConsumeVarint(b)
+		if n < 0 {
+			return 0, wire.ParseError(n)
+		}
+		list.Append(protoreflect.ValueOf(uint32(v)))
+		return n, nil
+	case protoreflect.Int64Kind:
+		if wtyp == wire.BytesType {
+			buf, n := wire.ConsumeBytes(b)
+			if n < 0 {
+				return 0, wire.ParseError(n)
+			}
+			for len(buf) > 0 {
+				v, n := wire.ConsumeVarint(buf)
+				if n < 0 {
+					return 0, wire.ParseError(n)
+				}
+				buf = buf[n:]
+				list.Append(protoreflect.ValueOf(int64(v)))
+			}
+			return n, nil
+		}
+		if wtyp != wire.VarintType {
+			return 0, errUnknown
+		}
+		v, n := wire.ConsumeVarint(b)
+		if n < 0 {
+			return 0, wire.ParseError(n)
+		}
+		list.Append(protoreflect.ValueOf(int64(v)))
+		return n, nil
+	case protoreflect.Sint64Kind:
+		if wtyp == wire.BytesType {
+			buf, n := wire.ConsumeBytes(b)
+			if n < 0 {
+				return 0, wire.ParseError(n)
+			}
+			for len(buf) > 0 {
+				v, n := wire.ConsumeVarint(buf)
+				if n < 0 {
+					return 0, wire.ParseError(n)
+				}
+				buf = buf[n:]
+				list.Append(protoreflect.ValueOf(wire.DecodeZigZag(v)))
+			}
+			return n, nil
+		}
+		if wtyp != wire.VarintType {
+			return 0, errUnknown
+		}
+		v, n := wire.ConsumeVarint(b)
+		if n < 0 {
+			return 0, wire.ParseError(n)
+		}
+		list.Append(protoreflect.ValueOf(wire.DecodeZigZag(v)))
+		return n, nil
+	case protoreflect.Uint64Kind:
+		if wtyp == wire.BytesType {
+			buf, n := wire.ConsumeBytes(b)
+			if n < 0 {
+				return 0, wire.ParseError(n)
+			}
+			for len(buf) > 0 {
+				v, n := wire.ConsumeVarint(buf)
+				if n < 0 {
+					return 0, wire.ParseError(n)
+				}
+				buf = buf[n:]
+				list.Append(protoreflect.ValueOf(v))
+			}
+			return n, nil
+		}
+		if wtyp != wire.VarintType {
+			return 0, errUnknown
+		}
+		v, n := wire.ConsumeVarint(b)
+		if n < 0 {
+			return 0, wire.ParseError(n)
+		}
+		list.Append(protoreflect.ValueOf(v))
+		return n, nil
+	case protoreflect.Sfixed32Kind:
+		if wtyp == wire.BytesType {
+			buf, n := wire.ConsumeBytes(b)
+			if n < 0 {
+				return 0, wire.ParseError(n)
+			}
+			for len(buf) > 0 {
+				v, n := wire.ConsumeFixed32(buf)
+				if n < 0 {
+					return 0, wire.ParseError(n)
+				}
+				buf = buf[n:]
+				list.Append(protoreflect.ValueOf(int32(v)))
+			}
+			return n, nil
+		}
+		if wtyp != wire.Fixed32Type {
+			return 0, errUnknown
+		}
+		v, n := wire.ConsumeFixed32(b)
+		if n < 0 {
+			return 0, wire.ParseError(n)
+		}
+		list.Append(protoreflect.ValueOf(int32(v)))
+		return n, nil
+	case protoreflect.Fixed32Kind:
+		if wtyp == wire.BytesType {
+			buf, n := wire.ConsumeBytes(b)
+			if n < 0 {
+				return 0, wire.ParseError(n)
+			}
+			for len(buf) > 0 {
+				v, n := wire.ConsumeFixed32(buf)
+				if n < 0 {
+					return 0, wire.ParseError(n)
+				}
+				buf = buf[n:]
+				list.Append(protoreflect.ValueOf(uint32(v)))
+			}
+			return n, nil
+		}
+		if wtyp != wire.Fixed32Type {
+			return 0, errUnknown
+		}
+		v, n := wire.ConsumeFixed32(b)
+		if n < 0 {
+			return 0, wire.ParseError(n)
+		}
+		list.Append(protoreflect.ValueOf(uint32(v)))
+		return n, nil
+	case protoreflect.FloatKind:
+		if wtyp == wire.BytesType {
+			buf, n := wire.ConsumeBytes(b)
+			if n < 0 {
+				return 0, wire.ParseError(n)
+			}
+			for len(buf) > 0 {
+				v, n := wire.ConsumeFixed32(buf)
+				if n < 0 {
+					return 0, wire.ParseError(n)
+				}
+				buf = buf[n:]
+				list.Append(protoreflect.ValueOf(math.Float32frombits(uint32(v))))
+			}
+			return n, nil
+		}
+		if wtyp != wire.Fixed32Type {
+			return 0, errUnknown
+		}
+		v, n := wire.ConsumeFixed32(b)
+		if n < 0 {
+			return 0, wire.ParseError(n)
+		}
+		list.Append(protoreflect.ValueOf(math.Float32frombits(uint32(v))))
+		return n, nil
+	case protoreflect.Sfixed64Kind:
+		if wtyp == wire.BytesType {
+			buf, n := wire.ConsumeBytes(b)
+			if n < 0 {
+				return 0, wire.ParseError(n)
+			}
+			for len(buf) > 0 {
+				v, n := wire.ConsumeFixed64(buf)
+				if n < 0 {
+					return 0, wire.ParseError(n)
+				}
+				buf = buf[n:]
+				list.Append(protoreflect.ValueOf(int64(v)))
+			}
+			return n, nil
+		}
+		if wtyp != wire.Fixed64Type {
+			return 0, errUnknown
+		}
+		v, n := wire.ConsumeFixed64(b)
+		if n < 0 {
+			return 0, wire.ParseError(n)
+		}
+		list.Append(protoreflect.ValueOf(int64(v)))
+		return n, nil
+	case protoreflect.Fixed64Kind:
+		if wtyp == wire.BytesType {
+			buf, n := wire.ConsumeBytes(b)
+			if n < 0 {
+				return 0, wire.ParseError(n)
+			}
+			for len(buf) > 0 {
+				v, n := wire.ConsumeFixed64(buf)
+				if n < 0 {
+					return 0, wire.ParseError(n)
+				}
+				buf = buf[n:]
+				list.Append(protoreflect.ValueOf(v))
+			}
+			return n, nil
+		}
+		if wtyp != wire.Fixed64Type {
+			return 0, errUnknown
+		}
+		v, n := wire.ConsumeFixed64(b)
+		if n < 0 {
+			return 0, wire.ParseError(n)
+		}
+		list.Append(protoreflect.ValueOf(v))
+		return n, nil
+	case protoreflect.DoubleKind:
+		if wtyp == wire.BytesType {
+			buf, n := wire.ConsumeBytes(b)
+			if n < 0 {
+				return 0, wire.ParseError(n)
+			}
+			for len(buf) > 0 {
+				v, n := wire.ConsumeFixed64(buf)
+				if n < 0 {
+					return 0, wire.ParseError(n)
+				}
+				buf = buf[n:]
+				list.Append(protoreflect.ValueOf(math.Float64frombits(v)))
+			}
+			return n, nil
+		}
+		if wtyp != wire.Fixed64Type {
+			return 0, errUnknown
+		}
+		v, n := wire.ConsumeFixed64(b)
+		if n < 0 {
+			return 0, wire.ParseError(n)
+		}
+		list.Append(protoreflect.ValueOf(math.Float64frombits(v)))
+		return n, nil
+	case protoreflect.StringKind:
+		if wtyp != wire.BytesType {
+			return 0, errUnknown
+		}
+		v, n := wire.ConsumeBytes(b)
+		if n < 0 {
+			return 0, wire.ParseError(n)
+		}
+		list.Append(protoreflect.ValueOf(string(v)))
+		return n, nil
+	case protoreflect.BytesKind:
+		if wtyp != wire.BytesType {
+			return 0, errUnknown
+		}
+		v, n := wire.ConsumeBytes(b)
+		if n < 0 {
+			return 0, wire.ParseError(n)
+		}
+		list.Append(protoreflect.ValueOf(append(([]byte)(nil), v...)))
+		return n, nil
+	case protoreflect.MessageKind:
+		if wtyp != wire.BytesType {
+			return 0, errUnknown
+		}
+		v, n := wire.ConsumeBytes(b)
+		if n < 0 {
+			return 0, wire.ParseError(n)
+		}
+		m := list.NewMessage().ProtoReflect()
+		if err := o.unmarshalMessage(v, m); err != nil {
+			return 0, err
+		}
+		list.Append(protoreflect.ValueOf(m))
+		return n, nil
+	case protoreflect.GroupKind:
+		if wtyp != wire.StartGroupType {
+			return 0, errUnknown
+		}
+		v, n := wire.ConsumeGroup(num, b)
+		if n < 0 {
+			return 0, wire.ParseError(n)
+		}
+		m := list.NewMessage().ProtoReflect()
+		if err := o.unmarshalMessage(v, m); err != nil {
+			return 0, err
+		}
+		list.Append(protoreflect.ValueOf(m))
+		return n, nil
+	default:
+		return 0, errUnknown
+	}
+}
diff --git a/proto/decode_test.go b/proto/decode_test.go
new file mode 100644
index 00000000..9560ab89
--- /dev/null
+++ b/proto/decode_test.go
@@ -0,0 +1,749 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style.
+// license that can be found in the LICENSE file.
+
+package proto
+
+import (
+	"fmt"
+	"reflect"
+	"testing"
+
+	protoV1 "github.com/golang/protobuf/proto"
+	"github.com/golang/protobuf/v2/internal/encoding/pack"
+	_ "github.com/golang/protobuf/v2/internal/legacy"
+	"github.com/golang/protobuf/v2/internal/scalar"
+	testpb "github.com/golang/protobuf/v2/internal/testprotos/test"
+	pref "github.com/golang/protobuf/v2/reflect/protoreflect"
+)
+
+type testProto struct {
+	desc     string
+	decodeTo []Message
+	wire     []byte
+}
+
+func TestDecode(t *testing.T) {
+	for _, test := range testProtos {
+		for _, want := range test.decodeTo {
+			t.Run(fmt.Sprintf("%s (%T)", test.desc, want), func(t *testing.T) {
+				wire := append(([]byte)(nil), test.wire...)
+				got := reflect.New(reflect.TypeOf(want).Elem()).Interface().(Message)
+				if err := Unmarshal(wire, got); err != nil {
+					t.Errorf("Unmarshal error: %v\nMessage:\n%v", err, protoV1.MarshalTextString(want.(protoV1.Message)))
+					return
+				}
+
+				// Aliasing check: Modifying the original wire bytes shouldn't
+				// affect the unmarshaled message.
+				for i := range wire {
+					wire[i] = 0
+				}
+
+				if !protoV1.Equal(got.(protoV1.Message), want.(protoV1.Message)) {
+					t.Errorf("Unmarshal returned unexpected result; got:\n%v\nwant:\n%v", protoV1.MarshalTextString(got.(protoV1.Message)), protoV1.MarshalTextString(want.(protoV1.Message)))
+				}
+			})
+		}
+	}
+}
+
+var testProtos = []testProto{
+	{
+		desc: "basic scalar types",
+		decodeTo: []Message{&testpb.TestAllTypes{
+			OptionalInt32:      scalar.Int32(1001),
+			OptionalInt64:      scalar.Int64(1002),
+			OptionalUint32:     scalar.Uint32(1003),
+			OptionalUint64:     scalar.Uint64(1004),
+			OptionalSint32:     scalar.Int32(1005),
+			OptionalSint64:     scalar.Int64(1006),
+			OptionalFixed32:    scalar.Uint32(1007),
+			OptionalFixed64:    scalar.Uint64(1008),
+			OptionalSfixed32:   scalar.Int32(1009),
+			OptionalSfixed64:   scalar.Int64(1010),
+			OptionalFloat:      scalar.Float32(1011.5),
+			OptionalDouble:     scalar.Float64(1012.5),
+			OptionalBool:       scalar.Bool(true),
+			OptionalString:     scalar.String("string"),
+			OptionalBytes:      []byte("bytes"),
+			OptionalNestedEnum: testpb.TestAllTypes_BAR.Enum(),
+		}, build(
+			&testpb.TestAllExtensions{},
+			extend(testpb.E_OptionalInt32Extension, scalar.Int32(1001)),
+			extend(testpb.E_OptionalInt64Extension, scalar.Int64(1002)),
+			extend(testpb.E_OptionalUint32Extension, scalar.Uint32(1003)),
+			extend(testpb.E_OptionalUint64Extension, scalar.Uint64(1004)),
+			extend(testpb.E_OptionalSint32Extension, scalar.Int32(1005)),
+			extend(testpb.E_OptionalSint64Extension, scalar.Int64(1006)),
+			extend(testpb.E_OptionalFixed32Extension, scalar.Uint32(1007)),
+			extend(testpb.E_OptionalFixed64Extension, scalar.Uint64(1008)),
+			extend(testpb.E_OptionalSfixed32Extension, scalar.Int32(1009)),
+			extend(testpb.E_OptionalSfixed64Extension, scalar.Int64(1010)),
+			extend(testpb.E_OptionalFloatExtension, scalar.Float32(1011.5)),
+			extend(testpb.E_OptionalDoubleExtension, scalar.Float64(1012.5)),
+			extend(testpb.E_OptionalBoolExtension, scalar.Bool(true)),
+			extend(testpb.E_OptionalStringExtension, scalar.String("string")),
+			extend(testpb.E_OptionalBytesExtension, []byte("bytes")),
+			extend(testpb.E_OptionalNestedEnumExtension, testpb.TestAllTypes_BAR.Enum()),
+		)},
+		wire: pack.Message{
+			pack.Tag{1, pack.VarintType}, pack.Varint(1001),
+			pack.Tag{2, pack.VarintType}, pack.Varint(1002),
+			pack.Tag{3, pack.VarintType}, pack.Uvarint(1003),
+			pack.Tag{4, pack.VarintType}, pack.Uvarint(1004),
+			pack.Tag{5, pack.VarintType}, pack.Svarint(1005),
+			pack.Tag{6, pack.VarintType}, pack.Svarint(1006),
+			pack.Tag{7, pack.Fixed32Type}, pack.Uint32(1007),
+			pack.Tag{8, pack.Fixed64Type}, pack.Uint64(1008),
+			pack.Tag{9, pack.Fixed32Type}, pack.Int32(1009),
+			pack.Tag{10, pack.Fixed64Type}, pack.Int64(1010),
+			pack.Tag{11, pack.Fixed32Type}, pack.Float32(1011.5),
+			pack.Tag{12, pack.Fixed64Type}, pack.Float64(1012.5),
+			pack.Tag{13, pack.VarintType}, pack.Bool(true),
+			pack.Tag{14, pack.BytesType}, pack.String("string"),
+			pack.Tag{15, pack.BytesType}, pack.Bytes([]byte("bytes")),
+			pack.Tag{21, pack.VarintType}, pack.Varint(int(testpb.TestAllTypes_BAR)),
+		}.Marshal(),
+	},
+	{
+		desc: "groups",
+		decodeTo: []Message{&testpb.TestAllTypes{
+			Optionalgroup: &testpb.TestAllTypes_OptionalGroup{
+				A: scalar.Int32(1017),
+			},
+		}, build(
+			&testpb.TestAllExtensions{},
+			extend(testpb.E_OptionalgroupExtension, &testpb.OptionalGroupExtension{
+				A: scalar.Int32(1017),
+			}),
+		)},
+		wire: pack.Message{
+			pack.Tag{16, pack.StartGroupType},
+			pack.Tag{17, pack.VarintType}, pack.Varint(1017),
+			pack.Tag{16, pack.EndGroupType},
+		}.Marshal(),
+	},
+	{
+		desc: "groups (field overridden)",
+		decodeTo: []Message{&testpb.TestAllTypes{
+			Optionalgroup: &testpb.TestAllTypes_OptionalGroup{
+				A: scalar.Int32(2),
+			},
+		}, build(
+			&testpb.TestAllExtensions{},
+			extend(testpb.E_OptionalgroupExtension, &testpb.OptionalGroupExtension{
+				A: scalar.Int32(2),
+			}),
+		)},
+		wire: pack.Message{
+			pack.Tag{16, pack.StartGroupType},
+			pack.Tag{17, pack.VarintType}, pack.Varint(1),
+			pack.Tag{16, pack.EndGroupType},
+			pack.Tag{16, pack.StartGroupType},
+			pack.Tag{17, pack.VarintType}, pack.Varint(2),
+			pack.Tag{16, pack.EndGroupType},
+		}.Marshal(),
+	},
+	{
+		desc: "messages",
+		decodeTo: []Message{&testpb.TestAllTypes{
+			OptionalNestedMessage: &testpb.TestAllTypes_NestedMessage{
+				A: scalar.Int32(42),
+				Corecursive: &testpb.TestAllTypes{
+					OptionalInt32: scalar.Int32(43),
+				},
+			},
+		}, build(
+			&testpb.TestAllExtensions{},
+			extend(testpb.E_OptionalNestedMessageExtension, &testpb.TestAllTypes_NestedMessage{
+				A: scalar.Int32(42),
+				Corecursive: &testpb.TestAllTypes{
+					OptionalInt32: scalar.Int32(43),
+				},
+			}),
+		)},
+		wire: pack.Message{
+			pack.Tag{18, pack.BytesType}, pack.LengthPrefix(pack.Message{
+				pack.Tag{1, pack.VarintType}, pack.Varint(42),
+				pack.Tag{2, pack.BytesType}, pack.LengthPrefix(pack.Message{
+					pack.Tag{1, pack.VarintType}, pack.Varint(43),
+				}),
+			}),
+		}.Marshal(),
+	},
+	{
+		desc: "messages (split across multiple tags)",
+		decodeTo: []Message{&testpb.TestAllTypes{
+			OptionalNestedMessage: &testpb.TestAllTypes_NestedMessage{
+				A: scalar.Int32(42),
+				Corecursive: &testpb.TestAllTypes{
+					OptionalInt32: scalar.Int32(43),
+				},
+			},
+		}, build(
+			&testpb.TestAllExtensions{},
+			extend(testpb.E_OptionalNestedMessageExtension, &testpb.TestAllTypes_NestedMessage{
+				A: scalar.Int32(42),
+				Corecursive: &testpb.TestAllTypes{
+					OptionalInt32: scalar.Int32(43),
+				},
+			}),
+		)},
+		wire: pack.Message{
+			pack.Tag{18, pack.BytesType}, pack.LengthPrefix(pack.Message{
+				pack.Tag{1, pack.VarintType}, pack.Varint(42),
+			}),
+			pack.Tag{18, pack.BytesType}, pack.LengthPrefix(pack.Message{
+				pack.Tag{2, pack.BytesType}, pack.LengthPrefix(pack.Message{
+					pack.Tag{1, pack.VarintType}, pack.Varint(43),
+				}),
+			}),
+		}.Marshal(),
+	},
+	{
+		desc: "messages (field overridden)",
+		decodeTo: []Message{&testpb.TestAllTypes{
+			OptionalNestedMessage: &testpb.TestAllTypes_NestedMessage{
+				A: scalar.Int32(2),
+			},
+		}, build(
+			&testpb.TestAllExtensions{},
+			extend(testpb.E_OptionalNestedMessageExtension, &testpb.TestAllTypes_NestedMessage{
+				A: scalar.Int32(2),
+			}),
+		)},
+		wire: pack.Message{
+			pack.Tag{18, pack.BytesType}, pack.LengthPrefix(pack.Message{
+				pack.Tag{1, pack.VarintType}, pack.Varint(1),
+			}),
+			pack.Tag{18, pack.BytesType}, pack.LengthPrefix(pack.Message{
+				pack.Tag{1, pack.VarintType}, pack.Varint(2),
+			}),
+		}.Marshal(),
+	},
+	{
+		desc: "basic repeated types",
+		decodeTo: []Message{&testpb.TestAllTypes{
+			RepeatedInt32:    []int32{1001, 2001},
+			RepeatedInt64:    []int64{1002, 2002},
+			RepeatedUint32:   []uint32{1003, 2003},
+			RepeatedUint64:   []uint64{1004, 2004},
+			RepeatedSint32:   []int32{1005, 2005},
+			RepeatedSint64:   []int64{1006, 2006},
+			RepeatedFixed32:  []uint32{1007, 2007},
+			RepeatedFixed64:  []uint64{1008, 2008},
+			RepeatedSfixed32: []int32{1009, 2009},
+			RepeatedSfixed64: []int64{1010, 2010},
+			RepeatedFloat:    []float32{1011.5, 2011.5},
+			RepeatedDouble:   []float64{1012.5, 2012.5},
+			RepeatedBool:     []bool{true, false},
+			RepeatedString:   []string{"foo", "bar"},
+			RepeatedBytes:    [][]byte{[]byte("FOO"), []byte("BAR")},
+			RepeatedNestedEnum: []testpb.TestAllTypes_NestedEnum{
+				testpb.TestAllTypes_FOO,
+				testpb.TestAllTypes_BAR,
+			},
+		}, build(
+			&testpb.TestAllExtensions{},
+			extend(testpb.E_RepeatedInt32Extension, []int32{1001, 2001}),
+			extend(testpb.E_RepeatedInt64Extension, []int64{1002, 2002}),
+			extend(testpb.E_RepeatedUint32Extension, []uint32{1003, 2003}),
+			extend(testpb.E_RepeatedUint64Extension, []uint64{1004, 2004}),
+			extend(testpb.E_RepeatedSint32Extension, []int32{1005, 2005}),
+			extend(testpb.E_RepeatedSint64Extension, []int64{1006, 2006}),
+			extend(testpb.E_RepeatedFixed32Extension, []uint32{1007, 2007}),
+			extend(testpb.E_RepeatedFixed64Extension, []uint64{1008, 2008}),
+			extend(testpb.E_RepeatedSfixed32Extension, []int32{1009, 2009}),
+			extend(testpb.E_RepeatedSfixed64Extension, []int64{1010, 2010}),
+			extend(testpb.E_RepeatedFloatExtension, []float32{1011.5, 2011.5}),
+			extend(testpb.E_RepeatedDoubleExtension, []float64{1012.5, 2012.5}),
+			extend(testpb.E_RepeatedBoolExtension, []bool{true, false}),
+			extend(testpb.E_RepeatedStringExtension, []string{"foo", "bar"}),
+			extend(testpb.E_RepeatedBytesExtension, [][]byte{[]byte("FOO"), []byte("BAR")}),
+			extend(testpb.E_RepeatedNestedEnumExtension, []testpb.TestAllTypes_NestedEnum{
+				testpb.TestAllTypes_FOO,
+				testpb.TestAllTypes_BAR,
+			}),
+		)},
+		wire: pack.Message{
+			pack.Tag{31, pack.VarintType}, pack.Varint(1001),
+			pack.Tag{31, pack.VarintType}, pack.Varint(2001),
+			pack.Tag{32, pack.VarintType}, pack.Varint(1002),
+			pack.Tag{32, pack.VarintType}, pack.Varint(2002),
+			pack.Tag{33, pack.VarintType}, pack.Uvarint(1003),
+			pack.Tag{33, pack.VarintType}, pack.Uvarint(2003),
+			pack.Tag{34, pack.VarintType}, pack.Uvarint(1004),
+			pack.Tag{34, pack.VarintType}, pack.Uvarint(2004),
+			pack.Tag{35, pack.VarintType}, pack.Svarint(1005),
+			pack.Tag{35, pack.VarintType}, pack.Svarint(2005),
+			pack.Tag{36, pack.VarintType}, pack.Svarint(1006),
+			pack.Tag{36, pack.VarintType}, pack.Svarint(2006),
+			pack.Tag{37, pack.Fixed32Type}, pack.Uint32(1007),
+			pack.Tag{37, pack.Fixed32Type}, pack.Uint32(2007),
+			pack.Tag{38, pack.Fixed64Type}, pack.Uint64(1008),
+			pack.Tag{38, pack.Fixed64Type}, pack.Uint64(2008),
+			pack.Tag{39, pack.Fixed32Type}, pack.Int32(1009),
+			pack.Tag{39, pack.Fixed32Type}, pack.Int32(2009),
+			pack.Tag{40, pack.Fixed64Type}, pack.Int64(1010),
+			pack.Tag{40, pack.Fixed64Type}, pack.Int64(2010),
+			pack.Tag{41, pack.Fixed32Type}, pack.Float32(1011.5),
+			pack.Tag{41, pack.Fixed32Type}, pack.Float32(2011.5),
+			pack.Tag{42, pack.Fixed64Type}, pack.Float64(1012.5),
+			pack.Tag{42, pack.Fixed64Type}, pack.Float64(2012.5),
+			pack.Tag{43, pack.VarintType}, pack.Bool(true),
+			pack.Tag{43, pack.VarintType}, pack.Bool(false),
+			pack.Tag{44, pack.BytesType}, pack.String("foo"),
+			pack.Tag{44, pack.BytesType}, pack.String("bar"),
+			pack.Tag{45, pack.BytesType}, pack.Bytes([]byte("FOO")),
+			pack.Tag{45, pack.BytesType}, pack.Bytes([]byte("BAR")),
+			pack.Tag{51, pack.VarintType}, pack.Varint(int(testpb.TestAllTypes_FOO)),
+			pack.Tag{51, pack.VarintType}, pack.Varint(int(testpb.TestAllTypes_BAR)),
+		}.Marshal(),
+	},
+	{
+		desc: "basic repeated types (packed encoding)",
+		decodeTo: []Message{&testpb.TestAllTypes{
+			RepeatedInt32:    []int32{1001, 2001},
+			RepeatedInt64:    []int64{1002, 2002},
+			RepeatedUint32:   []uint32{1003, 2003},
+			RepeatedUint64:   []uint64{1004, 2004},
+			RepeatedSint32:   []int32{1005, 2005},
+			RepeatedSint64:   []int64{1006, 2006},
+			RepeatedFixed32:  []uint32{1007, 2007},
+			RepeatedFixed64:  []uint64{1008, 2008},
+			RepeatedSfixed32: []int32{1009, 2009},
+			RepeatedSfixed64: []int64{1010, 2010},
+			RepeatedFloat:    []float32{1011.5, 2011.5},
+			RepeatedDouble:   []float64{1012.5, 2012.5},
+			RepeatedBool:     []bool{true, false},
+			RepeatedNestedEnum: []testpb.TestAllTypes_NestedEnum{
+				testpb.TestAllTypes_FOO,
+				testpb.TestAllTypes_BAR,
+			},
+		}, build(
+			&testpb.TestAllExtensions{},
+			extend(testpb.E_RepeatedInt32Extension, []int32{1001, 2001}),
+			extend(testpb.E_RepeatedInt64Extension, []int64{1002, 2002}),
+			extend(testpb.E_RepeatedUint32Extension, []uint32{1003, 2003}),
+			extend(testpb.E_RepeatedUint64Extension, []uint64{1004, 2004}),
+			extend(testpb.E_RepeatedSint32Extension, []int32{1005, 2005}),
+			extend(testpb.E_RepeatedSint64Extension, []int64{1006, 2006}),
+			extend(testpb.E_RepeatedFixed32Extension, []uint32{1007, 2007}),
+			extend(testpb.E_RepeatedFixed64Extension, []uint64{1008, 2008}),
+			extend(testpb.E_RepeatedSfixed32Extension, []int32{1009, 2009}),
+			extend(testpb.E_RepeatedSfixed64Extension, []int64{1010, 2010}),
+			extend(testpb.E_RepeatedFloatExtension, []float32{1011.5, 2011.5}),
+			extend(testpb.E_RepeatedDoubleExtension, []float64{1012.5, 2012.5}),
+			extend(testpb.E_RepeatedBoolExtension, []bool{true, false}),
+			extend(testpb.E_RepeatedNestedEnumExtension, []testpb.TestAllTypes_NestedEnum{
+				testpb.TestAllTypes_FOO,
+				testpb.TestAllTypes_BAR,
+			}),
+		)},
+		wire: pack.Message{
+			pack.Tag{31, pack.BytesType}, pack.LengthPrefix{
+				pack.Varint(1001), pack.Varint(2001),
+			},
+			pack.Tag{32, pack.BytesType}, pack.LengthPrefix{
+				pack.Varint(1002), pack.Varint(2002),
+			},
+			pack.Tag{33, pack.BytesType}, pack.LengthPrefix{
+				pack.Uvarint(1003), pack.Uvarint(2003),
+			},
+			pack.Tag{34, pack.BytesType}, pack.LengthPrefix{
+				pack.Uvarint(1004), pack.Uvarint(2004),
+			},
+			pack.Tag{35, pack.BytesType}, pack.LengthPrefix{
+				pack.Svarint(1005), pack.Svarint(2005),
+			},
+			pack.Tag{36, pack.BytesType}, pack.LengthPrefix{
+				pack.Svarint(1006), pack.Svarint(2006),
+			},
+			pack.Tag{37, pack.BytesType}, pack.LengthPrefix{
+				pack.Uint32(1007), pack.Uint32(2007),
+			},
+			pack.Tag{38, pack.BytesType}, pack.LengthPrefix{
+				pack.Uint64(1008), pack.Uint64(2008),
+			},
+			pack.Tag{39, pack.BytesType}, pack.LengthPrefix{
+				pack.Int32(1009), pack.Int32(2009),
+			},
+			pack.Tag{40, pack.BytesType}, pack.LengthPrefix{
+				pack.Int64(1010), pack.Int64(2010),
+			},
+			pack.Tag{41, pack.BytesType}, pack.LengthPrefix{
+				pack.Float32(1011.5), pack.Float32(2011.5),
+			},
+			pack.Tag{42, pack.BytesType}, pack.LengthPrefix{
+				pack.Float64(1012.5), pack.Float64(2012.5),
+			},
+			pack.Tag{43, pack.BytesType}, pack.LengthPrefix{
+				pack.Bool(true), pack.Bool(false),
+			},
+			pack.Tag{51, pack.BytesType}, pack.LengthPrefix{
+				pack.Varint(int(testpb.TestAllTypes_FOO)),
+				pack.Varint(int(testpb.TestAllTypes_BAR)),
+			},
+		}.Marshal(),
+	},
+	{
+		desc: "repeated messages",
+		decodeTo: []Message{&testpb.TestAllTypes{
+			RepeatedNestedMessage: []*testpb.TestAllTypes_NestedMessage{
+				{A: scalar.Int32(1)},
+				{A: scalar.Int32(2)},
+			},
+		}, build(
+			&testpb.TestAllExtensions{},
+			extend(testpb.E_RepeatedNestedMessageExtension, []*testpb.TestAllTypes_NestedMessage{
+				{A: scalar.Int32(1)},
+				{A: scalar.Int32(2)},
+			}),
+		)},
+		wire: pack.Message{
+			pack.Tag{48, pack.BytesType}, pack.LengthPrefix(pack.Message{
+				pack.Tag{1, pack.VarintType}, pack.Varint(1),
+			}),
+			pack.Tag{48, pack.BytesType}, pack.LengthPrefix(pack.Message{
+				pack.Tag{1, pack.VarintType}, pack.Varint(2),
+			}),
+		}.Marshal(),
+	},
+	{
+		desc: "repeated groups",
+		decodeTo: []Message{&testpb.TestAllTypes{
+			Repeatedgroup: []*testpb.TestAllTypes_RepeatedGroup{
+				{A: scalar.Int32(1017)},
+				{A: scalar.Int32(2017)},
+			},
+		}, build(
+			&testpb.TestAllExtensions{},
+			extend(testpb.E_RepeatedgroupExtension, []*testpb.RepeatedGroupExtension{
+				{A: scalar.Int32(1017)},
+				{A: scalar.Int32(2017)},
+			}),
+		)},
+		wire: pack.Message{
+			pack.Tag{46, pack.StartGroupType},
+			pack.Tag{47, pack.VarintType}, pack.Varint(1017),
+			pack.Tag{46, pack.EndGroupType},
+			pack.Tag{46, pack.StartGroupType},
+			pack.Tag{47, pack.VarintType}, pack.Varint(2017),
+			pack.Tag{46, pack.EndGroupType},
+		}.Marshal(),
+	},
+	{
+		desc: "maps",
+		decodeTo: []Message{&testpb.TestAllTypes{
+			MapInt32Int32:       map[int32]int32{1056: 1156, 2056: 2156},
+			MapInt64Int64:       map[int64]int64{1057: 1157, 2057: 2157},
+			MapUint32Uint32:     map[uint32]uint32{1058: 1158, 2058: 2158},
+			MapUint64Uint64:     map[uint64]uint64{1059: 1159, 2059: 2159},
+			MapSint32Sint32:     map[int32]int32{1060: 1160, 2060: 2160},
+			MapSint64Sint64:     map[int64]int64{1061: 1161, 2061: 2161},
+			MapFixed32Fixed32:   map[uint32]uint32{1062: 1162, 2062: 2162},
+			MapFixed64Fixed64:   map[uint64]uint64{1063: 1163, 2063: 2163},
+			MapSfixed32Sfixed32: map[int32]int32{1064: 1164, 2064: 2164},
+			MapSfixed64Sfixed64: map[int64]int64{1065: 1165, 2065: 2165},
+			MapInt32Float:       map[int32]float32{1066: 1166.5, 2066: 2166.5},
+			MapInt32Double:      map[int32]float64{1067: 1167.5, 2067: 2167.5},
+			MapBoolBool:         map[bool]bool{true: false, false: true},
+			MapStringString:     map[string]string{"69.1.key": "69.1.val", "69.2.key": "69.2.val"},
+			MapStringBytes:      map[string][]byte{"70.1.key": []byte("70.1.val"), "70.2.key": []byte("70.2.val")},
+			MapStringNestedMessage: map[string]*testpb.TestAllTypes_NestedMessage{
+				"71.1.key": {A: scalar.Int32(1171)},
+				"71.2.key": {A: scalar.Int32(2171)},
+			},
+			MapStringNestedEnum: map[string]testpb.TestAllTypes_NestedEnum{
+				"73.1.key": testpb.TestAllTypes_FOO,
+				"73.2.key": testpb.TestAllTypes_BAR,
+			},
+		}},
+		wire: pack.Message{
+			pack.Tag{56, pack.BytesType}, pack.LengthPrefix(pack.Message{
+				pack.Tag{1, pack.VarintType}, pack.Varint(1056),
+				pack.Tag{2, pack.VarintType}, pack.Varint(1156),
+			}),
+			pack.Tag{56, pack.BytesType}, pack.LengthPrefix(pack.Message{
+				pack.Tag{1, pack.VarintType}, pack.Varint(2056),
+				pack.Tag{2, pack.VarintType}, pack.Varint(2156),
+			}),
+			pack.Tag{57, pack.BytesType}, pack.LengthPrefix(pack.Message{
+				pack.Tag{1, pack.VarintType}, pack.Varint(1057),
+				pack.Tag{2, pack.VarintType}, pack.Varint(1157),
+			}),
+			pack.Tag{57, pack.BytesType}, pack.LengthPrefix(pack.Message{
+				pack.Tag{1, pack.VarintType}, pack.Varint(2057),
+				pack.Tag{2, pack.VarintType}, pack.Varint(2157),
+			}),
+			pack.Tag{58, pack.BytesType}, pack.LengthPrefix(pack.Message{
+				pack.Tag{1, pack.VarintType}, pack.Varint(1058),
+				pack.Tag{2, pack.VarintType}, pack.Varint(1158),
+			}),
+			pack.Tag{58, pack.BytesType}, pack.LengthPrefix(pack.Message{
+				pack.Tag{1, pack.VarintType}, pack.Varint(2058),
+				pack.Tag{2, pack.VarintType}, pack.Varint(2158),
+			}),
+			pack.Tag{59, pack.BytesType}, pack.LengthPrefix(pack.Message{
+				pack.Tag{1, pack.VarintType}, pack.Varint(1059),
+				pack.Tag{2, pack.VarintType}, pack.Varint(1159),
+			}),
+			pack.Tag{59, pack.BytesType}, pack.LengthPrefix(pack.Message{
+				pack.Tag{1, pack.VarintType}, pack.Varint(2059),
+				pack.Tag{2, pack.VarintType}, pack.Varint(2159),
+			}),
+			pack.Tag{60, pack.BytesType}, pack.LengthPrefix(pack.Message{
+				pack.Tag{1, pack.VarintType}, pack.Svarint(1060),
+				pack.Tag{2, pack.VarintType}, pack.Svarint(1160),
+			}),
+			pack.Tag{60, pack.BytesType}, pack.LengthPrefix(pack.Message{
+				pack.Tag{1, pack.VarintType}, pack.Svarint(2060),
+				pack.Tag{2, pack.VarintType}, pack.Svarint(2160),
+			}),
+			pack.Tag{61, pack.BytesType}, pack.LengthPrefix(pack.Message{
+				pack.Tag{1, pack.VarintType}, pack.Svarint(1061),
+				pack.Tag{2, pack.VarintType}, pack.Svarint(1161),
+			}),
+			pack.Tag{61, pack.BytesType}, pack.LengthPrefix(pack.Message{
+				pack.Tag{1, pack.VarintType}, pack.Svarint(2061),
+				pack.Tag{2, pack.VarintType}, pack.Svarint(2161),
+			}),
+			pack.Tag{62, pack.BytesType}, pack.LengthPrefix(pack.Message{
+				pack.Tag{1, pack.Fixed32Type}, pack.Int32(1062),
+				pack.Tag{2, pack.Fixed32Type}, pack.Int32(1162),
+			}),
+			pack.Tag{62, pack.BytesType}, pack.LengthPrefix(pack.Message{
+				pack.Tag{1, pack.Fixed32Type}, pack.Int32(2062),
+				pack.Tag{2, pack.Fixed32Type}, pack.Int32(2162),
+			}),
+			pack.Tag{63, pack.BytesType}, pack.LengthPrefix(pack.Message{
+				pack.Tag{1, pack.Fixed64Type}, pack.Int64(1063),
+				pack.Tag{2, pack.Fixed64Type}, pack.Int64(1163),
+			}),
+			pack.Tag{63, pack.BytesType}, pack.LengthPrefix(pack.Message{
+				pack.Tag{1, pack.Fixed64Type}, pack.Int64(2063),
+				pack.Tag{2, pack.Fixed64Type}, pack.Int64(2163),
+			}),
+			pack.Tag{64, pack.BytesType}, pack.LengthPrefix(pack.Message{
+				pack.Tag{1, pack.Fixed32Type}, pack.Int32(1064),
+				pack.Tag{2, pack.Fixed32Type}, pack.Int32(1164),
+			}),
+			pack.Tag{64, pack.BytesType}, pack.LengthPrefix(pack.Message{
+				pack.Tag{1, pack.Fixed32Type}, pack.Int32(2064),
+				pack.Tag{2, pack.Fixed32Type}, pack.Int32(2164),
+			}),
+			pack.Tag{65, pack.BytesType}, pack.LengthPrefix(pack.Message{
+				pack.Tag{1, pack.Fixed64Type}, pack.Int64(1065),
+				pack.Tag{2, pack.Fixed64Type}, pack.Int64(1165),
+			}),
+			pack.Tag{65, pack.BytesType}, pack.LengthPrefix(pack.Message{
+				pack.Tag{1, pack.Fixed64Type}, pack.Int64(2065),
+				pack.Tag{2, pack.Fixed64Type}, pack.Int64(2165),
+			}),
+			pack.Tag{66, pack.BytesType}, pack.LengthPrefix(pack.Message{
+				pack.Tag{1, pack.VarintType}, pack.Varint(1066),
+				pack.Tag{2, pack.Fixed32Type}, pack.Float32(1166.5),
+			}),
+			pack.Tag{66, pack.BytesType}, pack.LengthPrefix(pack.Message{
+				pack.Tag{1, pack.VarintType}, pack.Varint(2066),
+				pack.Tag{2, pack.Fixed32Type}, pack.Float32(2166.5),
+			}),
+			pack.Tag{67, pack.BytesType}, pack.LengthPrefix(pack.Message{
+				pack.Tag{1, pack.VarintType}, pack.Varint(1067),
+				pack.Tag{2, pack.Fixed64Type}, pack.Float64(1167.5),
+			}),
+			pack.Tag{67, pack.BytesType}, pack.LengthPrefix(pack.Message{
+				pack.Tag{1, pack.VarintType}, pack.Varint(2067),
+				pack.Tag{2, pack.Fixed64Type}, pack.Float64(2167.5),
+			}),
+			pack.Tag{68, pack.BytesType}, pack.LengthPrefix(pack.Message{
+				pack.Tag{1, pack.VarintType}, pack.Bool(true),
+				pack.Tag{2, pack.VarintType}, pack.Bool(false),
+			}),
+			pack.Tag{68, pack.BytesType}, pack.LengthPrefix(pack.Message{
+				pack.Tag{1, pack.VarintType}, pack.Bool(false),
+				pack.Tag{2, pack.VarintType}, pack.Bool(true),
+			}),
+			pack.Tag{69, pack.BytesType}, pack.LengthPrefix(pack.Message{
+				pack.Tag{1, pack.BytesType}, pack.String("69.1.key"),
+				pack.Tag{2, pack.BytesType}, pack.String("69.1.val"),
+			}),
+			pack.Tag{69, pack.BytesType}, pack.LengthPrefix(pack.Message{
+				pack.Tag{1, pack.BytesType}, pack.String("69.2.key"),
+				pack.Tag{2, pack.BytesType}, pack.String("69.2.val"),
+			}),
+			pack.Tag{70, pack.BytesType}, pack.LengthPrefix(pack.Message{
+				pack.Tag{1, pack.BytesType}, pack.String("70.1.key"),
+				pack.Tag{2, pack.BytesType}, pack.String("70.1.val"),
+			}),
+			pack.Tag{70, pack.BytesType}, pack.LengthPrefix(pack.Message{
+				pack.Tag{1, pack.BytesType}, pack.String("70.2.key"),
+				pack.Tag{2, pack.BytesType}, pack.String("70.2.val"),
+			}),
+			pack.Tag{71, pack.BytesType}, pack.LengthPrefix(pack.Message{
+				pack.Tag{1, pack.BytesType}, pack.String("71.1.key"),
+				pack.Tag{2, pack.BytesType}, pack.LengthPrefix(pack.Message{
+					pack.Tag{1, pack.VarintType}, pack.Varint(1171),
+				}),
+			}),
+			pack.Tag{71, pack.BytesType}, pack.LengthPrefix(pack.Message{
+				pack.Tag{1, pack.BytesType}, pack.String("71.2.key"),
+				pack.Tag{2, pack.BytesType}, pack.LengthPrefix(pack.Message{
+					pack.Tag{1, pack.VarintType}, pack.Varint(2171),
+				}),
+			}),
+			pack.Tag{73, pack.BytesType}, pack.LengthPrefix(pack.Message{
+				pack.Tag{1, pack.BytesType}, pack.String("73.1.key"),
+				pack.Tag{2, pack.VarintType}, pack.Varint(int(testpb.TestAllTypes_FOO)),
+			}),
+			pack.Tag{73, pack.BytesType}, pack.LengthPrefix(pack.Message{
+				pack.Tag{1, pack.BytesType}, pack.String("73.2.key"),
+				pack.Tag{2, pack.VarintType}, pack.Varint(int(testpb.TestAllTypes_BAR)),
+			}),
+		}.Marshal(),
+	},
+	{
+		desc:     "oneof (uint32)",
+		decodeTo: []Message{&testpb.TestAllTypes{OneofField: &testpb.TestAllTypes_OneofUint32{1111}}},
+		wire:     pack.Message{pack.Tag{111, pack.VarintType}, pack.Varint(1111)}.Marshal(),
+	},
+	{
+		desc: "oneof (message)",
+		decodeTo: []Message{&testpb.TestAllTypes{OneofField: &testpb.TestAllTypes_OneofNestedMessage{
+			&testpb.TestAllTypes_NestedMessage{A: scalar.Int32(1112)},
+		}}},
+		wire: pack.Message{pack.Tag{112, pack.BytesType}, pack.LengthPrefix(pack.Message{
+			pack.Message{pack.Tag{1, pack.VarintType}, pack.Varint(1112)},
+		})}.Marshal(),
+	},
+	{
+		desc: "oneof (overridden message)",
+		decodeTo: []Message{&testpb.TestAllTypes{OneofField: &testpb.TestAllTypes_OneofNestedMessage{
+			&testpb.TestAllTypes_NestedMessage{
+				Corecursive: &testpb.TestAllTypes{
+					OptionalInt32: scalar.Int32(43),
+				},
+			},
+		}}},
+		wire: pack.Message{
+			pack.Tag{112, pack.BytesType}, pack.LengthPrefix(pack.Message{
+				pack.Message{pack.Tag{1, pack.VarintType}, pack.Varint(1)},
+			}),
+			pack.Tag{112, pack.BytesType}, pack.LengthPrefix(pack.Message{
+				pack.Tag{2, pack.BytesType}, pack.LengthPrefix(pack.Message{
+					pack.Tag{1, pack.VarintType}, pack.Varint(43),
+				}),
+			}),
+		}.Marshal(),
+	},
+	{
+		desc:     "oneof (string)",
+		decodeTo: []Message{&testpb.TestAllTypes{OneofField: &testpb.TestAllTypes_OneofString{"1113"}}},
+		wire:     pack.Message{pack.Tag{113, pack.BytesType}, pack.String("1113")}.Marshal(),
+	},
+	{
+		desc:     "oneof (bytes)",
+		decodeTo: []Message{&testpb.TestAllTypes{OneofField: &testpb.TestAllTypes_OneofBytes{[]byte("1114")}}},
+		wire:     pack.Message{pack.Tag{114, pack.BytesType}, pack.String("1114")}.Marshal(),
+	},
+	{
+		desc:     "oneof (bool)",
+		decodeTo: []Message{&testpb.TestAllTypes{OneofField: &testpb.TestAllTypes_OneofBool{true}}},
+		wire:     pack.Message{pack.Tag{115, pack.VarintType}, pack.Bool(true)}.Marshal(),
+	},
+	{
+		desc:     "oneof (uint64)",
+		decodeTo: []Message{&testpb.TestAllTypes{OneofField: &testpb.TestAllTypes_OneofUint64{116}}},
+		wire:     pack.Message{pack.Tag{116, pack.VarintType}, pack.Varint(116)}.Marshal(),
+	},
+	{
+		desc:     "oneof (float)",
+		decodeTo: []Message{&testpb.TestAllTypes{OneofField: &testpb.TestAllTypes_OneofFloat{117.5}}},
+		wire:     pack.Message{pack.Tag{117, pack.Fixed32Type}, pack.Float32(117.5)}.Marshal(),
+	},
+	{
+		desc:     "oneof (double)",
+		decodeTo: []Message{&testpb.TestAllTypes{OneofField: &testpb.TestAllTypes_OneofDouble{118.5}}},
+		wire:     pack.Message{pack.Tag{118, pack.Fixed64Type}, pack.Float64(118.5)}.Marshal(),
+	},
+	{
+		desc:     "oneof (enum)",
+		decodeTo: []Message{&testpb.TestAllTypes{OneofField: &testpb.TestAllTypes_OneofEnum{testpb.TestAllTypes_BAR}}},
+		wire:     pack.Message{pack.Tag{119, pack.VarintType}, pack.Varint(int(testpb.TestAllTypes_BAR))}.Marshal(),
+	},
+	{
+		desc:     "oneof (overridden value)",
+		decodeTo: []Message{&testpb.TestAllTypes{OneofField: &testpb.TestAllTypes_OneofUint64{2}}},
+		wire: pack.Message{
+			pack.Tag{111, pack.VarintType}, pack.Varint(1),
+			pack.Tag{116, pack.VarintType}, pack.Varint(2),
+		}.Marshal(),
+	},
+	// TODO: More unknown field tests for ordering, repeated fields, etc.
+	//
+	// It is currently impossible to produce results that the v1 Equal
+	// considers equivalent to those of the v1 decoder. Figure out if
+	// that's a problem or not.
+	{
+		desc: "unknown fields",
+		decodeTo: []Message{build(
+			&testpb.TestAllTypes{},
+			unknown(100000, pack.Message{
+				pack.Tag{100000, pack.VarintType}, pack.Varint(1),
+			}.Marshal()),
+		)},
+		wire: pack.Message{
+			pack.Tag{100000, pack.VarintType}, pack.Varint(1),
+		}.Marshal(),
+	},
+	{
+		desc: "field type mismatch",
+		decodeTo: []Message{build(
+			&testpb.TestAllTypes{},
+			unknown(1, pack.Message{
+				pack.Tag{1, pack.BytesType}, pack.String("string"),
+			}.Marshal()),
+		)},
+		wire: pack.Message{
+			pack.Tag{1, pack.BytesType}, pack.String("string"),
+		}.Marshal(),
+	},
+	{
+		desc: "map field element mismatch",
+		decodeTo: []Message{
+			&testpb.TestAllTypes{
+				MapInt32Int32: map[int32]int32{1: 0},
+			},
+		},
+		wire: pack.Message{
+			pack.Tag{56, pack.BytesType}, pack.LengthPrefix(pack.Message{
+				pack.Tag{1, pack.VarintType}, pack.Varint(1),
+				pack.Tag{2, pack.BytesType}, pack.String("string"),
+			}),
+		}.Marshal(),
+	},
+}
+
+func build(m Message, opts ...buildOpt) Message {
+	for _, opt := range opts {
+		opt(m)
+	}
+	return m
+}
+
+type buildOpt func(Message)
+
+func unknown(num pref.FieldNumber, raw pref.RawFields) buildOpt {
+	return func(m Message) {
+		m.ProtoReflect().UnknownFields().Set(num, raw)
+	}
+}
+
+func extend(desc *protoV1.ExtensionDesc, value interface{}) buildOpt {
+	return func(m Message) {
+		if err := protoV1.SetExtension(m.(protoV1.Message), desc, value); err != nil {
+			panic(err)
+		}
+	}
+}
diff --git a/regenerate.bash b/regenerate.bash
index f207a11e..d5ae4d89 100755
--- a/regenerate.bash
+++ b/regenerate.bash
@@ -5,6 +5,8 @@
 
 set -e
 
+go generate internal/cmd/generate-types/main.go
+
 # Install the working tree's protoc-gen-gen in a tempdir.
 tmpdir=$(mktemp -d -t protobuf-regen.XXXXXX)
 trap 'rm -rf $tmpdir' EXIT
@@ -17,6 +19,7 @@ GOBIN=$tmpdir/bin go install ./cmd/protoc-gen-go-grpc
 PROTO_DIRS=(
   cmd/protoc-gen-go/testdata
   cmd/protoc-gen-go-grpc/testdata
+  internal/testprotos/test
 )
 for dir in ${PROTO_DIRS[@]}; do
   for p in `find $dir -name "*.proto"`; do