feat: value renderer for google.protobuf.Any (#13671)

* chore: skeleton files for any renderer

* feat: first cut at Any renderer and tests

* test: Any fields, more tests, rename lookup by field

* docs: make Any example match the stated spec, and the implementation.

* refactor: use protojson for better test case legibility

* test: use protocmp for proto equality

See https://developers.google.com/protocol-buffers/docs/reference/go/faq#deepequal

* refactor: use json.RawMessage instead of remarshalling

* refactor: consistent pointer receiver for Textual
This commit is contained in:
Jim Larson
2022-11-24 08:04:55 +00:00
committed by GitHub
parent cfa224c04e
commit 077abae250
15 changed files with 592 additions and 153 deletions
@@ -182,17 +182,18 @@ Object: <type_url>
#### Examples
```
Object: /cosmos.gov.v1.Vote
> Proposal id: 4
> Vote: cosmos1abc...def
> Options: 2 WeightedVoteOptions
> Options (1/2): WeightedVoteOption object
>> Option: Yes
>> Weight: 0.7
> Options (2/2): WeightedVoteOption object
>> Option: No
>> Weight: 0.3
> End of Options
Object: type.googleapis.com/cosmos.gov.v1.Vote
> Vote object
>> Proposal id: 4
>> Vote: cosmos1abc...def
>> Options: 2 WeightedVoteOptions
>> Options (1/2): WeightedVoteOption object
>>> Option: Yes
>>> Weight: 0.7
>> Options (2/2): WeightedVoteOption object
>>> Option: No
>>> Weight: 0.3
>> End of Options
```
### `google.protobuf.Timestamp`
+76
View File
@@ -0,0 +1,76 @@
[
{
"proto": {
"@type": "type.googleapis.com/Foo"
},
"screens": [
{"text": "Object: type.googleapis.com/Foo"},
{"text": "Foo object", "indent": 1}
]
},
{
"proto": {
"@type": "type.googleapis.com/Foo",
"full_name": "testing"
},
"screens": [
{"text": "Object: type.googleapis.com/Foo"},
{"text": "Foo object", "indent": 1},
{"text": "Full name: testing", "indent": 2}
]
},
{
"proto": {
"@type": "type.googleapis.com/google.protobuf.Timestamp",
"value": "2006-01-02T15:04:05Z"
},
"screens": [
{"text": "Object: type.googleapis.com/google.protobuf.Timestamp"},
{"text": "2006-01-02T15:04:05Z", "indent": 1}
]
},
{
"proto": {
"@type": "type.googleapis.com/google.protobuf.Any",
"value": {
"@type": "type.googleapis.com/Foo"
}
},
"screens": [
{"text": "Object: type.googleapis.com/google.protobuf.Any"},
{"text": "Object: type.googleapis.com/Foo", "indent": 1},
{"text": "Foo object", "indent": 2}
]
},
{
"proto": {
"@type": "type.googleapis.com/google.protobuf.Any",
"value": {
"@type": "type.googleapis.com/Foo",
"full_name": "testing"
}
},
"screens": [
{"text": "Object: type.googleapis.com/google.protobuf.Any"},
{"text": "Object: type.googleapis.com/Foo", "indent": 1},
{"text": "Foo object", "indent": 2},
{"text": "Full name: testing", "indent": 3}
]
},
{
"proto": {
"@type": "type.googleapis.com/A",
"ANY": {
"@type": "type.googleapis.com/Foo",
"full_name": "testing"
}
},
"screens": [
{"text": "Object: type.googleapis.com/A"},
{"text": "A object", "indent": 1},
{"text": "ANY: Object: type.googleapis.com/Foo", "indent": 2},
{"text": "Foo object", "indent": 3},
{"text": "Full name: testing", "indent": 4}
]
}
]
+6 -3
View File
@@ -2,6 +2,7 @@ syntax = "proto3";
option go_package = "cosmossdk.io/tx/textual/internal/testpb";
import "google/protobuf/any.proto";
import "google/protobuf/descriptor.proto";
import "google/protobuf/duration.proto";
import "google/protobuf/timestamp.proto";
@@ -23,6 +24,7 @@ message A {
google.protobuf.Timestamp TIMESTAMP = 10;
google.protobuf.Duration DURATION = 11;
ExternalEnum ENUM = 12;
google.protobuf.Any ANY = 13;
// Fields that are not handled by SIGN_MODE_TEXTUAL.
sint32 SINT32 = 101;
@@ -48,8 +50,9 @@ message Foo {
// Bar is a sample message type used for testing message rendering.
message Bar {
string bar_id = 1;
bytes data = 2;
string bar_id = 1;
bytes data = 2;
google.protobuf.Any payload = 3;
}
enum ExternalEnum {
@@ -77,4 +80,4 @@ enum BallotOption {
BALLOT_OPTION_ABSTAIN = 2;
BALLOT_OPTION_NO = 3;
BALLOT_OPTION_NO_WITH_VETO = 4;
}
}
+304 -119
View File
@@ -11,6 +11,7 @@ import (
protoiface "google.golang.org/protobuf/runtime/protoiface"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
_ "google.golang.org/protobuf/types/descriptorpb"
anypb "google.golang.org/protobuf/types/known/anypb"
durationpb "google.golang.org/protobuf/types/known/durationpb"
timestamppb "google.golang.org/protobuf/types/known/timestamppb"
io "io"
@@ -175,6 +176,7 @@ var (
fd_A_TIMESTAMP protoreflect.FieldDescriptor
fd_A_DURATION protoreflect.FieldDescriptor
fd_A_ENUM protoreflect.FieldDescriptor
fd_A_ANY protoreflect.FieldDescriptor
fd_A_SINT32 protoreflect.FieldDescriptor
fd_A_SINT64 protoreflect.FieldDescriptor
fd_A_SFIXED32 protoreflect.FieldDescriptor
@@ -201,6 +203,7 @@ func init() {
fd_A_TIMESTAMP = md_A.Fields().ByName("TIMESTAMP")
fd_A_DURATION = md_A.Fields().ByName("DURATION")
fd_A_ENUM = md_A.Fields().ByName("ENUM")
fd_A_ANY = md_A.Fields().ByName("ANY")
fd_A_SINT32 = md_A.Fields().ByName("SINT32")
fd_A_SINT64 = md_A.Fields().ByName("SINT64")
fd_A_SFIXED32 = md_A.Fields().ByName("SFIXED32")
@@ -349,6 +352,12 @@ func (x *fastReflection_A) Range(f func(protoreflect.FieldDescriptor, protorefle
return
}
}
if x.ANY != nil {
value := protoreflect.ValueOfMessage(x.ANY.ProtoReflect())
if !f(fd_A_ANY, value) {
return
}
}
if x.SINT32 != int32(0) {
value := protoreflect.ValueOfInt32(x.SINT32)
if !f(fd_A_SINT32, value) {
@@ -442,6 +451,8 @@ func (x *fastReflection_A) Has(fd protoreflect.FieldDescriptor) bool {
return x.DURATION != nil
case "A.ENUM":
return x.ENUM != 0
case "A.ANY":
return x.ANY != nil
case "A.SINT32":
return x.SINT32 != int32(0)
case "A.SINT64":
@@ -500,6 +511,8 @@ func (x *fastReflection_A) Clear(fd protoreflect.FieldDescriptor) {
x.DURATION = nil
case "A.ENUM":
x.ENUM = 0
case "A.ANY":
x.ANY = nil
case "A.SINT32":
x.SINT32 = int32(0)
case "A.SINT64":
@@ -573,6 +586,9 @@ func (x *fastReflection_A) Get(descriptor protoreflect.FieldDescriptor) protoref
case "A.ENUM":
value := x.ENUM
return protoreflect.ValueOfEnum((protoreflect.EnumNumber)(value))
case "A.ANY":
value := x.ANY
return protoreflect.ValueOfMessage(value.ProtoReflect())
case "A.SINT32":
value := x.SINT32
return protoreflect.ValueOfInt32(value)
@@ -649,6 +665,8 @@ func (x *fastReflection_A) Set(fd protoreflect.FieldDescriptor, value protorefle
x.DURATION = value.Message().Interface().(*durationpb.Duration)
case "A.ENUM":
x.ENUM = (ExternalEnum)(value.Enum())
case "A.ANY":
x.ANY = value.Message().Interface().(*anypb.Any)
case "A.SINT32":
x.SINT32 = int32(value.Int())
case "A.SINT64":
@@ -710,6 +728,11 @@ func (x *fastReflection_A) Mutable(fd protoreflect.FieldDescriptor) protoreflect
x.DURATION = new(durationpb.Duration)
}
return protoreflect.ValueOfMessage(x.DURATION.ProtoReflect())
case "A.ANY":
if x.ANY == nil {
x.ANY = new(anypb.Any)
}
return protoreflect.ValueOfMessage(x.ANY.ProtoReflect())
case "A.MAP":
if x.MAP == nil {
x.MAP = make(map[string]*A)
@@ -789,6 +812,9 @@ func (x *fastReflection_A) NewField(fd protoreflect.FieldDescriptor) protoreflec
return protoreflect.ValueOfMessage(m.ProtoReflect())
case "A.ENUM":
return protoreflect.ValueOfEnum(0)
case "A.ANY":
m := new(anypb.Any)
return protoreflect.ValueOfMessage(m.ProtoReflect())
case "A.SINT32":
return protoreflect.ValueOfInt32(int32(0))
case "A.SINT64":
@@ -922,6 +948,10 @@ func (x *fastReflection_A) ProtoMethods() *protoiface.Methods {
if x.ENUM != 0 {
n += 1 + runtime.Sov(uint64(x.ENUM))
}
if x.ANY != nil {
l = options.Size(x.ANY)
n += 1 + l + runtime.Sov(uint64(l))
}
if x.SINT32 != 0 {
n += 2 + runtime.Soz(uint64(x.SINT32))
}
@@ -1115,6 +1145,20 @@ func (x *fastReflection_A) ProtoMethods() *protoiface.Methods {
i--
dAtA[i] = 0xa8
}
if x.ANY != nil {
encoded, err := options.Marshal(x.ANY)
if err != nil {
return protoiface.MarshalOutput{
NoUnkeyedLiterals: input.NoUnkeyedLiterals,
Buf: input.Buf,
}, err
}
i -= len(encoded)
copy(dAtA[i:], encoded)
i = runtime.EncodeVarint(dAtA, i, uint64(len(encoded)))
i--
dAtA[i] = 0x6a
}
if x.ENUM != 0 {
i = runtime.EncodeVarint(dAtA, i, uint64(x.ENUM))
i--
@@ -1603,6 +1647,42 @@ func (x *fastReflection_A) ProtoMethods() *protoiface.Methods {
break
}
}
case 13:
if wireType != 2 {
return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field ANY", wireType)
}
var msglen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrIntOverflow
}
if iNdEx >= l {
return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
msglen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
if msglen < 0 {
return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength
}
postIndex := iNdEx + msglen
if postIndex < 0 {
return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength
}
if postIndex > l {
return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF
}
if x.ANY == nil {
x.ANY = &anypb.Any{}
}
if err := options.Unmarshal(dAtA[iNdEx:postIndex], x.ANY); err != nil {
return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, err
}
iNdEx = postIndex
case 101:
if wireType != 0 {
return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field SINT32", wireType)
@@ -2672,9 +2752,10 @@ func (x *fastReflection_Foo) ProtoMethods() *protoiface.Methods {
}
var (
md_Bar protoreflect.MessageDescriptor
fd_Bar_bar_id protoreflect.FieldDescriptor
fd_Bar_data protoreflect.FieldDescriptor
md_Bar protoreflect.MessageDescriptor
fd_Bar_bar_id protoreflect.FieldDescriptor
fd_Bar_data protoreflect.FieldDescriptor
fd_Bar_payload protoreflect.FieldDescriptor
)
func init() {
@@ -2682,6 +2763,7 @@ func init() {
md_Bar = File__1_proto.Messages().ByName("Bar")
fd_Bar_bar_id = md_Bar.Fields().ByName("bar_id")
fd_Bar_data = md_Bar.Fields().ByName("data")
fd_Bar_payload = md_Bar.Fields().ByName("payload")
}
var _ protoreflect.Message = (*fastReflection_Bar)(nil)
@@ -2761,6 +2843,12 @@ func (x *fastReflection_Bar) Range(f func(protoreflect.FieldDescriptor, protoref
return
}
}
if x.Payload != nil {
value := protoreflect.ValueOfMessage(x.Payload.ProtoReflect())
if !f(fd_Bar_payload, value) {
return
}
}
}
// Has reports whether a field is populated.
@@ -2780,6 +2868,8 @@ func (x *fastReflection_Bar) Has(fd protoreflect.FieldDescriptor) bool {
return x.BarId != ""
case "Bar.data":
return len(x.Data) != 0
case "Bar.payload":
return x.Payload != nil
default:
if fd.IsExtension() {
panic(fmt.Errorf("proto3 declared messages do not support extensions: Bar"))
@@ -2800,6 +2890,8 @@ func (x *fastReflection_Bar) Clear(fd protoreflect.FieldDescriptor) {
x.BarId = ""
case "Bar.data":
x.Data = nil
case "Bar.payload":
x.Payload = nil
default:
if fd.IsExtension() {
panic(fmt.Errorf("proto3 declared messages do not support extensions: Bar"))
@@ -2822,6 +2914,9 @@ func (x *fastReflection_Bar) Get(descriptor protoreflect.FieldDescriptor) protor
case "Bar.data":
value := x.Data
return protoreflect.ValueOfBytes(value)
case "Bar.payload":
value := x.Payload
return protoreflect.ValueOfMessage(value.ProtoReflect())
default:
if descriptor.IsExtension() {
panic(fmt.Errorf("proto3 declared messages do not support extensions: Bar"))
@@ -2846,6 +2941,8 @@ func (x *fastReflection_Bar) Set(fd protoreflect.FieldDescriptor, value protoref
x.BarId = value.Interface().(string)
case "Bar.data":
x.Data = value.Bytes()
case "Bar.payload":
x.Payload = value.Message().Interface().(*anypb.Any)
default:
if fd.IsExtension() {
panic(fmt.Errorf("proto3 declared messages do not support extensions: Bar"))
@@ -2866,6 +2963,11 @@ func (x *fastReflection_Bar) Set(fd protoreflect.FieldDescriptor, value protoref
// Mutable is a mutating operation and unsafe for concurrent use.
func (x *fastReflection_Bar) Mutable(fd protoreflect.FieldDescriptor) protoreflect.Value {
switch fd.FullName() {
case "Bar.payload":
if x.Payload == nil {
x.Payload = new(anypb.Any)
}
return protoreflect.ValueOfMessage(x.Payload.ProtoReflect())
case "Bar.bar_id":
panic(fmt.Errorf("field bar_id of message Bar is not mutable"))
case "Bar.data":
@@ -2887,6 +2989,9 @@ func (x *fastReflection_Bar) NewField(fd protoreflect.FieldDescriptor) protorefl
return protoreflect.ValueOfString("")
case "Bar.data":
return protoreflect.ValueOfBytes(nil)
case "Bar.payload":
m := new(anypb.Any)
return protoreflect.ValueOfMessage(m.ProtoReflect())
default:
if fd.IsExtension() {
panic(fmt.Errorf("proto3 declared messages do not support extensions: Bar"))
@@ -2964,6 +3069,10 @@ func (x *fastReflection_Bar) ProtoMethods() *protoiface.Methods {
if l > 0 {
n += 1 + l + runtime.Sov(uint64(l))
}
if x.Payload != nil {
l = options.Size(x.Payload)
n += 1 + l + runtime.Sov(uint64(l))
}
if x.unknownFields != nil {
n += len(x.unknownFields)
}
@@ -2993,6 +3102,20 @@ func (x *fastReflection_Bar) ProtoMethods() *protoiface.Methods {
i -= len(x.unknownFields)
copy(dAtA[i:], x.unknownFields)
}
if x.Payload != nil {
encoded, err := options.Marshal(x.Payload)
if err != nil {
return protoiface.MarshalOutput{
NoUnkeyedLiterals: input.NoUnkeyedLiterals,
Buf: input.Buf,
}, err
}
i -= len(encoded)
copy(dAtA[i:], encoded)
i = runtime.EncodeVarint(dAtA, i, uint64(len(encoded)))
i--
dAtA[i] = 0x1a
}
if len(x.Data) > 0 {
i -= len(x.Data)
copy(dAtA[i:], x.Data)
@@ -3122,6 +3245,42 @@ func (x *fastReflection_Bar) ProtoMethods() *protoiface.Methods {
x.Data = []byte{}
}
iNdEx = postIndex
case 3:
if wireType != 2 {
return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field Payload", wireType)
}
var msglen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrIntOverflow
}
if iNdEx >= l {
return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
msglen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
if msglen < 0 {
return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength
}
postIndex := iNdEx + msglen
if postIndex < 0 {
return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength
}
if postIndex > l {
return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF
}
if x.Payload == nil {
x.Payload = &anypb.Any{}
}
if err := options.Unmarshal(dAtA[iNdEx:postIndex], x.Payload); err != nil {
return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, err
}
iNdEx = postIndex
default:
iNdEx = preIndex
skippy, err := runtime.Skip(dAtA[iNdEx:])
@@ -3839,6 +3998,7 @@ type A struct {
TIMESTAMP *timestamppb.Timestamp `protobuf:"bytes,10,opt,name=TIMESTAMP,proto3" json:"TIMESTAMP,omitempty"`
DURATION *durationpb.Duration `protobuf:"bytes,11,opt,name=DURATION,proto3" json:"DURATION,omitempty"`
ENUM ExternalEnum `protobuf:"varint,12,opt,name=ENUM,proto3,enum=ExternalEnum" json:"ENUM,omitempty"`
ANY *anypb.Any `protobuf:"bytes,13,opt,name=ANY,proto3" json:"ANY,omitempty"`
// Fields that are not handled by SIGN_MODE_TEXTUAL.
SINT32 int32 `protobuf:"zigzag32,101,opt,name=SINT32,proto3" json:"SINT32,omitempty"`
SINT64 int64 `protobuf:"zigzag64,102,opt,name=SINT64,proto3" json:"SINT64,omitempty"`
@@ -3955,6 +4115,13 @@ func (x *A) GetENUM() ExternalEnum {
return ExternalEnum_One
}
func (x *A) GetANY() *anypb.Any {
if x != nil {
return x.ANY
}
return nil
}
func (x *A) GetSINT32() int32 {
if x != nil {
return x.SINT32
@@ -4100,8 +4267,9 @@ type Bar struct {
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
BarId string `protobuf:"bytes,1,opt,name=bar_id,json=barId,proto3" json:"bar_id,omitempty"`
Data []byte `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"`
BarId string `protobuf:"bytes,1,opt,name=bar_id,json=barId,proto3" json:"bar_id,omitempty"`
Data []byte `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"`
Payload *anypb.Any `protobuf:"bytes,3,opt,name=payload,proto3" json:"payload,omitempty"`
}
func (x *Bar) Reset() {
@@ -4138,7 +4306,14 @@ func (x *Bar) GetData() []byte {
return nil
}
// Baz is a sampel message type used for testing enum rendering.
func (x *Bar) GetPayload() *anypb.Any {
if x != nil {
return x.Payload
}
return nil
}
// Baz is a sample message type used for testing enum rendering.
type Baz struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
@@ -4193,105 +4368,112 @@ func (x *Baz) GetOption() BallotOption {
var File__1_proto protoreflect.FileDescriptor
var file__1_proto_rawDesc = []byte{
0x0a, 0x07, 0x31, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 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, 0x1a, 0x1e, 0x67, 0x6f, 0x6f,
0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x64, 0x75, 0x72,
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1f, 0x67, 0x6f, 0x6f,
0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d,
0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x19, 0x63, 0x6f,
0x73, 0x6d, 0x6f, 0x73, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x63, 0x6f, 0x73, 0x6d, 0x6f,
0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2f,
0x62, 0x61, 0x73, 0x65, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x63, 0x6f, 0x69,
0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xde, 0x05, 0x0a, 0x01, 0x41, 0x12, 0x16, 0x0a,
0x06, 0x55, 0x49, 0x4e, 0x54, 0x33, 0x32, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x06, 0x55,
0x49, 0x4e, 0x54, 0x33, 0x32, 0x12, 0x16, 0x0a, 0x06, 0x55, 0x49, 0x4e, 0x54, 0x36, 0x34, 0x18,
0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x55, 0x49, 0x4e, 0x54, 0x36, 0x34, 0x12, 0x14, 0x0a,
0x05, 0x49, 0x4e, 0x54, 0x33, 0x32, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x49, 0x4e,
0x54, 0x33, 0x32, 0x12, 0x14, 0x0a, 0x05, 0x49, 0x4e, 0x54, 0x36, 0x34, 0x18, 0x04, 0x20, 0x01,
0x28, 0x03, 0x52, 0x05, 0x49, 0x4e, 0x54, 0x36, 0x34, 0x12, 0x26, 0x0a, 0x06, 0x53, 0x44, 0x4b,
0x49, 0x4e, 0x54, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x42, 0x0e, 0xd2, 0xb4, 0x2d, 0x0a, 0x63,
0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x49, 0x6e, 0x74, 0x52, 0x06, 0x53, 0x44, 0x4b, 0x49, 0x4e,
0x54, 0x12, 0x26, 0x0a, 0x06, 0x53, 0x44, 0x4b, 0x44, 0x45, 0x43, 0x18, 0x06, 0x20, 0x01, 0x28,
0x09, 0x42, 0x0e, 0xd2, 0xb4, 0x2d, 0x0a, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x44, 0x65,
0x63, 0x52, 0x06, 0x53, 0x44, 0x4b, 0x44, 0x45, 0x43, 0x12, 0x2d, 0x0a, 0x04, 0x43, 0x4f, 0x49,
0x4e, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73,
0x2e, 0x62, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x43, 0x6f,
0x69, 0x6e, 0x52, 0x04, 0x43, 0x4f, 0x49, 0x4e, 0x12, 0x2f, 0x0a, 0x05, 0x43, 0x4f, 0x49, 0x4e,
0x53, 0x18, 0x08, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73,
0x2e, 0x62, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x43, 0x6f,
0x69, 0x6e, 0x52, 0x05, 0x43, 0x4f, 0x49, 0x4e, 0x53, 0x12, 0x14, 0x0a, 0x05, 0x42, 0x59, 0x54,
0x45, 0x53, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x42, 0x59, 0x54, 0x45, 0x53, 0x12,
0x38, 0x0a, 0x09, 0x54, 0x49, 0x4d, 0x45, 0x53, 0x54, 0x41, 0x4d, 0x50, 0x18, 0x0a, 0x20, 0x01,
0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74,
0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09,
0x54, 0x49, 0x4d, 0x45, 0x53, 0x54, 0x41, 0x4d, 0x50, 0x12, 0x35, 0x0a, 0x08, 0x44, 0x55, 0x52,
0x41, 0x54, 0x49, 0x4f, 0x4e, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f,
0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75,
0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x08, 0x44, 0x55, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e,
0x12, 0x21, 0x0a, 0x04, 0x45, 0x4e, 0x55, 0x4d, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x0d,
0x2e, 0x45, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x45, 0x6e, 0x75, 0x6d, 0x52, 0x04, 0x45,
0x4e, 0x55, 0x4d, 0x12, 0x16, 0x0a, 0x06, 0x53, 0x49, 0x4e, 0x54, 0x33, 0x32, 0x18, 0x65, 0x20,
0x01, 0x28, 0x11, 0x52, 0x06, 0x53, 0x49, 0x4e, 0x54, 0x33, 0x32, 0x12, 0x16, 0x0a, 0x06, 0x53,
0x49, 0x4e, 0x54, 0x36, 0x34, 0x18, 0x66, 0x20, 0x01, 0x28, 0x12, 0x52, 0x06, 0x53, 0x49, 0x4e,
0x54, 0x36, 0x34, 0x12, 0x1a, 0x0a, 0x08, 0x53, 0x46, 0x49, 0x58, 0x45, 0x44, 0x33, 0x32, 0x18,
0x69, 0x20, 0x01, 0x28, 0x0f, 0x52, 0x08, 0x53, 0x46, 0x49, 0x58, 0x45, 0x44, 0x33, 0x32, 0x12,
0x18, 0x0a, 0x07, 0x46, 0x49, 0x58, 0x45, 0x44, 0x33, 0x32, 0x18, 0x6a, 0x20, 0x01, 0x28, 0x07,
0x52, 0x07, 0x46, 0x49, 0x58, 0x45, 0x44, 0x33, 0x32, 0x12, 0x14, 0x0a, 0x05, 0x46, 0x4c, 0x4f,
0x41, 0x54, 0x18, 0x6b, 0x20, 0x01, 0x28, 0x02, 0x52, 0x05, 0x46, 0x4c, 0x4f, 0x41, 0x54, 0x12,
0x1a, 0x0a, 0x08, 0x53, 0x46, 0x49, 0x58, 0x45, 0x44, 0x36, 0x34, 0x18, 0x6c, 0x20, 0x01, 0x28,
0x10, 0x52, 0x08, 0x53, 0x46, 0x49, 0x58, 0x45, 0x44, 0x36, 0x34, 0x12, 0x18, 0x0a, 0x07, 0x46,
0x49, 0x58, 0x45, 0x44, 0x36, 0x34, 0x18, 0x6d, 0x20, 0x01, 0x28, 0x06, 0x52, 0x07, 0x46, 0x49,
0x58, 0x45, 0x44, 0x36, 0x34, 0x12, 0x16, 0x0a, 0x06, 0x44, 0x4f, 0x55, 0x42, 0x4c, 0x45, 0x18,
0x6e, 0x20, 0x01, 0x28, 0x01, 0x52, 0x06, 0x44, 0x4f, 0x55, 0x42, 0x4c, 0x45, 0x12, 0x1d, 0x0a,
0x03, 0x4d, 0x41, 0x50, 0x18, 0x6f, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0b, 0x2e, 0x41, 0x2e, 0x4d,
0x41, 0x50, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x03, 0x4d, 0x41, 0x50, 0x1a, 0x3a, 0x0a, 0x08,
0x4d, 0x41, 0x50, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18,
0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x18, 0x0a, 0x05, 0x76, 0x61,
0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x02, 0x2e, 0x41, 0x52, 0x05, 0x76,
0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xbe, 0x01, 0x0a, 0x03, 0x46, 0x6f, 0x6f,
0x12, 0x1b, 0x0a, 0x09, 0x66, 0x75, 0x6c, 0x6c, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20,
0x01, 0x28, 0x09, 0x52, 0x08, 0x66, 0x75, 0x6c, 0x6c, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1a, 0x0a,
0x08, 0x6e, 0x69, 0x63, 0x6b, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52,
0x08, 0x6e, 0x69, 0x63, 0x6b, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x30, 0x0a, 0x05, 0x6d, 0x74, 0x69,
0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73,
0x74, 0x61, 0x6d, 0x70, 0x52, 0x05, 0x6d, 0x74, 0x69, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x04, 0x6c,
0x65, 0x66, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x04, 0x2e, 0x46, 0x6f, 0x6f, 0x52,
0x04, 0x6c, 0x65, 0x66, 0x74, 0x12, 0x1a, 0x0a, 0x05, 0x72, 0x69, 0x67, 0x68, 0x74, 0x18, 0x05,
0x20, 0x01, 0x28, 0x0b, 0x32, 0x04, 0x2e, 0x46, 0x6f, 0x6f, 0x52, 0x05, 0x72, 0x69, 0x67, 0x68,
0x74, 0x12, 0x16, 0x0a, 0x03, 0x62, 0x61, 0x72, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x04,
0x2e, 0x42, 0x61, 0x72, 0x52, 0x03, 0x62, 0x61, 0x72, 0x22, 0x30, 0x0a, 0x03, 0x42, 0x61, 0x72,
0x12, 0x15, 0x0a, 0x06, 0x62, 0x61, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
0x52, 0x05, 0x62, 0x61, 0x72, 0x49, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18,
0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x22, 0x94, 0x01, 0x0a, 0x03,
0x42, 0x61, 0x7a, 0x12, 0x1d, 0x0a, 0x02, 0x65, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32,
0x0d, 0x2e, 0x45, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x45, 0x6e, 0x75, 0x6d, 0x52, 0x02,
0x65, 0x65, 0x12, 0x22, 0x0a, 0x02, 0x69, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x12,
0x2e, 0x42, 0x61, 0x7a, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x45, 0x6e,
0x75, 0x6d, 0x52, 0x02, 0x69, 0x65, 0x12, 0x25, 0x0a, 0x06, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e,
0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x0d, 0x2e, 0x42, 0x61, 0x6c, 0x6c, 0x6f, 0x74, 0x4f,
0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x06, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x23, 0x0a,
0x0d, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x45, 0x6e, 0x75, 0x6d, 0x12, 0x08,
0x0a, 0x04, 0x46, 0x6f, 0x75, 0x72, 0x10, 0x00, 0x12, 0x08, 0x0a, 0x04, 0x46, 0x69, 0x76, 0x65,
0x10, 0x01, 0x2a, 0x39, 0x0a, 0x0c, 0x45, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x45, 0x6e,
0x75, 0x6d, 0x12, 0x07, 0x0a, 0x03, 0x4f, 0x6e, 0x65, 0x10, 0x00, 0x12, 0x07, 0x0a, 0x03, 0x54,
0x77, 0x6f, 0x10, 0x01, 0x12, 0x17, 0x0a, 0x13, 0x45, 0x58, 0x54, 0x45, 0x52, 0x4e, 0x41, 0x4c,
0x5f, 0x45, 0x4e, 0x55, 0x4d, 0x5f, 0x54, 0x48, 0x52, 0x45, 0x45, 0x10, 0x7f, 0x2a, 0x95, 0x01,
0x0a, 0x0c, 0x42, 0x61, 0x6c, 0x6c, 0x6f, 0x74, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1d,
0x0a, 0x19, 0x42, 0x41, 0x4c, 0x4c, 0x4f, 0x54, 0x5f, 0x4f, 0x50, 0x54, 0x49, 0x4f, 0x4e, 0x5f,
0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x15, 0x0a,
0x11, 0x42, 0x41, 0x4c, 0x4c, 0x4f, 0x54, 0x5f, 0x4f, 0x50, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x59,
0x45, 0x53, 0x10, 0x01, 0x12, 0x19, 0x0a, 0x15, 0x42, 0x41, 0x4c, 0x4c, 0x4f, 0x54, 0x5f, 0x4f,
0x50, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x41, 0x42, 0x53, 0x54, 0x41, 0x49, 0x4e, 0x10, 0x02, 0x12,
0x14, 0x0a, 0x10, 0x42, 0x41, 0x4c, 0x4c, 0x4f, 0x54, 0x5f, 0x4f, 0x50, 0x54, 0x49, 0x4f, 0x4e,
0x5f, 0x4e, 0x4f, 0x10, 0x03, 0x12, 0x1e, 0x0a, 0x1a, 0x42, 0x41, 0x4c, 0x4c, 0x4f, 0x54, 0x5f,
0x4f, 0x50, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x4e, 0x4f, 0x5f, 0x57, 0x49, 0x54, 0x48, 0x5f, 0x56,
0x45, 0x54, 0x4f, 0x10, 0x04, 0x42, 0x33, 0x42, 0x06, 0x31, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50,
0x01, 0x5a, 0x27, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x73, 0x64, 0x6b, 0x2e, 0x69, 0x6f, 0x2f,
0x74, 0x78, 0x2f, 0x74, 0x65, 0x78, 0x74, 0x75, 0x61, 0x6c, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72,
0x6e, 0x61, 0x6c, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74,
0x6f, 0x33,
0x0a, 0x07, 0x31, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x19, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x61, 0x6e, 0x79, 0x2e, 0x70,
0x72, 0x6f, 0x74, 0x6f, 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, 0x1a, 0x1e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70,
0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e,
0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70,
0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d,
0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x19, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x5f,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x70, 0x72, 0x6f,
0x74, 0x6f, 0x1a, 0x1e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2f, 0x62, 0x61, 0x73, 0x65, 0x2f,
0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x63, 0x6f, 0x69, 0x6e, 0x2e, 0x70, 0x72, 0x6f,
0x74, 0x6f, 0x22, 0x86, 0x06, 0x0a, 0x01, 0x41, 0x12, 0x16, 0x0a, 0x06, 0x55, 0x49, 0x4e, 0x54,
0x33, 0x32, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x06, 0x55, 0x49, 0x4e, 0x54, 0x33, 0x32,
0x12, 0x16, 0x0a, 0x06, 0x55, 0x49, 0x4e, 0x54, 0x36, 0x34, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04,
0x52, 0x06, 0x55, 0x49, 0x4e, 0x54, 0x36, 0x34, 0x12, 0x14, 0x0a, 0x05, 0x49, 0x4e, 0x54, 0x33,
0x32, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x49, 0x4e, 0x54, 0x33, 0x32, 0x12, 0x14,
0x0a, 0x05, 0x49, 0x4e, 0x54, 0x36, 0x34, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x49,
0x4e, 0x54, 0x36, 0x34, 0x12, 0x26, 0x0a, 0x06, 0x53, 0x44, 0x4b, 0x49, 0x4e, 0x54, 0x18, 0x05,
0x20, 0x01, 0x28, 0x09, 0x42, 0x0e, 0xd2, 0xb4, 0x2d, 0x0a, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73,
0x2e, 0x49, 0x6e, 0x74, 0x52, 0x06, 0x53, 0x44, 0x4b, 0x49, 0x4e, 0x54, 0x12, 0x26, 0x0a, 0x06,
0x53, 0x44, 0x4b, 0x44, 0x45, 0x43, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x42, 0x0e, 0xd2, 0xb4,
0x2d, 0x0a, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x44, 0x65, 0x63, 0x52, 0x06, 0x53, 0x44,
0x4b, 0x44, 0x45, 0x43, 0x12, 0x2d, 0x0a, 0x04, 0x43, 0x4f, 0x49, 0x4e, 0x18, 0x07, 0x20, 0x01,
0x28, 0x0b, 0x32, 0x19, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x62, 0x61, 0x73, 0x65,
0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x43, 0x6f, 0x69, 0x6e, 0x52, 0x04, 0x43,
0x4f, 0x49, 0x4e, 0x12, 0x2f, 0x0a, 0x05, 0x43, 0x4f, 0x49, 0x4e, 0x53, 0x18, 0x08, 0x20, 0x03,
0x28, 0x0b, 0x32, 0x19, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x62, 0x61, 0x73, 0x65,
0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x43, 0x6f, 0x69, 0x6e, 0x52, 0x05, 0x43,
0x4f, 0x49, 0x4e, 0x53, 0x12, 0x14, 0x0a, 0x05, 0x42, 0x59, 0x54, 0x45, 0x53, 0x18, 0x09, 0x20,
0x01, 0x28, 0x0c, 0x52, 0x05, 0x42, 0x59, 0x54, 0x45, 0x53, 0x12, 0x38, 0x0a, 0x09, 0x54, 0x49,
0x4d, 0x45, 0x53, 0x54, 0x41, 0x4d, 0x50, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e,
0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e,
0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x54, 0x49, 0x4d, 0x45, 0x53,
0x54, 0x41, 0x4d, 0x50, 0x12, 0x35, 0x0a, 0x08, 0x44, 0x55, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e,
0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f,
0x6e, 0x52, 0x08, 0x44, 0x55, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x12, 0x21, 0x0a, 0x04, 0x45,
0x4e, 0x55, 0x4d, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x0d, 0x2e, 0x45, 0x78, 0x74, 0x65,
0x72, 0x6e, 0x61, 0x6c, 0x45, 0x6e, 0x75, 0x6d, 0x52, 0x04, 0x45, 0x4e, 0x55, 0x4d, 0x12, 0x26,
0x0a, 0x03, 0x41, 0x4e, 0x59, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x6f,
0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x41, 0x6e,
0x79, 0x52, 0x03, 0x41, 0x4e, 0x59, 0x12, 0x16, 0x0a, 0x06, 0x53, 0x49, 0x4e, 0x54, 0x33, 0x32,
0x18, 0x65, 0x20, 0x01, 0x28, 0x11, 0x52, 0x06, 0x53, 0x49, 0x4e, 0x54, 0x33, 0x32, 0x12, 0x16,
0x0a, 0x06, 0x53, 0x49, 0x4e, 0x54, 0x36, 0x34, 0x18, 0x66, 0x20, 0x01, 0x28, 0x12, 0x52, 0x06,
0x53, 0x49, 0x4e, 0x54, 0x36, 0x34, 0x12, 0x1a, 0x0a, 0x08, 0x53, 0x46, 0x49, 0x58, 0x45, 0x44,
0x33, 0x32, 0x18, 0x69, 0x20, 0x01, 0x28, 0x0f, 0x52, 0x08, 0x53, 0x46, 0x49, 0x58, 0x45, 0x44,
0x33, 0x32, 0x12, 0x18, 0x0a, 0x07, 0x46, 0x49, 0x58, 0x45, 0x44, 0x33, 0x32, 0x18, 0x6a, 0x20,
0x01, 0x28, 0x07, 0x52, 0x07, 0x46, 0x49, 0x58, 0x45, 0x44, 0x33, 0x32, 0x12, 0x14, 0x0a, 0x05,
0x46, 0x4c, 0x4f, 0x41, 0x54, 0x18, 0x6b, 0x20, 0x01, 0x28, 0x02, 0x52, 0x05, 0x46, 0x4c, 0x4f,
0x41, 0x54, 0x12, 0x1a, 0x0a, 0x08, 0x53, 0x46, 0x49, 0x58, 0x45, 0x44, 0x36, 0x34, 0x18, 0x6c,
0x20, 0x01, 0x28, 0x10, 0x52, 0x08, 0x53, 0x46, 0x49, 0x58, 0x45, 0x44, 0x36, 0x34, 0x12, 0x18,
0x0a, 0x07, 0x46, 0x49, 0x58, 0x45, 0x44, 0x36, 0x34, 0x18, 0x6d, 0x20, 0x01, 0x28, 0x06, 0x52,
0x07, 0x46, 0x49, 0x58, 0x45, 0x44, 0x36, 0x34, 0x12, 0x16, 0x0a, 0x06, 0x44, 0x4f, 0x55, 0x42,
0x4c, 0x45, 0x18, 0x6e, 0x20, 0x01, 0x28, 0x01, 0x52, 0x06, 0x44, 0x4f, 0x55, 0x42, 0x4c, 0x45,
0x12, 0x1d, 0x0a, 0x03, 0x4d, 0x41, 0x50, 0x18, 0x6f, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0b, 0x2e,
0x41, 0x2e, 0x4d, 0x41, 0x50, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x03, 0x4d, 0x41, 0x50, 0x1a,
0x3a, 0x0a, 0x08, 0x4d, 0x41, 0x50, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b,
0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x18, 0x0a,
0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x02, 0x2e, 0x41,
0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xbe, 0x01, 0x0a, 0x03,
0x46, 0x6f, 0x6f, 0x12, 0x1b, 0x0a, 0x09, 0x66, 0x75, 0x6c, 0x6c, 0x5f, 0x6e, 0x61, 0x6d, 0x65,
0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x66, 0x75, 0x6c, 0x6c, 0x4e, 0x61, 0x6d, 0x65,
0x12, 0x1a, 0x0a, 0x08, 0x6e, 0x69, 0x63, 0x6b, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01,
0x28, 0x09, 0x52, 0x08, 0x6e, 0x69, 0x63, 0x6b, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x30, 0x0a, 0x05,
0x6d, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f,
0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69,
0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x05, 0x6d, 0x74, 0x69, 0x6d, 0x65, 0x12, 0x18,
0x0a, 0x04, 0x6c, 0x65, 0x66, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x04, 0x2e, 0x46,
0x6f, 0x6f, 0x52, 0x04, 0x6c, 0x65, 0x66, 0x74, 0x12, 0x1a, 0x0a, 0x05, 0x72, 0x69, 0x67, 0x68,
0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x04, 0x2e, 0x46, 0x6f, 0x6f, 0x52, 0x05, 0x72,
0x69, 0x67, 0x68, 0x74, 0x12, 0x16, 0x0a, 0x03, 0x62, 0x61, 0x72, 0x18, 0x08, 0x20, 0x01, 0x28,
0x0b, 0x32, 0x04, 0x2e, 0x42, 0x61, 0x72, 0x52, 0x03, 0x62, 0x61, 0x72, 0x22, 0x60, 0x0a, 0x03,
0x42, 0x61, 0x72, 0x12, 0x15, 0x0a, 0x06, 0x62, 0x61, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20,
0x01, 0x28, 0x09, 0x52, 0x05, 0x62, 0x61, 0x72, 0x49, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x61,
0x74, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x12, 0x2e,
0x0a, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32,
0x14, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75,
0x66, 0x2e, 0x41, 0x6e, 0x79, 0x52, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x22, 0x94,
0x01, 0x0a, 0x03, 0x42, 0x61, 0x7a, 0x12, 0x1d, 0x0a, 0x02, 0x65, 0x65, 0x18, 0x01, 0x20, 0x01,
0x28, 0x0e, 0x32, 0x0d, 0x2e, 0x45, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x45, 0x6e, 0x75,
0x6d, 0x52, 0x02, 0x65, 0x65, 0x12, 0x22, 0x0a, 0x02, 0x69, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28,
0x0e, 0x32, 0x12, 0x2e, 0x42, 0x61, 0x7a, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c,
0x5f, 0x45, 0x6e, 0x75, 0x6d, 0x52, 0x02, 0x69, 0x65, 0x12, 0x25, 0x0a, 0x06, 0x6f, 0x70, 0x74,
0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x0d, 0x2e, 0x42, 0x61, 0x6c, 0x6c,
0x6f, 0x74, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x06, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e,
0x22, 0x23, 0x0a, 0x0d, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x45, 0x6e, 0x75,
0x6d, 0x12, 0x08, 0x0a, 0x04, 0x46, 0x6f, 0x75, 0x72, 0x10, 0x00, 0x12, 0x08, 0x0a, 0x04, 0x46,
0x69, 0x76, 0x65, 0x10, 0x01, 0x2a, 0x39, 0x0a, 0x0c, 0x45, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61,
0x6c, 0x45, 0x6e, 0x75, 0x6d, 0x12, 0x07, 0x0a, 0x03, 0x4f, 0x6e, 0x65, 0x10, 0x00, 0x12, 0x07,
0x0a, 0x03, 0x54, 0x77, 0x6f, 0x10, 0x01, 0x12, 0x17, 0x0a, 0x13, 0x45, 0x58, 0x54, 0x45, 0x52,
0x4e, 0x41, 0x4c, 0x5f, 0x45, 0x4e, 0x55, 0x4d, 0x5f, 0x54, 0x48, 0x52, 0x45, 0x45, 0x10, 0x7f,
0x2a, 0x95, 0x01, 0x0a, 0x0c, 0x42, 0x61, 0x6c, 0x6c, 0x6f, 0x74, 0x4f, 0x70, 0x74, 0x69, 0x6f,
0x6e, 0x12, 0x1d, 0x0a, 0x19, 0x42, 0x41, 0x4c, 0x4c, 0x4f, 0x54, 0x5f, 0x4f, 0x50, 0x54, 0x49,
0x4f, 0x4e, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00,
0x12, 0x15, 0x0a, 0x11, 0x42, 0x41, 0x4c, 0x4c, 0x4f, 0x54, 0x5f, 0x4f, 0x50, 0x54, 0x49, 0x4f,
0x4e, 0x5f, 0x59, 0x45, 0x53, 0x10, 0x01, 0x12, 0x19, 0x0a, 0x15, 0x42, 0x41, 0x4c, 0x4c, 0x4f,
0x54, 0x5f, 0x4f, 0x50, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x41, 0x42, 0x53, 0x54, 0x41, 0x49, 0x4e,
0x10, 0x02, 0x12, 0x14, 0x0a, 0x10, 0x42, 0x41, 0x4c, 0x4c, 0x4f, 0x54, 0x5f, 0x4f, 0x50, 0x54,
0x49, 0x4f, 0x4e, 0x5f, 0x4e, 0x4f, 0x10, 0x03, 0x12, 0x1e, 0x0a, 0x1a, 0x42, 0x41, 0x4c, 0x4c,
0x4f, 0x54, 0x5f, 0x4f, 0x50, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x4e, 0x4f, 0x5f, 0x57, 0x49, 0x54,
0x48, 0x5f, 0x56, 0x45, 0x54, 0x4f, 0x10, 0x04, 0x42, 0x33, 0x42, 0x06, 0x31, 0x50, 0x72, 0x6f,
0x74, 0x6f, 0x50, 0x01, 0x5a, 0x27, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x73, 0x64, 0x6b, 0x2e,
0x69, 0x6f, 0x2f, 0x74, 0x78, 0x2f, 0x74, 0x65, 0x78, 0x74, 0x75, 0x61, 0x6c, 0x2f, 0x69, 0x6e,
0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x70, 0x62, 0x62, 0x06, 0x70,
0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
@@ -4320,6 +4502,7 @@ var file__1_proto_goTypes = []interface{}{
(*v1beta1.Coin)(nil), // 8: cosmos.base.v1beta1.Coin
(*timestamppb.Timestamp)(nil), // 9: google.protobuf.Timestamp
(*durationpb.Duration)(nil), // 10: google.protobuf.Duration
(*anypb.Any)(nil), // 11: google.protobuf.Any
}
var file__1_proto_depIdxs = []int32{
8, // 0: A.COIN:type_name -> cosmos.base.v1beta1.Coin
@@ -4327,20 +4510,22 @@ var file__1_proto_depIdxs = []int32{
9, // 2: A.TIMESTAMP:type_name -> google.protobuf.Timestamp
10, // 3: A.DURATION:type_name -> google.protobuf.Duration
0, // 4: A.ENUM:type_name -> ExternalEnum
7, // 5: A.MAP:type_name -> A.MAPEntry
9, // 6: Foo.mtime:type_name -> google.protobuf.Timestamp
4, // 7: Foo.left:type_name -> Foo
4, // 8: Foo.right:type_name -> Foo
5, // 9: Foo.bar:type_name -> Bar
0, // 10: Baz.ee:type_name -> ExternalEnum
2, // 11: Baz.ie:type_name -> Baz.Internal_Enum
1, // 12: Baz.option:type_name -> BallotOption
3, // 13: A.MAPEntry.value:type_name -> A
14, // [14:14] is the sub-list for method output_type
14, // [14:14] is the sub-list for method input_type
14, // [14:14] is the sub-list for extension type_name
14, // [14:14] is the sub-list for extension extendee
0, // [0:14] is the sub-list for field type_name
11, // 5: A.ANY:type_name -> google.protobuf.Any
7, // 6: A.MAP:type_name -> A.MAPEntry
9, // 7: Foo.mtime:type_name -> google.protobuf.Timestamp
4, // 8: Foo.left:type_name -> Foo
4, // 9: Foo.right:type_name -> Foo
5, // 10: Foo.bar:type_name -> Bar
11, // 11: Bar.payload:type_name -> google.protobuf.Any
0, // 12: Baz.ee:type_name -> ExternalEnum
2, // 13: Baz.ie:type_name -> Baz.Internal_Enum
1, // 14: Baz.option:type_name -> BallotOption
3, // 15: A.MAPEntry.value:type_name -> A
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
}
func init() { file__1_proto_init() }
+102
View File
@@ -0,0 +1,102 @@
package valuerenderer
import (
"context"
"fmt"
"strings"
"google.golang.org/protobuf/reflect/protoreflect"
"google.golang.org/protobuf/reflect/protoregistry"
"google.golang.org/protobuf/types/known/anypb"
)
// Any messages are rendered as a one-screen header of "Object: <type_url>"
// followed by an indented rendering of the contained message.
// anyValueRenderer is a ValueRenderer for google.protobuf.Any messages.
type anyValueRenderer struct {
tr *Textual
}
// NewAnyValueRenderer returns a ValueRenderer for google.protobuf.Any messages.
func NewAnyValueRenderer(t *Textual) ValueRenderer {
return anyValueRenderer{tr: t}
}
// Format implements the ValueRenderer interface.
func (ar anyValueRenderer) Format(ctx context.Context, v protoreflect.Value) ([]Screen, error) {
msg := v.Message().Interface()
anymsg, ok := msg.(*anypb.Any)
if !ok {
return nil, fmt.Errorf("expected Any, got %T", msg)
}
internalMsg, err := anymsg.UnmarshalNew()
if err != nil {
return nil, err
}
vr, err := ar.tr.GetMessageValueRenderer(internalMsg.ProtoReflect().Descriptor())
if err != nil {
return nil, err
}
subscreens, err := vr.Format(ctx, protoreflect.ValueOfMessage(internalMsg.ProtoReflect()))
if err != nil {
return nil, err
}
screens := make([]Screen, 1+len(subscreens))
screens[0].Text = "Object: " + anymsg.GetTypeUrl()
for i, subscreen := range subscreens {
subscreen.Indent++
screens[i+1] = subscreen
}
return screens, nil
}
// Parse implements the ValueRenderer interface.
func (ar anyValueRenderer) Parse(ctx context.Context, screens []Screen) (protoreflect.Value, error) {
if len(screens) == 0 {
return nilValue, fmt.Errorf("expect at least one screen")
}
if screens[0].Indent != 0 {
return nilValue, fmt.Errorf("bad indentation: want 0, got %d", screens[0].Indent)
}
prefix := "Object: "
if !strings.HasPrefix(screens[0].Text, prefix) {
return nilValue, fmt.Errorf("bad Any header: %s", screens[0].Text)
}
url := strings.TrimPrefix(screens[0].Text, prefix)
msgType, err := protoregistry.GlobalTypes.FindMessageByURL(url)
if err != nil {
return nilValue, err
}
vr, err := ar.tr.GetMessageValueRenderer(msgType.Descriptor())
if err != nil {
return nilValue, err
}
subscreens := make([]Screen, len(screens)-1)
for i := 1; i < len(screens); i++ {
if screens[i].Indent < 1 {
return nilValue, fmt.Errorf("bad indent for subscreen %d: %d", i, screens[i].Indent)
}
subscreens[i-1] = screens[i]
subscreens[i-1].Indent--
}
internalMsg, err := vr.Parse(ctx, subscreens)
if err != nil {
return nilValue, err
}
anyMsg, err := anypb.New(internalMsg.Message().Interface())
if err != nil {
return nilValue, err
}
return protoreflect.ValueOfMessage(anyMsg.ProtoReflect()), nil
}
+57
View File
@@ -0,0 +1,57 @@
package valuerenderer_test
import (
"context"
"encoding/json"
"fmt"
"os"
"testing"
"cosmossdk.io/tx/textual/valuerenderer"
"github.com/google/go-cmp/cmp"
"github.com/stretchr/testify/require"
"google.golang.org/protobuf/encoding/protojson"
"google.golang.org/protobuf/reflect/protoreflect"
"google.golang.org/protobuf/testing/protocmp"
"google.golang.org/protobuf/types/known/anypb"
)
type anyJsonTest struct {
Proto json.RawMessage
Screens []valuerenderer.Screen
}
func TestAny(t *testing.T) {
raw, err := os.ReadFile("../internal/testdata/any.json")
require.NoError(t, err)
var testcases []anyJsonTest
err = json.Unmarshal(raw, &testcases)
require.NoError(t, err)
tr := valuerenderer.NewTextual(EmptyCoinMetadataQuerier)
for i, tc := range testcases {
t.Run(fmt.Sprintf("%d", i), func(t *testing.T) {
anyMsg := anypb.Any{}
err = protojson.Unmarshal(tc.Proto, &anyMsg)
require.NoError(t, err)
// Format into screens and check vs expected
rend := valuerenderer.NewAnyValueRenderer((&tr))
screens, err := rend.Format(context.Background(), protoreflect.ValueOfMessage(anyMsg.ProtoReflect()))
require.NoError(t, err)
require.Equal(t, tc.Screens, screens)
// Parse back into a google.Protobuf.Any message.
val, err := rend.Parse(context.Background(), screens)
require.NoError(t, err)
parsedMsg := val.Message().Interface()
require.IsType(t, &anypb.Any{}, parsedMsg)
parsedAny := parsedMsg.(*anypb.Any)
diff := cmp.Diff(anyMsg, parsedAny, protocmp.Transform())
require.Empty(t, diff)
})
}
}
+1 -1
View File
@@ -27,7 +27,7 @@ func TestBytesJsonTestCases(t *testing.T) {
data, err := base64.StdEncoding.DecodeString(tc.base64)
require.NoError(t, err)
valrend, err := textual.GetValueRenderer(fieldDescriptorFromName("BYTES"))
valrend, err := textual.GetFieldValueRenderer(fieldDescriptorFromName("BYTES"))
require.NoError(t, err)
screens, err := valrend.Format(context.Background(), protoreflect.ValueOfBytes(data))
+3 -3
View File
@@ -34,7 +34,7 @@ func mockCoinMetadataQuerier(ctx context.Context, denom string) (*bankv1beta1.Me
func TestMetadataQuerier(t *testing.T) {
// Errors on nil metadata querier
textual := valuerenderer.NewTextual(nil)
vr, err := textual.GetValueRenderer(fieldDescriptorFromName("COIN"))
vr, err := textual.GetFieldValueRenderer(fieldDescriptorFromName("COIN"))
require.NoError(t, err)
_, err = vr.Format(context.Background(), protoreflect.ValueOf((&basev1beta1.Coin{}).ProtoReflect()))
require.Error(t, err)
@@ -44,7 +44,7 @@ func TestMetadataQuerier(t *testing.T) {
textual = valuerenderer.NewTextual(func(_ context.Context, _ string) (*bankv1beta1.Metadata, error) {
return nil, expErr
})
vr, err = textual.GetValueRenderer(fieldDescriptorFromName("COIN"))
vr, err = textual.GetFieldValueRenderer(fieldDescriptorFromName("COIN"))
require.NoError(t, err)
_, err = vr.Format(context.Background(), protoreflect.ValueOf((&basev1beta1.Coin{}).ProtoReflect()))
require.ErrorIs(t, err, expErr)
@@ -60,7 +60,7 @@ func TestCoinJsonTestcases(t *testing.T) {
require.NoError(t, err)
textual := valuerenderer.NewTextual(mockCoinMetadataQuerier)
vr, err := textual.GetValueRenderer(fieldDescriptorFromName("COIN"))
vr, err := textual.GetFieldValueRenderer(fieldDescriptorFromName("COIN"))
require.NoError(t, err)
for _, tc := range testcases {
+1 -1
View File
@@ -21,7 +21,7 @@ func TestCoinsJsonTestcases(t *testing.T) {
require.NoError(t, err)
textual := valuerenderer.NewTextual(mockCoinMetadataQuerier)
vr, err := textual.GetValueRenderer(fieldDescriptorFromName("COINS"))
vr, err := textual.GetFieldValueRenderer(fieldDescriptorFromName("COINS"))
require.NoError(t, err)
for _, tc := range testcases {
+1 -1
View File
@@ -23,7 +23,7 @@ func TestDecJsonTestcases(t *testing.T) {
for _, tc := range testcases {
tc := tc
t.Run(tc[0], func(t *testing.T) {
r, err := textual.GetValueRenderer(fieldDescriptorFromName("SDKDEC"))
r, err := textual.GetFieldValueRenderer(fieldDescriptorFromName("SDKDEC"))
require.NoError(t, err)
checkNumberTest(t, r, protoreflect.ValueOf(tc[0]), tc[1])
+1 -1
View File
@@ -37,7 +37,7 @@ func TestEnumJsonTestcases(t *testing.T) {
require.NoError(t, err)
fd := getFd(tc.Proto, m)
valrend, err := textual.GetValueRenderer(fd)
valrend, err := textual.GetFieldValueRenderer(fd)
require.NoError(t, err)
val := m.ProtoReflect().Get(fd)
+3 -3
View File
@@ -28,7 +28,7 @@ func TestIntJsonTestcases(t *testing.T) {
// Parse test case strings as protobuf uint64
i, err := strconv.ParseUint(tc[0], 10, 64)
if err == nil {
r, err := textual.GetValueRenderer(fieldDescriptorFromName("UINT64"))
r, err := textual.GetFieldValueRenderer(fieldDescriptorFromName("UINT64"))
require.NoError(t, err)
checkNumberTest(t, r, protoreflect.ValueOf(i), tc[1])
@@ -37,7 +37,7 @@ func TestIntJsonTestcases(t *testing.T) {
// Parse test case strings as protobuf uint32
i, err = strconv.ParseUint(tc[0], 10, 32)
if err == nil {
r, err := textual.GetValueRenderer(fieldDescriptorFromName("UINT32"))
r, err := textual.GetFieldValueRenderer(fieldDescriptorFromName("UINT32"))
require.NoError(t, err)
checkNumberTest(t, r, protoreflect.ValueOf(i), tc[1])
@@ -46,7 +46,7 @@ func TestIntJsonTestcases(t *testing.T) {
// Parse test case strings as sdk.Ints
_, ok := math.NewIntFromString(tc[0])
if ok {
r, err := textual.GetValueRenderer(fieldDescriptorFromName("SDKINT"))
r, err := textual.GetFieldValueRenderer(fieldDescriptorFromName("SDKINT"))
require.NoError(t, err)
checkNumberTest(t, r, protoreflect.ValueOf(tc[0]), tc[1])
+6 -6
View File
@@ -42,14 +42,14 @@ func (mr *messageValueRenderer) Format(ctx context.Context, v protoreflect.Value
screens[0].Text = mr.header()
for _, fd := range mr.fds {
vr, err := mr.tr.GetValueRenderer(fd)
if !v.Message().Has(fd) {
// Skip default values.
continue
}
vr, err := mr.tr.GetFieldValueRenderer(fd)
if err != nil {
return nil, err
}
// Skip default values.
if !v.Message().Has(fd) {
continue
}
subscreens, err := vr.Format(ctx, v.Message().Get(fd))
if err != nil {
@@ -116,7 +116,7 @@ func (mr *messageValueRenderer) Parse(ctx context.Context, screens []Screen) (pr
break
}
vr, err := mr.tr.GetValueRenderer(fd)
vr, err := mr.tr.GetFieldValueRenderer(fd)
if err != nil {
return nilValue, err
}
+17 -3
View File
@@ -6,6 +6,7 @@ import (
"google.golang.org/protobuf/proto"
"google.golang.org/protobuf/reflect/protoreflect"
"google.golang.org/protobuf/types/known/anypb"
"google.golang.org/protobuf/types/known/durationpb"
"google.golang.org/protobuf/types/known/timestamppb"
@@ -45,8 +46,8 @@ func NewTextual(q CoinMetadataQueryFn) Textual {
return t
}
// GetValueRenderer returns the value renderer for the given FieldDescriptor.
func (r Textual) GetValueRenderer(fd protoreflect.FieldDescriptor) (ValueRenderer, error) {
// GetFieldValueRenderer returns the value renderer for the given FieldDescriptor.
func (r *Textual) GetFieldValueRenderer(fd protoreflect.FieldDescriptor) (ValueRenderer, error) {
switch {
// Scalars, such as sdk.Int and sdk.Dec encoded as strings.
case fd.Kind() == protoreflect.StringKind && proto.GetExtension(fd.Options(), cosmos_proto.E_Scalar) != "":
@@ -96,13 +97,25 @@ func (r Textual) GetValueRenderer(fd protoreflect.FieldDescriptor) (ValueRendere
// This will be implemented in https://github.com/cosmos/cosmos-sdk/issues/12714
return nil, fmt.Errorf("repeated field renderer not yet implemented")
}
return NewMessageValueRenderer(&r, md), nil
return NewMessageValueRenderer(r, md), nil
default:
return nil, fmt.Errorf("value renderers cannot format value of type %s", fd.Kind())
}
}
// GetMessageValueRenderer is a specialization of GetValueRenderer for messages.
// It is useful when the message type is discovered outside the context of a field,
// e.g. when handling a google.protobuf.Any.
func (r *Textual) GetMessageValueRenderer(md protoreflect.MessageDescriptor) (ValueRenderer, error) {
fullName := md.FullName()
vr, found := r.messages[fullName]
if found {
return vr, nil
}
return NewMessageValueRenderer(r, md), nil
}
func (r *Textual) init() {
if r.scalars == nil {
r.scalars = map[string]ValueRenderer{}
@@ -114,6 +127,7 @@ func (r *Textual) init() {
r.messages[(&basev1beta1.Coin{}).ProtoReflect().Descriptor().FullName()] = NewCoinsValueRenderer(r.coinMetadataQuerier)
r.messages[(&durationpb.Duration{}).ProtoReflect().Descriptor().FullName()] = NewDurationValueRenderer()
r.messages[(&timestamppb.Timestamp{}).ProtoReflect().Descriptor().FullName()] = NewTimestampValueRenderer()
r.messages[(&anypb.Any{}).ProtoReflect().Descriptor().FullName()] = NewAnyValueRenderer(r)
}
}
@@ -27,6 +27,7 @@ func TestDispatcher(t *testing.T) {
{"COIN", false, valuerenderer.NewCoinsValueRenderer(nil)},
{"COINS", false, valuerenderer.NewCoinsValueRenderer(nil)},
{"ENUM", false, valuerenderer.NewEnumValueRenderer(fieldDescriptorFromName("ENUM"))},
{"ANY", false, valuerenderer.NewAnyValueRenderer(nil)},
{"FLOAT", true, nil},
}
@@ -34,7 +35,7 @@ func TestDispatcher(t *testing.T) {
tc := tc
t.Run(tc.name, func(t *testing.T) {
textual := valuerenderer.NewTextual(nil)
rend, err := textual.GetValueRenderer(fieldDescriptorFromName(tc.name))
rend, err := textual.GetFieldValueRenderer(fieldDescriptorFromName(tc.name))
if tc.expErr {
require.Error(t, err)