encoding/prototext: use testmessages_test.go approach, too

With this change, we establish a similar mechanism in encoding/prototext as
already exists in the proto package: a testmessages_test.go which serves as an
extension point where one can inject more variants into the corpus of test
messages.

Change-Id: I9f83735a44e5fd2e4736f888aaca428e4cc8ed42
Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/623116
Reviewed-by: Chressie Himpel <chressie@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
diff --git a/encoding/protojson/encode_test.go b/encoding/protojson/encode_test.go
index 63ddb78..e5f066a 100644
--- a/encoding/protojson/encode_test.go
+++ b/encoding/protojson/encode_test.go
@@ -111,8 +111,8 @@
   "optUint64": "0",
   "optFloat": 0,
   "optDouble": 0,
-  "optString": "",
   "optBytes": "",
+  "optString": "",
   "optEnum": "ZERO",
   "optMessage": {}
 }`,
diff --git a/encoding/prototext/decode_test.go b/encoding/prototext/decode_test.go
index 2346fe3..a0be9ce 100644
--- a/encoding/prototext/decode_test.go
+++ b/encoding/prototext/decode_test.go
@@ -5,12 +5,14 @@
 package prototext_test
 
 import (
+	"fmt"
 	"math"
 	"strings"
 	"testing"
 
 	"google.golang.org/protobuf/encoding/prototext"
 	"google.golang.org/protobuf/internal/flags"
+	"google.golang.org/protobuf/internal/protobuild"
 	"google.golang.org/protobuf/proto"
 	"google.golang.org/protobuf/reflect/protoregistry"
 
@@ -23,7 +25,7 @@
 )
 
 func TestUnmarshal(t *testing.T) {
-	tests := []struct {
+	type test struct {
 		desc         string
 		umo          prototext.UnmarshalOptions
 		inputMessage proto.Message
@@ -31,253 +33,13 @@
 		wantMessage  proto.Message
 		wantErr      string // Expected error substring.
 		skip         bool
-	}{{
-		desc:         "proto2 empty message",
-		inputMessage: &pb2.Scalars{},
-		wantMessage:  &pb2.Scalars{},
-	}, {
-		desc:         "proto2 optional scalars set to zero values",
-		inputMessage: &pb2.Scalars{},
-		inputText: `opt_bool: false
-opt_int32: 0
-opt_int64: 0
-opt_uint32: 0
-opt_uint64: 0
-opt_sint32: 0
-opt_sint64: 0
-opt_fixed32: 0
-opt_fixed64: 0
-opt_sfixed32: 0
-opt_sfixed64: 0
-opt_float: 0
-opt_double: 0
-opt_bytes: ""
-opt_string: ""
-`,
-		wantMessage: &pb2.Scalars{
-			OptBool:     proto.Bool(false),
-			OptInt32:    proto.Int32(0),
-			OptInt64:    proto.Int64(0),
-			OptUint32:   proto.Uint32(0),
-			OptUint64:   proto.Uint64(0),
-			OptSint32:   proto.Int32(0),
-			OptSint64:   proto.Int64(0),
-			OptFixed32:  proto.Uint32(0),
-			OptFixed64:  proto.Uint64(0),
-			OptSfixed32: proto.Int32(0),
-			OptSfixed64: proto.Int64(0),
-			OptFloat:    proto.Float32(0),
-			OptDouble:   proto.Float64(0),
-			OptBytes:    []byte{},
-			OptString:   proto.String(""),
-		},
-	}, {
-		desc:         "protoeditions explicit scalars set to zero values",
-		inputMessage: &pbeditions.Scalars{},
-		inputText: `opt_bool: false
-opt_int32: 0
-opt_int64: 0
-opt_uint32: 0
-opt_uint64: 0
-opt_sint32: 0
-opt_sint64: 0
-opt_fixed32: 0
-opt_fixed64: 0
-opt_sfixed32: 0
-opt_sfixed64: 0
-opt_float: 0
-opt_double: 0
-opt_bytes: ""
-opt_string: ""
-`,
-		wantMessage: &pbeditions.Scalars{
-			OptBool:     proto.Bool(false),
-			OptInt32:    proto.Int32(0),
-			OptInt64:    proto.Int64(0),
-			OptUint32:   proto.Uint32(0),
-			OptUint64:   proto.Uint64(0),
-			OptSint32:   proto.Int32(0),
-			OptSint64:   proto.Int64(0),
-			OptFixed32:  proto.Uint32(0),
-			OptFixed64:  proto.Uint64(0),
-			OptSfixed32: proto.Int32(0),
-			OptSfixed64: proto.Int64(0),
-			OptFloat:    proto.Float32(0),
-			OptDouble:   proto.Float64(0),
-			OptBytes:    []byte{},
-			OptString:   proto.String(""),
-		},
-	}, {
-		desc:         "protoeditions implicit scalars set to zero values",
-		inputMessage: &pbeditions.ImplicitScalars{},
-		inputText: `s_bool: false
-s_int32: 0
-s_int64: 0
-s_uint32: 0
-s_uint64: 0
-s_sint32: 0
-s_sint64: 0
-s_fixed32: 0
-s_fixed64: 0
-s_sfixed32: 0
-s_sfixed64: 0
-s_float: 0
-s_double: 0
-s_bytes: ""
-s_string: ""
-`,
-		wantMessage: &pbeditions.ImplicitScalars{},
-	}, {
-		desc:         "proto3 scalars set to zero values",
-		inputMessage: &pb3.Scalars{},
-		inputText: `s_bool: false
-s_int32: 0
-s_int64: 0
-s_uint32: 0
-s_uint64: 0
-s_sint32: 0
-s_sint64: 0
-s_fixed32: 0
-s_fixed64: 0
-s_sfixed32: 0
-s_sfixed64: 0
-s_float: 0
-s_double: 0
-s_bytes: ""
-s_string: ""
-`,
-		wantMessage: &pb3.Scalars{},
-	}, {
-		desc:         "proto3 optional set to zero values",
-		inputMessage: &pb3.Proto3Optional{},
-		inputText: `opt_bool: false
-opt_int32: 0
-opt_int64: 0
-opt_uint32: 0
-opt_uint64: 0
-opt_float: 0
-opt_double: 0
-opt_string: ""
-opt_bytes: ""
-opt_enum: ZERO
-opt_message: {}
-`,
-		wantMessage: &pb3.Proto3Optional{
-			OptBool:    proto.Bool(false),
-			OptInt32:   proto.Int32(0),
-			OptInt64:   proto.Int64(0),
-			OptUint32:  proto.Uint32(0),
-			OptUint64:  proto.Uint64(0),
-			OptFloat:   proto.Float32(0),
-			OptDouble:  proto.Float64(0),
-			OptString:  proto.String(""),
-			OptBytes:   []byte{},
-			OptEnum:    pb3.Enum_ZERO.Enum(),
-			OptMessage: &pb3.Nested{},
-		},
-	}, {
-		desc:         "proto2 optional scalars",
-		inputMessage: &pb2.Scalars{},
-		inputText: `opt_bool: true
-opt_int32: 255
-opt_int64: 3735928559
-opt_uint32: 0xff
-opt_uint64: 0xdeadbeef
-opt_sint32: -1001
-opt_sint64: -   0xffff
-opt_fixed64: 64
-opt_sfixed32: -		32
-opt_float: 1.234
-opt_double: 1.23e+100
-opt_bytes: "\xe8\xb0\xb7\xe6\xad\x8c"
-opt_string: "谷歌"
-`,
-		wantMessage: &pb2.Scalars{
-			OptBool:     proto.Bool(true),
-			OptInt32:    proto.Int32(0xff),
-			OptInt64:    proto.Int64(0xdeadbeef),
-			OptUint32:   proto.Uint32(0xff),
-			OptUint64:   proto.Uint64(0xdeadbeef),
-			OptSint32:   proto.Int32(-1001),
-			OptSint64:   proto.Int64(-0xffff),
-			OptFixed64:  proto.Uint64(64),
-			OptSfixed32: proto.Int32(-32),
-			OptFloat:    proto.Float32(1.234),
-			OptDouble:   proto.Float64(1.23e100),
-			OptBytes:    []byte("\xe8\xb0\xb7\xe6\xad\x8c"),
-			OptString:   proto.String("谷歌"),
-		},
-	}, {
-		desc:         "protoeditions explicit scalars",
-		inputMessage: &pbeditions.Scalars{},
-		inputText: `opt_bool: true
-opt_int32: 255
-opt_int64: 3735928559
-opt_uint32: 0xff
-opt_uint64: 0xdeadbeef
-opt_sint32: -1001
-opt_sint64: -   0xffff
-opt_fixed64: 64
-opt_sfixed32: -		32
-opt_float: 1.234
-opt_double: 1.23e+100
-opt_bytes: "\xe8\xb0\xb7\xe6\xad\x8c"
-opt_string: "谷歌"
-`,
-		wantMessage: &pbeditions.Scalars{
-			OptBool:     proto.Bool(true),
-			OptInt32:    proto.Int32(0xff),
-			OptInt64:    proto.Int64(0xdeadbeef),
-			OptUint32:   proto.Uint32(0xff),
-			OptUint64:   proto.Uint64(0xdeadbeef),
-			OptSint32:   proto.Int32(-1001),
-			OptSint64:   proto.Int64(-0xffff),
-			OptFixed64:  proto.Uint64(64),
-			OptSfixed32: proto.Int32(-32),
-			OptFloat:    proto.Float32(1.234),
-			OptDouble:   proto.Float64(1.23e100),
-			OptBytes:    []byte("\xe8\xb0\xb7\xe6\xad\x8c"),
-			OptString:   proto.String("谷歌"),
-		},
-	}, {
+	}
+	tests := []test{{
 		desc:         "case sensitive",
 		inputMessage: &pb3.Scalars{},
 		inputText:    `S_BOOL: true`,
 		wantErr:      "unknown field: S_BOOL",
 	}, {
-		desc:         "proto3 scalars",
-		inputMessage: &pb3.Scalars{},
-		inputText: `s_bool: true
-s_int32: 255
-s_int64: 3735928559
-s_uint32: 0xff
-s_uint64: 0xdeadbeef
-s_sint32: -1001
-s_sint64: -  #
-             0xffff
-s_fixed64: 64
-s_sfixed32: -32
-s_float: 1.234
-s_double: 1.23e+100
-s_bytes: "\xe8\xb0\xb7\xe6\xad\x8c"
-s_string: "谷歌"
-`,
-		wantMessage: &pb3.Scalars{
-			SBool:     true,
-			SInt32:    0xff,
-			SInt64:    0xdeadbeef,
-			SUint32:   0xff,
-			SUint64:   0xdeadbeef,
-			SSint32:   -1001,
-			SSint64:   -0xffff,
-			SFixed64:  64,
-			SSfixed32: -32,
-			SFloat:    1.234,
-			SDouble:   1.23e100,
-			SBytes:    []byte("\xe8\xb0\xb7\xe6\xad\x8c"),
-			SString:   "谷歌",
-		},
-	}, {
 		desc:         "proto2 string with invalid UTF-8",
 		inputMessage: &pb2.Scalars{},
 		inputText:    `opt_string: "abc\xff"`,
@@ -509,28 +271,6 @@
 `,
 		wantErr: `non-repeated field "s_bool" is repeated`,
 	}, {
-		desc:         "proto2 enum",
-		inputMessage: &pb2.Enums{},
-		inputText: `
-opt_enum: ONE
-opt_nested_enum: UNO
-`,
-		wantMessage: &pb2.Enums{
-			OptEnum:       pb2.Enum_ONE.Enum(),
-			OptNestedEnum: pb2.Enums_UNO.Enum(),
-		},
-	}, {
-		desc:         "protoeditions closed enum",
-		inputMessage: &pbeditions.Enums{},
-		inputText: `
-opt_enum: ONE
-opt_nested_enum: UNO
-`,
-		wantMessage: &pbeditions.Enums{
-			OptEnum:       pbeditions.Enum_ONE.Enum(),
-			OptNestedEnum: pbeditions.Enums_UNO.Enum(),
-		},
-	}, {
 		desc:         "protoeditions open enum",
 		inputMessage: &pbeditions.Enums{},
 		inputText: `
@@ -553,17 +293,6 @@
 			ImplicitNestedEnum: pbeditions.Enums_ZEHN,
 		},
 	}, {
-		desc:         "proto2 enum set to numeric values",
-		inputMessage: &pb2.Enums{},
-		inputText: `
-opt_enum: 2
-opt_nested_enum: 2
-`,
-		wantMessage: &pb2.Enums{
-			OptEnum:       pb2.Enum_TWO.Enum(),
-			OptNestedEnum: pb2.Enums_DOS.Enum(),
-		},
-	}, {
 		desc:         "proto2 enum set to unnamed numeric values",
 		inputMessage: &pb2.Enums{},
 		inputText: `
@@ -1905,6 +1634,175 @@
 		skip:         !flags.ProtoLegacy,
 	}}
 
