From 971c7126c2ea7b74103f31245e01d22f87f6dc8f Mon Sep 17 00:00:00 2001 From: Josh Humphries Date: Thu, 30 May 2024 10:56:58 -0400 Subject: [PATCH] gofeatures: allow setting legacy_unmarshal_json_enum feature at file level All of the other features, including custom features for C++ and Java, allow setting a file-wide default. This makes it easier to migrate proto2 files, so that the feature can be set at the file level instead of needing to manually annotate each enum element. This adds the same convenience to the (pb.go).legacy_unmarshal_json_enum feature that is defined in this repo. Change-Id: If3a925674a9daeed464b589747b7f78a0200118b Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/589336 Auto-Submit: Lasse Folger LUCI-TryBot-Result: Go LUCI Reviewed-by: Lasse Folger Reviewed-by: Michael Stapelberg --- .../testdata/protoeditions/legacy_enum.pb.go | 320 ++++++++++++++++++ .../testdata/protoeditions/legacy_enum.proto | 38 +++ src/google/protobuf/go_features.proto | 1 + types/gofeaturespb/go_features.pb.go | 40 +-- 4 files changed, 379 insertions(+), 20 deletions(-) create mode 100644 cmd/protoc-gen-go/testdata/protoeditions/legacy_enum.pb.go create mode 100644 cmd/protoc-gen-go/testdata/protoeditions/legacy_enum.proto diff --git a/cmd/protoc-gen-go/testdata/protoeditions/legacy_enum.pb.go b/cmd/protoc-gen-go/testdata/protoeditions/legacy_enum.pb.go new file mode 100644 index 000000000..916f5dc16 --- /dev/null +++ b/cmd/protoc-gen-go/testdata/protoeditions/legacy_enum.pb.go @@ -0,0 +1,320 @@ +// 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. + +// Code generated by protoc-gen-go. DO NOT EDIT. +// source: cmd/protoc-gen-go/testdata/protoeditions/legacy_enum.proto + +package protoeditions + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + _ "google.golang.org/protobuf/types/gofeaturespb" + reflect "reflect" + sync "sync" +) + +// EnumTypeWithLegacyUnmarshalJSON comment. +type EnumTypeWithLegacyUnmarshalJSON int32 + +const ( + // EnumTypeWithLegacyUnmarshalJSON_ONE comment. + EnumTypeWithLegacyUnmarshalJSON_FIRST EnumTypeWithLegacyUnmarshalJSON = 1 + // EnumTypeWithLegacyUnmarshalJSON_TWO comment. + EnumTypeWithLegacyUnmarshalJSON_SECOND EnumTypeWithLegacyUnmarshalJSON = 2 +) + +// Enum value maps for EnumTypeWithLegacyUnmarshalJSON. +var ( + EnumTypeWithLegacyUnmarshalJSON_name = map[int32]string{ + 1: "FIRST", + 2: "SECOND", + } + EnumTypeWithLegacyUnmarshalJSON_value = map[string]int32{ + "FIRST": 1, + "SECOND": 2, + } +) + +func (x EnumTypeWithLegacyUnmarshalJSON) Enum() *EnumTypeWithLegacyUnmarshalJSON { + p := new(EnumTypeWithLegacyUnmarshalJSON) + *p = x + return p +} + +func (x EnumTypeWithLegacyUnmarshalJSON) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (EnumTypeWithLegacyUnmarshalJSON) Descriptor() protoreflect.EnumDescriptor { + return file_cmd_protoc_gen_go_testdata_protoeditions_legacy_enum_proto_enumTypes[0].Descriptor() +} + +func (EnumTypeWithLegacyUnmarshalJSON) Type() protoreflect.EnumType { + return &file_cmd_protoc_gen_go_testdata_protoeditions_legacy_enum_proto_enumTypes[0] +} + +func (x EnumTypeWithLegacyUnmarshalJSON) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Do not use. +func (x *EnumTypeWithLegacyUnmarshalJSON) UnmarshalJSON(b []byte) error { + num, err := protoimpl.X.UnmarshalJSONEnum(x.Descriptor(), b) + if err != nil { + return err + } + *x = EnumTypeWithLegacyUnmarshalJSON(num) + return nil +} + +// Deprecated: Use EnumTypeWithLegacyUnmarshalJSON.Descriptor instead. +func (EnumTypeWithLegacyUnmarshalJSON) EnumDescriptor() ([]byte, []int) { + return file_cmd_protoc_gen_go_testdata_protoeditions_legacy_enum_proto_rawDescGZIP(), []int{0} +} + +type EnumWithoutUnmarshalJSON int32 + +const ( + EnumWithoutUnmarshalJSON_WITHOUT_UNMARSHAL_JSON_FOO EnumWithoutUnmarshalJSON = 0 + EnumWithoutUnmarshalJSON_WITHOUT_UNMARSHAL_JSON_BAR EnumWithoutUnmarshalJSON = 1 + EnumWithoutUnmarshalJSON_WITHOUT_UNMARSHAL_JSON_BAZ EnumWithoutUnmarshalJSON = 2 +) + +// Enum value maps for EnumWithoutUnmarshalJSON. +var ( + EnumWithoutUnmarshalJSON_name = map[int32]string{ + 0: "WITHOUT_UNMARSHAL_JSON_FOO", + 1: "WITHOUT_UNMARSHAL_JSON_BAR", + 2: "WITHOUT_UNMARSHAL_JSON_BAZ", + } + EnumWithoutUnmarshalJSON_value = map[string]int32{ + "WITHOUT_UNMARSHAL_JSON_FOO": 0, + "WITHOUT_UNMARSHAL_JSON_BAR": 1, + "WITHOUT_UNMARSHAL_JSON_BAZ": 2, + } +) + +func (x EnumWithoutUnmarshalJSON) Enum() *EnumWithoutUnmarshalJSON { + p := new(EnumWithoutUnmarshalJSON) + *p = x + return p +} + +func (x EnumWithoutUnmarshalJSON) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (EnumWithoutUnmarshalJSON) Descriptor() protoreflect.EnumDescriptor { + return file_cmd_protoc_gen_go_testdata_protoeditions_legacy_enum_proto_enumTypes[1].Descriptor() +} + +func (EnumWithoutUnmarshalJSON) Type() protoreflect.EnumType { + return &file_cmd_protoc_gen_go_testdata_protoeditions_legacy_enum_proto_enumTypes[1] +} + +func (x EnumWithoutUnmarshalJSON) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use EnumWithoutUnmarshalJSON.Descriptor instead. +func (EnumWithoutUnmarshalJSON) EnumDescriptor() ([]byte, []int) { + return file_cmd_protoc_gen_go_testdata_protoeditions_legacy_enum_proto_rawDescGZIP(), []int{1} +} + +// NestedEnumType1A comment. +type ContainerForNestedEnum_NestedEnum int32 + +const ( + // NestedEnum_VALUE comment. + ContainerForNestedEnum_VALUE ContainerForNestedEnum_NestedEnum = 0 +) + +// Enum value maps for ContainerForNestedEnum_NestedEnum. +var ( + ContainerForNestedEnum_NestedEnum_name = map[int32]string{ + 0: "VALUE", + } + ContainerForNestedEnum_NestedEnum_value = map[string]int32{ + "VALUE": 0, + } +) + +func (x ContainerForNestedEnum_NestedEnum) Enum() *ContainerForNestedEnum_NestedEnum { + p := new(ContainerForNestedEnum_NestedEnum) + *p = x + return p +} + +func (x ContainerForNestedEnum_NestedEnum) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (ContainerForNestedEnum_NestedEnum) Descriptor() protoreflect.EnumDescriptor { + return file_cmd_protoc_gen_go_testdata_protoeditions_legacy_enum_proto_enumTypes[2].Descriptor() +} + +func (ContainerForNestedEnum_NestedEnum) Type() protoreflect.EnumType { + return &file_cmd_protoc_gen_go_testdata_protoeditions_legacy_enum_proto_enumTypes[2] +} + +func (x ContainerForNestedEnum_NestedEnum) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Do not use. +func (x *ContainerForNestedEnum_NestedEnum) UnmarshalJSON(b []byte) error { + num, err := protoimpl.X.UnmarshalJSONEnum(x.Descriptor(), b) + if err != nil { + return err + } + *x = ContainerForNestedEnum_NestedEnum(num) + return nil +} + +// Deprecated: Use ContainerForNestedEnum_NestedEnum.Descriptor instead. +func (ContainerForNestedEnum_NestedEnum) EnumDescriptor() ([]byte, []int) { + return file_cmd_protoc_gen_go_testdata_protoeditions_legacy_enum_proto_rawDescGZIP(), []int{0, 0} +} + +type ContainerForNestedEnum struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *ContainerForNestedEnum) Reset() { + *x = ContainerForNestedEnum{} + if protoimpl.UnsafeEnabled { + mi := &file_cmd_protoc_gen_go_testdata_protoeditions_legacy_enum_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ContainerForNestedEnum) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ContainerForNestedEnum) ProtoMessage() {} + +func (x *ContainerForNestedEnum) ProtoReflect() protoreflect.Message { + mi := &file_cmd_protoc_gen_go_testdata_protoeditions_legacy_enum_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ContainerForNestedEnum.ProtoReflect.Descriptor instead. +func (*ContainerForNestedEnum) Descriptor() ([]byte, []int) { + return file_cmd_protoc_gen_go_testdata_protoeditions_legacy_enum_proto_rawDescGZIP(), []int{0} +} + +var File_cmd_protoc_gen_go_testdata_protoeditions_legacy_enum_proto protoreflect.FileDescriptor + +var file_cmd_protoc_gen_go_testdata_protoeditions_legacy_enum_proto_rawDesc = []byte{ + 0x0a, 0x3a, 0x63, 0x6d, 0x64, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x2d, 0x67, 0x65, 0x6e, + 0x2d, 0x67, 0x6f, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x64, 0x61, 0x74, 0x61, 0x2f, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x65, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x6c, 0x65, 0x67, 0x61, 0x63, + 0x79, 0x5f, 0x65, 0x6e, 0x75, 0x6d, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x1c, 0x67, 0x6f, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x65, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x1a, 0x21, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x67, 0x6f, 0x5f, 0x66, + 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x31, 0x0a, + 0x16, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x46, 0x6f, 0x72, 0x4e, 0x65, 0x73, + 0x74, 0x65, 0x64, 0x45, 0x6e, 0x75, 0x6d, 0x22, 0x17, 0x0a, 0x0a, 0x4e, 0x65, 0x73, 0x74, 0x65, + 0x64, 0x45, 0x6e, 0x75, 0x6d, 0x12, 0x09, 0x0a, 0x05, 0x56, 0x41, 0x4c, 0x55, 0x45, 0x10, 0x00, + 0x2a, 0x3e, 0x0a, 0x1f, 0x45, 0x6e, 0x75, 0x6d, 0x54, 0x79, 0x70, 0x65, 0x57, 0x69, 0x74, 0x68, + 0x4c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x55, 0x6e, 0x6d, 0x61, 0x72, 0x73, 0x68, 0x61, 0x6c, 0x4a, + 0x53, 0x4f, 0x4e, 0x12, 0x09, 0x0a, 0x05, 0x46, 0x49, 0x52, 0x53, 0x54, 0x10, 0x01, 0x12, 0x0a, + 0x0a, 0x06, 0x53, 0x45, 0x43, 0x4f, 0x4e, 0x44, 0x10, 0x02, 0x1a, 0x04, 0x3a, 0x02, 0x10, 0x02, + 0x2a, 0x83, 0x01, 0x0a, 0x18, 0x45, 0x6e, 0x75, 0x6d, 0x57, 0x69, 0x74, 0x68, 0x6f, 0x75, 0x74, + 0x55, 0x6e, 0x6d, 0x61, 0x72, 0x73, 0x68, 0x61, 0x6c, 0x4a, 0x53, 0x4f, 0x4e, 0x12, 0x1e, 0x0a, + 0x1a, 0x57, 0x49, 0x54, 0x48, 0x4f, 0x55, 0x54, 0x5f, 0x55, 0x4e, 0x4d, 0x41, 0x52, 0x53, 0x48, + 0x41, 0x4c, 0x5f, 0x4a, 0x53, 0x4f, 0x4e, 0x5f, 0x46, 0x4f, 0x4f, 0x10, 0x00, 0x12, 0x1e, 0x0a, + 0x1a, 0x57, 0x49, 0x54, 0x48, 0x4f, 0x55, 0x54, 0x5f, 0x55, 0x4e, 0x4d, 0x41, 0x52, 0x53, 0x48, + 0x41, 0x4c, 0x5f, 0x4a, 0x53, 0x4f, 0x4e, 0x5f, 0x42, 0x41, 0x52, 0x10, 0x01, 0x12, 0x1e, 0x0a, + 0x1a, 0x57, 0x49, 0x54, 0x48, 0x4f, 0x55, 0x54, 0x5f, 0x55, 0x4e, 0x4d, 0x41, 0x52, 0x53, 0x48, + 0x41, 0x4c, 0x5f, 0x4a, 0x53, 0x4f, 0x4e, 0x5f, 0x42, 0x41, 0x5a, 0x10, 0x02, 0x1a, 0x07, 0x3a, + 0x05, 0xd2, 0x3e, 0x02, 0x08, 0x00, 0x42, 0x4d, 0x5a, 0x43, 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, 0x63, 0x6d, 0x64, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x2d, + 0x67, 0x65, 0x6e, 0x2d, 0x67, 0x6f, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x64, 0x61, 0x74, 0x61, 0x2f, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x65, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x92, 0x03, 0x05, + 0xd2, 0x3e, 0x02, 0x08, 0x01, 0x62, 0x08, 0x65, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x70, + 0xe8, 0x07, +} + +var ( + file_cmd_protoc_gen_go_testdata_protoeditions_legacy_enum_proto_rawDescOnce sync.Once + file_cmd_protoc_gen_go_testdata_protoeditions_legacy_enum_proto_rawDescData = file_cmd_protoc_gen_go_testdata_protoeditions_legacy_enum_proto_rawDesc +) + +func file_cmd_protoc_gen_go_testdata_protoeditions_legacy_enum_proto_rawDescGZIP() []byte { + file_cmd_protoc_gen_go_testdata_protoeditions_legacy_enum_proto_rawDescOnce.Do(func() { + file_cmd_protoc_gen_go_testdata_protoeditions_legacy_enum_proto_rawDescData = protoimpl.X.CompressGZIP(file_cmd_protoc_gen_go_testdata_protoeditions_legacy_enum_proto_rawDescData) + }) + return file_cmd_protoc_gen_go_testdata_protoeditions_legacy_enum_proto_rawDescData +} + +var file_cmd_protoc_gen_go_testdata_protoeditions_legacy_enum_proto_enumTypes = make([]protoimpl.EnumInfo, 3) +var file_cmd_protoc_gen_go_testdata_protoeditions_legacy_enum_proto_msgTypes = make([]protoimpl.MessageInfo, 1) +var file_cmd_protoc_gen_go_testdata_protoeditions_legacy_enum_proto_goTypes = []any{ + (EnumTypeWithLegacyUnmarshalJSON)(0), // 0: goproto.protoc.protoeditions.EnumTypeWithLegacyUnmarshalJSON + (EnumWithoutUnmarshalJSON)(0), // 1: goproto.protoc.protoeditions.EnumWithoutUnmarshalJSON + (ContainerForNestedEnum_NestedEnum)(0), // 2: goproto.protoc.protoeditions.ContainerForNestedEnum.NestedEnum + (*ContainerForNestedEnum)(nil), // 3: goproto.protoc.protoeditions.ContainerForNestedEnum +} +var file_cmd_protoc_gen_go_testdata_protoeditions_legacy_enum_proto_depIdxs = []int32{ + 0, // [0:0] is the sub-list for method output_type + 0, // [0:0] is the sub-list for method input_type + 0, // [0:0] is the sub-list for extension type_name + 0, // [0:0] is the sub-list for extension extendee + 0, // [0:0] is the sub-list for field type_name +} + +func init() { file_cmd_protoc_gen_go_testdata_protoeditions_legacy_enum_proto_init() } +func file_cmd_protoc_gen_go_testdata_protoeditions_legacy_enum_proto_init() { + if File_cmd_protoc_gen_go_testdata_protoeditions_legacy_enum_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_cmd_protoc_gen_go_testdata_protoeditions_legacy_enum_proto_msgTypes[0].Exporter = func(v any, i int) any { + switch v := v.(*ContainerForNestedEnum); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_cmd_protoc_gen_go_testdata_protoeditions_legacy_enum_proto_rawDesc, + NumEnums: 3, + NumMessages: 1, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_cmd_protoc_gen_go_testdata_protoeditions_legacy_enum_proto_goTypes, + DependencyIndexes: file_cmd_protoc_gen_go_testdata_protoeditions_legacy_enum_proto_depIdxs, + EnumInfos: file_cmd_protoc_gen_go_testdata_protoeditions_legacy_enum_proto_enumTypes, + MessageInfos: file_cmd_protoc_gen_go_testdata_protoeditions_legacy_enum_proto_msgTypes, + }.Build() + File_cmd_protoc_gen_go_testdata_protoeditions_legacy_enum_proto = out.File + file_cmd_protoc_gen_go_testdata_protoeditions_legacy_enum_proto_rawDesc = nil + file_cmd_protoc_gen_go_testdata_protoeditions_legacy_enum_proto_goTypes = nil + file_cmd_protoc_gen_go_testdata_protoeditions_legacy_enum_proto_depIdxs = nil +} diff --git a/cmd/protoc-gen-go/testdata/protoeditions/legacy_enum.proto b/cmd/protoc-gen-go/testdata/protoeditions/legacy_enum.proto new file mode 100644 index 000000000..ff84f493a --- /dev/null +++ b/cmd/protoc-gen-go/testdata/protoeditions/legacy_enum.proto @@ -0,0 +1,38 @@ +// 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. + +edition = "2023"; + +package goproto.protoc.protoeditions; + +import "google/protobuf/go_features.proto"; + +option go_package = "google.golang.org/protobuf/cmd/protoc-gen-go/testdata/protoeditions"; +option features.(pb.go).legacy_unmarshal_json_enum = true; + +// EnumTypeWithLegacyUnmarshalJSON comment. +enum EnumTypeWithLegacyUnmarshalJSON { + option features.enum_type = CLOSED; + + // EnumTypeWithLegacyUnmarshalJSON_ONE comment. + FIRST = 1; + // EnumTypeWithLegacyUnmarshalJSON_TWO comment. + SECOND = 2; +} + +message ContainerForNestedEnum { + // NestedEnumType1A comment. + enum NestedEnum { + // NestedEnum_VALUE comment. + VALUE = 0; + } +} + +enum EnumWithoutUnmarshalJSON { + option features.(pb.go).legacy_unmarshal_json_enum = false; + + WITHOUT_UNMARSHAL_JSON_FOO = 0; + WITHOUT_UNMARSHAL_JSON_BAR = 1; + WITHOUT_UNMARSHAL_JSON_BAZ = 2; +} diff --git a/src/google/protobuf/go_features.proto b/src/google/protobuf/go_features.proto index 6f99d6c8c..4d026f54e 100644 --- a/src/google/protobuf/go_features.proto +++ b/src/google/protobuf/go_features.proto @@ -22,6 +22,7 @@ message GoFeatures { optional bool legacy_unmarshal_json_enum = 1 [ retention = RETENTION_RUNTIME, targets = TARGET_TYPE_ENUM, + targets = TARGET_TYPE_FILE, feature_support = { edition_introduced: EDITION_2023, edition_deprecated: EDITION_2023, diff --git a/types/gofeaturespb/go_features.pb.go b/types/gofeaturespb/go_features.pb.go index aebdddba1..a2ca940c5 100644 --- a/types/gofeaturespb/go_features.pb.go +++ b/types/gofeaturespb/go_features.pb.go @@ -90,27 +90,27 @@ var file_google_protobuf_go_features_proto_rawDesc = []byte{ 0x66, 0x2f, 0x67, 0x6f, 0x5f, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x02, 0x70, 0x62, 0x1a, 0x20, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, - 0x74, 0x6f, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xc9, 0x01, 0x0a, 0x0a, 0x47, 0x6f, - 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x12, 0xba, 0x01, 0x0a, 0x1a, 0x6c, 0x65, 0x67, + 0x74, 0x6f, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xcd, 0x01, 0x0a, 0x0a, 0x47, 0x6f, + 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x12, 0xbe, 0x01, 0x0a, 0x1a, 0x6c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x5f, 0x75, 0x6e, 0x6d, 0x61, 0x72, 0x73, 0x68, 0x61, 0x6c, 0x5f, 0x6a, 0x73, - 0x6f, 0x6e, 0x5f, 0x65, 0x6e, 0x75, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x42, 0x7d, 0x88, - 0x01, 0x01, 0x98, 0x01, 0x06, 0xa2, 0x01, 0x09, 0x12, 0x04, 0x74, 0x72, 0x75, 0x65, 0x18, 0x84, - 0x07, 0xa2, 0x01, 0x0a, 0x12, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x18, 0xe7, 0x07, 0xb2, 0x01, - 0x5b, 0x08, 0xe8, 0x07, 0x10, 0xe8, 0x07, 0x1a, 0x53, 0x54, 0x68, 0x65, 0x20, 0x6c, 0x65, 0x67, - 0x61, 0x63, 0x79, 0x20, 0x55, 0x6e, 0x6d, 0x61, 0x72, 0x73, 0x68, 0x61, 0x6c, 0x4a, 0x53, 0x4f, - 0x4e, 0x20, 0x41, 0x50, 0x49, 0x20, 0x69, 0x73, 0x20, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, - 0x74, 0x65, 0x64, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, - 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x61, 0x20, 0x66, 0x75, 0x74, - 0x75, 0x72, 0x65, 0x20, 0x65, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x52, 0x17, 0x6c, 0x65, - 0x67, 0x61, 0x63, 0x79, 0x55, 0x6e, 0x6d, 0x61, 0x72, 0x73, 0x68, 0x61, 0x6c, 0x4a, 0x73, 0x6f, - 0x6e, 0x45, 0x6e, 0x75, 0x6d, 0x3a, 0x3c, 0x0a, 0x02, 0x67, 0x6f, 0x12, 0x1b, 0x2e, 0x67, 0x6f, - 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x65, - 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x65, 0x74, 0x18, 0xea, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x0e, 0x2e, 0x70, 0x62, 0x2e, 0x47, 0x6f, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x52, - 0x02, 0x67, 0x6f, 0x42, 0x2f, 0x5a, 0x2d, 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, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x67, 0x6f, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, - 0x65, 0x73, 0x70, 0x62, + 0x6f, 0x6e, 0x5f, 0x65, 0x6e, 0x75, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x42, 0x80, 0x01, + 0x88, 0x01, 0x01, 0x98, 0x01, 0x06, 0x98, 0x01, 0x01, 0xa2, 0x01, 0x09, 0x12, 0x04, 0x74, 0x72, + 0x75, 0x65, 0x18, 0x84, 0x07, 0xa2, 0x01, 0x0a, 0x12, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x18, + 0xe7, 0x07, 0xb2, 0x01, 0x5b, 0x08, 0xe8, 0x07, 0x10, 0xe8, 0x07, 0x1a, 0x53, 0x54, 0x68, 0x65, + 0x20, 0x6c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x20, 0x55, 0x6e, 0x6d, 0x61, 0x72, 0x73, 0x68, 0x61, + 0x6c, 0x4a, 0x53, 0x4f, 0x4e, 0x20, 0x41, 0x50, 0x49, 0x20, 0x69, 0x73, 0x20, 0x64, 0x65, 0x70, + 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x77, 0x69, 0x6c, 0x6c, + 0x20, 0x62, 0x65, 0x20, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x61, + 0x20, 0x66, 0x75, 0x74, 0x75, 0x72, 0x65, 0x20, 0x65, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x2e, + 0x52, 0x17, 0x6c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x55, 0x6e, 0x6d, 0x61, 0x72, 0x73, 0x68, 0x61, + 0x6c, 0x4a, 0x73, 0x6f, 0x6e, 0x45, 0x6e, 0x75, 0x6d, 0x3a, 0x3c, 0x0a, 0x02, 0x67, 0x6f, 0x12, + 0x1b, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, + 0x66, 0x2e, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x65, 0x74, 0x18, 0xea, 0x07, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x70, 0x62, 0x2e, 0x47, 0x6f, 0x46, 0x65, 0x61, 0x74, 0x75, + 0x72, 0x65, 0x73, 0x52, 0x02, 0x67, 0x6f, 0x42, 0x2f, 0x5a, 0x2d, 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, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x67, 0x6f, 0x66, 0x65, + 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x70, 0x62, } var (