+	for _, msg := range makeMessages(protobuild.Message{},
+		&pb2.Scalars{},
+		&pb3.Scalars{},
+		&pbeditions.Scalars{},
+	) {
+		tests = append(tests, test{
+			desc:         fmt.Sprintf("empty message (%T)", msg),
+			inputMessage: msg.ProtoReflect().Type().New().Interface(),
+			wantMessage:  msg,
+		})
+	}
+
+	for _, msg := range makeMessages(protobuild.Message{
+		"opt_bool":     false,
+		"opt_int32":    0,
+		"opt_int64":    0,
+		"opt_uint32":   0,
+		"opt_uint64":   0,
+		"opt_sint32":   0,
+		"opt_sint64":   0,
+		"opt_fixed32":  0,
+		"opt_fixed64":  0,
+		"opt_sfixed32": 0,
+		"opt_sfixed64": 0,
+		"opt_float":    0,
+		"opt_double":   0,
+		"opt_bytes":    []byte{},
+		"opt_string":   "",
+	},
+		&pb2.Scalars{},
+		&pb3.Proto3Optional{},
+		&pbeditions.Scalars{},
+	) {
+		tests = append(tests, test{
+			desc:         fmt.Sprintf("optional scalars set to zero values (%T)", msg),
+			inputMessage: msg.ProtoReflect().Type().New().Interface(),
+			inputText: `opt_bool: false
+opt_int32: 0
+opt_int64: 0
+opt_uint32: 0
+opt_uint64: 0
+opt_sint32: 0
+opt_sint64: 0
+opt_fixed32: 0
+opt_fixed64: 0
+opt_sfixed32: 0
+opt_sfixed64: 0
+opt_float: 0
+opt_double: 0
+opt_bytes: ""
+opt_string: ""
+`,
+			wantMessage: msg,
+		})
+	}
+
+	for _, msg := range makeMessages(protobuild.Message{
+		"s_bool":     false,
+		"s_int32":    0,
+		"s_int64":    0,
+		"s_uint32":   0,
+		"s_uint64":   0,
+		"s_sint32":   0,
+		"s_sint64":   0,
+		"s_fixed32":  0,
+		"s_fixed64":  0,
+		"s_sfixed32": 0,
+		"s_sfixed64": 0,
+		"s_float":    0,
+		"s_double":   0,
+		"s_bytes":    []byte{},
+		"s_string":   "",
+	},
+		&pb3.Scalars{},
+		&pbeditions.ImplicitScalars{},
+	) {
+		tests = append(tests, test{
+			desc:         fmt.Sprintf("implicit scalars set to zero values (%T)", msg),
+			inputMessage: msg.ProtoReflect().Type().New().Interface(),
+			inputText: `s_bool: false
+s_int32: 0
+s_int64: 0
+s_uint32: 0
+s_uint64: 0
+s_sint32: 0
+s_sint64: 0
+s_fixed32: 0
+s_fixed64: 0
+s_sfixed32: 0
+s_sfixed64: 0
+s_float: 0
+s_double: 0
+s_bytes: ""
+s_string: ""
+	`,
+			wantMessage: msg,
+		})
+	}
+
+	for _, msg := range makeMessages(protobuild.Message{
+		"opt_bool":     true,
+		"opt_int32":    0xff,
+		"opt_int64":    int64(0xdeadbeef),
+		"opt_uint32":   0xff,
+		"opt_uint64":   uint64(0xdeadbeef),
+		"opt_sint32":   -1001,
+		"opt_sint64":   -0xffff,
+		"opt_fixed64":  64,
+		"opt_sfixed32": -32,
+		"opt_float":    1.234,
+		"opt_double":   1.23e100,
+		"opt_bytes":    []byte("\xe8\xb0\xb7\xe6\xad\x8c"),
+		"opt_string":   "谷歌",
+	},
+		&pb2.Scalars{},
+		&pb3.Proto3Optional{},
+		&pbeditions.Scalars{},
+	) {
+		tests = append(tests, test{
+			desc:         fmt.Sprintf("optional scalars (%T)", msg),
+			inputMessage: msg.ProtoReflect().Type().New().Interface(),
+			inputText: `opt_bool: true
+opt_int32: 255
+opt_int64: 3735928559
+opt_uint32: 0xff
+opt_uint64: 0xdeadbeef
+opt_sint32: -1001
+opt_sint64: -  #
+             0xffff
+opt_fixed64: 64
+opt_sfixed32: -		32
+opt_float: 1.234
+opt_double: 1.23e+100
+opt_bytes: "\xe8\xb0\xb7\xe6\xad\x8c"
+opt_string: "谷歌"
+`,
+			wantMessage: msg,
+		})
+	}
+
+	for _, msg := range makeMessages(protobuild.Message{
+		"opt_enum":        "ONE",
+		"opt_nested_enum": "UNO",
+	},
+		&pb2.Enums{},
+		&pb3.OptionalEnums{},
+		&pbeditions.Enums{},
+	) {
+		tests = append(tests, test{
+			desc:         fmt.Sprintf("enum (%T)", msg),
+			inputMessage: msg.ProtoReflect().Type().New().Interface(),
+			inputText: `
+opt_enum: ONE
+opt_nested_enum: UNO
+`,
+			wantMessage: msg,
+		})
+
+		tests = append(tests, test{
+			desc:         fmt.Sprintf("enum set to numeric values (%T)", msg),
+			inputMessage: msg.ProtoReflect().Type().New().Interface(),
+			inputText: `
+opt_enum: 1
+opt_nested_enum: 1
+`,
+			wantMessage: msg,
+		})
+	}
+
 	for _, tt := range tests {
 		tt := tt
 		if tt.skip {
diff --git a/encoding/prototext/encode_test.go b/encoding/prototext/encode_test.go
index f49f403..8241c22 100644
--- a/encoding/prototext/encode_test.go
+++ b/encoding/prototext/encode_test.go
@@ -6,6 +6,7 @@
 
 import (
 	"bytes"
+	"fmt"
 	"math"
 	"testing"
 
@@ -14,6 +15,7 @@
 	"google.golang.org/protobuf/encoding/prototext"
 	"google.golang.org/protobuf/internal/detrand"
 	"google.golang.org/protobuf/internal/flags"
+	"google.golang.org/protobuf/internal/protobuild"
 	"google.golang.org/protobuf/proto"
 	"google.golang.org/protobuf/reflect/protoregistry"
 	"google.golang.org/protobuf/testing/protopack"
@@ -30,233 +32,15 @@
 }
 
 func TestMarshal(t *testing.T) {
-	tests := []struct {
+	type test struct {
 		desc    string
 		mo      prototext.MarshalOptions
 		input   proto.Message
 		want    string
 		wantErr bool // TODO: Verify error message content.
 		skip    bool
-	}{{
-		desc:  "proto2 optional scalars not set",
-		input: &pb2.Scalars{},
-		want:  "",
-	}, {
-		desc:  "protoeditions optional scalars not set",
-		input: &pbeditions.Scalars{},
-		want:  "",
-	}, {
-		desc:  "proto3 scalars not set",
-		input: &pb3.Scalars{},
-		want:  "",
-	}, {
-		desc:  "proto3 optional not set",
-		input: &pb3.Proto3Optional{},
-		want:  "",
-	}, {
-		desc:  "protoeditions implicit not set",
-		input: &pbeditions.ImplicitScalars{},
-		want:  "",
-	}, {
-		desc: "proto2 optional scalars set to zero values",
-		input: &pb2.Scalars{
-			OptBool:     proto.Bool(false),
-			OptInt32:    proto.Int32(0),
-			OptInt64:    proto.Int64(0),
-			OptUint32:   proto.Uint32(0),
-			OptUint64:   proto.Uint64(0),
-			OptSint32:   proto.Int32(0),
-			OptSint64:   proto.Int64(0),
-			OptFixed32:  proto.Uint32(0),
-			OptFixed64:  proto.Uint64(0),
-			OptSfixed32: proto.Int32(0),
-			OptSfixed64: proto.Int64(0),
-			OptFloat:    proto.Float32(0),
-			OptDouble:   proto.Float64(0),
-			OptBytes:    []byte{},
-			OptString:   proto.String(""),
-		},
-		want: `opt_bool: false
-opt_int32: 0
-opt_int64: 0
-opt_uint32: 0
-opt_uint64: 0
-opt_sint32: 0
-opt_sint64: 0
-opt_fixed32: 0
-opt_fixed64: 0
-opt_sfixed32: 0
-opt_sfixed64: 0
-opt_float: 0
-opt_double: 0
-opt_bytes: ""
-opt_string: ""
-`,
-	}, {
-		desc: "protoeditions optional scalars set to zero values",
-		input: &pbeditions.Scalars{
-			OptBool:     proto.Bool(false),
-			OptInt32:    proto.Int32(0),
-			OptInt64:    proto.Int64(0),
-			OptUint32:   proto.Uint32(0),
-			OptUint64:   proto.Uint64(0),
-			OptSint32:   proto.Int32(0),
-			OptSint64:   proto.Int64(0),
-			OptFixed32:  proto.Uint32(0),
-			OptFixed64:  proto.Uint64(0),
-			OptSfixed32: proto.Int32(0),
-			OptSfixed64: proto.Int64(0),
-			OptFloat:    proto.Float32(0),
-			OptDouble:   proto.Float64(0),
-			OptBytes:    []byte{},
-			OptString:   proto.String(""),
-		},
-		want: `opt_bool: false
-opt_int32: 0
-opt_int64: 0
-opt_uint32: 0
-opt_uint64: 0
-opt_sint32: 0
-opt_sint64: 0
-opt_fixed32: 0
-opt_fixed64: 0
-opt_sfixed32: 0
-opt_sfixed64: 0
-opt_float: 0
-opt_double: 0
-opt_bytes: ""
-opt_string: ""
-`,
-	}, {
-		desc: "proto3 optional set to zero values",
-		input: &pb3.Proto3Optional{
-			OptBool:    proto.Bool(false),
-			OptInt32:   proto.Int32(0),
-			OptInt64:   proto.Int64(0),
-			OptUint32:  proto.Uint32(0),
-			OptUint64:  proto.Uint64(0),
-			OptFloat:   proto.Float32(0),
-			OptDouble:  proto.Float64(0),
-			OptString:  proto.String(""),
-			OptBytes:   []byte{},
-			OptEnum:    pb3.Enum_ZERO.Enum(),
-			OptMessage: &pb3.Nested{},
-		},
-		want: `opt_bool: false
-opt_int32: 0
-opt_int64: 0
-opt_uint32: 0
-opt_uint64: 0
-opt_float: 0
-opt_double: 0
-opt_string: ""
-opt_bytes: ""
-opt_enum: ZERO
-opt_message: {}
-`,
-	}, {
-		desc: "proto3 scalars set to zero values",
-		input: &pb3.Scalars{
-			SBool:     false,
-			SInt32:    0,
-			SInt64:    0,
-			SUint32:   0,
-			SUint64:   0,
-			SSint32:   0,
-			SSint64:   0,
-			SFixed32:  0,
-			SFixed64:  0,
-			SSfixed32: 0,
-			SSfixed64: 0,
-			SFloat:    0,
-			SDouble:   0,
-			SBytes:    []byte{},
-			SString:   "",
-		},
-		want: "",
-	}, {
-		desc: "protoeditions implicit scalars set to zero values",
-		input: &pbeditions.ImplicitScalars{
-			SBool:     false,
-			SInt32:    0,
-			SInt64:    0,
-			SUint32:   0,
-			SUint64:   0,
-			SSint32:   0,
-			SSint64:   0,
-			SFixed32:  0,
-			SFixed64:  0,
-			SSfixed32: 0,
-			SSfixed64: 0,
-			SFloat:    0,
-			SDouble:   0,
-			SBytes:    []byte{},
-			SString:   "",
-		},
-		want: "",
-	}, {
-		desc: "proto2 optional scalars set to some values",
-		input: &pb2.Scalars{
-			OptBool:     proto.Bool(true),
-			OptInt32:    proto.Int32(0xff),
-			OptInt64:    proto.Int64(0xdeadbeef),
-			OptUint32:   proto.Uint32(47),
-			OptUint64:   proto.Uint64(0xdeadbeef),
-			OptSint32:   proto.Int32(-1001),
-			OptSint64:   proto.Int64(-0xffff),
-			OptFixed64:  proto.Uint64(64),
-			OptSfixed32: proto.Int32(-32),
-			OptFloat:    proto.Float32(1.02),
-			OptDouble:   proto.Float64(1.0199999809265137),
-			OptBytes:    []byte("\xe8\xb0\xb7\xe6\xad\x8c"),
-			OptString:   proto.String("谷歌"),
-		},
-		want: `opt_bool: true
-opt_int32: 255
-opt_int64: 3735928559
-opt_uint32: 47
-opt_uint64: 3735928559
-opt_sint32: -1001
-opt_sint64: -65535
-opt_fixed64: 64
-opt_sfixed32: -32
-opt_float: 1.02
-opt_double: 1.0199999809265137
-opt_bytes: "谷歌"
-opt_string: "谷歌"
-`,
-	}, {
-		desc: "proto editions optional scalars set to some values",
-		input: &pbeditions.Scalars{
-			OptBool:     proto.Bool(true),
-			OptInt32:    proto.Int32(0xff),
-			OptInt64:    proto.Int64(0xdeadbeef),
-			OptUint32:   proto.Uint32(47),
-			OptUint64:   proto.Uint64(0xdeadbeef),
-			OptSint32:   proto.Int32(-1001),
-			OptSint64:   proto.Int64(-0xffff),
-			OptFixed64:  proto.Uint64(64),
-			OptSfixed32: proto.Int32(-32),
-			OptFloat:    proto.Float32(1.02),
-			OptDouble:   proto.Float64(1.0199999809265137),
-			OptBytes:    []byte("\xe8\xb0\xb7\xe6\xad\x8c"),
-			OptString:   proto.String("谷歌"),
-		},
-		want: `opt_bool: true
-opt_int32: 255
-opt_int64: 3735928559
-opt_uint32: 47
-opt_uint64: 3735928559
-opt_sint32: -1001
-opt_sint64: -65535
-opt_fixed64: 64
-opt_sfixed32: -32
-opt_float: 1.02
-opt_double: 1.0199999809265137
-opt_bytes: "谷歌"
-opt_string: "谷歌"
-`,
-	}, {
+	}
+	tests := []test{{
 		desc: "proto2 string with invalid UTF-8",
 		input: &pb2.Scalars{
 			OptString: proto.String("abc\xff"),
@@ -1650,6 +1434,128 @@
 `,
 	}}
 
+	for _, msg := range makeMessages(protobuild.Message{},
+		&pb2.Scalars{},
+		&pb3.Scalars{},
+		&pb3.Proto3Optional{},
+		&pbeditions.Scalars{},
+		&pbeditions.ImplicitScalars{},
+	) {
+		tests = append(tests, test{
+			desc:  fmt.Sprintf("optional scalars not set (%T)", msg),
+			input: msg,
+			want:  "",
+		})
+	}
+
+	for _, msg := range makeMessages(protobuild.Message{
+		"opt_bool":     false,
+		"opt_int32":    0,
+		"opt_int64":    0,
+		"opt_uint32":   0,
+		"opt_uint64":   0,
+		"opt_sint32":   0,
+		"opt_sint64":   0,
+		"opt_fixed32":  0,
+		"opt_fixed64":  0,
+		"opt_sfixed32": 0,
+		"opt_sfixed64": 0,
+		"opt_float":    0,
+		"opt_double":   0,
+		"opt_bytes":    []byte{},
+		"opt_string":   "",
+	},
+		&pb2.Scalars{},
+		&pb3.Proto3Optional{},
+		&pbeditions.Scalars{},
+	) {
+		tests = append(tests, test{
+			desc:  fmt.Sprintf("optional scalars set to zero values (%T)", msg),
+			input: msg,
+			want: `opt_bool: false
+opt_int32: 0
+opt_int64: 0
+opt_uint32: 0
+opt_uint64: 0
+opt_sint32: 0
+opt_sint64: 0
+opt_fixed32: 0
+opt_fixed64: 0
+opt_sfixed32: 0
+opt_sfixed64: 0
+opt_float: 0
+opt_double: 0
+opt_bytes: ""
+opt_string: ""
+`,
+		})
+	}
+
+	for _, msg := range makeMessages(protobuild.Message{
+		"s_bool":     false,
+		"s_int32":    0,
+		"s_int64":    0,
+		"s_uint32":   0,
+		"s_uint64":   0,
+		"s_sint32":   0,
+		"s_sint64":   0,
+		"s_fixed32":  0,
+		"s_fixed64":  0,
+		"s_sfixed32": 0,
+		"s_sfixed64": 0,
+		"s_float":    0,
+		"s_double":   0,
+		"s_bytes":    []byte{},
+		"s_string":   "",
+	},
+		&pb3.Scalars{},
+		&pbeditions.ImplicitScalars{},
+	) {
+		tests = append(tests, test{
+			desc:  fmt.Sprintf("implicit scalars set to zero values (%T)", msg),
+			input: msg,
+			want:  "",
+		})
+	}
+
+	for _, msg := range makeMessages(protobuild.Message{
+		"opt_bool":     true,
+		"opt_int32":    0xff,
+		"opt_int64":    int64(0xdeadbeef),
+		"opt_uint32":   47,
+		"opt_uint64":   uint64(0xdeadbeef),
+		"opt_sint32":   -1001,
+		"opt_sint64":   -0xffff,
+		"opt_fixed64":  64,
+		"opt_sfixed32": -32,
+		"opt_float":    1.02,
+		"opt_double":   1.0199999809265137,
+		"opt_bytes":    []byte("\xe8\xb0\xb7\xe6\xad\x8c"),
+		"opt_string":   "谷歌",
+	},
+		&pb2.Scalars{},
+		&pbeditions.Scalars{},
+	) {
+		tests = append(tests, test{
+			desc:  fmt.Sprintf("optional scalars set to some values (%T)", msg),
+			input: msg,
+			want: `opt_bool: true
+opt_int32: 255
+opt_int64: 3735928559
+opt_uint32: 47
+opt_uint64: 3735928559
+opt_sint32: -1001
+opt_sint64: -65535
+opt_fixed64: 64
+opt_sfixed32: -32
+opt_float: 1.02
+opt_double: 1.0199999809265137
+opt_bytes: "谷歌"
+opt_string: "谷歌"
+`,
+		})
+	}
+
 	for _, tt := range tests {
 		tt := tt
 		if tt.skip {
diff --git a/encoding/prototext/testmessages_test.go b/encoding/prototext/testmessages_test.go
new file mode 100644
index 0000000..4681db7
--- /dev/null
+++ b/encoding/prototext/testmessages_test.go
@@ -0,0 +1,17 @@
+// Copyright 2024 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 prototext_test
+
+import (
+	"google.golang.org/protobuf/internal/protobuild"
+	"google.golang.org/protobuf/proto"
+)
+
+func makeMessages(in protobuild.Message, messages ...proto.Message) []proto.Message {
+	for _, m := range messages {
+		in.Build(m.ProtoReflect())
+	}
+	return messages
+}
diff --git a/internal/testprotos/textpb3/test.pb.go b/internal/testprotos/textpb3/test.pb.go
index 5b7d9ef..7f58488 100644
--- a/internal/testprotos/textpb3/test.pb.go
+++ b/internal/testprotos/textpb3/test.pb.go
@@ -68,6 +68,58 @@
 	return file_internal_testprotos_textpb3_test_proto_rawDescGZIP(), []int{0}
 }
 
+type OptionalEnums_NestedEnum int32
+
+const (
+	OptionalEnums_CERO OptionalEnums_NestedEnum = 0
+	OptionalEnums_UNO  OptionalEnums_NestedEnum = 1
+	OptionalEnums_DOS  OptionalEnums_NestedEnum = 2
+	OptionalEnums_DIEZ OptionalEnums_NestedEnum = 10
+)
+
+// Enum value maps for OptionalEnums_NestedEnum.
+var (
+	OptionalEnums_NestedEnum_name = map[int32]string{
+		0:  "CERO",
+		1:  "UNO",
+		2:  "DOS",
+		10: "DIEZ",
+	}
+	OptionalEnums_NestedEnum_value = map[string]int32{
+		"CERO": 0,
+		"UNO":  1,
+		"DOS":  2,
+		"DIEZ": 10,
+	}
+)
+
+func (x OptionalEnums_NestedEnum) Enum() *OptionalEnums_NestedEnum {
+	p := new(OptionalEnums_NestedEnum)
+	*p = x
+	return p
+}
+
+func (x OptionalEnums_NestedEnum) String() string {
+	return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
+}
+
+func (OptionalEnums_NestedEnum) Descriptor() protoreflect.EnumDescriptor {
+	return file_internal_testprotos_textpb3_test_proto_enumTypes[1].Descriptor()
+}
+
+func (OptionalEnums_NestedEnum) Type() protoreflect.EnumType {
+	return &file_internal_testprotos_textpb3_test_proto_enumTypes[1]
+}
+
+func (x OptionalEnums_NestedEnum) Number() protoreflect.EnumNumber {
+	return protoreflect.EnumNumber(x)
+}
+
+// Deprecated: Use OptionalEnums_NestedEnum.Descriptor instead.
+func (OptionalEnums_NestedEnum) EnumDescriptor() ([]byte, []int) {
+	return file_internal_testprotos_textpb3_test_proto_rawDescGZIP(), []int{3, 0}
+}
+
 type Enums_NestedEnum int32
 
 const (
@@ -104,11 +156,11 @@
 }
 
 func (Enums_NestedEnum) Descriptor() protoreflect.EnumDescriptor {
-	return file_internal_testprotos_textpb3_test_proto_enumTypes[1].Descriptor()
+	return file_internal_testprotos_textpb3_test_proto_enumTypes[2].Descriptor()
 }
 
 func (Enums_NestedEnum) Type() protoreflect.EnumType {
-	return &file_internal_testprotos_textpb3_test_proto_enumTypes[1]
+	return &file_internal_testprotos_textpb3_test_proto_enumTypes[2]
 }
 
 func (x Enums_NestedEnum) Number() protoreflect.EnumNumber {
@@ -117,7 +169,7 @@
 
 // Deprecated: Use Enums_NestedEnum.Descriptor instead.
 func (Enums_NestedEnum) EnumDescriptor() ([]byte, []int) {
-	return file_internal_testprotos_textpb3_test_proto_rawDescGZIP(), []int{3, 0}
+	return file_internal_testprotos_textpb3_test_proto_rawDescGZIP(), []int{4, 0}
 }
 
 // Scalars contains scalar field types.
@@ -393,17 +445,23 @@
 	sizeCache     protoimpl.SizeCache
 	unknownFields protoimpl.UnknownFields
 
-	OptBool    *bool    `protobuf:"varint,1,opt,name=opt_bool,json=optBool,proto3,oneof" json:"opt_bool,omitempty"`
-	OptInt32   *int32   `protobuf:"varint,2,opt,name=opt_int32,json=optInt32,proto3,oneof" json:"opt_int32,omitempty"`
-	OptInt64   *int64   `protobuf:"varint,3,opt,name=opt_int64,json=optInt64,proto3,oneof" json:"opt_int64,omitempty"`
-	OptUint32  *uint32  `protobuf:"varint,4,opt,name=opt_uint32,json=optUint32,proto3,oneof" json:"opt_uint32,omitempty"`
-	OptUint64  *uint64  `protobuf:"varint,5,opt,name=opt_uint64,json=optUint64,proto3,oneof" json:"opt_uint64,omitempty"`
-	OptFloat   *float32 `protobuf:"fixed32,6,opt,name=opt_float,json=optFloat,proto3,oneof" json:"opt_float,omitempty"`
-	OptDouble  *float64 `protobuf:"fixed64,7,opt,name=opt_double,json=optDouble,proto3,oneof" json:"opt_double,omitempty"`
-	OptString  *string  `protobuf:"bytes,8,opt,name=opt_string,json=optString,proto3,oneof" json:"opt_string,omitempty"`
-	OptBytes   []byte   `protobuf:"bytes,9,opt,name=opt_bytes,json=optBytes,proto3,oneof" json:"opt_bytes,omitempty"`
-	OptEnum    *Enum    `protobuf:"varint,10,opt,name=opt_enum,json=optEnum,proto3,enum=pb3.Enum,oneof" json:"opt_enum,omitempty"`
-	OptMessage *Nested  `protobuf:"bytes,11,opt,name=opt_message,json=optMessage,proto3,oneof" json:"opt_message,omitempty"`
+	OptBool     *bool    `protobuf:"varint,1,opt,name=opt_bool,json=optBool,proto3,oneof" json:"opt_bool,omitempty"`
+	OptInt32    *int32   `protobuf:"varint,2,opt,name=opt_int32,json=optInt32,proto3,oneof" json:"opt_int32,omitempty"`
+	OptInt64    *int64   `protobuf:"varint,3,opt,name=opt_int64,json=optInt64,proto3,oneof" json:"opt_int64,omitempty"`
+	OptUint32   *uint32  `protobuf:"varint,4,opt,name=opt_uint32,json=optUint32,proto3,oneof" json:"opt_uint32,omitempty"`
+	OptUint64   *uint64  `protobuf:"varint,5,opt,name=opt_uint64,json=optUint64,proto3,oneof" json:"opt_uint64,omitempty"`
+	OptSint32   *int32   `protobuf:"zigzag32,12,opt,name=opt_sint32,json=optSint32,proto3,oneof" json:"opt_sint32,omitempty"`
+	OptSint64   *int64   `protobuf:"zigzag64,13,opt,name=opt_sint64,json=optSint64,proto3,oneof" json:"opt_sint64,omitempty"`
+	OptFixed32  *uint32  `protobuf:"fixed32,14,opt,name=opt_fixed32,json=optFixed32,proto3,oneof" json:"opt_fixed32,omitempty"`
+	OptFixed64  *uint64  `protobuf:"fixed64,15,opt,name=opt_fixed64,json=optFixed64,proto3,oneof" json:"opt_fixed64,omitempty"`
+	OptSfixed32 *int32   `protobuf:"fixed32,16,opt,name=opt_sfixed32,json=optSfixed32,proto3,oneof" json:"opt_sfixed32,omitempty"`
+	OptSfixed64 *int64   `protobuf:"fixed64,17,opt,name=opt_sfixed64,json=optSfixed64,proto3,oneof" json:"opt_sfixed64,omitempty"`
+	OptFloat    *float32 `protobuf:"fixed32,20,opt,name=opt_float,json=optFloat,proto3,oneof" json:"opt_float,omitempty"`
+	OptDouble   *float64 `protobuf:"fixed64,21,opt,name=opt_double,json=optDouble,proto3,oneof" json:"opt_double,omitempty"`
+	OptBytes    []byte   `protobuf:"bytes,8,opt,name=opt_bytes,json=optBytes,proto3,oneof" json:"opt_bytes,omitempty"`
+	OptString   *string  `protobuf:"bytes,9,opt,name=opt_string,json=optString,proto3,oneof" json:"opt_string,omitempty"`
+	OptEnum     *Enum    `protobuf:"varint,10,opt,name=opt_enum,json=optEnum,proto3,enum=pb3.Enum,oneof" json:"opt_enum,omitempty"`
+	OptMessage  *Nested  `protobuf:"bytes,11,opt,name=opt_message,json=optMessage,proto3,oneof" json:"opt_message,omitempty"`
 }
 
 func (x *Proto3Optional) Reset() {
@@ -471,6 +529,48 @@
 	return 0
 }
 
+func (x *Proto3Optional) GetOptSint32() int32 {
+	if x != nil && x.OptSint32 != nil {
+		return *x.OptSint32
+	}
+	return 0
+}
+
+func (x *Proto3Optional) GetOptSint64() int64 {
+	if x != nil && x.OptSint64 != nil {
+		return *x.OptSint64
+	}
+	return 0
+}
+
+func (x *Proto3Optional) GetOptFixed32() uint32 {
+	if x != nil && x.OptFixed32 != nil {
+		return *x.OptFixed32
+	}
+	return 0
+}
+
+func (x *Proto3Optional) GetOptFixed64() uint64 {
+	if x != nil && x.OptFixed64 != nil {
+		return *x.OptFixed64
+	}
+	return 0
+}
+
+func (x *Proto3Optional) GetOptSfixed32() int32 {
+	if x != nil && x.OptSfixed32 != nil {
+		return *x.OptSfixed32
+	}
+	return 0
+}
+
+func (x *Proto3Optional) GetOptSfixed64() int64 {
+	if x != nil && x.OptSfixed64 != nil {
+		return *x.OptSfixed64
+	}
+	return 0
+}
+
 func (x *Proto3Optional) GetOptFloat() float32 {
 	if x != nil && x.OptFloat != nil {
 		return *x.OptFloat
@@ -485,13 +585,6 @@
 	return 0
 }
 
-func (x *Proto3Optional) GetOptString() string {
-	if x != nil && x.OptString != nil {
-		return *x.OptString
-	}
-	return ""
-}
-
 func (x *Proto3Optional) GetOptBytes() []byte {
 	if x != nil {
 		return x.OptBytes
@@ -499,6 +592,13 @@
 	return nil
 }
 
+func (x *Proto3Optional) GetOptString() string {
+	if x != nil && x.OptString != nil {
+		return *x.OptString
+	}
+	return ""
+}
+
 func (x *Proto3Optional) GetOptEnum() Enum {
 	if x != nil && x.OptEnum != nil {
 		return *x.OptEnum
@@ -513,6 +613,59 @@
 	return nil
 }
 
+type OptionalEnums struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	OptEnum       *Enum                    `protobuf:"varint,1,opt,name=opt_enum,json=optEnum,proto3,enum=pb3.Enum,oneof" json:"opt_enum,omitempty"`
+	OptNestedEnum OptionalEnums_NestedEnum `protobuf:"varint,3,opt,name=opt_nested_enum,json=optNestedEnum,proto3,enum=pb3.OptionalEnums_NestedEnum" json:"opt_nested_enum,omitempty"`
+}
+
+func (x *OptionalEnums) Reset() {
+	*x = OptionalEnums{}
+	mi := &file_internal_testprotos_textpb3_test_proto_msgTypes[3]
+	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+	ms.StoreMessageInfo(mi)
+}
+
+func (x *OptionalEnums) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*OptionalEnums) ProtoMessage() {}
+
+func (x *OptionalEnums) ProtoReflect() protoreflect.Message {
+	mi := &file_internal_testprotos_textpb3_test_proto_msgTypes[3]
+	if x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use OptionalEnums.ProtoReflect.Descriptor instead.
+func (*OptionalEnums) Descriptor() ([]byte, []int) {
+	return file_internal_testprotos_textpb3_test_proto_rawDescGZIP(), []int{3}
+}
+
+func (x *OptionalEnums) GetOptEnum() Enum {
+	if x != nil && x.OptEnum != nil {
+		return *x.OptEnum
+	}
+	return Enum_ZERO
+}
+
+func (x *OptionalEnums) GetOptNestedEnum() OptionalEnums_NestedEnum {
+	if x != nil {
+		return x.OptNestedEnum
+	}
+	return OptionalEnums_CERO
+}
+
 // Message contains enum fields.
 type Enums struct {
 	state         protoimpl.MessageState
@@ -525,7 +678,7 @@
 
 func (x *Enums) Reset() {
 	*x = Enums{}
-	mi := &file_internal_testprotos_textpb3_test_proto_msgTypes[3]
+	mi := &file_internal_testprotos_textpb3_test_proto_msgTypes[4]
 	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 	ms.StoreMessageInfo(mi)
 }
@@ -537,7 +690,7 @@
 func (*Enums) ProtoMessage() {}
 
 func (x *Enums) ProtoReflect() protoreflect.Message {
-	mi := &file_internal_testprotos_textpb3_test_proto_msgTypes[3]
+	mi := &file_internal_testprotos_textpb3_test_proto_msgTypes[4]
 	if x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -550,7 +703,7 @@
 
 // Deprecated: Use Enums.ProtoReflect.Descriptor instead.
 func (*Enums) Descriptor() ([]byte, []int) {
-	return file_internal_testprotos_textpb3_test_proto_rawDescGZIP(), []int{3}
+	return file_internal_testprotos_textpb3_test_proto_rawDescGZIP(), []int{4}
 }
 
 func (x *Enums) GetSEnum() Enum {
@@ -578,7 +731,7 @@
 
 func (x *Nests) Reset() {
 	*x = Nests{}
-	mi := &file_internal_testprotos_textpb3_test_proto_msgTypes[4]
+	mi := &file_internal_testprotos_textpb3_test_proto_msgTypes[5]
 	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 	ms.StoreMessageInfo(mi)
 }
@@ -590,7 +743,7 @@
 func (*Nests) ProtoMessage() {}
 
 func (x *Nests) ProtoReflect() protoreflect.Message {
-	mi := &file_internal_testprotos_textpb3_test_proto_msgTypes[4]
+	mi := &file_internal_testprotos_textpb3_test_proto_msgTypes[5]
 	if x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -603,7 +756,7 @@
 
 // Deprecated: Use Nests.ProtoReflect.Descriptor instead.
 func (*Nests) Descriptor() ([]byte, []int) {
-	return file_internal_testprotos_textpb3_test_proto_rawDescGZIP(), []int{4}
+	return file_internal_testprotos_textpb3_test_proto_rawDescGZIP(), []int{5}
 }
 
 func (x *Nests) GetSNested() *Nested {
@@ -625,7 +778,7 @@
 
 func (x *Nested) Reset() {
 	*x = Nested{}
-	mi := &file_internal_testprotos_textpb3_test_proto_msgTypes[5]
+	mi := &file_internal_testprotos_textpb3_test_proto_msgTypes[6]
 	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 	ms.StoreMessageInfo(mi)
 }
@@ -637,7 +790,7 @@
 func (*Nested) ProtoMessage() {}
 
 func (x *Nested) ProtoReflect() protoreflect.Message {
-	mi := &file_internal_testprotos_textpb3_test_proto_msgTypes[5]
+	mi := &file_internal_testprotos_textpb3_test_proto_msgTypes[6]
 	if x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -650,7 +803,7 @@
 
 // Deprecated: Use Nested.ProtoReflect.Descriptor instead.
 func (*Nested) Descriptor() ([]byte, []int) {
-	return file_internal_testprotos_textpb3_test_proto_rawDescGZIP(), []int{5}
+	return file_internal_testprotos_textpb3_test_proto_rawDescGZIP(), []int{6}
 }
 
 func (x *Nested) GetSString() string {
@@ -683,7 +836,7 @@
 
 func (x *Oneofs) Reset() {
 	*x = Oneofs{}
-	mi := &file_internal_testprotos_textpb3_test_proto_msgTypes[6]
+	mi := &file_internal_testprotos_textpb3_test_proto_msgTypes[7]
 	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 	ms.StoreMessageInfo(mi)
 }
@@ -695,7 +848,7 @@
 func (*Oneofs) ProtoMessage() {}
 
 func (x *Oneofs) ProtoReflect() protoreflect.Message {
-	mi := &file_internal_testprotos_textpb3_test_proto_msgTypes[6]
+	mi := &file_internal_testprotos_textpb3_test_proto_msgTypes[7]
 	if x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -708,7 +861,7 @@
 
 // Deprecated: Use Oneofs.ProtoReflect.Descriptor instead.
 func (*Oneofs) Descriptor() ([]byte, []int) {
-	return file_internal_testprotos_textpb3_test_proto_rawDescGZIP(), []int{6}
+	return file_internal_testprotos_textpb3_test_proto_rawDescGZIP(), []int{7}
 }
 
 func (m *Oneofs) GetUnion() isOneofs_Union {
@@ -776,7 +929,7 @@
 
 func (x *Maps) Reset() {
 	*x = Maps{}
-	mi := &file_internal_testprotos_textpb3_test_proto_msgTypes[7]
+	mi := &file_internal_testprotos_textpb3_test_proto_msgTypes[8]
 	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 	ms.StoreMessageInfo(mi)
 }
@@ -788,7 +941,7 @@
 func (*Maps) ProtoMessage() {}
 
 func (x *Maps) ProtoReflect() protoreflect.Message {
-	mi := &file_internal_testprotos_textpb3_test_proto_msgTypes[7]
+	mi := &file_internal_testprotos_textpb3_test_proto_msgTypes[8]
 	if x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -801,7 +954,7 @@
 
 // Deprecated: Use Maps.ProtoReflect.Descriptor instead.
 func (*Maps) Descriptor() ([]byte, []int) {
-	return file_internal_testprotos_textpb3_test_proto_rawDescGZIP(), []int{7}
+	return file_internal_testprotos_textpb3_test_proto_rawDescGZIP(), []int{8}
 }
 
 func (x *Maps) GetInt32ToStr() map[int32]string {
@@ -850,7 +1003,7 @@
 
 func (x *JSONNames) Reset() {
 	*x = JSONNames{}
-	mi := &file_internal_testprotos_textpb3_test_proto_msgTypes[8]
+	mi := &file_internal_testprotos_textpb3_test_proto_msgTypes[9]
 	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 	ms.StoreMessageInfo(mi)
 }
@@ -862,7 +1015,7 @@
 func (*JSONNames) ProtoMessage() {}
 
 func (x *JSONNames) ProtoReflect() protoreflect.Message {
-	mi := &file_internal_testprotos_textpb3_test_proto_msgTypes[8]
+	mi := &file_internal_testprotos_textpb3_test_proto_msgTypes[9]
 	if x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -875,7 +1028,7 @@
 
 // Deprecated: Use JSONNames.ProtoReflect.Descriptor instead.
 func (*JSONNames) Descriptor() ([]byte, []int) {
-	return file_internal_testprotos_textpb3_test_proto_rawDescGZIP(), []int{8}
+	return file_internal_testprotos_textpb3_test_proto_rawDescGZIP(), []int{9}
 }
 
 func (x *JSONNames) GetSString() string {
@@ -896,7 +1049,7 @@
 
 func (x *ReservedFieldNames) Reset() {
 	*x = ReservedFieldNames{}
-	mi := &file_internal_testprotos_textpb3_test_proto_msgTypes[9]
+	mi := &file_internal_testprotos_textpb3_test_proto_msgTypes[10]
 	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 	ms.StoreMessageInfo(mi)
 }
@@ -908,7 +1061,7 @@
 func (*ReservedFieldNames) ProtoMessage() {}
 
 func (x *ReservedFieldNames) ProtoReflect() protoreflect.Message {
-	mi := &file_internal_testprotos_textpb3_test_proto_msgTypes[9]
+	mi := &file_internal_testprotos_textpb3_test_proto_msgTypes[10]
 	if x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -921,7 +1074,7 @@
 
 // Deprecated: Use ReservedFieldNames.ProtoReflect.Descriptor instead.
 func (*ReservedFieldNames) Descriptor() ([]byte, []int) {
-	return file_internal_testprotos_textpb3_test_proto_rawDescGZIP(), []int{9}
+	return file_internal_testprotos_textpb3_test_proto_rawDescGZIP(), []int{10}
 }
 
 func (x *ReservedFieldNames) GetOptInt32() int32 {
@@ -980,7 +1133,7 @@
 	0x5f, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x18, 0x08, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x72,
 	0x70, 0x74, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x12, 0x1b, 0x0a, 0x09, 0x72, 0x70, 0x74, 0x5f,
 	0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x09, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x08, 0x72, 0x70, 0x74,
-	0x42, 0x79, 0x74, 0x65, 0x73, 0x22, 0xc4, 0x04, 0x0a, 0x0e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x33,
+	0x42, 0x79, 0x74, 0x65, 0x73, 0x22, 0x88, 0x07, 0x0a, 0x0e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x33,
 	0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x12, 0x1e, 0x0a, 0x08, 0x6f, 0x70, 0x74, 0x5f,
 	0x62, 0x6f, 0x6f, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, 0x07, 0x6f, 0x70,
 	0x74, 0x42, 0x6f, 0x6f, 0x6c, 0x88, 0x01, 0x01, 0x12, 0x20, 0x0a, 0x09, 0x6f, 0x70, 0x74, 0x5f,
@@ -992,115 +1145,148 @@
 	0x48, 0x03, 0x52, 0x09, 0x6f, 0x70, 0x74, 0x55, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x88, 0x01, 0x01,
 	0x12, 0x22, 0x0a, 0x0a, 0x6f, 0x70, 0x74, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x18, 0x05,
 	0x20, 0x01, 0x28, 0x04, 0x48, 0x04, 0x52, 0x09, 0x6f, 0x70, 0x74, 0x55, 0x69, 0x6e, 0x74, 0x36,
-	0x34, 0x88, 0x01, 0x01, 0x12, 0x20, 0x0a, 0x09, 0x6f, 0x70, 0x74, 0x5f, 0x66, 0x6c, 0x6f, 0x61,
-	0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x02, 0x48, 0x05, 0x52, 0x08, 0x6f, 0x70, 0x74, 0x46, 0x6c,
-	0x6f, 0x61, 0x74, 0x88, 0x01, 0x01, 0x12, 0x22, 0x0a, 0x0a, 0x6f, 0x70, 0x74, 0x5f, 0x64, 0x6f,
-	0x75, 0x62, 0x6c, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x01, 0x48, 0x06, 0x52, 0x09, 0x6f, 0x70,
-	0x74, 0x44, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x88, 0x01, 0x01, 0x12, 0x22, 0x0a, 0x0a, 0x6f, 0x70,
-	0x74, 0x5f, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x48, 0x07,
-	0x52, 0x09, 0x6f, 0x70, 0x74, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x88, 0x01, 0x01, 0x12, 0x20,
-	0x0a, 0x09, 0x6f, 0x70, 0x74, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28,
-	0x0c, 0x48, 0x08, 0x52, 0x08, 0x6f, 0x70, 0x74, 0x42, 0x79, 0x74, 0x65, 0x73, 0x88, 0x01, 0x01,
-	0x12, 0x29, 0x0a, 0x08, 0x6f, 0x70, 0x74, 0x5f, 0x65, 0x6e, 0x75, 0x6d, 0x18, 0x0a, 0x20, 0x01,
-	0x28, 0x0e, 0x32, 0x09, 0x2e, 0x70, 0x62, 0x33, 0x2e, 0x45, 0x6e, 0x75, 0x6d, 0x48, 0x09, 0x52,
-	0x07, 0x6f, 0x70, 0x74, 0x45, 0x6e, 0x75, 0x6d, 0x88, 0x01, 0x01, 0x12, 0x31, 0x0a, 0x0b, 0x6f,
-	0x70, 0x74, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b,
-	0x32, 0x0b, 0x2e, 0x70, 0x62, 0x33, 0x2e, 0x4e, 0x65, 0x73, 0x74, 0x65, 0x64, 0x48, 0x0a, 0x52,
-	0x0a, 0x6f, 0x70, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x88, 0x01, 0x01, 0x42, 0x0b,
-	0x0a, 0x09, 0x5f, 0x6f, 0x70, 0x74, 0x5f, 0x62, 0x6f, 0x6f, 0x6c, 0x42, 0x0c, 0x0a, 0x0a, 0x5f,
-	0x6f, 0x70, 0x74, 0x5f, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x42, 0x0c, 0x0a, 0x0a, 0x5f, 0x6f, 0x70,
-	0x74, 0x5f, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x42, 0x0d, 0x0a, 0x0b, 0x5f, 0x6f, 0x70, 0x74, 0x5f,
-	0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x42, 0x0d, 0x0a, 0x0b, 0x5f, 0x6f, 0x70, 0x74, 0x5f, 0x75,
-	0x69, 0x6e, 0x74, 0x36, 0x34, 0x42, 0x0c, 0x0a, 0x0a, 0x5f, 0x6f, 0x70, 0x74, 0x5f, 0x66, 0x6c,
-	0x6f, 0x61, 0x74, 0x42, 0x0d, 0x0a, 0x0b, 0x5f, 0x6f, 0x70, 0x74, 0x5f, 0x64, 0x6f, 0x75, 0x62,
-	0x6c, 0x65, 0x42, 0x0d, 0x0a, 0x0b, 0x5f, 0x6f, 0x70, 0x74, 0x5f, 0x73, 0x74, 0x72, 0x69, 0x6e,
-	0x67, 0x42, 0x0c, 0x0a, 0x0a, 0x5f, 0x6f, 0x70, 0x74, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x42,
-	0x0b, 0x0a, 0x09, 0x5f, 0x6f, 0x70, 0x74, 0x5f, 0x65, 0x6e, 0x75, 0x6d, 0x42, 0x0e, 0x0a, 0x0c,
-	0x5f, 0x6f, 0x70, 0x74, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x98, 0x01, 0x0a,
-	0x05, 0x45, 0x6e, 0x75, 0x6d, 0x73, 0x12, 0x20, 0x0a, 0x06, 0x73, 0x5f, 0x65, 0x6e, 0x75, 0x6d,
-	0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x09, 0x2e, 0x70, 0x62, 0x33, 0x2e, 0x45, 0x6e, 0x75,
-	0x6d, 0x52, 0x05, 0x73, 0x45, 0x6e, 0x75, 0x6d, 0x12, 0x39, 0x0a, 0x0d, 0x73, 0x5f, 0x6e, 0x65,
-	0x73, 0x74, 0x65, 0x64, 0x5f, 0x65, 0x6e, 0x75, 0x6d, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32,
-	0x15, 0x2e, 0x70, 0x62, 0x33, 0x2e, 0x45, 0x6e, 0x75, 0x6d, 0x73, 0x2e, 0x4e, 0x65, 0x73, 0x74,
-	0x65, 0x64, 0x45, 0x6e, 0x75, 0x6d, 0x52, 0x0b, 0x73, 0x4e, 0x65, 0x73, 0x74, 0x65, 0x64, 0x45,
-	0x6e, 0x75, 0x6d, 0x22, 0x32, 0x0a, 0x0a, 0x4e, 0x65, 0x73, 0x74, 0x65, 0x64, 0x45, 0x6e, 0x75,
-	0x6d, 0x12, 0x08, 0x0a, 0x04, 0x43, 0x45, 0x52, 0x4f, 0x10, 0x00, 0x12, 0x07, 0x0a, 0x03, 0x55,
-	0x4e, 0x4f, 0x10, 0x01, 0x12, 0x07, 0x0a, 0x03, 0x44, 0x4f, 0x53, 0x10, 0x02, 0x12, 0x08, 0x0a,
-	0x04, 0x44, 0x49, 0x45, 0x5a, 0x10, 0x0a, 0x22, 0x2f, 0x0a, 0x05, 0x4e, 0x65, 0x73, 0x74, 0x73,
-	0x12, 0x26, 0x0a, 0x08, 0x73, 0x5f, 0x6e, 0x65, 0x73, 0x74, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01,
-	0x28, 0x0b, 0x32, 0x0b, 0x2e, 0x70, 0x62, 0x33, 0x2e, 0x4e, 0x65, 0x73, 0x74, 0x65, 0x64, 0x52,
-	0x07, 0x73, 0x4e, 0x65, 0x73, 0x74, 0x65, 0x64, 0x22, 0x4b, 0x0a, 0x06, 0x4e, 0x65, 0x73, 0x74,
-	0x65, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x5f, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x18, 0x01,
-	0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x73, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x12, 0x26, 0x0a,
-	0x08, 0x73, 0x5f, 0x6e, 0x65, 0x73, 0x74, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32,
-	0x0b, 0x2e, 0x70, 0x62, 0x33, 0x2e, 0x4e, 0x65, 0x73, 0x74, 0x65, 0x64, 0x52, 0x07, 0x73, 0x4e,
-	0x65, 0x73, 0x74, 0x65, 0x64, 0x22, 0x94, 0x01, 0x0a, 0x06, 0x4f, 0x6e, 0x65, 0x6f, 0x66, 0x73,
-	0x12, 0x2a, 0x0a, 0x0a, 0x6f, 0x6e, 0x65, 0x6f, 0x66, 0x5f, 0x65, 0x6e, 0x75, 0x6d, 0x18, 0x01,
+	0x34, 0x88, 0x01, 0x01, 0x12, 0x22, 0x0a, 0x0a, 0x6f, 0x70, 0x74, 0x5f, 0x73, 0x69, 0x6e, 0x74,
+	0x33, 0x32, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x11, 0x48, 0x05, 0x52, 0x09, 0x6f, 0x70, 0x74, 0x53,
+	0x69, 0x6e, 0x74, 0x33, 0x32, 0x88, 0x01, 0x01, 0x12, 0x22, 0x0a, 0x0a, 0x6f, 0x70, 0x74, 0x5f,
+	0x73, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x12, 0x48, 0x06, 0x52, 0x09,
+	0x6f, 0x70, 0x74, 0x53, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x88, 0x01, 0x01, 0x12, 0x24, 0x0a, 0x0b,
+	0x6f, 0x70, 0x74, 0x5f, 0x66, 0x69, 0x78, 0x65, 0x64, 0x33, 0x32, 0x18, 0x0e, 0x20, 0x01, 0x28,
+	0x07, 0x48, 0x07, 0x52, 0x0a, 0x6f, 0x70, 0x74, 0x46, 0x69, 0x78, 0x65, 0x64, 0x33, 0x32, 0x88,
+	0x01, 0x01, 0x12, 0x24, 0x0a, 0x0b, 0x6f, 0x70, 0x74, 0x5f, 0x66, 0x69, 0x78, 0x65, 0x64, 0x36,
+	0x34, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x06, 0x48, 0x08, 0x52, 0x0a, 0x6f, 0x70, 0x74, 0x46, 0x69,
+	0x78, 0x65, 0x64, 0x36, 0x34, 0x88, 0x01, 0x01, 0x12, 0x26, 0x0a, 0x0c, 0x6f, 0x70, 0x74, 0x5f,
+	0x73, 0x66, 0x69, 0x78, 0x65, 0x64, 0x33, 0x32, 0x18, 0x10, 0x20, 0x01, 0x28, 0x0f, 0x48, 0x09,
+	0x52, 0x0b, 0x6f, 0x70, 0x74, 0x53, 0x66, 0x69, 0x78, 0x65, 0x64, 0x33, 0x32, 0x88, 0x01, 0x01,
+	0x12, 0x26, 0x0a, 0x0c, 0x6f, 0x70, 0x74, 0x5f, 0x73, 0x66, 0x69, 0x78, 0x65, 0x64, 0x36, 0x34,
+	0x18, 0x11, 0x20, 0x01, 0x28, 0x10, 0x48, 0x0a, 0x52, 0x0b, 0x6f, 0x70, 0x74, 0x53, 0x66, 0x69,
+	0x78, 0x65, 0x64, 0x36, 0x34, 0x88, 0x01, 0x01, 0x12, 0x20, 0x0a, 0x09, 0x6f, 0x70, 0x74, 0x5f,
+	0x66, 0x6c, 0x6f, 0x61, 0x74, 0x18, 0x14, 0x20, 0x01, 0x28, 0x02, 0x48, 0x0b, 0x52, 0x08, 0x6f,
+	0x70, 0x74, 0x46, 0x6c, 0x6f, 0x61, 0x74, 0x88, 0x01, 0x01, 0x12, 0x22, 0x0a, 0x0a, 0x6f, 0x70,
+	0x74, 0x5f, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x18, 0x15, 0x20, 0x01, 0x28, 0x01, 0x48, 0x0c,
+	0x52, 0x09, 0x6f, 0x70, 0x74, 0x44, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x88, 0x01, 0x01, 0x12, 0x20,
+	0x0a, 0x09, 0x6f, 0x70, 0x74, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28,
+	0x0c, 0x48, 0x0d, 0x52, 0x08, 0x6f, 0x70, 0x74, 0x42, 0x79, 0x74, 0x65, 0x73, 0x88, 0x01, 0x01,
+	0x12, 0x22, 0x0a, 0x0a, 0x6f, 0x70, 0x74, 0x5f, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x18, 0x09,
+	0x20, 0x01, 0x28, 0x09, 0x48, 0x0e, 0x52, 0x09, 0x6f, 0x70, 0x74, 0x53, 0x74, 0x72, 0x69, 0x6e,
+	0x67, 0x88, 0x01, 0x01, 0x12, 0x29, 0x0a, 0x08, 0x6f, 0x70, 0x74, 0x5f, 0x65, 0x6e, 0x75, 0x6d,
+	0x18, 0x0a, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x09, 0x2e, 0x70, 0x62, 0x33, 0x2e, 0x45, 0x6e, 0x75,
+	0x6d, 0x48, 0x0f, 0x52, 0x07, 0x6f, 0x70, 0x74, 0x45, 0x6e, 0x75, 0x6d, 0x88, 0x01, 0x01, 0x12,
+	0x31, 0x0a, 0x0b, 0x6f, 0x70, 0x74, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x0b,
+	0x20, 0x01, 0x28, 0x0b, 0x32, 0x0b, 0x2e, 0x70, 0x62, 0x33, 0x2e, 0x4e, 0x65, 0x73, 0x74, 0x65,
+	0x64, 0x48, 0x10, 0x52, 0x0a, 0x6f, 0x70, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x88,
+	0x01, 0x01, 0x42, 0x0b, 0x0a, 0x09, 0x5f, 0x6f, 0x70, 0x74, 0x5f, 0x62, 0x6f, 0x6f, 0x6c, 0x42,
+	0x0c, 0x0a, 0x0a, 0x5f, 0x6f, 0x70, 0x74, 0x5f, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x42, 0x0c, 0x0a,
+	0x0a, 0x5f, 0x6f, 0x70, 0x74, 0x5f, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x42, 0x0d, 0x0a, 0x0b, 0x5f,
+	0x6f, 0x70, 0x74, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x42, 0x0d, 0x0a, 0x0b, 0x5f, 0x6f,
+	0x70, 0x74, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x42, 0x0d, 0x0a, 0x0b, 0x5f, 0x6f, 0x70,
+	0x74, 0x5f, 0x73, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x42, 0x0d, 0x0a, 0x0b, 0x5f, 0x6f, 0x70, 0x74,
+	0x5f, 0x73, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x42, 0x0e, 0x0a, 0x0c, 0x5f, 0x6f, 0x70, 0x74, 0x5f,
+	0x66, 0x69, 0x78, 0x65, 0x64, 0x33, 0x32, 0x42, 0x0e, 0x0a, 0x0c, 0x5f, 0x6f, 0x70, 0x74, 0x5f,
+	0x66, 0x69, 0x78, 0x65, 0x64, 0x36, 0x34, 0x42, 0x0f, 0x0a, 0x0d, 0x5f, 0x6f, 0x70, 0x74, 0x5f,
+	0x73, 0x66, 0x69, 0x78, 0x65, 0x64, 0x33, 0x32, 0x42, 0x0f, 0x0a, 0x0d, 0x5f, 0x6f, 0x70, 0x74,
+	0x5f, 0x73, 0x66, 0x69, 0x78, 0x65, 0x64, 0x36, 0x34, 0x42, 0x0c, 0x0a, 0x0a, 0x5f, 0x6f, 0x70,
+	0x74, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x42, 0x0d, 0x0a, 0x0b, 0x5f, 0x6f, 0x70, 0x74, 0x5f,
+	0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x42, 0x0c, 0x0a, 0x0a, 0x5f, 0x6f, 0x70, 0x74, 0x5f, 0x62,
+	0x79, 0x74, 0x65, 0x73, 0x42, 0x0d, 0x0a, 0x0b, 0x5f, 0x6f, 0x70, 0x74, 0x5f, 0x73, 0x74, 0x72,
+	0x69, 0x6e, 0x67, 0x42, 0x0b, 0x0a, 0x09, 0x5f, 0x6f, 0x70, 0x74, 0x5f, 0x65, 0x6e, 0x75, 0x6d,
+	0x42, 0x0e, 0x0a, 0x0c, 0x5f, 0x6f, 0x70, 0x74, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65,
+	0x22, 0xc2, 0x01, 0x0a, 0x0d, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x45, 0x6e, 0x75,
+	0x6d, 0x73, 0x12, 0x29, 0x0a, 0x08, 0x6f, 0x70, 0x74, 0x5f, 0x65, 0x6e, 0x75, 0x6d, 0x18, 0x01,
 	0x20, 0x01, 0x28, 0x0e, 0x32, 0x09, 0x2e, 0x70, 0x62, 0x33, 0x2e, 0x45, 0x6e, 0x75, 0x6d, 0x48,
-	0x00, 0x52, 0x09, 0x6f, 0x6e, 0x65, 0x6f, 0x66, 0x45, 0x6e, 0x75, 0x6d, 0x12, 0x23, 0x0a, 0x0c,
-	0x6f, 0x6e, 0x65, 0x6f, 0x66, 0x5f, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x18, 0x02, 0x20, 0x01,
-	0x28, 0x09, 0x48, 0x00, 0x52, 0x0b, 0x6f, 0x6e, 0x65, 0x6f, 0x66, 0x53, 0x74, 0x72, 0x69, 0x6e,
-	0x67, 0x12, 0x30, 0x0a, 0x0c, 0x6f, 0x6e, 0x65, 0x6f, 0x66, 0x5f, 0x6e, 0x65, 0x73, 0x74, 0x65,
-	0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0b, 0x2e, 0x70, 0x62, 0x33, 0x2e, 0x4e, 0x65,
-	0x73, 0x74, 0x65, 0x64, 0x48, 0x00, 0x52, 0x0b, 0x6f, 0x6e, 0x65, 0x6f, 0x66, 0x4e, 0x65, 0x73,
-	0x74, 0x65, 0x64, 0x42, 0x07, 0x0a, 0x05, 0x75, 0x6e, 0x69, 0x6f, 0x6e, 0x22, 0xaf, 0x05, 0x0a,
-	0x04, 0x4d, 0x61, 0x70, 0x73, 0x12, 0x3b, 0x0a, 0x0c, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x74,
-	0x6f, 0x5f, 0x73, 0x74, 0x72, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x70, 0x62,
-	0x33, 0x2e, 0x4d, 0x61, 0x70, 0x73, 0x2e, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x54, 0x6f, 0x53, 0x74,
-	0x72, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0a, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x54, 0x6f, 0x53,
-	0x74, 0x72, 0x12, 0x41, 0x0a, 0x0e, 0x62, 0x6f, 0x6f, 0x6c, 0x5f, 0x74, 0x6f, 0x5f, 0x75, 0x69,
-	0x6e, 0x74, 0x33, 0x32, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x70, 0x62, 0x33,
-	0x2e, 0x4d, 0x61, 0x70, 0x73, 0x2e, 0x42, 0x6f, 0x6f, 0x6c, 0x54, 0x6f, 0x55, 0x69, 0x6e, 0x74,
-	0x33, 0x32, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0c, 0x62, 0x6f, 0x6f, 0x6c, 0x54, 0x6f, 0x55,
-	0x69, 0x6e, 0x74, 0x33, 0x32, 0x12, 0x41, 0x0a, 0x0e, 0x75, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x5f,
-	0x74, 0x6f, 0x5f, 0x65, 0x6e, 0x75, 0x6d, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1b, 0x2e,
-	0x70, 0x62, 0x33, 0x2e, 0x4d, 0x61, 0x70, 0x73, 0x2e, 0x55, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x54,
-	0x6f, 0x45, 0x6e, 0x75, 0x6d, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0c, 0x75, 0x69, 0x6e, 0x74,
-	0x36, 0x34, 0x54, 0x6f, 0x45, 0x6e, 0x75, 0x6d, 0x12, 0x3e, 0x0a, 0x0d, 0x73, 0x74, 0x72, 0x5f,
-	0x74, 0x6f, 0x5f, 0x6e, 0x65, 0x73, 0x74, 0x65, 0x64, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32,
-	0x1a, 0x2e, 0x70, 0x62, 0x33, 0x2e, 0x4d, 0x61, 0x70, 0x73, 0x2e, 0x53, 0x74, 0x72, 0x54, 0x6f,
-	0x4e, 0x65, 0x73, 0x74, 0x65, 0x64, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0b, 0x73, 0x74, 0x72,
-	0x54, 0x6f, 0x4e, 0x65, 0x73, 0x74, 0x65, 0x64, 0x12, 0x3e, 0x0a, 0x0d, 0x73, 0x74, 0x72, 0x5f,
-	0x74, 0x6f, 0x5f, 0x6f, 0x6e, 0x65, 0x6f, 0x66, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32,
-	0x1a, 0x2e, 0x70, 0x62, 0x33, 0x2e, 0x4d, 0x61, 0x70, 0x73, 0x2e, 0x53, 0x74, 0x72, 0x54, 0x6f,
-	0x4f, 0x6e, 0x65, 0x6f, 0x66, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0b, 0x73, 0x74, 0x72,
-	0x54, 0x6f, 0x4f, 0x6e, 0x65, 0x6f, 0x66, 0x73, 0x1a, 0x3d, 0x0a, 0x0f, 0x49, 0x6e, 0x74, 0x33,
-	0x32, 0x54, 0x6f, 0x53, 0x74, 0x72, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b,
-	0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a,
-	0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61,
-	0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x3f, 0x0a, 0x11, 0x42, 0x6f, 0x6f, 0x6c, 0x54,
-	0x6f, 0x55, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03,
-	0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14,
-	0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x76,
-	0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x4a, 0x0a, 0x11, 0x55, 0x69, 0x6e, 0x74,
-	0x36, 0x34, 0x54, 0x6f, 0x45, 0x6e, 0x75, 0x6d, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a,
-	0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12,
-	0x1f, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x09,
-	0x2e, 0x70, 0x62, 0x33, 0x2e, 0x45, 0x6e, 0x75, 0x6d, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65,
-	0x3a, 0x02, 0x38, 0x01, 0x1a, 0x4b, 0x0a, 0x10, 0x53, 0x74, 0x72, 0x54, 0x6f, 0x4e, 0x65, 0x73,
-	0x74, 0x65, 0x64, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18,
-	0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x21, 0x0a, 0x05, 0x76, 0x61,
-	0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0b, 0x2e, 0x70, 0x62, 0x33, 0x2e,
-	0x4e, 0x65, 0x73, 0x74, 0x65, 0x64, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38,
-	0x01, 0x1a, 0x4b, 0x0a, 0x10, 0x53, 0x74, 0x72, 0x54, 0x6f, 0x4f, 0x6e, 0x65, 0x6f, 0x66, 0x73,
+	0x00, 0x52, 0x07, 0x6f, 0x70, 0x74, 0x45, 0x6e, 0x75, 0x6d, 0x88, 0x01, 0x01, 0x12, 0x45, 0x0a,
+	0x0f, 0x6f, 0x70, 0x74, 0x5f, 0x6e, 0x65, 0x73, 0x74, 0x65, 0x64, 0x5f, 0x65, 0x6e, 0x75, 0x6d,
+	0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1d, 0x2e, 0x70, 0x62, 0x33, 0x2e, 0x4f, 0x70, 0x74,
+	0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x45, 0x6e, 0x75, 0x6d, 0x73, 0x2e, 0x4e, 0x65, 0x73, 0x74, 0x65,
+	0x64, 0x45, 0x6e, 0x75, 0x6d, 0x52, 0x0d, 0x6f, 0x70, 0x74, 0x4e, 0x65, 0x73, 0x74, 0x65, 0x64,
+	0x45, 0x6e, 0x75, 0x6d, 0x22, 0x32, 0x0a, 0x0a, 0x4e, 0x65, 0x73, 0x74, 0x65, 0x64, 0x45, 0x6e,
+	0x75, 0x6d, 0x12, 0x08, 0x0a, 0x04, 0x43, 0x45, 0x52, 0x4f, 0x10, 0x00, 0x12, 0x07, 0x0a, 0x03,
+	0x55, 0x4e, 0x4f, 0x10, 0x01, 0x12, 0x07, 0x0a, 0x03, 0x44, 0x4f, 0x53, 0x10, 0x02, 0x12, 0x08,
+	0x0a, 0x04, 0x44, 0x49, 0x45, 0x5a, 0x10, 0x0a, 0x42, 0x0b, 0x0a, 0x09, 0x5f, 0x6f, 0x70, 0x74,
+	0x5f, 0x65, 0x6e, 0x75, 0x6d, 0x22, 0x98, 0x01, 0x0a, 0x05, 0x45, 0x6e, 0x75, 0x6d, 0x73, 0x12,
+	0x20, 0x0a, 0x06, 0x73, 0x5f, 0x65, 0x6e, 0x75, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32,
+	0x09, 0x2e, 0x70, 0x62, 0x33, 0x2e, 0x45, 0x6e, 0x75, 0x6d, 0x52, 0x05, 0x73, 0x45, 0x6e, 0x75,
+	0x6d, 0x12, 0x39, 0x0a, 0x0d, 0x73, 0x5f, 0x6e, 0x65, 0x73, 0x74, 0x65, 0x64, 0x5f, 0x65, 0x6e,
+	0x75, 0x6d, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x15, 0x2e, 0x70, 0x62, 0x33, 0x2e, 0x45,
+	0x6e, 0x75, 0x6d, 0x73, 0x2e, 0x4e, 0x65, 0x73, 0x74, 0x65, 0x64, 0x45, 0x6e, 0x75, 0x6d, 0x52,
+	0x0b, 0x73, 0x4e, 0x65, 0x73, 0x74, 0x65, 0x64, 0x45, 0x6e, 0x75, 0x6d, 0x22, 0x32, 0x0a, 0x0a,
+	0x4e, 0x65, 0x73, 0x74, 0x65, 0x64, 0x45, 0x6e, 0x75, 0x6d, 0x12, 0x08, 0x0a, 0x04, 0x43, 0x45,
+	0x52, 0x4f, 0x10, 0x00, 0x12, 0x07, 0x0a, 0x03, 0x55, 0x4e, 0x4f, 0x10, 0x01, 0x12, 0x07, 0x0a,
+	0x03, 0x44, 0x4f, 0x53, 0x10, 0x02, 0x12, 0x08, 0x0a, 0x04, 0x44, 0x49, 0x45, 0x5a, 0x10, 0x0a,
+	0x22, 0x2f, 0x0a, 0x05, 0x4e, 0x65, 0x73, 0x74, 0x73, 0x12, 0x26, 0x0a, 0x08, 0x73, 0x5f, 0x6e,
+	0x65, 0x73, 0x74, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0b, 0x2e, 0x70, 0x62,
+	0x33, 0x2e, 0x4e, 0x65, 0x73, 0x74, 0x65, 0x64, 0x52, 0x07, 0x73, 0x4e, 0x65, 0x73, 0x74, 0x65,
+	0x64, 0x22, 0x4b, 0x0a, 0x06, 0x4e, 0x65, 0x73, 0x74, 0x65, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x73,
+	0x5f, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x73,
+	0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x12, 0x26, 0x0a, 0x08, 0x73, 0x5f, 0x6e, 0x65, 0x73, 0x74,
+	0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0b, 0x2e, 0x70, 0x62, 0x33, 0x2e, 0x4e,
+	0x65, 0x73, 0x74, 0x65, 0x64, 0x52, 0x07, 0x73, 0x4e, 0x65, 0x73, 0x74, 0x65, 0x64, 0x22, 0x94,
+	0x01, 0x0a, 0x06, 0x4f, 0x6e, 0x65, 0x6f, 0x66, 0x73, 0x12, 0x2a, 0x0a, 0x0a, 0x6f, 0x6e, 0x65,
+	0x6f, 0x66, 0x5f, 0x65, 0x6e, 0x75, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x09, 0x2e,
+	0x70, 0x62, 0x33, 0x2e, 0x45, 0x6e, 0x75, 0x6d, 0x48, 0x00, 0x52, 0x09, 0x6f, 0x6e, 0x65, 0x6f,
+	0x66, 0x45, 0x6e, 0x75, 0x6d, 0x12, 0x23, 0x0a, 0x0c, 0x6f, 0x6e, 0x65, 0x6f, 0x66, 0x5f, 0x73,
+	0x74, 0x72, 0x69, 0x6e, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x0b, 0x6f,
+	0x6e, 0x65, 0x6f, 0x66, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x12, 0x30, 0x0a, 0x0c, 0x6f, 0x6e,
+	0x65, 0x6f, 0x66, 0x5f, 0x6e, 0x65, 0x73, 0x74, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b,
+	0x32, 0x0b, 0x2e, 0x70, 0x62, 0x33, 0x2e, 0x4e, 0x65, 0x73, 0x74, 0x65, 0x64, 0x48, 0x00, 0x52,
+	0x0b, 0x6f, 0x6e, 0x65, 0x6f, 0x66, 0x4e, 0x65, 0x73, 0x74, 0x65, 0x64, 0x42, 0x07, 0x0a, 0x05,
+	0x75, 0x6e, 0x69, 0x6f, 0x6e, 0x22, 0xaf, 0x05, 0x0a, 0x04, 0x4d, 0x61, 0x70, 0x73, 0x12, 0x3b,
+	0x0a, 0x0c, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x74, 0x6f, 0x5f, 0x73, 0x74, 0x72, 0x18, 0x01,
+	0x20, 0x03, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x70, 0x62, 0x33, 0x2e, 0x4d, 0x61, 0x70, 0x73, 0x2e,
+	0x49, 0x6e, 0x74, 0x33, 0x32, 0x54, 0x6f, 0x53, 0x74, 0x72, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52,
+	0x0a, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x54, 0x6f, 0x53, 0x74, 0x72, 0x12, 0x41, 0x0a, 0x0e, 0x62,
+	0x6f, 0x6f, 0x6c, 0x5f, 0x74, 0x6f, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x18, 0x02, 0x20,
+	0x03, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x70, 0x62, 0x33, 0x2e, 0x4d, 0x61, 0x70, 0x73, 0x2e, 0x42,
+	0x6f, 0x6f, 0x6c, 0x54, 0x6f, 0x55, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x45, 0x6e, 0x74, 0x72, 0x79,
+	0x52, 0x0c, 0x62, 0x6f, 0x6f, 0x6c, 0x54, 0x6f, 0x55, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x12, 0x41,
+	0x0a, 0x0e, 0x75, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x5f, 0x74, 0x6f, 0x5f, 0x65, 0x6e, 0x75, 0x6d,
+	0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x70, 0x62, 0x33, 0x2e, 0x4d, 0x61, 0x70,
+	0x73, 0x2e, 0x55, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x54, 0x6f, 0x45, 0x6e, 0x75, 0x6d, 0x45, 0x6e,
+	0x74, 0x72, 0x79, 0x52, 0x0c, 0x75, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x54, 0x6f, 0x45, 0x6e, 0x75,
+	0x6d, 0x12, 0x3e, 0x0a, 0x0d, 0x73, 0x74, 0x72, 0x5f, 0x74, 0x6f, 0x5f, 0x6e, 0x65, 0x73, 0x74,
+	0x65, 0x64, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x70, 0x62, 0x33, 0x2e, 0x4d,
+	0x61, 0x70, 0x73, 0x2e, 0x53, 0x74, 0x72, 0x54, 0x6f, 0x4e, 0x65, 0x73, 0x74, 0x65, 0x64, 0x45,
+	0x6e, 0x74, 0x72, 0x79, 0x52, 0x0b, 0x73, 0x74, 0x72, 0x54, 0x6f, 0x4e, 0x65, 0x73, 0x74, 0x65,
+	0x64, 0x12, 0x3e, 0x0a, 0x0d, 0x73, 0x74, 0x72, 0x5f, 0x74, 0x6f, 0x5f, 0x6f, 0x6e, 0x65, 0x6f,
+	0x66, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x70, 0x62, 0x33, 0x2e, 0x4d,
+	0x61, 0x70, 0x73, 0x2e, 0x53, 0x74, 0x72, 0x54, 0x6f, 0x4f, 0x6e, 0x65, 0x6f, 0x66, 0x73, 0x45,
+	0x6e, 0x74, 0x72, 0x79, 0x52, 0x0b, 0x73, 0x74, 0x72, 0x54, 0x6f, 0x4f, 0x6e, 0x65, 0x6f, 0x66,
+	0x73, 0x1a, 0x3d, 0x0a, 0x0f, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x54, 0x6f, 0x53, 0x74, 0x72, 0x45,
+	0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28,
+	0x05, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18,
+	0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01,
+	0x1a, 0x3f, 0x0a, 0x11, 0x42, 0x6f, 0x6f, 0x6c, 0x54, 0x6f, 0x55, 0x69, 0x6e, 0x74, 0x33, 0x32,
 	0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01,
-	0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x21, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65,
-	0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0b, 0x2e, 0x70, 0x62, 0x33, 0x2e, 0x4f, 0x6e, 0x65,
-	0x6f, 0x66, 0x73, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x26,
-	0x0a, 0x09, 0x4a, 0x53, 0x4f, 0x4e, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x12, 0x19, 0x0a, 0x08, 0x73,
-	0x5f, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x66,
-	0x6f, 0x6f, 0x5f, 0x62, 0x61, 0x72, 0x22, 0x41, 0x0a, 0x12, 0x52, 0x65, 0x73, 0x65, 0x72, 0x76,
-	0x65, 0x64, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x12, 0x1b, 0x0a, 0x09,
-	0x6f, 0x70, 0x74, 0x5f, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52,
-	0x08, 0x6f, 0x70, 0x74, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x52, 0x0e, 0x72, 0x65, 0x73, 0x65, 0x72,
-	0x76, 0x65, 0x64, 0x5f, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x2a, 0x2b, 0x0a, 0x04, 0x45, 0x6e, 0x75,
-	0x6d, 0x12, 0x08, 0x0a, 0x04, 0x5a, 0x45, 0x52, 0x4f, 0x10, 0x00, 0x12, 0x07, 0x0a, 0x03, 0x4f,
-	0x4e, 0x45, 0x10, 0x01, 0x12, 0x07, 0x0a, 0x03, 0x54, 0x57, 0x4f, 0x10, 0x02, 0x12, 0x07, 0x0a,
-	0x03, 0x54, 0x45, 0x4e, 0x10, 0x0a, 0x42, 0x38, 0x5a, 0x36, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
-	0x2e, 0x67, 0x6f, 0x6c, 0x61, 0x6e, 0x67, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x70, 0x72, 0x6f, 0x74,
-	0x6f, 0x62, 0x75, 0x66, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x74, 0x65,
-	0x73, 0x74, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x74, 0x65, 0x78, 0x74, 0x70, 0x62, 0x33,
-	0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
+	0x28, 0x08, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65,
+	0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38,
+	0x01, 0x1a, 0x4a, 0x0a, 0x11, 0x55, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x54, 0x6f, 0x45, 0x6e, 0x75,
+	0x6d, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20,
+	0x01, 0x28, 0x04, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x1f, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75,
+	0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x09, 0x2e, 0x70, 0x62, 0x33, 0x2e, 0x45, 0x6e,
+	0x75, 0x6d, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x4b, 0x0a,
+	0x10, 0x53, 0x74, 0x72, 0x54, 0x6f, 0x4e, 0x65, 0x73, 0x74, 0x65, 0x64, 0x45, 0x6e, 0x74, 0x72,
+	0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03,
+	0x6b, 0x65, 0x79, 0x12, 0x21, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01,
+	0x28, 0x0b, 0x32, 0x0b, 0x2e, 0x70, 0x62, 0x33, 0x2e, 0x4e, 0x65, 0x73, 0x74, 0x65, 0x64, 0x52,
+	0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x4b, 0x0a, 0x10, 0x53, 0x74,
+	0x72, 0x54, 0x6f, 0x4f, 0x6e, 0x65, 0x6f, 0x66, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10,
+	0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79,
+	0x12, 0x21, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32,
+	0x0b, 0x2e, 0x70, 0x62, 0x33, 0x2e, 0x4f, 0x6e, 0x65, 0x6f, 0x66, 0x73, 0x52, 0x05, 0x76, 0x61,
+	0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x26, 0x0a, 0x09, 0x4a, 0x53, 0x4f, 0x4e, 0x4e,
+	0x61, 0x6d, 0x65, 0x73, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x5f, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67,
+	0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x66, 0x6f, 0x6f, 0x5f, 0x62, 0x61, 0x72, 0x22,
+	0x41, 0x0a, 0x12, 0x52, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x46, 0x69, 0x65, 0x6c, 0x64,
+	0x4e, 0x61, 0x6d, 0x65, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x6f, 0x70, 0x74, 0x5f, 0x69, 0x6e, 0x74,
+	0x33, 0x32, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x6f, 0x70, 0x74, 0x49, 0x6e, 0x74,
+	0x33, 0x32, 0x52, 0x0e, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x5f, 0x66, 0x69, 0x65,
+	0x6c, 0x64, 0x2a, 0x2b, 0x0a, 0x04, 0x45, 0x6e, 0x75, 0x6d, 0x12, 0x08, 0x0a, 0x04, 0x5a, 0x45,
+	0x52, 0x4f, 0x10, 0x00, 0x12, 0x07, 0x0a, 0x03, 0x4f, 0x4e, 0x45, 0x10, 0x01, 0x12, 0x07, 0x0a,
+	0x03, 0x54, 0x57, 0x4f, 0x10, 0x02, 0x12, 0x07, 0x0a, 0x03, 0x54, 0x45, 0x4e, 0x10, 0x0a, 0x42,
+	0x38, 0x5a, 0x36, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x67, 0x6f, 0x6c, 0x61, 0x6e, 0x67,
+	0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x69, 0x6e,
+	0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+	0x73, 0x2f, 0x74, 0x65, 0x78, 0x74, 0x70, 0x62, 0x33, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+	0x33,
 }
 
 var (
@@ -1115,49 +1301,53 @@
 	return file_internal_testprotos_textpb3_test_proto_rawDescData
 }
 
-var file_internal_testprotos_textpb3_test_proto_enumTypes = make([]protoimpl.EnumInfo, 2)
-var file_internal_testprotos_textpb3_test_proto_msgTypes = make([]protoimpl.MessageInfo, 15)
+var file_internal_testprotos_textpb3_test_proto_enumTypes = make([]protoimpl.EnumInfo, 3)
+var file_internal_testprotos_textpb3_test_proto_msgTypes = make([]protoimpl.MessageInfo, 16)
 var file_internal_testprotos_textpb3_test_proto_goTypes = []any{
-	(Enum)(0),                  // 0: pb3.Enum
-	(Enums_NestedEnum)(0),      // 1: pb3.Enums.NestedEnum
-	(*Scalars)(nil),            // 2: pb3.Scalars
-	(*Repeats)(nil),            // 3: pb3.Repeats
-	(*Proto3Optional)(nil),     // 4: pb3.Proto3Optional
-	(*Enums)(nil),              // 5: pb3.Enums
-	(*Nests)(nil),              // 6: pb3.Nests
-	(*Nested)(nil),             // 7: pb3.Nested
-	(*Oneofs)(nil),             // 8: pb3.Oneofs
-	(*Maps)(nil),               // 9: pb3.Maps
-	(*JSONNames)(nil),          // 10: pb3.JSONNames
-	(*ReservedFieldNames)(nil), // 11: pb3.ReservedFieldNames
-	nil,                        // 12: pb3.Maps.Int32ToStrEntry
-	nil,                        // 13: pb3.Maps.BoolToUint32Entry
-	nil,                        // 14: pb3.Maps.Uint64ToEnumEntry
-	nil,                        // 15: pb3.Maps.StrToNestedEntry
-	nil,                        // 16: pb3.Maps.StrToOneofsEntry
+	(Enum)(0),                     // 0: pb3.Enum
+	(OptionalEnums_NestedEnum)(0), // 1: pb3.OptionalEnums.NestedEnum
+	(Enums_NestedEnum)(0),         // 2: pb3.Enums.NestedEnum
+	(*Scalars)(nil),               // 3: pb3.Scalars
+	(*Repeats)(nil),               // 4: pb3.Repeats
+	(*Proto3Optional)(nil),        // 5: pb3.Proto3Optional
+	(*OptionalEnums)(nil),         // 6: pb3.OptionalEnums
+	(*Enums)(nil),                 // 7: pb3.Enums
+	(*Nests)(nil),                 // 8: pb3.Nests
+	(*Nested)(nil),                // 9: pb3.Nested
+	(*Oneofs)(nil),                // 10: pb3.Oneofs
+	(*Maps)(nil),                  // 11: pb3.Maps
+	(*JSONNames)(nil),             // 12: pb3.JSONNames
+	(*ReservedFieldNames)(nil),    // 13: pb3.ReservedFieldNames
+	nil,                           // 14: pb3.Maps.Int32ToStrEntry
+	nil,                           // 15: pb3.Maps.BoolToUint32Entry
+	nil,                           // 16: pb3.Maps.Uint64ToEnumEntry
+	nil,                           // 17: pb3.Maps.StrToNestedEntry
+	nil,                           // 18: pb3.Maps.StrToOneofsEntry
 }
 var file_internal_testprotos_textpb3_test_proto_depIdxs = []int32{
 	0,  // 0: pb3.Proto3Optional.opt_enum:type_name -> pb3.Enum
-	7,  // 1: pb3.Proto3Optional.opt_message:type_name -> pb3.Nested
-	0,  // 2: pb3.Enums.s_enum:type_name -> pb3.Enum
-	1,  // 3: pb3.Enums.s_nested_enum:type_name -> pb3.Enums.NestedEnum
-	7,  // 4: pb3.Nests.s_nested:type_name -> pb3.Nested
-	7,  // 5: pb3.Nested.s_nested:type_name -> pb3.Nested
-	0,  // 6: pb3.Oneofs.oneof_enum:type_name -> pb3.Enum
-	7,  // 7: pb3.Oneofs.oneof_nested:type_name -> pb3.Nested
-	12, // 8: pb3.Maps.int32_to_str:type_name -> pb3.Maps.Int32ToStrEntry
-	13, // 9: pb3.Maps.bool_to_uint32:type_name -> pb3.Maps.BoolToUint32Entry
-	14, // 10: pb3.Maps.uint64_to_enum:type_name -> pb3.Maps.Uint64ToEnumEntry
-	15, // 11: pb3.Maps.str_to_nested:type_name -> pb3.Maps.StrToNestedEntry
-	16, // 12: pb3.Maps.str_to_oneofs:type_name -> pb3.Maps.StrToOneofsEntry
-	0,  // 13: pb3.Maps.Uint64ToEnumEntry.value:type_name -> pb3.Enum
-	7,  // 14: pb3.Maps.StrToNestedEntry.value:type_name -> pb3.Nested
-	8,  // 15: pb3.Maps.StrToOneofsEntry.value:type_name -> pb3.Oneofs
-	16, // [16:16] is the sub-list for method output_type
-	16, // [16:16] is the sub-list for method input_type
-	16, // [16:16] is the sub-list for extension type_name
-	16, // [16:16] is the sub-list for extension extendee
-	0,  // [0:16] is the sub-list for field type_name
+	9,  // 1: pb3.Proto3Optional.opt_message:type_name -> pb3.Nested
+	0,  // 2: pb3.OptionalEnums.opt_enum:type_name -> pb3.Enum
+	1,  // 3: pb3.OptionalEnums.opt_nested_enum:type_name -> pb3.OptionalEnums.NestedEnum
+	0,  // 4: pb3.Enums.s_enum:type_name -> pb3.Enum
+	2,  // 5: pb3.Enums.s_nested_enum:type_name -> pb3.Enums.NestedEnum
+	9,  // 6: pb3.Nests.s_nested:type_name -> pb3.Nested
+	9,  // 7: pb3.Nested.s_nested:type_name -> pb3.Nested
+	0,  // 8: pb3.Oneofs.oneof_enum:type_name -> pb3.Enum
+	9,  // 9: pb3.Oneofs.oneof_nested:type_name -> pb3.Nested
+	14, // 10: pb3.Maps.int32_to_str:type_name -> pb3.Maps.Int32ToStrEntry
+	15, // 11: pb3.Maps.bool_to_uint32:type_name -> pb3.Maps.BoolToUint32Entry
+	16, // 12: pb3.Maps.uint64_to_enum:type_name -> pb3.Maps.Uint64ToEnumEntry
+	17, // 13: pb3.Maps.str_to_nested:type_name -> pb3.Maps.StrToNestedEntry
+	18, // 14: pb3.Maps.str_to_oneofs:type_name -> pb3.Maps.StrToOneofsEntry
+	0,  // 15: pb3.Maps.Uint64ToEnumEntry.value:type_name -> pb3.Enum
+	9,  // 16: pb3.Maps.StrToNestedEntry.value:type_name -> pb3.Nested
+	10, // 17: pb3.Maps.StrToOneofsEntry.value:type_name -> pb3.Oneofs
+	18, // [18:18] is the sub-list for method output_type
+	18, // [18:18] is the sub-list for method input_type
+	18, // [18:18] is the sub-list for extension type_name
+	18, // [18:18] is the sub-list for extension extendee
+	0,  // [0:18] is the sub-list for field type_name
 }
 
 func init() { file_internal_testprotos_textpb3_test_proto_init() }
@@ -1166,7 +1356,8 @@
 		return
 	}
 	file_internal_testprotos_textpb3_test_proto_msgTypes[2].OneofWrappers = []any{}
-	file_internal_testprotos_textpb3_test_proto_msgTypes[6].OneofWrappers = []any{
+	file_internal_testprotos_textpb3_test_proto_msgTypes[3].OneofWrappers = []any{}
+	file_internal_testprotos_textpb3_test_proto_msgTypes[7].OneofWrappers = []any{
 		(*Oneofs_OneofEnum)(nil),
 		(*Oneofs_OneofString)(nil),
 		(*Oneofs_OneofNested)(nil),
@@ -1176,8 +1367,8 @@
 		File: protoimpl.DescBuilder{
 			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
 			RawDescriptor: file_internal_testprotos_textpb3_test_proto_rawDesc,
-			NumEnums:      2,
-			NumMessages:   15,
+			NumEnums:      3,
+			NumMessages:   16,
 			NumExtensions: 0,
 			NumServices:   0,
 		},
diff --git a/internal/testprotos/textpb3/test.proto b/internal/testprotos/textpb3/test.proto
index 7b3f406..b76e7ed 100644
--- a/internal/testprotos/textpb3/test.proto
+++ b/internal/testprotos/textpb3/test.proto
@@ -53,14 +53,38 @@
   optional int64 opt_int64 = 3;
   optional uint32 opt_uint32 = 4;
   optional uint64 opt_uint64 = 5;
-  optional float opt_float = 6;
-  optional double opt_double = 7;
-  optional string opt_string = 8;
-  optional bytes opt_bytes = 9;
+  optional sint32 opt_sint32 = 12;
+  optional sint64 opt_sint64 = 13;
+  optional fixed32 opt_fixed32 = 14;
+  optional fixed64 opt_fixed64 = 15;
+  optional sfixed32 opt_sfixed32 = 16;
+  optional sfixed64 opt_sfixed64 = 17;
+
+  // Textproto marshal outputs fields in the same order as this proto
+  // definition regardless of field number. Following fields are intended to
+  // test that assumption.
+
+  optional float opt_float = 20;
+  optional double opt_double = 21;
+
+  optional bytes opt_bytes = 8;
+  optional string opt_string = 9;
   optional Enum opt_enum = 10;
   optional Nested opt_message = 11;
 }
 
+message OptionalEnums {
+  optional Enum opt_enum = 1;
+
+  enum NestedEnum {
+    CERO = 0;
+    UNO = 1;
+    DOS = 2;
+    DIEZ = 10;
+  }
+  NestedEnum opt_nested_enum = 3;
+}
+
 enum Enum {
   ZERO = 0;
   ONE = 1;