diff --git a/_examples/02_simple/federation/federation.pb.go b/_examples/02_simple/federation/federation.pb.go index 25ec797a..ac2f0707 100644 --- a/_examples/02_simple/federation/federation.pb.go +++ b/_examples/02_simple/federation/federation.pb.go @@ -206,6 +206,7 @@ type GetPostResponse struct { NullTimestamp3 *timestamppb.Timestamp `protobuf:"bytes,30,opt,name=null_timestamp3,json=nullTimestamp3,proto3" json:"null_timestamp3,omitempty"` JpLoc string `protobuf:"bytes,31,opt,name=jp_loc,json=jpLoc,proto3" json:"jp_loc,omitempty"` StringsJoin string `protobuf:"bytes,32,opt,name=strings_join,json=stringsJoin,proto3" json:"strings_join,omitempty"` + UrlUserName string `protobuf:"bytes,33,opt,name=url_user_name,json=urlUserName,proto3" json:"url_user_name,omitempty"` } func (x *GetPostResponse) Reset() { @@ -464,6 +465,13 @@ func (x *GetPostResponse) GetStringsJoin() string { return "" } +func (x *GetPostResponse) GetUrlUserName() string { + if x != nil { + return x.UrlUserName + } + return "" +} + type A struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -1168,7 +1176,7 @@ var file_federation_federation_proto_rawDesc = []byte{ 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x66, 0x65, 0x64, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x20, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x50, 0x6f, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x22, 0xd7, 0x1d, 0x0a, 0x0f, 0x47, 0x65, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x22, 0xec, 0x1e, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x50, 0x6f, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2f, 0x0a, 0x04, 0x70, 0x6f, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x66, 0x65, 0x64, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x50, 0x6f, 0x73, 0x74, 0x42, 0x09, 0x9a, @@ -1346,207 +1354,216 @@ var file_federation_federation_proto_rawDesc = []byte{ 0x12, 0x34, 0x0a, 0x0c, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x73, 0x5f, 0x6a, 0x6f, 0x69, 0x6e, 0x18, 0x20, 0x20, 0x01, 0x28, 0x09, 0x42, 0x11, 0x9a, 0x4a, 0x0e, 0x12, 0x0c, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x73, 0x5f, 0x6a, 0x6f, 0x69, 0x6e, 0x52, 0x0b, 0x73, 0x74, 0x72, 0x69, 0x6e, - 0x67, 0x73, 0x4a, 0x6f, 0x69, 0x6e, 0x1a, 0x3b, 0x0a, 0x0d, 0x4d, 0x61, 0x70, 0x56, 0x61, 0x6c, - 0x75, 0x65, 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, 0x3a, 0xfd, 0x06, 0x9a, 0x4a, 0xf9, 0x06, 0x0a, 0x1a, 0x0a, 0x04, 0x70, 0x6f, - 0x73, 0x74, 0x6a, 0x12, 0x0a, 0x04, 0x50, 0x6f, 0x73, 0x74, 0x12, 0x0a, 0x0a, 0x02, 0x69, 0x64, - 0x12, 0x04, 0x24, 0x2e, 0x69, 0x64, 0x0a, 0x42, 0x0a, 0x0c, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, - 0x73, 0x5f, 0x6a, 0x6f, 0x69, 0x6e, 0x5a, 0x32, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x66, 0x65, 0x64, - 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x73, 0x2e, - 0x6a, 0x6f, 0x69, 0x6e, 0x28, 0x5b, 0x27, 0x61, 0x27, 0x2c, 0x20, 0x27, 0x62, 0x27, 0x2c, 0x20, - 0x27, 0x63, 0x27, 0x5d, 0x2c, 0x20, 0x27, 0x2c, 0x27, 0x29, 0x0a, 0x59, 0x0a, 0x04, 0x64, 0x61, - 0x74, 0x65, 0x5a, 0x51, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x66, 0x65, 0x64, 0x65, 0x72, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x2e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x64, 0x61, 0x74, 0x65, 0x28, 0x32, 0x30, - 0x32, 0x33, 0x2c, 0x20, 0x31, 0x32, 0x2c, 0x20, 0x32, 0x35, 0x2c, 0x20, 0x31, 0x32, 0x2c, 0x20, - 0x31, 0x30, 0x2c, 0x20, 0x35, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x66, - 0x65, 0x64, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x55, - 0x54, 0x43, 0x28, 0x29, 0x29, 0x0a, 0x3a, 0x0a, 0x0b, 0x72, 0x61, 0x6e, 0x64, 0x5f, 0x73, 0x6f, - 0x75, 0x72, 0x63, 0x65, 0x5a, 0x2b, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x66, 0x65, 0x64, 0x65, 0x72, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x72, 0x61, 0x6e, 0x64, 0x2e, 0x6e, 0x65, 0x77, 0x53, 0x6f, - 0x75, 0x72, 0x63, 0x65, 0x28, 0x64, 0x61, 0x74, 0x65, 0x2e, 0x75, 0x6e, 0x69, 0x78, 0x28, 0x29, - 0x29, 0x0a, 0x33, 0x0a, 0x0a, 0x66, 0x69, 0x78, 0x65, 0x64, 0x5f, 0x72, 0x61, 0x6e, 0x64, 0x5a, - 0x25, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x66, 0x65, 0x64, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x2e, 0x72, 0x61, 0x6e, 0x64, 0x2e, 0x6e, 0x65, 0x77, 0x28, 0x72, 0x61, 0x6e, 0x64, 0x5f, 0x73, - 0x6f, 0x75, 0x72, 0x63, 0x65, 0x29, 0x0a, 0x3b, 0x0a, 0x04, 0x75, 0x75, 0x69, 0x64, 0x5a, 0x33, - 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x66, 0x65, 0x64, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x2e, 0x75, 0x75, 0x69, 0x64, 0x2e, 0x6e, 0x65, 0x77, 0x52, 0x61, 0x6e, 0x64, 0x6f, 0x6d, 0x46, - 0x72, 0x6f, 0x6d, 0x52, 0x61, 0x6e, 0x64, 0x28, 0x66, 0x69, 0x78, 0x65, 0x64, 0x5f, 0x72, 0x61, - 0x6e, 0x64, 0x29, 0x0a, 0x36, 0x0a, 0x03, 0x6c, 0x6f, 0x63, 0x5a, 0x2f, 0x67, 0x72, 0x70, 0x63, - 0x2e, 0x66, 0x65, 0x64, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x74, 0x69, 0x6d, 0x65, - 0x2e, 0x6c, 0x6f, 0x61, 0x64, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x27, 0x41, - 0x73, 0x69, 0x61, 0x2f, 0x54, 0x6f, 0x6b, 0x79, 0x6f, 0x27, 0x29, 0x0a, 0x45, 0x0a, 0x07, 0x6a, - 0x70, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5a, 0x3a, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x66, 0x65, 0x64, - 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x64, 0x61, 0x74, - 0x65, 0x28, 0x32, 0x30, 0x32, 0x33, 0x2c, 0x20, 0x31, 0x32, 0x2c, 0x20, 0x32, 0x35, 0x2c, 0x20, - 0x31, 0x32, 0x2c, 0x20, 0x31, 0x30, 0x2c, 0x20, 0x35, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x6c, 0x6f, - 0x63, 0x29, 0x0a, 0x38, 0x0a, 0x06, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x31, 0x5a, 0x2e, 0x67, 0x72, - 0x70, 0x63, 0x2e, 0x66, 0x65, 0x64, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x6d, 0x65, - 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x69, 0x6e, 0x63, 0x6f, 0x6d, 0x69, 0x6e, 0x67, 0x28, - 0x29, 0x5b, 0x27, 0x6b, 0x65, 0x79, 0x31, 0x27, 0x5d, 0x5b, 0x30, 0x5d, 0x0a, 0x08, 0x0a, 0x01, - 0x61, 0x6a, 0x03, 0x0a, 0x01, 0x41, 0x0a, 0x2b, 0x0a, 0x0d, 0x73, 0x6f, 0x72, 0x74, 0x65, 0x64, - 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x5a, 0x1a, 0x5b, 0x34, 0x2c, 0x20, 0x31, 0x2c, 0x20, - 0x33, 0x2c, 0x20, 0x32, 0x5d, 0x2e, 0x73, 0x6f, 0x72, 0x74, 0x41, 0x73, 0x63, 0x28, 0x76, 0x2c, - 0x20, 0x76, 0x29, 0x0a, 0x95, 0x01, 0x0a, 0x0c, 0x73, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x5f, 0x69, - 0x74, 0x65, 0x6d, 0x73, 0x5a, 0x84, 0x01, 0x5b, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x49, 0x74, 0x65, - 0x6d, 0x7b, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x75, 0x73, 0x65, 0x72, 0x2e, - 0x49, 0x74, 0x65, 0x6d, 0x2e, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x7b, 0x61, 0x64, - 0x64, 0x72, 0x31, 0x3a, 0x27, 0x61, 0x27, 0x7d, 0x7d, 0x2c, 0x20, 0x75, 0x73, 0x65, 0x72, 0x2e, - 0x49, 0x74, 0x65, 0x6d, 0x7b, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x75, 0x73, - 0x65, 0x72, 0x2e, 0x49, 0x74, 0x65, 0x6d, 0x2e, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x7b, 0x61, 0x64, 0x64, 0x72, 0x31, 0x3a, 0x27, 0x62, 0x27, 0x7d, 0x7d, 0x5d, 0x2e, 0x73, 0x6f, - 0x72, 0x74, 0x44, 0x65, 0x73, 0x63, 0x28, 0x76, 0x2c, 0x20, 0x76, 0x2e, 0x6c, 0x6f, 0x63, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x61, 0x64, 0x64, 0x72, 0x31, 0x29, 0x0a, 0x25, 0x0a, 0x09, 0x6d, - 0x61, 0x70, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x5a, 0x18, 0x7b, 0x31, 0x3a, 0x20, 0x27, 0x61, - 0x27, 0x2c, 0x20, 0x32, 0x3a, 0x20, 0x27, 0x62, 0x27, 0x2c, 0x20, 0x33, 0x3a, 0x20, 0x27, 0x63, - 0x27, 0x7d, 0x0a, 0x12, 0x0a, 0x0a, 0x6e, 0x75, 0x6c, 0x6c, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, - 0x5a, 0x04, 0x6e, 0x75, 0x6c, 0x6c, 0x0a, 0x4b, 0x5a, 0x49, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x66, - 0x65, 0x64, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x6c, 0x6f, 0x67, 0x2e, 0x69, 0x6e, - 0x66, 0x6f, 0x28, 0x27, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x20, 0x66, 0x65, 0x64, 0x65, 0x72, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6c, 0x6f, 0x67, 0x27, 0x2c, 0x20, 0x7b, 0x27, 0x70, 0x6f, - 0x73, 0x74, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x27, 0x3a, 0x20, 0x70, 0x6f, 0x73, - 0x74, 0x7d, 0x29, 0x22, 0xdf, 0x03, 0x0a, 0x01, 0x41, 0x12, 0x25, 0x0a, 0x01, 0x62, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x66, 0x65, 0x64, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x2e, 0x41, 0x2e, 0x42, 0x42, 0x06, 0x9a, 0x4a, 0x03, 0x12, 0x01, 0x62, 0x52, 0x01, 0x62, - 0x1a, 0xa1, 0x03, 0x0a, 0x01, 0x42, 0x12, 0x2d, 0x0a, 0x03, 0x66, 0x6f, 0x6f, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x66, 0x65, 0x64, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x2e, 0x41, 0x2e, 0x42, 0x2e, 0x43, 0x42, 0x08, 0x9a, 0x4a, 0x05, 0x12, 0x03, 0x66, 0x6f, 0x6f, - 0x52, 0x03, 0x66, 0x6f, 0x6f, 0x12, 0x2d, 0x0a, 0x03, 0x62, 0x61, 0x72, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x66, 0x65, 0x64, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, - 0x41, 0x2e, 0x42, 0x2e, 0x43, 0x42, 0x08, 0x9a, 0x4a, 0x05, 0x12, 0x03, 0x62, 0x61, 0x72, 0x52, - 0x03, 0x62, 0x61, 0x72, 0x1a, 0x24, 0x0a, 0x01, 0x43, 0x12, 0x1f, 0x0a, 0x04, 0x74, 0x79, 0x70, - 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x0b, 0x9a, 0x4a, 0x08, 0x12, 0x06, 0x24, 0x2e, - 0x74, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x97, 0x02, 0x9a, 0x4a, 0x93, - 0x02, 0x0a, 0x1d, 0x0a, 0x03, 0x66, 0x6f, 0x6f, 0x6a, 0x16, 0x0a, 0x05, 0x41, 0x2e, 0x42, 0x2e, - 0x43, 0x12, 0x0d, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x05, 0x27, 0x66, 0x6f, 0x6f, 0x27, - 0x0a, 0x1d, 0x0a, 0x03, 0x62, 0x61, 0x72, 0x6a, 0x16, 0x0a, 0x05, 0x41, 0x2e, 0x42, 0x2e, 0x43, - 0x12, 0x0d, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x05, 0x27, 0x62, 0x61, 0x72, 0x27, 0x0a, - 0x89, 0x01, 0x12, 0x11, 0x66, 0x6f, 0x6f, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x20, 0x3d, 0x3d, 0x20, - 0x27, 0x66, 0x6f, 0x6f, 0x27, 0x5a, 0x74, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x66, 0x65, 0x64, 0x65, - 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x6c, 0x6f, 0x67, 0x2e, 0x69, 0x6e, 0x66, 0x6f, 0x28, - 0x27, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x20, 0x66, 0x65, 0x64, 0x65, 0x72, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x20, 0x6c, 0x6f, 0x67, 0x27, 0x2c, 0x20, 0x7b, 0x27, 0x6d, 0x65, 0x73, 0x73, 0x61, - 0x67, 0x65, 0x73, 0x27, 0x3a, 0x20, 0x5b, 0x66, 0x6f, 0x6f, 0x2c, 0x20, 0x62, 0x61, 0x72, 0x5d, - 0x2c, 0x20, 0x27, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x6d, 0x61, 0x70, 0x27, 0x3a, - 0x20, 0x7b, 0x27, 0x66, 0x6f, 0x6f, 0x27, 0x3a, 0x20, 0x66, 0x6f, 0x6f, 0x2c, 0x20, 0x27, 0x62, - 0x61, 0x72, 0x27, 0x3a, 0x20, 0x62, 0x61, 0x72, 0x7d, 0x7d, 0x29, 0x0a, 0x47, 0x5a, 0x45, 0x67, + 0x67, 0x73, 0x4a, 0x6f, 0x69, 0x6e, 0x12, 0x42, 0x0a, 0x0d, 0x75, 0x72, 0x6c, 0x5f, 0x75, 0x73, + 0x65, 0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x21, 0x20, 0x01, 0x28, 0x09, 0x42, 0x1e, 0x9a, + 0x4a, 0x1b, 0x12, 0x19, 0x75, 0x72, 0x6c, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x69, 0x6e, 0x66, 0x6f, + 0x28, 0x29, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x28, 0x29, 0x52, 0x0b, 0x75, + 0x72, 0x6c, 0x55, 0x73, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x1a, 0x3b, 0x0a, 0x0d, 0x4d, 0x61, + 0x70, 0x56, 0x61, 0x6c, 0x75, 0x65, 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, 0x3a, 0xce, 0x07, 0x9a, 0x4a, 0xca, 0x07, 0x0a, 0x1a, + 0x0a, 0x04, 0x70, 0x6f, 0x73, 0x74, 0x6a, 0x12, 0x0a, 0x04, 0x50, 0x6f, 0x73, 0x74, 0x12, 0x0a, + 0x0a, 0x02, 0x69, 0x64, 0x12, 0x04, 0x24, 0x2e, 0x69, 0x64, 0x0a, 0x42, 0x0a, 0x0c, 0x73, 0x74, + 0x72, 0x69, 0x6e, 0x67, 0x73, 0x5f, 0x6a, 0x6f, 0x69, 0x6e, 0x5a, 0x32, 0x67, 0x72, 0x70, 0x63, + 0x2e, 0x66, 0x65, 0x64, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x73, 0x74, 0x72, 0x69, + 0x6e, 0x67, 0x73, 0x2e, 0x6a, 0x6f, 0x69, 0x6e, 0x28, 0x5b, 0x27, 0x61, 0x27, 0x2c, 0x20, 0x27, + 0x62, 0x27, 0x2c, 0x20, 0x27, 0x63, 0x27, 0x5d, 0x2c, 0x20, 0x27, 0x2c, 0x27, 0x29, 0x0a, 0x4f, + 0x0a, 0x03, 0x75, 0x72, 0x6c, 0x5a, 0x48, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x66, 0x65, 0x64, 0x65, + 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x75, 0x72, 0x6c, 0x2e, 0x70, 0x61, 0x72, 0x73, 0x65, + 0x28, 0x27, 0x68, 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x75, + 0x73, 0x65, 0x72, 0x3a, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x40, 0x65, 0x78, 0x61, + 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x61, 0x74, 0x68, 0x27, 0x29, 0x0a, + 0x59, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x65, 0x5a, 0x51, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x66, 0x65, + 0x64, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x64, 0x61, + 0x74, 0x65, 0x28, 0x32, 0x30, 0x32, 0x33, 0x2c, 0x20, 0x31, 0x32, 0x2c, 0x20, 0x32, 0x35, 0x2c, + 0x20, 0x31, 0x32, 0x2c, 0x20, 0x31, 0x30, 0x2c, 0x20, 0x35, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x67, + 0x72, 0x70, 0x63, 0x2e, 0x66, 0x65, 0x64, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x74, + 0x69, 0x6d, 0x65, 0x2e, 0x55, 0x54, 0x43, 0x28, 0x29, 0x29, 0x0a, 0x3a, 0x0a, 0x0b, 0x72, 0x61, + 0x6e, 0x64, 0x5f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5a, 0x2b, 0x67, 0x72, 0x70, 0x63, 0x2e, + 0x66, 0x65, 0x64, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x72, 0x61, 0x6e, 0x64, 0x2e, + 0x6e, 0x65, 0x77, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x28, 0x64, 0x61, 0x74, 0x65, 0x2e, 0x75, + 0x6e, 0x69, 0x78, 0x28, 0x29, 0x29, 0x0a, 0x33, 0x0a, 0x0a, 0x66, 0x69, 0x78, 0x65, 0x64, 0x5f, + 0x72, 0x61, 0x6e, 0x64, 0x5a, 0x25, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x66, 0x65, 0x64, 0x65, 0x72, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x72, 0x61, 0x6e, 0x64, 0x2e, 0x6e, 0x65, 0x77, 0x28, 0x72, + 0x61, 0x6e, 0x64, 0x5f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x29, 0x0a, 0x3b, 0x0a, 0x04, 0x75, + 0x75, 0x69, 0x64, 0x5a, 0x33, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x66, 0x65, 0x64, 0x65, 0x72, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x75, 0x75, 0x69, 0x64, 0x2e, 0x6e, 0x65, 0x77, 0x52, 0x61, + 0x6e, 0x64, 0x6f, 0x6d, 0x46, 0x72, 0x6f, 0x6d, 0x52, 0x61, 0x6e, 0x64, 0x28, 0x66, 0x69, 0x78, + 0x65, 0x64, 0x5f, 0x72, 0x61, 0x6e, 0x64, 0x29, 0x0a, 0x36, 0x0a, 0x03, 0x6c, 0x6f, 0x63, 0x5a, + 0x2f, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x66, 0x65, 0x64, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x2e, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x6c, 0x6f, 0x61, 0x64, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x28, 0x27, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x54, 0x6f, 0x6b, 0x79, 0x6f, 0x27, 0x29, + 0x0a, 0x45, 0x0a, 0x07, 0x6a, 0x70, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5a, 0x3a, 0x67, 0x72, 0x70, + 0x63, 0x2e, 0x66, 0x65, 0x64, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x74, 0x69, 0x6d, + 0x65, 0x2e, 0x64, 0x61, 0x74, 0x65, 0x28, 0x32, 0x30, 0x32, 0x33, 0x2c, 0x20, 0x31, 0x32, 0x2c, + 0x20, 0x32, 0x35, 0x2c, 0x20, 0x31, 0x32, 0x2c, 0x20, 0x31, 0x30, 0x2c, 0x20, 0x35, 0x2c, 0x20, + 0x30, 0x2c, 0x20, 0x6c, 0x6f, 0x63, 0x29, 0x0a, 0x38, 0x0a, 0x06, 0x76, 0x61, 0x6c, 0x75, 0x65, + 0x31, 0x5a, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x66, 0x65, 0x64, 0x65, 0x72, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x2e, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x69, 0x6e, 0x63, 0x6f, + 0x6d, 0x69, 0x6e, 0x67, 0x28, 0x29, 0x5b, 0x27, 0x6b, 0x65, 0x79, 0x31, 0x27, 0x5d, 0x5b, 0x30, + 0x5d, 0x0a, 0x08, 0x0a, 0x01, 0x61, 0x6a, 0x03, 0x0a, 0x01, 0x41, 0x0a, 0x2b, 0x0a, 0x0d, 0x73, + 0x6f, 0x72, 0x74, 0x65, 0x64, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x5a, 0x1a, 0x5b, 0x34, + 0x2c, 0x20, 0x31, 0x2c, 0x20, 0x33, 0x2c, 0x20, 0x32, 0x5d, 0x2e, 0x73, 0x6f, 0x72, 0x74, 0x41, + 0x73, 0x63, 0x28, 0x76, 0x2c, 0x20, 0x76, 0x29, 0x0a, 0x95, 0x01, 0x0a, 0x0c, 0x73, 0x6f, 0x72, + 0x74, 0x65, 0x64, 0x5f, 0x69, 0x74, 0x65, 0x6d, 0x73, 0x5a, 0x84, 0x01, 0x5b, 0x75, 0x73, 0x65, + 0x72, 0x2e, 0x49, 0x74, 0x65, 0x6d, 0x7b, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3a, + 0x75, 0x73, 0x65, 0x72, 0x2e, 0x49, 0x74, 0x65, 0x6d, 0x2e, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x7b, 0x61, 0x64, 0x64, 0x72, 0x31, 0x3a, 0x27, 0x61, 0x27, 0x7d, 0x7d, 0x2c, 0x20, + 0x75, 0x73, 0x65, 0x72, 0x2e, 0x49, 0x74, 0x65, 0x6d, 0x7b, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x3a, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x49, 0x74, 0x65, 0x6d, 0x2e, 0x4c, 0x6f, 0x63, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x7b, 0x61, 0x64, 0x64, 0x72, 0x31, 0x3a, 0x27, 0x62, 0x27, 0x7d, + 0x7d, 0x5d, 0x2e, 0x73, 0x6f, 0x72, 0x74, 0x44, 0x65, 0x73, 0x63, 0x28, 0x76, 0x2c, 0x20, 0x76, + 0x2e, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x61, 0x64, 0x64, 0x72, 0x31, 0x29, + 0x0a, 0x25, 0x0a, 0x09, 0x6d, 0x61, 0x70, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x5a, 0x18, 0x7b, + 0x31, 0x3a, 0x20, 0x27, 0x61, 0x27, 0x2c, 0x20, 0x32, 0x3a, 0x20, 0x27, 0x62, 0x27, 0x2c, 0x20, + 0x33, 0x3a, 0x20, 0x27, 0x63, 0x27, 0x7d, 0x0a, 0x12, 0x0a, 0x0a, 0x6e, 0x75, 0x6c, 0x6c, 0x5f, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x5a, 0x04, 0x6e, 0x75, 0x6c, 0x6c, 0x0a, 0x4b, 0x5a, 0x49, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x66, 0x65, 0x64, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x6c, - 0x6f, 0x67, 0x2e, 0x61, 0x64, 0x64, 0x28, 0x7b, 0x27, 0x66, 0x6f, 0x6f, 0x5f, 0x74, 0x79, 0x70, - 0x65, 0x27, 0x3a, 0x20, 0x66, 0x6f, 0x6f, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x2c, 0x20, 0x27, 0x62, - 0x61, 0x72, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x27, 0x3a, 0x20, 0x62, 0x61, 0x72, 0x2e, 0x74, 0x79, - 0x70, 0x65, 0x7d, 0x29, 0x3a, 0x0f, 0x9a, 0x4a, 0x0c, 0x0a, 0x0a, 0x0a, 0x01, 0x62, 0x6a, 0x05, - 0x0a, 0x03, 0x41, 0x2e, 0x42, 0x22, 0xe6, 0x01, 0x0a, 0x04, 0x50, 0x6f, 0x73, 0x74, 0x12, 0x0e, - 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x14, - 0x0a, 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x74, - 0x69, 0x74, 0x6c, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x12, 0x2f, - 0x0a, 0x04, 0x75, 0x73, 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x66, - 0x65, 0x64, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x42, 0x09, - 0x9a, 0x4a, 0x06, 0x12, 0x04, 0x75, 0x73, 0x65, 0x72, 0x52, 0x04, 0x75, 0x73, 0x65, 0x72, 0x3a, - 0x6d, 0x9a, 0x4a, 0x6a, 0x0a, 0x3c, 0x0a, 0x03, 0x72, 0x65, 0x73, 0x72, 0x35, 0x0a, 0x18, 0x70, - 0x6f, 0x73, 0x74, 0x2e, 0x50, 0x6f, 0x73, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2f, - 0x47, 0x65, 0x74, 0x50, 0x6f, 0x73, 0x74, 0x12, 0x0a, 0x0a, 0x02, 0x69, 0x64, 0x12, 0x04, 0x24, - 0x2e, 0x69, 0x64, 0x1a, 0x03, 0x31, 0x30, 0x73, 0x22, 0x08, 0x0a, 0x06, 0x0a, 0x02, 0x32, 0x73, - 0x10, 0x03, 0x0a, 0x12, 0x0a, 0x04, 0x70, 0x6f, 0x73, 0x74, 0x18, 0x01, 0x5a, 0x08, 0x72, 0x65, - 0x73, 0x2e, 0x70, 0x6f, 0x73, 0x74, 0x0a, 0x16, 0x0a, 0x04, 0x75, 0x73, 0x65, 0x72, 0x6a, 0x0e, - 0x0a, 0x04, 0x55, 0x73, 0x65, 0x72, 0x12, 0x06, 0x1a, 0x04, 0x70, 0x6f, 0x73, 0x74, 0x22, 0xc8, - 0x04, 0x0a, 0x04, 0x55, 0x73, 0x65, 0x72, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x26, 0x0a, 0x05, 0x69, - 0x74, 0x65, 0x6d, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x66, 0x65, 0x64, - 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x49, 0x74, 0x65, 0x6d, 0x52, 0x05, 0x69, 0x74, - 0x65, 0x6d, 0x73, 0x12, 0x37, 0x0a, 0x07, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x04, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x66, 0x65, 0x64, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x2e, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x45, 0x6e, - 0x74, 0x72, 0x79, 0x52, 0x07, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x12, 0x2f, 0x0a, 0x06, - 0x61, 0x74, 0x74, 0x72, 0x5f, 0x61, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x66, - 0x65, 0x64, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x2e, 0x41, - 0x74, 0x74, 0x72, 0x41, 0x48, 0x00, 0x52, 0x05, 0x61, 0x74, 0x74, 0x72, 0x41, 0x12, 0x26, 0x0a, - 0x01, 0x62, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x66, 0x65, 0x64, 0x65, 0x72, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x2e, 0x41, 0x74, 0x74, 0x72, 0x42, - 0x48, 0x00, 0x52, 0x01, 0x62, 0x1a, 0x50, 0x0a, 0x0c, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, - 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x2a, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, - 0x18, 0x02, 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, 0x05, 0x76, 0x61, - 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x2f, 0x0a, 0x05, 0x41, 0x74, 0x74, 0x72, 0x41, - 0x12, 0x10, 0x0a, 0x03, 0x66, 0x6f, 0x6f, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x66, - 0x6f, 0x6f, 0x3a, 0x14, 0x9a, 0x4a, 0x11, 0x1a, 0x0f, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x55, 0x73, - 0x65, 0x72, 0x2e, 0x41, 0x74, 0x74, 0x72, 0x41, 0x1a, 0x2f, 0x0a, 0x05, 0x41, 0x74, 0x74, 0x72, - 0x42, 0x12, 0x10, 0x0a, 0x03, 0x62, 0x61, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x03, - 0x62, 0x61, 0x72, 0x3a, 0x14, 0x9a, 0x4a, 0x11, 0x1a, 0x0f, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x55, - 0x73, 0x65, 0x72, 0x2e, 0x41, 0x74, 0x74, 0x72, 0x42, 0x3a, 0xa5, 0x01, 0x9a, 0x4a, 0xa1, 0x01, - 0x0a, 0x8a, 0x01, 0x0a, 0x03, 0x72, 0x65, 0x73, 0x72, 0x82, 0x01, 0x0a, 0x18, 0x75, 0x73, 0x65, - 0x72, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2f, 0x47, 0x65, - 0x74, 0x55, 0x73, 0x65, 0x72, 0x12, 0x0f, 0x0a, 0x02, 0x69, 0x64, 0x12, 0x09, 0x24, 0x2e, 0x75, - 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x12, 0x2f, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x27, - 0x75, 0x73, 0x65, 0x72, 0x2e, 0x49, 0x74, 0x65, 0x6d, 0x2e, 0x49, 0x74, 0x65, 0x6d, 0x54, 0x79, - 0x70, 0x65, 0x2e, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x28, 0x27, 0x49, 0x54, 0x45, 0x4d, 0x5f, 0x54, - 0x59, 0x50, 0x45, 0x5f, 0x31, 0x27, 0x29, 0x1a, 0x03, 0x32, 0x30, 0x73, 0x22, 0x1f, 0x12, 0x1d, - 0x0a, 0x02, 0x31, 0x73, 0x11, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0xe6, 0x3f, 0x19, 0x33, 0x33, - 0x33, 0x33, 0x33, 0x33, 0xfb, 0x3f, 0x22, 0x03, 0x33, 0x30, 0x73, 0x28, 0x03, 0x0a, 0x12, 0x0a, - 0x04, 0x75, 0x73, 0x65, 0x72, 0x18, 0x01, 0x5a, 0x08, 0x72, 0x65, 0x73, 0x2e, 0x75, 0x73, 0x65, - 0x72, 0x42, 0x06, 0x0a, 0x04, 0x61, 0x74, 0x74, 0x72, 0x22, 0x8d, 0x05, 0x0a, 0x04, 0x49, 0x74, - 0x65, 0x6d, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x2d, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x0e, 0x32, 0x19, 0x2e, 0x66, 0x65, 0x64, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x2e, 0x49, 0x74, 0x65, 0x6d, 0x2e, 0x49, 0x74, 0x65, 0x6d, 0x54, 0x79, 0x70, 0x65, 0x52, - 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x35, 0x0a, 0x08, 0x6c, - 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, - 0x66, 0x65, 0x64, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x49, 0x74, 0x65, 0x6d, 0x2e, - 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x08, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x1a, 0xf1, 0x02, 0x0a, 0x08, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, - 0x14, 0x0a, 0x05, 0x61, 0x64, 0x64, 0x72, 0x31, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, - 0x61, 0x64, 0x64, 0x72, 0x31, 0x12, 0x14, 0x0a, 0x05, 0x61, 0x64, 0x64, 0x72, 0x32, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x61, 0x64, 0x64, 0x72, 0x32, 0x12, 0x38, 0x0a, 0x06, 0x61, - 0x64, 0x64, 0x72, 0x5f, 0x61, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x66, 0x65, - 0x64, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x49, 0x74, 0x65, 0x6d, 0x2e, 0x4c, 0x6f, - 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x41, 0x48, 0x00, 0x52, 0x05, - 0x61, 0x64, 0x64, 0x72, 0x41, 0x12, 0x2f, 0x0a, 0x01, 0x62, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, + 0x6f, 0x67, 0x2e, 0x69, 0x6e, 0x66, 0x6f, 0x28, 0x27, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x20, + 0x66, 0x65, 0x64, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6c, 0x6f, 0x67, 0x27, 0x2c, + 0x20, 0x7b, 0x27, 0x70, 0x6f, 0x73, 0x74, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x27, + 0x3a, 0x20, 0x70, 0x6f, 0x73, 0x74, 0x7d, 0x29, 0x22, 0xdf, 0x03, 0x0a, 0x01, 0x41, 0x12, 0x25, + 0x0a, 0x01, 0x62, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x66, 0x65, 0x64, 0x65, + 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x41, 0x2e, 0x42, 0x42, 0x06, 0x9a, 0x4a, 0x03, 0x12, + 0x01, 0x62, 0x52, 0x01, 0x62, 0x1a, 0xa1, 0x03, 0x0a, 0x01, 0x42, 0x12, 0x2d, 0x0a, 0x03, 0x66, + 0x6f, 0x6f, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x66, 0x65, 0x64, 0x65, 0x72, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x41, 0x2e, 0x42, 0x2e, 0x43, 0x42, 0x08, 0x9a, 0x4a, 0x05, + 0x12, 0x03, 0x66, 0x6f, 0x6f, 0x52, 0x03, 0x66, 0x6f, 0x6f, 0x12, 0x2d, 0x0a, 0x03, 0x62, 0x61, + 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x66, 0x65, 0x64, 0x65, 0x72, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x41, 0x2e, 0x42, 0x2e, 0x43, 0x42, 0x08, 0x9a, 0x4a, 0x05, 0x12, + 0x03, 0x62, 0x61, 0x72, 0x52, 0x03, 0x62, 0x61, 0x72, 0x1a, 0x24, 0x0a, 0x01, 0x43, 0x12, 0x1f, + 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x0b, 0x9a, 0x4a, + 0x08, 0x12, 0x06, 0x24, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x3a, + 0x97, 0x02, 0x9a, 0x4a, 0x93, 0x02, 0x0a, 0x1d, 0x0a, 0x03, 0x66, 0x6f, 0x6f, 0x6a, 0x16, 0x0a, + 0x05, 0x41, 0x2e, 0x42, 0x2e, 0x43, 0x12, 0x0d, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x05, + 0x27, 0x66, 0x6f, 0x6f, 0x27, 0x0a, 0x1d, 0x0a, 0x03, 0x62, 0x61, 0x72, 0x6a, 0x16, 0x0a, 0x05, + 0x41, 0x2e, 0x42, 0x2e, 0x43, 0x12, 0x0d, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x05, 0x27, + 0x62, 0x61, 0x72, 0x27, 0x0a, 0x89, 0x01, 0x12, 0x11, 0x66, 0x6f, 0x6f, 0x2e, 0x74, 0x79, 0x70, + 0x65, 0x20, 0x3d, 0x3d, 0x20, 0x27, 0x66, 0x6f, 0x6f, 0x27, 0x5a, 0x74, 0x67, 0x72, 0x70, 0x63, + 0x2e, 0x66, 0x65, 0x64, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x6c, 0x6f, 0x67, 0x2e, + 0x69, 0x6e, 0x66, 0x6f, 0x28, 0x27, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x20, 0x66, 0x65, 0x64, + 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6c, 0x6f, 0x67, 0x27, 0x2c, 0x20, 0x7b, 0x27, + 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x27, 0x3a, 0x20, 0x5b, 0x66, 0x6f, 0x6f, 0x2c, + 0x20, 0x62, 0x61, 0x72, 0x5d, 0x2c, 0x20, 0x27, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, + 0x6d, 0x61, 0x70, 0x27, 0x3a, 0x20, 0x7b, 0x27, 0x66, 0x6f, 0x6f, 0x27, 0x3a, 0x20, 0x66, 0x6f, + 0x6f, 0x2c, 0x20, 0x27, 0x62, 0x61, 0x72, 0x27, 0x3a, 0x20, 0x62, 0x61, 0x72, 0x7d, 0x7d, 0x29, + 0x0a, 0x47, 0x5a, 0x45, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x66, 0x65, 0x64, 0x65, 0x72, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x2e, 0x6c, 0x6f, 0x67, 0x2e, 0x61, 0x64, 0x64, 0x28, 0x7b, 0x27, 0x66, 0x6f, + 0x6f, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x27, 0x3a, 0x20, 0x66, 0x6f, 0x6f, 0x2e, 0x74, 0x79, 0x70, + 0x65, 0x2c, 0x20, 0x27, 0x62, 0x61, 0x72, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x27, 0x3a, 0x20, 0x62, + 0x61, 0x72, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x7d, 0x29, 0x3a, 0x0f, 0x9a, 0x4a, 0x0c, 0x0a, 0x0a, + 0x0a, 0x01, 0x62, 0x6a, 0x05, 0x0a, 0x03, 0x41, 0x2e, 0x42, 0x22, 0xe6, 0x01, 0x0a, 0x04, 0x50, + 0x6f, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x02, 0x69, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x6e, + 0x74, 0x65, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x74, + 0x65, 0x6e, 0x74, 0x12, 0x2f, 0x0a, 0x04, 0x75, 0x73, 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x10, 0x2e, 0x66, 0x65, 0x64, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x55, + 0x73, 0x65, 0x72, 0x42, 0x09, 0x9a, 0x4a, 0x06, 0x12, 0x04, 0x75, 0x73, 0x65, 0x72, 0x52, 0x04, + 0x75, 0x73, 0x65, 0x72, 0x3a, 0x6d, 0x9a, 0x4a, 0x6a, 0x0a, 0x3c, 0x0a, 0x03, 0x72, 0x65, 0x73, + 0x72, 0x35, 0x0a, 0x18, 0x70, 0x6f, 0x73, 0x74, 0x2e, 0x50, 0x6f, 0x73, 0x74, 0x53, 0x65, 0x72, + 0x76, 0x69, 0x63, 0x65, 0x2f, 0x47, 0x65, 0x74, 0x50, 0x6f, 0x73, 0x74, 0x12, 0x0a, 0x0a, 0x02, + 0x69, 0x64, 0x12, 0x04, 0x24, 0x2e, 0x69, 0x64, 0x1a, 0x03, 0x31, 0x30, 0x73, 0x22, 0x08, 0x0a, + 0x06, 0x0a, 0x02, 0x32, 0x73, 0x10, 0x03, 0x0a, 0x12, 0x0a, 0x04, 0x70, 0x6f, 0x73, 0x74, 0x18, + 0x01, 0x5a, 0x08, 0x72, 0x65, 0x73, 0x2e, 0x70, 0x6f, 0x73, 0x74, 0x0a, 0x16, 0x0a, 0x04, 0x75, + 0x73, 0x65, 0x72, 0x6a, 0x0e, 0x0a, 0x04, 0x55, 0x73, 0x65, 0x72, 0x12, 0x06, 0x1a, 0x04, 0x70, + 0x6f, 0x73, 0x74, 0x22, 0xc8, 0x04, 0x0a, 0x04, 0x55, 0x73, 0x65, 0x72, 0x12, 0x0e, 0x0a, 0x02, + 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, + 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, + 0x12, 0x26, 0x0a, 0x05, 0x69, 0x74, 0x65, 0x6d, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x10, 0x2e, 0x66, 0x65, 0x64, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x49, 0x74, 0x65, + 0x6d, 0x52, 0x05, 0x69, 0x74, 0x65, 0x6d, 0x73, 0x12, 0x37, 0x0a, 0x07, 0x70, 0x72, 0x6f, 0x66, + 0x69, 0x6c, 0x65, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x66, 0x65, 0x64, 0x65, + 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x2e, 0x50, 0x72, 0x6f, 0x66, + 0x69, 0x6c, 0x65, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x07, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, + 0x65, 0x12, 0x2f, 0x0a, 0x06, 0x61, 0x74, 0x74, 0x72, 0x5f, 0x61, 0x18, 0x05, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x16, 0x2e, 0x66, 0x65, 0x64, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x55, + 0x73, 0x65, 0x72, 0x2e, 0x41, 0x74, 0x74, 0x72, 0x41, 0x48, 0x00, 0x52, 0x05, 0x61, 0x74, 0x74, + 0x72, 0x41, 0x12, 0x26, 0x0a, 0x01, 0x62, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, + 0x66, 0x65, 0x64, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x2e, + 0x41, 0x74, 0x74, 0x72, 0x42, 0x48, 0x00, 0x52, 0x01, 0x62, 0x1a, 0x50, 0x0a, 0x0c, 0x50, 0x72, + 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, + 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x2a, 0x0a, 0x05, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 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, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x2f, 0x0a, 0x05, + 0x41, 0x74, 0x74, 0x72, 0x41, 0x12, 0x10, 0x0a, 0x03, 0x66, 0x6f, 0x6f, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x03, 0x66, 0x6f, 0x6f, 0x3a, 0x14, 0x9a, 0x4a, 0x11, 0x1a, 0x0f, 0x75, 0x73, + 0x65, 0x72, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x2e, 0x41, 0x74, 0x74, 0x72, 0x41, 0x1a, 0x2f, 0x0a, + 0x05, 0x41, 0x74, 0x74, 0x72, 0x42, 0x12, 0x10, 0x0a, 0x03, 0x62, 0x61, 0x72, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x08, 0x52, 0x03, 0x62, 0x61, 0x72, 0x3a, 0x14, 0x9a, 0x4a, 0x11, 0x1a, 0x0f, 0x75, + 0x73, 0x65, 0x72, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x2e, 0x41, 0x74, 0x74, 0x72, 0x42, 0x3a, 0xa5, + 0x01, 0x9a, 0x4a, 0xa1, 0x01, 0x0a, 0x8a, 0x01, 0x0a, 0x03, 0x72, 0x65, 0x73, 0x72, 0x82, 0x01, + 0x0a, 0x18, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x53, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x2f, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x12, 0x0f, 0x0a, 0x02, 0x69, 0x64, + 0x12, 0x09, 0x24, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x12, 0x2f, 0x0a, 0x04, 0x74, + 0x79, 0x70, 0x65, 0x12, 0x27, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x49, 0x74, 0x65, 0x6d, 0x2e, 0x49, + 0x74, 0x65, 0x6d, 0x54, 0x79, 0x70, 0x65, 0x2e, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x28, 0x27, 0x49, + 0x54, 0x45, 0x4d, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x31, 0x27, 0x29, 0x1a, 0x03, 0x32, 0x30, + 0x73, 0x22, 0x1f, 0x12, 0x1d, 0x0a, 0x02, 0x31, 0x73, 0x11, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0xe6, 0x3f, 0x19, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0xfb, 0x3f, 0x22, 0x03, 0x33, 0x30, 0x73, + 0x28, 0x03, 0x0a, 0x12, 0x0a, 0x04, 0x75, 0x73, 0x65, 0x72, 0x18, 0x01, 0x5a, 0x08, 0x72, 0x65, + 0x73, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x42, 0x06, 0x0a, 0x04, 0x61, 0x74, 0x74, 0x72, 0x22, 0x8d, + 0x05, 0x0a, 0x04, 0x49, 0x74, 0x65, 0x6d, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x2d, 0x0a, 0x04, 0x74, + 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x19, 0x2e, 0x66, 0x65, 0x64, 0x65, + 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x49, 0x74, 0x65, 0x6d, 0x2e, 0x49, 0x74, 0x65, 0x6d, + 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, + 0x6c, 0x75, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, + 0x12, 0x35, 0x0a, 0x08, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x66, 0x65, 0x64, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, + 0x49, 0x74, 0x65, 0x6d, 0x2e, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x08, 0x6c, + 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x1a, 0xf1, 0x02, 0x0a, 0x08, 0x4c, 0x6f, 0x63, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x14, 0x0a, 0x05, 0x61, 0x64, 0x64, 0x72, 0x31, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x05, 0x61, 0x64, 0x64, 0x72, 0x31, 0x12, 0x14, 0x0a, 0x05, 0x61, 0x64, + 0x64, 0x72, 0x32, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x61, 0x64, 0x64, 0x72, 0x32, + 0x12, 0x38, 0x0a, 0x06, 0x61, 0x64, 0x64, 0x72, 0x5f, 0x61, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x66, 0x65, 0x64, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x49, 0x74, 0x65, 0x6d, 0x2e, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x41, 0x64, 0x64, 0x72, - 0x42, 0x48, 0x00, 0x52, 0x01, 0x62, 0x1a, 0x38, 0x0a, 0x05, 0x41, 0x64, 0x64, 0x72, 0x41, 0x12, - 0x10, 0x0a, 0x03, 0x66, 0x6f, 0x6f, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x66, 0x6f, - 0x6f, 0x3a, 0x1d, 0x9a, 0x4a, 0x1a, 0x1a, 0x18, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x49, 0x74, 0x65, - 0x6d, 0x2e, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x41, - 0x1a, 0x38, 0x0a, 0x05, 0x41, 0x64, 0x64, 0x72, 0x42, 0x12, 0x10, 0x0a, 0x03, 0x62, 0x61, 0x72, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x03, 0x62, 0x61, 0x72, 0x3a, 0x1d, 0x9a, 0x4a, 0x1a, - 0x1a, 0x18, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x49, 0x74, 0x65, 0x6d, 0x2e, 0x4c, 0x6f, 0x63, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x42, 0x22, 0x38, 0x0a, 0x0c, 0x4c, 0x6f, - 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x12, 0x13, 0x0a, 0x0f, 0x4c, 0x4f, - 0x43, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x30, 0x10, 0x00, 0x12, + 0x41, 0x48, 0x00, 0x52, 0x05, 0x61, 0x64, 0x64, 0x72, 0x41, 0x12, 0x2f, 0x0a, 0x01, 0x62, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x66, 0x65, 0x64, 0x65, 0x72, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x2e, 0x49, 0x74, 0x65, 0x6d, 0x2e, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x2e, 0x41, 0x64, 0x64, 0x72, 0x42, 0x48, 0x00, 0x52, 0x01, 0x62, 0x1a, 0x38, 0x0a, 0x05, 0x41, + 0x64, 0x64, 0x72, 0x41, 0x12, 0x10, 0x0a, 0x03, 0x66, 0x6f, 0x6f, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x03, 0x66, 0x6f, 0x6f, 0x3a, 0x1d, 0x9a, 0x4a, 0x1a, 0x1a, 0x18, 0x75, 0x73, 0x65, + 0x72, 0x2e, 0x49, 0x74, 0x65, 0x6d, 0x2e, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, + 0x41, 0x64, 0x64, 0x72, 0x41, 0x1a, 0x38, 0x0a, 0x05, 0x41, 0x64, 0x64, 0x72, 0x42, 0x12, 0x10, + 0x0a, 0x03, 0x62, 0x61, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x03, 0x62, 0x61, 0x72, + 0x3a, 0x1d, 0x9a, 0x4a, 0x1a, 0x1a, 0x18, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x49, 0x74, 0x65, 0x6d, + 0x2e, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x42, 0x22, + 0x38, 0x0a, 0x0c, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x12, 0x13, 0x0a, 0x0f, 0x4c, 0x4f, 0x43, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x54, 0x59, 0x50, 0x45, - 0x5f, 0x31, 0x10, 0x01, 0x3a, 0x17, 0x9a, 0x4a, 0x14, 0x1a, 0x12, 0x75, 0x73, 0x65, 0x72, 0x2e, - 0x49, 0x74, 0x65, 0x6d, 0x2e, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x07, 0x0a, - 0x05, 0x61, 0x64, 0x64, 0x72, 0x33, 0x22, 0x71, 0x0a, 0x08, 0x49, 0x74, 0x65, 0x6d, 0x54, 0x79, - 0x70, 0x65, 0x12, 0x19, 0x0a, 0x15, 0x49, 0x54, 0x45, 0x4d, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, - 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0f, 0x0a, - 0x0b, 0x49, 0x54, 0x45, 0x4d, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x31, 0x10, 0x01, 0x12, 0x0f, - 0x0a, 0x0b, 0x49, 0x54, 0x45, 0x4d, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x32, 0x10, 0x02, 0x12, - 0x0f, 0x0a, 0x0b, 0x49, 0x54, 0x45, 0x4d, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x33, 0x10, 0x03, - 0x1a, 0x17, 0x9a, 0x4a, 0x14, 0x0a, 0x12, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x49, 0x74, 0x65, 0x6d, - 0x2e, 0x49, 0x74, 0x65, 0x6d, 0x54, 0x79, 0x70, 0x65, 0x3a, 0x0e, 0x9a, 0x4a, 0x0b, 0x1a, 0x09, - 0x75, 0x73, 0x65, 0x72, 0x2e, 0x49, 0x74, 0x65, 0x6d, 0x32, 0x5e, 0x0a, 0x11, 0x46, 0x65, 0x64, - 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x44, - 0x0a, 0x07, 0x47, 0x65, 0x74, 0x50, 0x6f, 0x73, 0x74, 0x12, 0x1a, 0x2e, 0x66, 0x65, 0x64, 0x65, - 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x47, 0x65, 0x74, 0x50, 0x6f, 0x73, 0x74, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x66, 0x65, 0x64, 0x65, 0x72, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x2e, 0x47, 0x65, 0x74, 0x50, 0x6f, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x22, 0x00, 0x1a, 0x03, 0x9a, 0x4a, 0x00, 0x42, 0xad, 0x01, 0x9a, 0x4a, 0x22, 0x12, - 0x0f, 0x70, 0x6f, 0x73, 0x74, 0x2f, 0x70, 0x6f, 0x73, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x12, 0x0f, 0x75, 0x73, 0x65, 0x72, 0x2f, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x0a, 0x0e, 0x63, 0x6f, 0x6d, 0x2e, 0x66, 0x65, 0x64, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x42, 0x0f, 0x46, 0x65, 0x64, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x72, 0x6f, - 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x1d, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2f, 0x66, 0x65, - 0x64, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3b, 0x66, 0x65, 0x64, 0x65, 0x72, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0xa2, 0x02, 0x03, 0x46, 0x58, 0x58, 0xaa, 0x02, 0x0a, 0x46, 0x65, 0x64, 0x65, - 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0xca, 0x02, 0x0a, 0x46, 0x65, 0x64, 0x65, 0x72, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0xe2, 0x02, 0x16, 0x46, 0x65, 0x64, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x0a, 0x46, - 0x65, 0x64, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x33, + 0x5f, 0x30, 0x10, 0x00, 0x12, 0x13, 0x0a, 0x0f, 0x4c, 0x4f, 0x43, 0x41, 0x54, 0x49, 0x4f, 0x4e, + 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x31, 0x10, 0x01, 0x3a, 0x17, 0x9a, 0x4a, 0x14, 0x1a, 0x12, + 0x75, 0x73, 0x65, 0x72, 0x2e, 0x49, 0x74, 0x65, 0x6d, 0x2e, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x42, 0x07, 0x0a, 0x05, 0x61, 0x64, 0x64, 0x72, 0x33, 0x22, 0x71, 0x0a, 0x08, 0x49, + 0x74, 0x65, 0x6d, 0x54, 0x79, 0x70, 0x65, 0x12, 0x19, 0x0a, 0x15, 0x49, 0x54, 0x45, 0x4d, 0x5f, + 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, + 0x10, 0x00, 0x12, 0x0f, 0x0a, 0x0b, 0x49, 0x54, 0x45, 0x4d, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, + 0x31, 0x10, 0x01, 0x12, 0x0f, 0x0a, 0x0b, 0x49, 0x54, 0x45, 0x4d, 0x5f, 0x54, 0x59, 0x50, 0x45, + 0x5f, 0x32, 0x10, 0x02, 0x12, 0x0f, 0x0a, 0x0b, 0x49, 0x54, 0x45, 0x4d, 0x5f, 0x54, 0x59, 0x50, + 0x45, 0x5f, 0x33, 0x10, 0x03, 0x1a, 0x17, 0x9a, 0x4a, 0x14, 0x0a, 0x12, 0x75, 0x73, 0x65, 0x72, + 0x2e, 0x49, 0x74, 0x65, 0x6d, 0x2e, 0x49, 0x74, 0x65, 0x6d, 0x54, 0x79, 0x70, 0x65, 0x3a, 0x0e, + 0x9a, 0x4a, 0x0b, 0x1a, 0x09, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x49, 0x74, 0x65, 0x6d, 0x32, 0x5e, + 0x0a, 0x11, 0x46, 0x65, 0x64, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x72, 0x76, + 0x69, 0x63, 0x65, 0x12, 0x44, 0x0a, 0x07, 0x47, 0x65, 0x74, 0x50, 0x6f, 0x73, 0x74, 0x12, 0x1a, + 0x2e, 0x66, 0x65, 0x64, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x47, 0x65, 0x74, 0x50, + 0x6f, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x66, 0x65, 0x64, + 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x47, 0x65, 0x74, 0x50, 0x6f, 0x73, 0x74, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x1a, 0x03, 0x9a, 0x4a, 0x00, 0x42, 0xad, + 0x01, 0x9a, 0x4a, 0x22, 0x12, 0x0f, 0x70, 0x6f, 0x73, 0x74, 0x2f, 0x70, 0x6f, 0x73, 0x74, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0f, 0x75, 0x73, 0x65, 0x72, 0x2f, 0x75, 0x73, 0x65, 0x72, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x0a, 0x0e, 0x63, 0x6f, 0x6d, 0x2e, 0x66, 0x65, 0x64, 0x65, + 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x0f, 0x46, 0x65, 0x64, 0x65, 0x72, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x1d, 0x65, 0x78, 0x61, 0x6d, 0x70, + 0x6c, 0x65, 0x2f, 0x66, 0x65, 0x64, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3b, 0x66, 0x65, + 0x64, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0xa2, 0x02, 0x03, 0x46, 0x58, 0x58, 0xaa, 0x02, + 0x0a, 0x46, 0x65, 0x64, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0xca, 0x02, 0x0a, 0x46, 0x65, + 0x64, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0xe2, 0x02, 0x16, 0x46, 0x65, 0x64, 0x65, 0x72, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, + 0x61, 0xea, 0x02, 0x0a, 0x46, 0x65, 0x64, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x62, 0x06, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/_examples/02_simple/federation/federation_grpc_federation.pb.go b/_examples/02_simple/federation/federation_grpc_federation.pb.go index 3fa18222..0373cd6f 100644 --- a/_examples/02_simple/federation/federation_grpc_federation.pb.go +++ b/_examples/02_simple/federation/federation_grpc_federation.pb.go @@ -59,6 +59,7 @@ type FederationService_Federation_GetPostResponseArgument struct { SortedItems []*user.Item SortedValues []int64 StringsJoin string + Url *grpcfedcel.URL Uuid *grpcfedcel.UUID Value1 string } @@ -666,7 +667,7 @@ func (s *FederationService) resolve_Federation_GetPostResponse(ctx context.Conte type localValueType struct { *grpcfed.LocalValue vars struct { - _def14 bool + _def15 bool a *A date *grpcfedcel.Time fixed_rand *grpcfedcel.Rand @@ -679,6 +680,7 @@ func (s *FederationService) resolve_Federation_GetPostResponse(ctx context.Conte sorted_items []*user.Item sorted_values []int64 strings_join string + url *grpcfedcel.URL uuid *grpcfedcel.UUID value1 string } @@ -687,7 +689,7 @@ func (s *FederationService) resolve_Federation_GetPostResponse(ctx context.Conte // A tree view of message dependencies is shown below. /* post ─┐ - _def14 ─┐ + _def15 ─┐ a ─┤ loc ─┐ │ jp_time ─┤ @@ -696,6 +698,7 @@ func (s *FederationService) resolve_Federation_GetPostResponse(ctx context.Conte sorted_items ─┤ sorted_values ─┤ strings_join ─┤ + url ─┤ date ─┐ │ rand_source ─┐ │ fixed_rand ─┐ │ @@ -751,15 +754,15 @@ func (s *FederationService) resolve_Federation_GetPostResponse(ctx context.Conte // This section's codes are generated by the following proto definition. /* def { - name: "_def14" + name: "_def15" by: "grpc.federation.log.info('output federation log', {'post_message': post})" } */ if err := grpcfed.EvalDef(ctx1, value, grpcfed.Def[bool, *localValueType]{ - Name: `_def14`, + Name: `_def15`, Type: grpcfed.CELBoolType, Setter: func(value *localValueType, v bool) error { - value.vars._def14 = v + value.vars._def15 = v return nil }, By: `grpc.federation.log.info('output federation log', {'post_message': post})`, @@ -975,6 +978,31 @@ func (s *FederationService) resolve_Federation_GetPostResponse(ctx context.Conte return nil, nil }) + grpcfed.GoWithRecover(eg, func() (any, error) { + + // This section's codes are generated by the following proto definition. + /* + def { + name: "url" + by: "grpc.federation.url.parse('https://test_user:password@example.com/path')" + } + */ + if err := grpcfed.EvalDef(ctx1, value, grpcfed.Def[*grpcfedcel.URL, *localValueType]{ + Name: `url`, + Type: grpcfed.CELObjectType("grpc.federation.url.URL"), + Setter: func(value *localValueType, v *grpcfedcel.URL) error { + value.vars.url = v + return nil + }, + By: `grpc.federation.url.parse('https://test_user:password@example.com/path')`, + ByCacheIndex: 21, + }); err != nil { + grpcfed.RecordErrorToSpan(ctx1, err) + return nil, err + } + return nil, nil + }) + grpcfed.GoWithRecover(eg, func() (any, error) { // This section's codes are generated by the following proto definition. @@ -992,7 +1020,7 @@ func (s *FederationService) resolve_Federation_GetPostResponse(ctx context.Conte return nil }, By: `grpc.federation.time.date(2023, 12, 25, 12, 10, 5, 0, grpc.federation.time.UTC())`, - ByCacheIndex: 21, + ByCacheIndex: 22, }); err != nil { grpcfed.RecordErrorToSpan(ctx1, err) return nil, err @@ -1013,7 +1041,7 @@ func (s *FederationService) resolve_Federation_GetPostResponse(ctx context.Conte return nil }, By: `grpc.federation.rand.newSource(date.unix())`, - ByCacheIndex: 22, + ByCacheIndex: 23, }); err != nil { grpcfed.RecordErrorToSpan(ctx1, err) return nil, err @@ -1034,7 +1062,7 @@ func (s *FederationService) resolve_Federation_GetPostResponse(ctx context.Conte return nil }, By: `grpc.federation.rand.new(rand_source)`, - ByCacheIndex: 23, + ByCacheIndex: 24, }); err != nil { grpcfed.RecordErrorToSpan(ctx1, err) return nil, err @@ -1055,7 +1083,7 @@ func (s *FederationService) resolve_Federation_GetPostResponse(ctx context.Conte return nil }, By: `.grpc.federation.uuid.newRandomFromRand(fixed_rand)`, - ByCacheIndex: 24, + ByCacheIndex: 25, }); err != nil { grpcfed.RecordErrorToSpan(ctx1, err) return nil, err @@ -1080,7 +1108,7 @@ func (s *FederationService) resolve_Federation_GetPostResponse(ctx context.Conte return nil }, By: `grpc.federation.metadata.incoming()['key1'][0]`, - ByCacheIndex: 25, + ByCacheIndex: 26, }); err != nil { grpcfed.RecordErrorToSpan(ctx1, err) return nil, err @@ -1105,6 +1133,7 @@ func (s *FederationService) resolve_Federation_GetPostResponse(ctx context.Conte req.SortedItems = value.vars.sorted_items req.SortedValues = value.vars.sorted_values req.StringsJoin = value.vars.strings_join + req.Url = value.vars.url req.Uuid = value.vars.uuid req.Value1 = value.vars.value1 @@ -1116,7 +1145,7 @@ func (s *FederationService) resolve_Federation_GetPostResponse(ctx context.Conte if err := grpcfed.SetCELValue(ctx, &grpcfed.SetCELValueParam[*Post]{ Value: value, Expr: `post`, - CacheIndex: 26, + CacheIndex: 27, Setter: func(v *Post) error { ret.Post = v return nil @@ -1129,7 +1158,7 @@ func (s *FederationService) resolve_Federation_GetPostResponse(ctx context.Conte if err := grpcfed.SetCELValue(ctx, &grpcfed.SetCELValueParam[string]{ Value: value, Expr: `'hello'`, - CacheIndex: 27, + CacheIndex: 28, Setter: func(v string) error { ret.Str = v return nil @@ -1142,7 +1171,7 @@ func (s *FederationService) resolve_Federation_GetPostResponse(ctx context.Conte if err := grpcfed.SetCELValue(ctx, &grpcfed.SetCELValueParam[string]{ Value: value, Expr: `uuid.string()`, - CacheIndex: 28, + CacheIndex: 29, Setter: func(v string) error { ret.Uuid = v return nil @@ -1155,7 +1184,7 @@ func (s *FederationService) resolve_Federation_GetPostResponse(ctx context.Conte if err := grpcfed.SetCELValue(ctx, &grpcfed.SetCELValueParam[string]{ Value: value, Expr: `loc.string()`, - CacheIndex: 29, + CacheIndex: 30, Setter: func(v string) error { ret.Loc = v return nil @@ -1168,7 +1197,7 @@ func (s *FederationService) resolve_Federation_GetPostResponse(ctx context.Conte if err := grpcfed.SetCELValue(ctx, &grpcfed.SetCELValueParam[string]{ Value: value, Expr: `value1`, - CacheIndex: 30, + CacheIndex: 31, Setter: func(v string) error { ret.Value1 = v return nil @@ -1181,7 +1210,7 @@ func (s *FederationService) resolve_Federation_GetPostResponse(ctx context.Conte if err := grpcfed.SetCELValue(ctx, &grpcfed.SetCELValueParam[string]{ Value: value, Expr: `Item.ItemType.name(Item.ItemType.ITEM_TYPE_1)`, - CacheIndex: 31, + CacheIndex: 32, Setter: func(v string) error { ret.ItemTypeName = v return nil @@ -1194,7 +1223,7 @@ func (s *FederationService) resolve_Federation_GetPostResponse(ctx context.Conte if err := grpcfed.SetCELValue(ctx, &grpcfed.SetCELValueParam[string]{ Value: value, Expr: `Item.Location.LocationType.name(Item.Location.LocationType.LOCATION_TYPE_1)`, - CacheIndex: 32, + CacheIndex: 33, Setter: func(v string) error { ret.LocationTypeName = v return nil @@ -1207,7 +1236,7 @@ func (s *FederationService) resolve_Federation_GetPostResponse(ctx context.Conte if err := grpcfed.SetCELValue(ctx, &grpcfed.SetCELValueParam[string]{ Value: value, Expr: `user.Item.ItemType.name(user.Item.ItemType.ITEM_TYPE_2)`, - CacheIndex: 33, + CacheIndex: 34, Setter: func(v string) error { ret.UserItemTypeName = v return nil @@ -1220,7 +1249,7 @@ func (s *FederationService) resolve_Federation_GetPostResponse(ctx context.Conte if err := grpcfed.SetCELValue(ctx, &grpcfed.SetCELValueParam[user.Item_ItemType]{ Value: value, Expr: `user.Item.ItemType.value('ITEM_TYPE_1')`, - CacheIndex: 34, + CacheIndex: 35, Setter: func(v user.Item_ItemType) error { itemTypeValueEnumValue, err := s.cast_User_Item_ItemType__to__Federation_Item_ItemType(v) if err != nil { @@ -1237,7 +1266,7 @@ func (s *FederationService) resolve_Federation_GetPostResponse(ctx context.Conte if err := grpcfed.SetCELValue(ctx, &grpcfed.SetCELValueParam[user.Item_ItemType]{ Value: value, Expr: `user.Item.ItemType.value('ITEM_TYPE_1')`, - CacheIndex: 35, + CacheIndex: 36, Setter: func(v user.Item_ItemType) error { itemTypeValueIntValue, err := s.cast_User_Item_ItemType__to__int32(v) if err != nil { @@ -1254,7 +1283,7 @@ func (s *FederationService) resolve_Federation_GetPostResponse(ctx context.Conte if err := grpcfed.SetCELValue(ctx, &grpcfed.SetCELValueParam[Item_ItemType]{ Value: value, Expr: `1`, - CacheIndex: 36, + CacheIndex: 37, Setter: func(v Item_ItemType) error { ret.ItemTypeValueCast = v return nil @@ -1267,7 +1296,7 @@ func (s *FederationService) resolve_Federation_GetPostResponse(ctx context.Conte if err := grpcfed.SetCELValue(ctx, &grpcfed.SetCELValueParam[Item_Location_LocationType]{ Value: value, Expr: `Item.Location.LocationType.value('LOCATION_TYPE_1')`, - CacheIndex: 37, + CacheIndex: 38, Setter: func(v Item_Location_LocationType) error { locationTypeValueValue, err := s.cast_Federation_Item_Location_LocationType__to__int32(v) if err != nil { @@ -1284,7 +1313,7 @@ func (s *FederationService) resolve_Federation_GetPostResponse(ctx context.Conte if err := grpcfed.SetCELValue(ctx, &grpcfed.SetCELValueParam[user.Item_ItemType]{ Value: value, Expr: `user.Item.ItemType.value('ITEM_TYPE_2')`, - CacheIndex: 38, + CacheIndex: 39, Setter: func(v user.Item_ItemType) error { userItemTypeValueValue, err := s.cast_User_Item_ItemType__to__int32(v) if err != nil { @@ -1301,7 +1330,7 @@ func (s *FederationService) resolve_Federation_GetPostResponse(ctx context.Conte if err := grpcfed.SetCELValue(ctx, &grpcfed.SetCELValueParam[*A]{ Value: value, Expr: `a`, - CacheIndex: 39, + CacheIndex: 40, Setter: func(v *A) error { ret.A = v return nil @@ -1314,7 +1343,7 @@ func (s *FederationService) resolve_Federation_GetPostResponse(ctx context.Conte if err := grpcfed.SetCELValue(ctx, &grpcfed.SetCELValueParam[[]int32]{ Value: value, Expr: `sorted_values`, - CacheIndex: 40, + CacheIndex: 41, Setter: func(v []int32) error { ret.SortedValues = v return nil @@ -1327,7 +1356,7 @@ func (s *FederationService) resolve_Federation_GetPostResponse(ctx context.Conte if err := grpcfed.SetCELValue(ctx, &grpcfed.SetCELValueParam[[]*user.Item]{ Value: value, Expr: `sorted_items`, - CacheIndex: 41, + CacheIndex: 42, Setter: func(v []*user.Item) error { sortedItemsValue, err := s.cast_repeated_User_Item__to__repeated_Federation_Item(v) if err != nil { @@ -1344,7 +1373,7 @@ func (s *FederationService) resolve_Federation_GetPostResponse(ctx context.Conte if err := grpcfed.SetCELValue(ctx, &grpcfed.SetCELValueParam[map[int64]string]{ Value: value, Expr: `map_value`, - CacheIndex: 42, + CacheIndex: 43, Setter: func(v map[int64]string) error { mapValueValue, err := s.cast_map_int64_string__to__map_int32_string(v) if err != nil { @@ -1361,7 +1390,7 @@ func (s *FederationService) resolve_Federation_GetPostResponse(ctx context.Conte if err := grpcfed.SetCELValue(ctx, &grpcfed.SetCELValueParam[*wrapperspb.DoubleValue]{ Value: value, Expr: `google.protobuf.DoubleValue{value: 1.23}`, - CacheIndex: 43, + CacheIndex: 44, Setter: func(v *wrapperspb.DoubleValue) error { doubleWrapperValueValue, err := s.cast_Google_Protobuf_DoubleValue__to__Google_Protobuf_DoubleValue(v) if err != nil { @@ -1378,7 +1407,7 @@ func (s *FederationService) resolve_Federation_GetPostResponse(ctx context.Conte if err := grpcfed.SetCELValue(ctx, &grpcfed.SetCELValueParam[*wrapperspb.DoubleValue]{ Value: value, Expr: `google.protobuf.FloatValue{value: 3.45}`, - CacheIndex: 44, + CacheIndex: 45, Setter: func(v *wrapperspb.DoubleValue) error { floatWrapperValueValue, err := s.cast_Google_Protobuf_DoubleValue__to__Google_Protobuf_FloatValue(v) if err != nil { @@ -1395,7 +1424,7 @@ func (s *FederationService) resolve_Federation_GetPostResponse(ctx context.Conte if err := grpcfed.SetCELValue(ctx, &grpcfed.SetCELValueParam[*wrapperspb.Int64Value]{ Value: value, Expr: `google.protobuf.Int64Value{value: 1}`, - CacheIndex: 45, + CacheIndex: 46, Setter: func(v *wrapperspb.Int64Value) error { i64WrapperValueValue, err := s.cast_Google_Protobuf_Int64Value__to__Google_Protobuf_Int64Value(v) if err != nil { @@ -1412,7 +1441,7 @@ func (s *FederationService) resolve_Federation_GetPostResponse(ctx context.Conte if err := grpcfed.SetCELValue(ctx, &grpcfed.SetCELValueParam[*wrapperspb.UInt64Value]{ Value: value, Expr: `google.protobuf.UInt64Value{value: uint(2)}`, - CacheIndex: 46, + CacheIndex: 47, Setter: func(v *wrapperspb.UInt64Value) error { u64WrapperValueValue, err := s.cast_Google_Protobuf_UInt64Value__to__Google_Protobuf_UInt64Value(v) if err != nil { @@ -1429,7 +1458,7 @@ func (s *FederationService) resolve_Federation_GetPostResponse(ctx context.Conte if err := grpcfed.SetCELValue(ctx, &grpcfed.SetCELValueParam[*wrapperspb.Int64Value]{ Value: value, Expr: `google.protobuf.Int32Value{value: 3}`, - CacheIndex: 47, + CacheIndex: 48, Setter: func(v *wrapperspb.Int64Value) error { i32WrapperValueValue, err := s.cast_Google_Protobuf_Int64Value__to__Google_Protobuf_Int32Value(v) if err != nil { @@ -1446,7 +1475,7 @@ func (s *FederationService) resolve_Federation_GetPostResponse(ctx context.Conte if err := grpcfed.SetCELValue(ctx, &grpcfed.SetCELValueParam[*wrapperspb.UInt64Value]{ Value: value, Expr: `google.protobuf.UInt32Value{value: uint(4)}`, - CacheIndex: 48, + CacheIndex: 49, Setter: func(v *wrapperspb.UInt64Value) error { u32WrapperValueValue, err := s.cast_Google_Protobuf_UInt64Value__to__Google_Protobuf_UInt32Value(v) if err != nil { @@ -1463,7 +1492,7 @@ func (s *FederationService) resolve_Federation_GetPostResponse(ctx context.Conte if err := grpcfed.SetCELValue(ctx, &grpcfed.SetCELValueParam[*wrapperspb.BoolValue]{ Value: value, Expr: `google.protobuf.BoolValue{value: true}`, - CacheIndex: 49, + CacheIndex: 50, Setter: func(v *wrapperspb.BoolValue) error { boolWrapperValueValue, err := s.cast_Google_Protobuf_BoolValue__to__Google_Protobuf_BoolValue(v) if err != nil { @@ -1480,7 +1509,7 @@ func (s *FederationService) resolve_Federation_GetPostResponse(ctx context.Conte if err := grpcfed.SetCELValue(ctx, &grpcfed.SetCELValueParam[*wrapperspb.StringValue]{ Value: value, Expr: `google.protobuf.StringValue{value: 'hello'}`, - CacheIndex: 50, + CacheIndex: 51, Setter: func(v *wrapperspb.StringValue) error { stringWrapperValueValue, err := s.cast_Google_Protobuf_StringValue__to__Google_Protobuf_StringValue(v) if err != nil { @@ -1497,7 +1526,7 @@ func (s *FederationService) resolve_Federation_GetPostResponse(ctx context.Conte if err := grpcfed.SetCELValue(ctx, &grpcfed.SetCELValueParam[*wrapperspb.BytesValue]{ Value: value, Expr: `google.protobuf.BytesValue{value: bytes('world')}`, - CacheIndex: 51, + CacheIndex: 52, Setter: func(v *wrapperspb.BytesValue) error { bytesWrapperValueValue, err := s.cast_Google_Protobuf_BytesValue__to__Google_Protobuf_BytesValue(v) if err != nil { @@ -1514,7 +1543,7 @@ func (s *FederationService) resolve_Federation_GetPostResponse(ctx context.Conte if err := grpcfed.SetCELValue(ctx, &grpcfed.SetCELValueParam[string]{ Value: value, Expr: `'hello\nworld'`, - CacheIndex: 52, + CacheIndex: 53, Setter: func(v string) error { ret.Hello = v return nil @@ -1527,7 +1556,7 @@ func (s *FederationService) resolve_Federation_GetPostResponse(ctx context.Conte if err := grpcfed.SetCELValue(ctx, &grpcfed.SetCELValueParam[*timestamppb.Timestamp]{ Value: value, Expr: `null`, - CacheIndex: 53, + CacheIndex: 54, Setter: func(v *timestamppb.Timestamp) error { ret.NullTimestamp = v return nil @@ -1540,7 +1569,7 @@ func (s *FederationService) resolve_Federation_GetPostResponse(ctx context.Conte if err := grpcfed.SetCELValue(ctx, &grpcfed.SetCELValueParam[*timestamppb.Timestamp]{ Value: value, Expr: `null_value`, - CacheIndex: 54, + CacheIndex: 55, Setter: func(v *timestamppb.Timestamp) error { ret.NullTimestamp2 = v return nil @@ -1553,7 +1582,7 @@ func (s *FederationService) resolve_Federation_GetPostResponse(ctx context.Conte if err := grpcfed.SetCELValue(ctx, &grpcfed.SetCELValueParam[*timestamppb.Timestamp]{ Value: value, Expr: `true ? null : google.protobuf.Timestamp{}`, - CacheIndex: 55, + CacheIndex: 56, Setter: func(v *timestamppb.Timestamp) error { ret.NullTimestamp3 = v return nil @@ -1566,7 +1595,7 @@ func (s *FederationService) resolve_Federation_GetPostResponse(ctx context.Conte if err := grpcfed.SetCELValue(ctx, &grpcfed.SetCELValueParam[string]{ Value: value, Expr: `jp_time.location().string()`, - CacheIndex: 56, + CacheIndex: 57, Setter: func(v string) error { ret.JpLoc = v return nil @@ -1579,7 +1608,7 @@ func (s *FederationService) resolve_Federation_GetPostResponse(ctx context.Conte if err := grpcfed.SetCELValue(ctx, &grpcfed.SetCELValueParam[string]{ Value: value, Expr: `strings_join`, - CacheIndex: 57, + CacheIndex: 58, Setter: func(v string) error { ret.StringsJoin = v return nil @@ -1588,6 +1617,19 @@ func (s *FederationService) resolve_Federation_GetPostResponse(ctx context.Conte grpcfed.RecordErrorToSpan(ctx, err) return nil, err } + // (grpc.federation.field).by = "url.userinfo().username()" + if err := grpcfed.SetCELValue(ctx, &grpcfed.SetCELValueParam[string]{ + Value: value, + Expr: `url.userinfo().username()`, + CacheIndex: 59, + Setter: func(v string) error { + ret.UrlUserName = v + return nil + }, + }); err != nil { + grpcfed.RecordErrorToSpan(ctx, err) + return nil, err + } grpcfed.Logger(ctx).DebugContext(ctx, "resolved federation.GetPostResponse", slog.Any("federation.GetPostResponse", s.logvalue_Federation_GetPostResponse(ret))) return ret, nil @@ -1633,7 +1675,7 @@ func (s *FederationService) resolve_Federation_Post(ctx context.Context, req *Fe if err := grpcfed.SetCELValue(ctx, &grpcfed.SetCELValueParam[string]{ Value: value, Expr: `$.id`, - CacheIndex: 58, + CacheIndex: 60, Setter: func(v string) error { args.Id = v return nil @@ -1649,7 +1691,7 @@ func (s *FederationService) resolve_Federation_Post(ctx context.Context, req *Fe return grpcfed.WithRetry(ctx, &grpcfed.RetryParam[post.GetPostResponse]{ Value: value, If: `true`, - CacheIndex: 59, + CacheIndex: 61, BackOff: b, Body: func() (*post.GetPostResponse, error) { return s.client.Post_PostServiceClient.GetPost(ctx, args) @@ -1684,7 +1726,7 @@ func (s *FederationService) resolve_Federation_Post(ctx context.Context, req *Fe return nil }, By: `res.post`, - ByCacheIndex: 60, + ByCacheIndex: 62, }); err != nil { grpcfed.RecordErrorToSpan(ctx, err) return nil, err @@ -1713,7 +1755,7 @@ func (s *FederationService) resolve_Federation_Post(ctx context.Context, req *Fe if err := grpcfed.SetCELValue(ctx, &grpcfed.SetCELValueParam[*post.Post]{ Value: value, Expr: `post`, - CacheIndex: 61, + CacheIndex: 63, Setter: func(v *post.Post) error { args.Id = v.GetId() args.Title = v.GetTitle() @@ -1751,7 +1793,7 @@ func (s *FederationService) resolve_Federation_Post(ctx context.Context, req *Fe if err := grpcfed.SetCELValue(ctx, &grpcfed.SetCELValueParam[*User]{ Value: value, Expr: `user`, - CacheIndex: 62, + CacheIndex: 64, Setter: func(v *User) error { ret.User = v return nil @@ -1807,7 +1849,7 @@ func (s *FederationService) resolve_Federation_User(ctx context.Context, req *Fe if err := grpcfed.SetCELValue(ctx, &grpcfed.SetCELValueParam[string]{ Value: value, Expr: `$.user_id`, - CacheIndex: 63, + CacheIndex: 65, Setter: func(v string) error { args.Id = v return nil @@ -1819,7 +1861,7 @@ func (s *FederationService) resolve_Federation_User(ctx context.Context, req *Fe if err := grpcfed.SetCELValue(ctx, &grpcfed.SetCELValueParam[user.Item_ItemType]{ Value: value, Expr: `user.Item.ItemType.value('ITEM_TYPE_1')`, - CacheIndex: 64, + CacheIndex: 66, Setter: func(v user.Item_ItemType) error { typeValue, err := s.cast_User_Item_ItemType__to__int32(v) if err != nil { @@ -1845,7 +1887,7 @@ func (s *FederationService) resolve_Federation_User(ctx context.Context, req *Fe return grpcfed.WithRetry(ctx, &grpcfed.RetryParam[user.GetUserResponse]{ Value: value, If: `true`, - CacheIndex: 65, + CacheIndex: 67, BackOff: b, Body: func() (*user.GetUserResponse, error) { return s.client.User_UserServiceClient.GetUser(ctx, args) @@ -1880,7 +1922,7 @@ func (s *FederationService) resolve_Federation_User(ctx context.Context, req *Fe return nil }, By: `res.user`, - ByCacheIndex: 66, + ByCacheIndex: 68, }); err != nil { grpcfed.RecordErrorToSpan(ctx, err) return nil, err @@ -2386,6 +2428,7 @@ func (s *FederationService) logvalue_Federation_GetPostResponse(v *GetPostRespon slog.Any("null_timestamp3", s.logvalue_Google_Protobuf_Timestamp(v.GetNullTimestamp3())), slog.String("jp_loc", v.GetJpLoc()), slog.String("strings_join", v.GetStringsJoin()), + slog.String("url_user_name", v.GetUrlUserName()), ) } diff --git a/_examples/02_simple/main_test.go b/_examples/02_simple/main_test.go index 05c702e4..070bcd26 100644 --- a/_examples/02_simple/main_test.go +++ b/_examples/02_simple/main_test.go @@ -205,6 +205,7 @@ func TestFederation(t *testing.T) { if err != nil { t.Fatal(err) } + if diff := cmp.Diff(res, &federation.GetPostResponse{ Post: &federation.Post{ Id: "foo", @@ -317,6 +318,7 @@ func TestFederation(t *testing.T) { NullTimestamp3: nil, JpLoc: "JST", StringsJoin: "a,b,c", + UrlUserName: "test_user", }, cmpopts.IgnoreUnexported( federation.GetPostResponse{}, federation.Post{}, diff --git a/_examples/02_simple/proto/federation/federation.proto b/_examples/02_simple/proto/federation/federation.proto index d22b788d..cc6b7c20 100644 --- a/_examples/02_simple/proto/federation/federation.proto +++ b/_examples/02_simple/proto/federation/federation.proto @@ -32,6 +32,7 @@ message GetPostResponse { } } def { name: "strings_join" by: "grpc.federation.strings.join(['a', 'b', 'c'], ',')" } + def { name: "url" by: "grpc.federation.url.parse('https://test_user:password@example.com/path')" } def { name: "date" by: "grpc.federation.time.date(2023, 12, 25, 12, 10, 5, 0, grpc.federation.time.UTC())" } def { name: "rand_source" by: "grpc.federation.rand.newSource(date.unix())" } def { name: "fixed_rand" by: "grpc.federation.rand.new(rand_source)" } @@ -78,6 +79,7 @@ message GetPostResponse { google.protobuf.Timestamp null_timestamp3 = 30 [(grpc.federation.field).by = "true ? null : google.protobuf.Timestamp{}"]; string jp_loc = 31 [(grpc.federation.field).by = "jp_time.location().string()"]; string strings_join = 32 [(grpc.federation.field).by = "strings_join"]; + string url_user_name = 33 [(grpc.federation.field).by = "url.userinfo().username()"]; } message A { diff --git a/docs/cel/url.md b/docs/cel/url.md new file mode 100644 index 00000000..2b807cc0 --- /dev/null +++ b/docs/cel/url.md @@ -0,0 +1,609 @@ +# grpc.federation.url APIs + +The API for this package was created based on Go's [`net/url`](https://pkg.go.dev/net/url) package. + +# Index + +## Functions + +- [`joinPath`](#joinPath) +- [`pathEscape`](#pathEscape) +- [`pathUnescape`](#pathUnescape) +- [`queryEscape`](#queryEscape) +- [`queryUnescape`](#queryUnescape) + +## URL + +- [`parse`](#parse) +- [`parseRequestURI`](#parseRequestURI) +- [`URL.scheme`](#urlscheme) +- [`URL.opaque`](#urlopaque) +- [`URL.userinfo`](#urluserinfo) +- [`URL.host`](#urlhost) +- [`URL.path`](#urlpath) +- [`URL.rawPath`](#urlrawpath) +- [`URL.forceQuery`](#urlforceQuery) +- [`URL.rawQuery`](#urlrawQuery) +- [`URL.fragment`](#urlfragment) +- [`URL.rawFragment`](#urlrawFragment) +- [`URL.escapedFragment`](#urlescapedFragment) +- [`URL.escapedPath`](#urlescapedPath) +- [`URL.hostname`](#urlhostname) +- [`URL.isAbs`](#urlisAbs) +- [`URL.joinPath`](#urljoinPath) +- [`URL.marshalBinary`](#urlmarshalBinary) +- [`URL.parse`](#urlparse) +- [`URL.port`](#urlport) +- [`URL.query`](#urlquery) +- [`URL.redacted`](#urlredacted) +- [`URL.requestURI`](#urlrequestURI) +- [`URL.resolveReference`](#urlresolveReference) +- [`URL.string`](#urlstring) +- [`URL.unmarshalBinary`](#urlunmarshalBinary) + +## Userinfo + +- [`user`](#user) +- [`userPassword`](#userPassword) +- [`Userinfo.username`](#userinfousername) +- [`Userinfo.password`](#userinfopassword) +- [`Userinfo.passwordSet`](#userinfopasswordSet) +- [`Userinfo.string`](#userinfostring) + +# Functions + +## joinPath + +`joinPath` concatenates a base URL with additional path elements to form a complete URL. + +### Parameters + +`joinPath(baseURL string, elements []string) string` + +- `baseURL`: the base URL to start with. +- `elements`: an array of path segments to join with the base URL. + +### Example + +```cel +grpc.federation.url.joinPath("https://example.com", ["path", "to", "resource"]) //=> "https://example.com/path/to/resource" +``` + +## pathEscape + +`pathEscape` escapes the string so it can be safely placed inside a URL path segment. + +### Parameters + +`pathEscape(path string) string` + +- `path`: the path segment to escape. + +### Examples + +```cel +grpc.federation.url.pathEscape("/path with spaces/") +``` + +## pathUnescape + +`pathUnescape` unescapes a path segment. + +### Parameters + +`pathUnescape(path string) string` + +- `path`: the path segment to unescape. + +### Examples + +```cel +grpc.federation.url.pathUnescape("/path%20with%20spaces/") +``` + +## queryEscape + +`queryEscape` escapes the string so it can be safely placed inside a URL query. + +### Parameters + +`queryEscape(query string) string` + +- `query`: the query string to escape. + +### Examples + +```cel +grpc.federation.url.queryEscape("query with spaces") +``` + +## queryUnescape + +`queryUnescape` unescapes a query string. + +### Parameters + +`queryUnescape(query string) string` + +- `query`: the query string to unescape. + +### Examples + +```cel +grpc.federation.url.queryUnescape("query%20with%20spaces") +``` + +# URL Methods + +## parse + +`parse` parses a URL and returns a URL struct. + +### Parameters + +`parse(url string) URL` + +- `url`: the URL string to parse. + +### Examples + +```cel +grpc.federation.url.parse("https://www.example.com/path?query=value#fragment") +``` + +## parseRequestURI + +`parseRequestURI` parses a URL in request context and returns a URL struct. + +### Parameters + +`parseRequestURI(requestURI string) URL` + +- `requestURI`: the URI for a request. + +### Examples + +```cel +grpc.federation.url.parseRequestURI("/path?query=value#fragment") +``` + +## URL.scheme + +`scheme` returns the scheme of the URL. + +### Parameters + +`URL.scheme() string` + +### Examples + +```cel +grpc.federation.url.parse("https://example.com").scheme() //=> "https" +``` + +## URL.opaque + +`opaque` returns the opaque part of the URL. + +### Parameters + +`URL.opaque() string` + +### Examples + +```cel +grpc.federation.url.parse("mailto:John.Doe@example.com").opaque() //=> "John.Doe@example.com" +``` + +## URL.userinfo + +`userinfo` returns the user information in the URL. + +### Parameters + +`URL.userinfo() Userinfo` + +### Examples + +```cel +grpc.federation.url.parse("https://user:pass@example.com").userinfo() //=> grpc.federation.url.Userinfo{username: "user", password: "pass"} +``` + +## URL.host + +`host` returns the host of the URL. + +### Parameters + +`URL.host() string` + +### Examples + +```cel +grpc.federation.url.parse("https://example.com").host() //=> "example.com" +``` + +## URL.path + +`path` returns the path of the URL. + +### Parameters + +`URL.path() string` + +### Examples + +```cel +grpc.federation.url.parse("https://example.com/path").path() //=> "/path" +``` + +## URL.rawPath + +`rawPath` returns the raw path of the URL. + +### Parameters + +`URL.rawPath() string` + +### Examples + +```cel +grpc.federation.url.parse("https://example.com/%2Fpath%2F").rawPath() //=> "/%2Fpath%2F" +``` + +## URL.forceQuery + +`forceQuery` returns the URL string with the ForceQuery field set to true. + +### Parameters + +`URL.forceQuery() string` + +### Examples + +```cel +grpc.federation.url.parse("https://example.com").forceQuery() +``` +## URL.rawQuery + +`rawQuery` returns the raw query string of the URL. + +### Parameters + +`URL.rawQuery() string` + +### Examples + +```cel +grpc.federation.url.parse("https://example.com?query=value").rawQuery() //=> "query=value" +``` + +## URL.fragment + +`fragment` returns the fragment of the URL. + +### Parameters + +`URL.fragment() string` + +### Examples + +```cel +grpc.federation.url.parse("https://example.com#fragment").fragment() //=> "fragment" +``` + +## URL.rawFragment + +`rawFragment` returns the raw fragment of the URL. + +### Parameters + +`URL.rawFragment() string` + +### Examples + +```cel +grpc.federation.url.parse("https://example.com#fragment").rawFragment() //=> "fragment" +``` + +## URL.escapedFragment + +`escapedFragment` returns the escaped fragment of the URL. + +### Parameters + +`URL.escapedFragment() string` + +### Examples + +```cel +grpc.federation.url.parse("https://example.com#frag ment").escapedFragment() //=> "frag%20ment" +``` + +## URL.escapedPath + +`escapedPath` returns the escaped path of the URL. + +### Parameters + +`URL.escapedPath() string` + +### Examples + +```cel +grpc.federation.url.parse("https://example.com/path with spaces").escapedPath() //=> "/path%20with%20spaces" +``` + +## URL.hostname + +`hostname` returns the host name of the URL. + +### Parameters + +`URL.hostname() string` + +### Examples + +```cel +grpc.federation.url.parse("https://example.com:8080").hostname() //=> "example.com" +``` + +## URL.isAbs + +`isAbs` reports whether the URL is absolute. + +### Parameters + +`URL.isAbs() bool` + +### Examples + +```cel +grpc.federation.url.parse("https://example.com").isAbs() //=> true +grpc.federation.url.parse("/path").isAbs() //=> false +``` + +## URL.joinPath + +`joinPath` joins the path elements with the URL path. + +### Parameters + +`URL.joinPath(elements []string) URL` + +- `elements`: list of path elements to join with the URL path. + +### Examples + +```cel +grpc.federation.url.parse("https://example.com/path").joinPath(["to", "resource"]) //=> "https://example.com/path/to/resource" +``` + +## URL.marshalBinary + +`marshalBinary` returns the URL in a binary format. + +### Parameters + +`URL.marshalBinary() bytes` + +### Examples + +```cel +grpc.federation.url.parse("https://example.com").marshalBinary() +``` + +## URL.parse + +`parse` parses a URL string in the context of the current URL. + +### Parameters + +`URL.parse(ref string) URL` + +- `ref`: the URL reference string to parse. + +### Examples + +```cel +grpc.federation.url.parse("https://example.com/base").parse("/resource") //=> "https://example.com/resource" +``` + +## URL.port + +`port` returns the port of the URL. + +### Parameters + +`URL.port() string` + +### Examples + +```cel +grpc.federation.url.parse("https://example.com:8080").port() //=> "8080" +``` + +## URL.query + +`query` returns the parsed query parameters of the URL. + +### Parameters + +`URL.query() map` + +### Examples + +```cel +grpc.federation.url.parse("https://example.com?key=value&key=another").query() //=> {"key": ["value", "another"]} +``` + +## URL.redacted + +`redacted` returns the URL with password part redacted. + +### Parameters + +`URL.redacted() string` + +### Examples + +```cel +grpc.federation.url.parse("https://user:password@example.com").redacted() //=> "https://user:xxxxx@example.com" +``` + +## URL.requestURI + +`requestURI` returns the request URI of the URL. + +### Parameters + +`URL.requestURI() string` + +### Examples + +```cel +grpc.federation.url.parse("https://example.com/path?query=value").requestURI() //=> "/path?query=value" +``` + +## URL.resolveReference + +`resolveReference` resolves a reference URL against the base URL. + +### Parameters + +`URL.resolveReference(ref URL) URL` + +- `ref`: the reference URL to resolve. + +### Examples + +```cel +base := grpc.federation.url.parse("https://example.com/base") +ref := grpc.federation.url.parse("/resource") +base.resolveReference(ref) //=> "https://example.com/resource" +``` + +## URL.string + +`string` returns the URL as a string. + +### Parameters + +`URL.string() string` + +### Examples + +```cel +grpc.federation.url.parse("https://example.com").string() +``` + +## URL.unmarshalBinary + +`unmarshalBinary` unmarshals a binary format URL into a URL struct. + +### Parameters + +`URL.unmarshalBinary(data bytes) URL` + +- `data`: binary format URL data. + +### Examples + +```cel +url := grpc.federation.url.parse("https://example.com") +binaryData := url.marshalBinary() +grpc.federation.url.parse("https://example.com").unmarshalBinary(binaryData) +``` + +# Userinfo Methods + +## user + +`user` returns a Userinfo object with the provided username. + +### Parameters + +`user(username string) Userinfo` + +- `username`: the username for the userinfo. + +### Examples + +```cel +grpc.federation.url.user("user") +``` + +## userPassword + +`userPassword` returns a Userinfo object with the provided username and password. + +### Parameters + +`userPassword(username string, password string) Userinfo` + +- `username`: the username for the userinfo. +- `password`: the password for the userinfo. + +### Examples + +```cel +grpc.federation.url.userPassword("user", "password") +``` + +## Userinfo.username + +`username` returns the username of the Userinfo. + +### Parameters + +`Userinfo.username() string` + +### Examples + +```cel +grpc.federation.url.user("user").username() //=> "user" +``` + +## Userinfo.password + +`password` returns the password of the Userinfo, if set. + +### Parameters + +`Userinfo.password() string` + +### Examples + +```cel +grpc.federation.url.userPassword("user", "password").password() //=> "password" +``` + +## Userinfo.passwordSet + +`passwordSet` returns true if the password is set for the Userinfo. + +### Parameters + +`Userinfo.passwordSet() bool` + +### Examples + +```cel +grpc.federation.url.userPassword("user", "password").passwordSet() //=> true +grpc.federation.url.user("user").passwordSet() //=> false +``` + +## Userinfo.string + +`string` returns the Userinfo as a string. + +### Parameters + +`Userinfo.string() string` + +### Examples + +```cel +grpc.federation.url.userPassword("user", "password").string() //=> "user:password" +grpc.federation.url.user("user").string() //=> "user" +``` diff --git a/grpc/federation/cel/lib.go b/grpc/federation/cel/lib.go index 24f55c10..8d42c833 100644 --- a/grpc/federation/cel/lib.go +++ b/grpc/federation/cel/lib.go @@ -18,6 +18,7 @@ func NewLibrary(typeAdapter types.Adapter) *Library { return &Library{ name: "grpc.federation.static", subLibs: []cel.SingletonLibrary{ + NewURLLibrary(typeAdapter), NewStringsLibrary(), NewTimeLibrary(typeAdapter), NewListLibrary(typeAdapter), diff --git a/grpc/federation/cel/url.go b/grpc/federation/cel/url.go new file mode 100644 index 00000000..fe3f14b5 --- /dev/null +++ b/grpc/federation/cel/url.go @@ -0,0 +1,532 @@ +package cel + +import ( + "context" + "net/url" + + "github.com/google/cel-go/cel" + "github.com/google/cel-go/common/types" + "github.com/google/cel-go/common/types/ref" + "github.com/google/cel-go/common/types/traits" +) + +const URLPackageName = "url" + +var ( + URLType = cel.ObjectType("grpc.federation.url.URL") + UserinfoType = cel.ObjectType("grpc.federation.url.Userinfo") +) + +func (x *URL) GoURL() url.URL { + return url.URL{ + Scheme: x.GetScheme(), + Opaque: x.GetOpaque(), + User: x.GetUser().GoUserinfo(), + Host: x.GetHost(), + Path: x.GetPath(), + RawPath: x.GetRawPath(), + OmitHost: x.GetOmitHost(), + ForceQuery: x.GetForceQuery(), + RawQuery: x.GetRawQuery(), + Fragment: x.GetFragment(), + RawFragment: x.GetRawFragment(), + } +} + +func (x *Userinfo) GoUserinfo() *url.Userinfo { + if x == nil { + return nil + } + if x.GetPasswordSet() { + return url.UserPassword(x.GetUsername(), x.GetPassword()) + } + return url.User(x.GetUsername()) +} + +var _ cel.SingletonLibrary = new(URLLibrary) + +type URLLibrary struct { + typeAdapter types.Adapter +} + +func NewURLLibrary(typeAdapter types.Adapter) *URLLibrary { + return &URLLibrary{ + typeAdapter: typeAdapter, + } +} + +func (lib *URLLibrary) LibraryName() string { + return packageName(URLPackageName) +} + +func createURLName(name string) string { + return createName(URLPackageName, name) +} + +func createURLID(name string) string { + return createID(URLPackageName, name) +} + +func (lib *URLLibrary) refToGoURLValue(v ref.Val) url.URL { + return v.Value().(*URL).GoURL() +} + +func (lib *URLLibrary) refToGoUserinfoValue(v ref.Val) *url.Userinfo { + return v.Value().(*Userinfo).GoUserinfo() +} + +func (lib *URLLibrary) toURLValue(v url.URL) ref.Val { + var userinfo *Userinfo + if v.User != nil { + password, hasPassword := v.User.Password() + userinfo = &Userinfo{ + Username: v.User.Username(), + Password: password, + PasswordSet: hasPassword, + } + } + + return lib.typeAdapter.NativeToValue(&URL{ + Scheme: v.Scheme, + Opaque: v.Opaque, + User: userinfo, + Host: v.Host, + Path: v.Path, + RawPath: v.RawPath, + OmitHost: v.OmitHost, + ForceQuery: v.ForceQuery, + RawQuery: v.RawQuery, + Fragment: v.Fragment, + RawFragment: v.RawFragment, + }) +} + +func (lib *URLLibrary) toUserinfoValue(username, password string, passwordSet bool) ref.Val { + return lib.typeAdapter.NativeToValue(&Userinfo{Username: username, Password: password, PasswordSet: passwordSet}) +} + +func (lib *URLLibrary) CompileOptions() []cel.EnvOption { + opts := []cel.EnvOption{} + + for _, funcOpts := range [][]cel.EnvOption{ + BindFunction( + createURLName("joinPath"), + OverloadFunc(createURLID("joinPath_string_strings_string"), []*cel.Type{cel.StringType, cel.ListType(cel.StringType)}, cel.StringType, + func(_ context.Context, args ...ref.Val) ref.Val { + base := string(args[0].(types.String)) + elems := args[1].(traits.Lister) + var paths []string + for i := types.Int(0); i < elems.Size().(types.Int); i++ { + pathElem := elems.Get(i) + paths = append(paths, string(pathElem.(types.String))) + } + + result, err := url.JoinPath(base, paths...) + if err != nil { + return types.NewErr(err.Error()) + } + return types.String(result) + }, + ), + ), + BindFunction( + createURLName("pathEscape"), + OverloadFunc(createURLID("pathEscape_string_string"), []*cel.Type{cel.StringType}, cel.StringType, + func(_ context.Context, args ...ref.Val) ref.Val { + return types.String(url.PathEscape(string(args[0].(types.String)))) + }, + ), + ), + BindFunction( + createURLName("pathUnescape"), + OverloadFunc(createURLID("pathUnescape_string_string"), []*cel.Type{cel.StringType}, cel.StringType, + func(_ context.Context, args ...ref.Val) ref.Val { + result, err := url.PathUnescape(string(args[0].(types.String))) + if err != nil { + return types.NewErr(err.Error()) + } + return types.String(result) + }, + ), + ), + BindFunction( + createURLName("queryEscape"), + OverloadFunc(createURLID("queryEscape_string_string"), []*cel.Type{cel.StringType}, cel.StringType, + func(_ context.Context, args ...ref.Val) ref.Val { + return types.String(url.QueryEscape(string(args[0].(types.String)))) + }, + ), + ), + BindFunction( + createURLName("queryUnescape"), + OverloadFunc(createURLID("queryUnescape_string_string"), []*cel.Type{cel.StringType}, cel.StringType, + func(_ context.Context, args ...ref.Val) ref.Val { + result, err := url.QueryUnescape(string(args[0].(types.String))) + if err != nil { + return types.NewErr(err.Error()) + } + return types.String(result) + }, + ), + ), + + // URL functions + BindFunction( + createURLName("parse"), + OverloadFunc(createURLID("parse_string_url"), []*cel.Type{cel.StringType}, URLType, + func(_ context.Context, args ...ref.Val) ref.Val { + v, err := url.Parse(string(args[0].(types.String))) + if err != nil { + return types.NewErr(err.Error()) + } + return lib.toURLValue(*v) + }, + ), + ), + BindFunction( + createURLName("parseRequestURI"), + OverloadFunc(createURLID("parseRequestURI_string_url"), []*cel.Type{cel.StringType}, URLType, + func(_ context.Context, args ...ref.Val) ref.Val { + v, err := url.ParseRequestURI(string(args[0].(types.String))) + if err != nil { + return types.NewErr(err.Error()) + } + return lib.toURLValue(*v) + }, + ), + ), + BindMemberFunction( + "scheme", + MemberOverloadFunc(createURLID("scheme_url_string"), URLType, []*cel.Type{}, cel.StringType, + func(_ context.Context, self ref.Val, args ...ref.Val) ref.Val { + v := lib.refToGoURLValue(self) + return types.String(v.Scheme) + }, + ), + ), + BindMemberFunction( + "opaque", + MemberOverloadFunc(createURLID("opaque_url_string"), URLType, []*cel.Type{}, cel.StringType, + func(_ context.Context, self ref.Val, args ...ref.Val) ref.Val { + v := lib.refToGoURLValue(self) + return types.String(v.Opaque) + }, + ), + ), + BindMemberFunction( + "userinfo", // user is not a valid field name + MemberOverloadFunc(createURLID("user_url_userinfo"), URLType, []*cel.Type{}, UserinfoType, + func(_ context.Context, self ref.Val, args ...ref.Val) ref.Val { + v := lib.refToGoURLValue(self) + password, hasPassword := v.User.Password() + return lib.toUserinfoValue(v.User.Username(), password, hasPassword) + }, + ), + ), + BindMemberFunction( + "host", + MemberOverloadFunc(createURLID("host_url_string"), URLType, []*cel.Type{}, cel.StringType, + func(_ context.Context, self ref.Val, args ...ref.Val) ref.Val { + v := lib.refToGoURLValue(self) + return types.String(v.Host) + }, + ), + ), + BindMemberFunction( + "path", + MemberOverloadFunc(createURLID("path_url_string"), URLType, []*cel.Type{}, cel.StringType, + func(_ context.Context, self ref.Val, args ...ref.Val) ref.Val { + v := lib.refToGoURLValue(self) + return types.String(v.Path) + }, + ), + ), + BindMemberFunction( + "rawPath", + MemberOverloadFunc(createURLID("rawPath_url_string"), URLType, []*cel.Type{}, cel.StringType, + func(_ context.Context, self ref.Val, args ...ref.Val) ref.Val { + v := lib.refToGoURLValue(self) + return types.String(v.RawPath) + }, + ), + ), + BindMemberFunction( + "omitHost", + MemberOverloadFunc(createURLID("omitHost_url_bool"), URLType, []*cel.Type{}, cel.BoolType, + func(_ context.Context, self ref.Val, args ...ref.Val) ref.Val { + v := lib.refToGoURLValue(self) + return types.Bool(v.OmitHost) + }, + ), + ), + BindMemberFunction( + "forceQuery", + MemberOverloadFunc(createURLID("forceQuery_url_bool"), URLType, []*cel.Type{}, cel.BoolType, + func(_ context.Context, self ref.Val, args ...ref.Val) ref.Val { + v := lib.refToGoURLValue(self) + return types.Bool(v.ForceQuery) + }, + ), + ), + BindMemberFunction( + "rawQuery", + MemberOverloadFunc(createURLID("rawQuery_url_string"), URLType, []*cel.Type{}, cel.StringType, + func(_ context.Context, self ref.Val, args ...ref.Val) ref.Val { + v := lib.refToGoURLValue(self) + return types.String(v.RawQuery) + }, + ), + ), + BindMemberFunction( + "fragment", + MemberOverloadFunc(createURLID("fragment_url_string"), URLType, []*cel.Type{}, cel.StringType, + func(_ context.Context, self ref.Val, args ...ref.Val) ref.Val { + v := lib.refToGoURLValue(self) + return types.String(v.Fragment) + }, + ), + ), + BindMemberFunction( + "rawFragment", + MemberOverloadFunc(createURLID("rawFragment_url_string"), URLType, []*cel.Type{}, cel.StringType, + func(_ context.Context, self ref.Val, args ...ref.Val) ref.Val { + v := lib.refToGoURLValue(self) + return types.String(v.RawFragment) + }, + ), + ), + BindMemberFunction( + "escapedFragment", + MemberOverloadFunc(createURLID("escapedFragment_url_string"), URLType, []*cel.Type{}, cel.StringType, + func(_ context.Context, self ref.Val, args ...ref.Val) ref.Val { + v := lib.refToGoURLValue(self) + return types.String(v.EscapedFragment()) + }, + ), + ), + BindMemberFunction( + "escapedPath", + MemberOverloadFunc(createURLID("escapedPath_url_string"), URLType, []*cel.Type{}, cel.StringType, + func(_ context.Context, self ref.Val, args ...ref.Val) ref.Val { + v := lib.refToGoURLValue(self) + return types.String(v.EscapedPath()) + }, + ), + ), + BindMemberFunction( + "hostname", + MemberOverloadFunc(createURLID("hostname_url_string"), URLType, []*cel.Type{}, cel.StringType, + func(_ context.Context, self ref.Val, args ...ref.Val) ref.Val { + v := lib.refToGoURLValue(self) + return types.String(v.Hostname()) + }, + ), + ), + BindMemberFunction( + "isAbs", + MemberOverloadFunc(createURLID("isAbs_url_bool"), URLType, []*cel.Type{}, cel.BoolType, + func(_ context.Context, self ref.Val, args ...ref.Val) ref.Val { + v := lib.refToGoURLValue(self) + return types.Bool(v.IsAbs()) + }, + ), + ), + BindMemberFunction( + "joinPath", + MemberOverloadFunc(createURLID("joinPath_url_strings_url"), URLType, []*cel.Type{cel.ListType(cel.StringType)}, URLType, + func(_ context.Context, self ref.Val, args ...ref.Val) ref.Val { + v := lib.refToGoURLValue(self) + + elems := args[0].(traits.Lister) + var paths []string + for i := types.Int(0); i < elems.Size().(types.Int); i++ { + pathElem := elems.Get(i) + paths = append(paths, string(pathElem.(types.String))) + } + + var err error + v.Path, err = url.JoinPath(v.Path, paths...) + if err != nil { + return types.NewErr(err.Error()) + } + + return lib.toURLValue(v) + }, + ), + ), + BindMemberFunction( + "marshalBinary", + MemberOverloadFunc(createURLID("MarshalBinary_url_bytes"), URLType, []*cel.Type{}, cel.BytesType, + func(_ context.Context, self ref.Val, args ...ref.Val) ref.Val { + v := lib.refToGoURLValue(self) + + b, err := v.MarshalBinary() + if err != nil { + return types.NewErr(err.Error()) + } + + return types.Bytes(b) + }, + ), + ), + BindMemberFunction( + "parse", + MemberOverloadFunc(createURLID("parse_url_string_url"), URLType, []*cel.Type{cel.StringType}, URLType, + func(_ context.Context, self ref.Val, args ...ref.Val) ref.Val { + v := lib.refToGoURLValue(self) + + u, err := v.Parse(string(args[0].(types.String))) + if err != nil { + return types.NewErr(err.Error()) + } + + return lib.toURLValue(*u) + }, + ), + ), + BindMemberFunction( + "port", + MemberOverloadFunc(createURLID("port_url_string"), URLType, []*cel.Type{}, cel.StringType, + func(_ context.Context, self ref.Val, args ...ref.Val) ref.Val { + v := lib.refToGoURLValue(self) + return types.String(v.Port()) + }, + ), + ), + // func (u *URL) Query() Values : returns map[string][]string + BindMemberFunction( + "query", + MemberOverloadFunc(createURLID("query_url_map"), URLType, []*cel.Type{}, cel.MapType(cel.StringType, cel.ListType(cel.StringType)), + func(ctx context.Context, self ref.Val, args ...ref.Val) ref.Val { + v := lib.refToGoURLValue(self) + + adapter := types.DefaultTypeAdapter + queryParams := v.Query() + queryMap := map[ref.Val]ref.Val{} + for key, values := range queryParams { + queryMap[types.String(key)] = types.NewStringList(adapter, values) + } + + return types.NewRefValMap(adapter, queryMap) + }, + ), + ), + BindMemberFunction( + "redacted", + MemberOverloadFunc(createURLID("redacted_url_string"), URLType, []*cel.Type{}, cel.StringType, + func(_ context.Context, self ref.Val, args ...ref.Val) ref.Val { + v := lib.refToGoURLValue(self) + return types.String(v.Redacted()) + }, + ), + ), + BindMemberFunction( + "requestURI", + MemberOverloadFunc(createURLID("requestURI_url_string"), URLType, []*cel.Type{}, cel.StringType, + func(_ context.Context, self ref.Val, args ...ref.Val) ref.Val { + v := lib.refToGoURLValue(self) + return types.String(v.RequestURI()) + }, + ), + ), + BindMemberFunction( + "resolveReference", + MemberOverloadFunc(createURLID("resolveReference_url_url_url"), URLType, []*cel.Type{URLType}, URLType, + func(_ context.Context, self ref.Val, args ...ref.Val) ref.Val { + v := lib.refToGoURLValue(self) + + r := args[0].Value().(*URL).GoURL() + u := v.ResolveReference(&r) + + return lib.toURLValue(*u) + }, + ), + ), + BindMemberFunction( + "string", + MemberOverloadFunc(createURLID("string_url_string"), URLType, []*cel.Type{}, cel.StringType, + func(_ context.Context, self ref.Val, args ...ref.Val) ref.Val { + v := lib.refToGoURLValue(self) + return types.String(v.String()) + }, + ), + ), + BindMemberFunction( + "unmarshalBinary", + MemberOverloadFunc(createURLID("unmarshalBinary_url_bytes_url"), URLType, []*cel.Type{cel.BytesType}, URLType, + func(_ context.Context, self ref.Val, args ...ref.Val) ref.Val { + var u url.URL + err := u.UnmarshalBinary(args[0].(types.Bytes)) + if err != nil { + return types.NewErr(err.Error()) + } + return lib.toURLValue(u) + }, + ), + ), + + // Userinfo functions + BindFunction( + createURLName("user"), + OverloadFunc(createURLID("user_string_userinfo"), []*cel.Type{cel.StringType}, UserinfoType, + func(_ context.Context, args ...ref.Val) ref.Val { + return lib.toUserinfoValue(string(args[0].(types.String)), "", false) + }, + ), + ), + BindFunction( + createURLName("userPassword"), + OverloadFunc(createURLID("userPassword_string_string_userinfo"), []*cel.Type{cel.StringType, cel.StringType}, UserinfoType, + func(_ context.Context, args ...ref.Val) ref.Val { + return lib.toUserinfoValue(string(args[0].(types.String)), string(args[1].(types.String)), true) + }, + ), + ), + BindMemberFunction( + "username", + MemberOverloadFunc(createURLID("username_userinfo_string"), UserinfoType, []*cel.Type{}, cel.StringType, + func(_ context.Context, self ref.Val, args ...ref.Val) ref.Val { + v := lib.refToGoUserinfoValue(self) + return types.String(v.Username()) + }, + ), + ), + BindMemberFunction( + "password", + MemberOverloadFunc(createURLID("password_userinfo_string"), UserinfoType, []*cel.Type{}, cel.StringType, + func(_ context.Context, self ref.Val, args ...ref.Val) ref.Val { + v := lib.refToGoUserinfoValue(self) + password, _ := v.Password() + return types.String(password) + }, + ), + ), + BindMemberFunction( + "passwordSet", + MemberOverloadFunc(createURLID("passwordSet_userinfo_bool"), UserinfoType, []*cel.Type{}, cel.BoolType, + func(_ context.Context, self ref.Val, args ...ref.Val) ref.Val { + v := lib.refToGoUserinfoValue(self) + _, hasPassword := v.Password() + return types.Bool(hasPassword) + }, + ), + ), + BindMemberFunction( + "string", + MemberOverloadFunc(createURLID("string_userinfo_string"), UserinfoType, []*cel.Type{}, cel.StringType, + func(_ context.Context, self ref.Val, args ...ref.Val) ref.Val { + v := lib.refToGoUserinfoValue(self) + return types.String(v.String()) + }, + ), + ), + } { + opts = append(opts, funcOpts...) + } + + return opts +} + +func (lib *URLLibrary) ProgramOptions() []cel.ProgramOption { + return []cel.ProgramOption{} +} diff --git a/grpc/federation/cel/url.pb.go b/grpc/federation/cel/url.pb.go new file mode 100644 index 00000000..4b9a1c17 --- /dev/null +++ b/grpc/federation/cel/url.pb.go @@ -0,0 +1,330 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.33.0 +// protoc (unknown) +// source: grpc/federation/url.proto + +package cel + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +// URL represents the structure of the URL in net/url package. +type URL struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Scheme string `protobuf:"bytes,1,opt,name=scheme,proto3" json:"scheme,omitempty"` + Opaque string `protobuf:"bytes,2,opt,name=opaque,proto3" json:"opaque,omitempty"` + User *Userinfo `protobuf:"bytes,3,opt,name=user,proto3" json:"user,omitempty"` + Host string `protobuf:"bytes,4,opt,name=host,proto3" json:"host,omitempty"` + Path string `protobuf:"bytes,5,opt,name=path,proto3" json:"path,omitempty"` + RawPath string `protobuf:"bytes,6,opt,name=raw_path,json=rawPath,proto3" json:"raw_path,omitempty"` + OmitHost bool `protobuf:"varint,7,opt,name=omit_host,json=omitHost,proto3" json:"omit_host,omitempty"` + ForceQuery bool `protobuf:"varint,8,opt,name=force_query,json=forceQuery,proto3" json:"force_query,omitempty"` + RawQuery string `protobuf:"bytes,9,opt,name=raw_query,json=rawQuery,proto3" json:"raw_query,omitempty"` + Fragment string `protobuf:"bytes,10,opt,name=fragment,proto3" json:"fragment,omitempty"` + RawFragment string `protobuf:"bytes,11,opt,name=raw_fragment,json=rawFragment,proto3" json:"raw_fragment,omitempty"` +} + +func (x *URL) Reset() { + *x = URL{} + if protoimpl.UnsafeEnabled { + mi := &file_grpc_federation_url_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *URL) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*URL) ProtoMessage() {} + +func (x *URL) ProtoReflect() protoreflect.Message { + mi := &file_grpc_federation_url_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 URL.ProtoReflect.Descriptor instead. +func (*URL) Descriptor() ([]byte, []int) { + return file_grpc_federation_url_proto_rawDescGZIP(), []int{0} +} + +func (x *URL) GetScheme() string { + if x != nil { + return x.Scheme + } + return "" +} + +func (x *URL) GetOpaque() string { + if x != nil { + return x.Opaque + } + return "" +} + +func (x *URL) GetUser() *Userinfo { + if x != nil { + return x.User + } + return nil +} + +func (x *URL) GetHost() string { + if x != nil { + return x.Host + } + return "" +} + +func (x *URL) GetPath() string { + if x != nil { + return x.Path + } + return "" +} + +func (x *URL) GetRawPath() string { + if x != nil { + return x.RawPath + } + return "" +} + +func (x *URL) GetOmitHost() bool { + if x != nil { + return x.OmitHost + } + return false +} + +func (x *URL) GetForceQuery() bool { + if x != nil { + return x.ForceQuery + } + return false +} + +func (x *URL) GetRawQuery() string { + if x != nil { + return x.RawQuery + } + return "" +} + +func (x *URL) GetFragment() string { + if x != nil { + return x.Fragment + } + return "" +} + +func (x *URL) GetRawFragment() string { + if x != nil { + return x.RawFragment + } + return "" +} + +// Userinfo represents username and password information. +type Userinfo struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Username string `protobuf:"bytes,1,opt,name=username,proto3" json:"username,omitempty"` + Password string `protobuf:"bytes,2,opt,name=password,proto3" json:"password,omitempty"` + PasswordSet bool `protobuf:"varint,3,opt,name=password_set,json=passwordSet,proto3" json:"password_set,omitempty"` +} + +func (x *Userinfo) Reset() { + *x = Userinfo{} + if protoimpl.UnsafeEnabled { + mi := &file_grpc_federation_url_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Userinfo) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Userinfo) ProtoMessage() {} + +func (x *Userinfo) ProtoReflect() protoreflect.Message { + mi := &file_grpc_federation_url_proto_msgTypes[1] + 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 Userinfo.ProtoReflect.Descriptor instead. +func (*Userinfo) Descriptor() ([]byte, []int) { + return file_grpc_federation_url_proto_rawDescGZIP(), []int{1} +} + +func (x *Userinfo) GetUsername() string { + if x != nil { + return x.Username + } + return "" +} + +func (x *Userinfo) GetPassword() string { + if x != nil { + return x.Password + } + return "" +} + +func (x *Userinfo) GetPasswordSet() bool { + if x != nil { + return x.PasswordSet + } + return false +} + +var File_grpc_federation_url_proto protoreflect.FileDescriptor + +var file_grpc_federation_url_proto_rawDesc = []byte{ + 0x0a, 0x19, 0x67, 0x72, 0x70, 0x63, 0x2f, 0x66, 0x65, 0x64, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x2f, 0x75, 0x72, 0x6c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x13, 0x67, 0x72, 0x70, + 0x63, 0x2e, 0x66, 0x65, 0x64, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x75, 0x72, 0x6c, + 0x22, 0xc5, 0x02, 0x0a, 0x03, 0x55, 0x52, 0x4c, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x63, 0x68, 0x65, + 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x65, + 0x12, 0x16, 0x0a, 0x06, 0x6f, 0x70, 0x61, 0x71, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x06, 0x6f, 0x70, 0x61, 0x71, 0x75, 0x65, 0x12, 0x31, 0x0a, 0x04, 0x75, 0x73, 0x65, 0x72, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x66, 0x65, + 0x64, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x75, 0x72, 0x6c, 0x2e, 0x55, 0x73, 0x65, + 0x72, 0x69, 0x6e, 0x66, 0x6f, 0x52, 0x04, 0x75, 0x73, 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x68, + 0x6f, 0x73, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x68, 0x6f, 0x73, 0x74, 0x12, + 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, + 0x61, 0x74, 0x68, 0x12, 0x19, 0x0a, 0x08, 0x72, 0x61, 0x77, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, + 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x72, 0x61, 0x77, 0x50, 0x61, 0x74, 0x68, 0x12, 0x1b, + 0x0a, 0x09, 0x6f, 0x6d, 0x69, 0x74, 0x5f, 0x68, 0x6f, 0x73, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, + 0x08, 0x52, 0x08, 0x6f, 0x6d, 0x69, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x66, + 0x6f, 0x72, 0x63, 0x65, 0x5f, 0x71, 0x75, 0x65, 0x72, 0x79, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, + 0x52, 0x0a, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x51, 0x75, 0x65, 0x72, 0x79, 0x12, 0x1b, 0x0a, 0x09, + 0x72, 0x61, 0x77, 0x5f, 0x71, 0x75, 0x65, 0x72, 0x79, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x08, 0x72, 0x61, 0x77, 0x51, 0x75, 0x65, 0x72, 0x79, 0x12, 0x1a, 0x0a, 0x08, 0x66, 0x72, 0x61, + 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x66, 0x72, 0x61, + 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x21, 0x0a, 0x0c, 0x72, 0x61, 0x77, 0x5f, 0x66, 0x72, 0x61, + 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x72, 0x61, 0x77, + 0x46, 0x72, 0x61, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x22, 0x65, 0x0a, 0x08, 0x55, 0x73, 0x65, 0x72, + 0x69, 0x6e, 0x66, 0x6f, 0x12, 0x1a, 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, + 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x12, 0x21, 0x0a, 0x0c, + 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x5f, 0x73, 0x65, 0x74, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x08, 0x52, 0x0b, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x53, 0x65, 0x74, 0x42, + 0x3c, 0x5a, 0x3a, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6d, 0x65, + 0x72, 0x63, 0x61, 0x72, 0x69, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x2d, 0x66, 0x65, 0x64, 0x65, 0x72, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x2f, 0x66, 0x65, 0x64, 0x65, 0x72, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x63, 0x65, 0x6c, 0x3b, 0x63, 0x65, 0x6c, 0x62, 0x06, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_grpc_federation_url_proto_rawDescOnce sync.Once + file_grpc_federation_url_proto_rawDescData = file_grpc_federation_url_proto_rawDesc +) + +func file_grpc_federation_url_proto_rawDescGZIP() []byte { + file_grpc_federation_url_proto_rawDescOnce.Do(func() { + file_grpc_federation_url_proto_rawDescData = protoimpl.X.CompressGZIP(file_grpc_federation_url_proto_rawDescData) + }) + return file_grpc_federation_url_proto_rawDescData +} + +var file_grpc_federation_url_proto_msgTypes = make([]protoimpl.MessageInfo, 2) +var file_grpc_federation_url_proto_goTypes = []interface{}{ + (*URL)(nil), // 0: grpc.federation.url.URL + (*Userinfo)(nil), // 1: grpc.federation.url.Userinfo +} +var file_grpc_federation_url_proto_depIdxs = []int32{ + 1, // 0: grpc.federation.url.URL.user:type_name -> grpc.federation.url.Userinfo + 1, // [1:1] is the sub-list for method output_type + 1, // [1:1] is the sub-list for method input_type + 1, // [1:1] is the sub-list for extension type_name + 1, // [1:1] is the sub-list for extension extendee + 0, // [0:1] is the sub-list for field type_name +} + +func init() { file_grpc_federation_url_proto_init() } +func file_grpc_federation_url_proto_init() { + if File_grpc_federation_url_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_grpc_federation_url_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*URL); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_grpc_federation_url_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Userinfo); 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_grpc_federation_url_proto_rawDesc, + NumEnums: 0, + NumMessages: 2, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_grpc_federation_url_proto_goTypes, + DependencyIndexes: file_grpc_federation_url_proto_depIdxs, + MessageInfos: file_grpc_federation_url_proto_msgTypes, + }.Build() + File_grpc_federation_url_proto = out.File + file_grpc_federation_url_proto_rawDesc = nil + file_grpc_federation_url_proto_goTypes = nil + file_grpc_federation_url_proto_depIdxs = nil +} diff --git a/grpc/federation/cel/url_test.go b/grpc/federation/cel/url_test.go new file mode 100644 index 00000000..a4554140 --- /dev/null +++ b/grpc/federation/cel/url_test.go @@ -0,0 +1,804 @@ +package cel_test + +import ( + "context" + "fmt" + "net/url" + "strings" + "testing" + + "github.com/google/cel-go/cel" + "github.com/google/cel-go/common/types" + "github.com/google/cel-go/common/types/ref" + "github.com/google/cel-go/common/types/traits" + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + + cellib "github.com/mercari/grpc-federation/grpc/federation/cel" +) + +func TestURLFunctions(t *testing.T) { + tests := []struct { + name string + expr string + args map[string]any + cmp func(ref.Val) error + }{ + { + name: "join path", + expr: `grpc.federation.url.joinPath('https://example.com/path?query=1#fragment', ['/new'])`, + cmp: func(got ref.Val) error { + gotV, ok := got.(types.String) + if !ok { + return fmt.Errorf("invalid result type: %T", got) + } + expected, err := url.JoinPath("https://example.com/path?query=1#fragment", "/new") + if err != nil { + return err + } + if diff := cmp.Diff(string(gotV), expected); diff != "" { + return fmt.Errorf("(-got, +want)\n%s", diff) + } + return nil + }, + }, + { + name: "path escape", + expr: `grpc.federation.url.pathEscape('あ /')`, + cmp: func(got ref.Val) error { + gotV, ok := got.(types.String) + if !ok { + return fmt.Errorf("invalid result type: %T", got) + } + expected := url.PathEscape("あ /") + if diff := cmp.Diff(string(gotV), expected); diff != "" { + return fmt.Errorf("(-got, +want)\n%s", diff) + } + return nil + }, + }, + { + name: "path unescape", + expr: `grpc.federation.url.pathUnescape('%E3%81%82%20%2F')`, + cmp: func(got ref.Val) error { + gotV, ok := got.(types.String) + if !ok { + return fmt.Errorf("invalid result type: %T", got) + } + expected, err := url.PathUnescape("%E3%81%82%20%2F") + if err != nil { + return err + } + if diff := cmp.Diff(string(gotV), expected); diff != "" { + return fmt.Errorf("(-got, +want)\n%s", diff) + } + return nil + }, + }, + { + name: "query escape", + expr: `grpc.federation.url.queryEscape('あ /')`, + cmp: func(got ref.Val) error { + gotV, ok := got.(types.String) + if !ok { + return fmt.Errorf("invalid result type: %T", got) + } + expected := url.QueryEscape("あ /") + if diff := cmp.Diff(string(gotV), expected); diff != "" { + return fmt.Errorf("(-got, +want)\n%s", diff) + } + return nil + }, + }, + { + name: "query unescape", + expr: `grpc.federation.url.queryUnescape('%E3%81%82%20%2F')`, + cmp: func(got ref.Val) error { + gotV, ok := got.(types.String) + if !ok { + return fmt.Errorf("invalid result type: %T", got) + } + expected, err := url.QueryUnescape("%E3%81%82%20%2F") + if err != nil { + return err + } + if diff := cmp.Diff(string(gotV), expected); diff != "" { + return fmt.Errorf("(-got, +want)\n%s", diff) + } + return nil + }, + }, + + // url functions + { + name: "parse", + expr: "grpc.federation.url.parse('https://example.com/path?query=1#fragment')", + cmp: func(got ref.Val) error { + gotV, ok := got.Value().(*cellib.URL) + if !ok { + return fmt.Errorf("invalid result type: %T", got) + } + gotURL := gotV.GoURL() + expected, err := url.Parse("https://example.com/path?query=1#fragment") + if err != nil { + return err + } + if diff := cmp.Diff(gotURL, *expected, cmpopts.IgnoreUnexported(url.URL{})); diff != "" { + return fmt.Errorf("(-got, +want)\n%s", diff) + } + return nil + }, + }, + { + name: "parse request uri", + expr: `grpc.federation.url.parseRequestURI('https://example.com/path?query=1#fragment')`, + cmp: func(got ref.Val) error { + gotV, ok := got.Value().(*cellib.URL) + if !ok { + return fmt.Errorf("invalid result type: %T", got) + } + gotURL := gotV.GoURL() + expected, err := url.ParseRequestURI("https://example.com/path?query=1#fragment") + if err != nil { + return err + } + if diff := cmp.Diff(gotURL, *expected, cmpopts.IgnoreUnexported(url.URL{})); diff != "" { + return fmt.Errorf("(-got, +want)\n%s", diff) + } + return nil + }, + }, + { + name: "parse scheme", + expr: `grpc.federation.url.parse('https://example.com/path?query=1#fragment').scheme()`, + cmp: func(got ref.Val) error { + gotV, ok := got.(types.String) + if !ok { + return fmt.Errorf("invalid result type: %T", got) + } + parse, err := url.Parse("https://example.com/path?query=1#fragment") + if err != nil { + return err + } + expected := parse.Scheme + if diff := cmp.Diff(string(gotV), expected); diff != "" { + return fmt.Errorf("(-got, +want)\n%s", diff) + } + return nil + }, + }, + { + name: "parse opaque", + expr: `grpc.federation.url.parse('https://example.com/path?query=1#fragment').opaque()`, + cmp: func(got ref.Val) error { + gotV, ok := got.(types.String) + if !ok { + return fmt.Errorf("invalid result type: %T", got) + } + parse, err := url.Parse("https://example.com/path?query=1#fragment") + if err != nil { + return err + } + expected := parse.Opaque + if diff := cmp.Diff(string(gotV), expected); diff != "" { + return fmt.Errorf("(-got, +want)\n%s", diff) + } + return nil + }, + }, + { + name: "parse user", + expr: `grpc.federation.url.parse('https://example.com/path?query=1#fragment').userinfo()`, + cmp: func(got ref.Val) error { + gotV, ok := got.Value().(*cellib.Userinfo) + if !ok { + return fmt.Errorf("invalid result type: %T", got) + } + gotUser := gotV.GoUserinfo() + parse, err := url.Parse("https://example.com/path?query=1#fragment") + if err != nil { + return err + } + expected := parse.User + if diff := userinfoDiff(gotUser, expected); diff != "" { + return fmt.Errorf("(-got, +want)\n%s", diff) + } + return nil + }, + }, + { + name: "parse host", + expr: `grpc.federation.url.parse('https://example.com/path?query=1#fragment').host()`, + cmp: func(got ref.Val) error { + gotV, ok := got.(types.String) + if !ok { + return fmt.Errorf("invalid result type: %T", got) + } + parse, err := url.Parse("https://example.com/path?query=1#fragment") + if err != nil { + return err + } + expected := parse.Host + if diff := cmp.Diff(string(gotV), expected); diff != "" { + return fmt.Errorf("(-got, +want)\n%s", diff) + } + return nil + }, + }, + { + name: "parse path", + expr: `grpc.federation.url.parse('https://example.com/path?query=1#fragment').path()`, + cmp: func(got ref.Val) error { + gotV, ok := got.(types.String) + if !ok { + return fmt.Errorf("invalid result type: %T", got) + } + parse, err := url.Parse("https://example.com/path?query=1#fragment") + if err != nil { + return err + } + expected := parse.Path + if diff := cmp.Diff(string(gotV), expected); diff != "" { + return fmt.Errorf("(-got, +want)\n%s", diff) + } + return nil + }, + }, + { + name: "parse raw path", + expr: `grpc.federation.url.parse('https://example.com/%E3%81%82%20%2Fpath?query=1#fragment').rawPath()`, + cmp: func(got ref.Val) error { + gotV, ok := got.(types.String) + if !ok { + return fmt.Errorf("invalid result type: %T", got) + } + parse, err := url.Parse("https://example.com/%E3%81%82%20%2Fpath?query=1#fragment") + if err != nil { + return err + } + expected := parse.RawPath + if diff := cmp.Diff(string(gotV), expected); diff != "" { + return fmt.Errorf("(-got, +want)\n%s", diff) + } + return nil + }, + }, + { + name: "parse force query", + expr: `grpc.federation.url.parse('https://example.com/path?').forceQuery()`, + cmp: func(got ref.Val) error { + gotV := got.(types.Bool) + parse, err := url.Parse("https://example.com/path?") + if err != nil { + return err + } + expected := parse.ForceQuery + if diff := cmp.Diff(bool(gotV), expected); diff != "" { + return fmt.Errorf("(-got, +want)\n%s", diff) + } + return nil + }, + }, + { + name: "parse raw query", + expr: `grpc.federation.url.parse('https://example.com/path?query=1#fragment').rawQuery()`, + cmp: func(got ref.Val) error { + gotV, ok := got.(types.String) + if !ok { + return fmt.Errorf("invalid result type: %T", got) + } + parse, err := url.Parse("https://example.com/path?query=1#fragment") + if err != nil { + return err + } + expected := parse.RawQuery + if diff := cmp.Diff(string(gotV), expected); diff != "" { + return fmt.Errorf("(-got, +want)\n%s", diff) + } + return nil + }, + }, + { + name: "parse fragment", + expr: `grpc.federation.url.parse('https://example.com/path?query=1#fragment').fragment()`, + cmp: func(got ref.Val) error { + gotV, ok := got.(types.String) + if !ok { + return fmt.Errorf("invalid result type: %T", got) + } + parse, err := url.Parse("https://example.com/path?query=1#fragment") + if err != nil { + return err + } + expected := parse.Fragment + if diff := cmp.Diff(string(gotV), expected); diff != "" { + return fmt.Errorf("(-got, +want)\n%s", diff) + } + return nil + }, + }, + { + name: "parse raw fragment", + expr: `grpc.federation.url.parse('https://example.com/path?query=1#frag%20ment').rawFragment()`, + cmp: func(got ref.Val) error { + gotV, ok := got.(types.String) + if !ok { + return fmt.Errorf("invalid result type: %T", got) + } + parse, err := url.Parse("https://example.com/path?query=1#frag%20ment") + if err != nil { + return err + } + expected := parse.RawFragment + if diff := cmp.Diff(string(gotV), expected); diff != "" { + return fmt.Errorf("(-got, +want)\n%s", diff) + } + return nil + }, + }, + { + name: "parse escaped fragment", + expr: `grpc.federation.url.parse('https://example.com/path?query=1#fragment').escapedFragment()`, + cmp: func(got ref.Val) error { + gotV, ok := got.(types.String) + if !ok { + return fmt.Errorf("invalid result type: %T", got) + } + parse, err := url.Parse("https://example.com/path?query=1#fragment") + if err != nil { + return err + } + expected := parse.EscapedFragment() + if diff := cmp.Diff(string(gotV), expected); diff != "" { + return fmt.Errorf("(-got, +want)\n%s", diff) + } + return nil + }, + }, + { + name: "parse escaped path", + expr: `grpc.federation.url.parse('https://example.com/pa th?query=1#fragment').escapedPath()`, + cmp: func(got ref.Val) error { + gotV, ok := got.(types.String) + if !ok { + return fmt.Errorf("invalid result type: %T", got) + } + parse, err := url.Parse("https://example.com/pa th?query=1#fragment") + if err != nil { + return err + } + expected := parse.EscapedPath() + if diff := cmp.Diff(string(gotV), expected); diff != "" { + return fmt.Errorf("(-got, +want)\n%s", diff) + } + return nil + }, + }, + { + name: "parse hostname", + expr: `grpc.federation.url.parse('https://example.com/path?query=1#fragment').hostname()`, + cmp: func(got ref.Val) error { + gotV, ok := got.(types.String) + if !ok { + return fmt.Errorf("invalid result type: %T", got) + } + parse, err := url.Parse("https://example.com/path?query=1#fragment") + if err != nil { + return err + } + expected := parse.Hostname() + if diff := cmp.Diff(string(gotV), expected); diff != "" { + return fmt.Errorf("(-got, +want)\n%s", diff) + } + return nil + }, + }, + { + name: "is abs", + expr: `grpc.federation.url.parse('https://example.com/path?query=1#fragment').isAbs()`, + cmp: func(got ref.Val) error { + gotV, ok := got.(types.Bool) + if !ok { + return fmt.Errorf("invalid result type: %T", got) + } + parse, err := url.Parse("https://example.com/path?query=1#fragment") + if err != nil { + return err + } + expected := parse.IsAbs() + if diff := cmp.Diff(bool(gotV), expected); diff != "" { + return fmt.Errorf("(-got, +want)\n%s", diff) + } + return nil + }, + }, + { + name: "url join path", + expr: `grpc.federation.url.parse('https://example.com/path?query=1#fragment').joinPath(['/new'])`, + cmp: func(got ref.Val) error { + gotV, ok := got.Value().(*cellib.URL) + if !ok { + return fmt.Errorf("invalid result type: %T", got) + } + gotURL := gotV.GoURL() + parse, err := url.Parse("https://example.com/path?query=1#fragment") + if err != nil { + return err + } + expected := parse.JoinPath("/new") + if diff := cmp.Diff(gotURL, *expected, cmpopts.IgnoreUnexported(url.URL{})); diff != "" { + return fmt.Errorf("(-got, +want)\n%s", diff) + } + return nil + }, + }, + { + name: "marshal binary", + expr: `grpc.federation.url.parse('https://example.com/path?query=1#fragment').marshalBinary()`, + cmp: func(got ref.Val) error { + gotV, ok := got.(types.Bytes) + if !ok { + return fmt.Errorf("invalid result type: %T", got) + } + parse, err := url.Parse("https://example.com/path?query=1#fragment") + if err != nil { + return err + } + expected, err := parse.MarshalBinary() + if err != nil { + return err + } + if diff := cmp.Diff(gotV.Value(), expected); diff != "" { + return fmt.Errorf("(-got, +want)\n%s", diff) + } + return nil + }, + }, + { + name: "url parse", + expr: `grpc.federation.url.parse('https://example.com/path?query=1#fragment').parse('/relativePath')`, + cmp: func(got ref.Val) error { + gotV, ok := got.Value().(*cellib.URL) + if !ok { + return fmt.Errorf("invalid result type: %T", got) + } + gotURL := gotV.GoURL() + parse, err := url.Parse("https://example.com/path?query=1#fragment") + if err != nil { + return err + } + expected, err := parse.Parse("/relativePath") + if err != nil { + return err + } + if diff := cmp.Diff(gotURL, *expected, cmpopts.IgnoreUnexported(url.URL{})); diff != "" { + return fmt.Errorf("(-got, +want)\n%s", diff) + } + return nil + }, + }, + { + name: "port", + expr: `grpc.federation.url.parse('https://example.com/path?query=1#fragment').port()`, + cmp: func(got ref.Val) error { + gotV, ok := got.(types.String) + if !ok { + return fmt.Errorf("invalid result type: %T", got) + } + parse, err := url.Parse("https://example.com/path?query=1#fragment") + if err != nil { + return err + } + expected := parse.Port() + if diff := cmp.Diff(string(gotV), expected); diff != "" { + return fmt.Errorf("(-got, +want)\n%s", diff) + } + return nil + }, + }, + { + name: "query", + expr: `grpc.federation.url.parse('https://example.com/path?query=1#fragment').query()`, + cmp: func(got ref.Val) error { + gotV, ok := got.(traits.Mapper) + if !ok { + return fmt.Errorf("invalid result type: %T", got) + } + gotQueryMap := make(map[string][]string) + it := gotV.Iterator() + for it.HasNext() == types.True { + key := it.Next() + keyStr := string(key.(types.String)) + valueList := gotV.Get(key).(traits.Lister) + + var values []string + for i := int64(0); i < int64(valueList.Size().(types.Int)); i++ { + values = append(values, string(valueList.Get(types.Int(i)).(types.String))) + } + gotQueryMap[keyStr] = values + } + + parse, err := url.Parse("https://example.com/path?query=1#fragment") + if err != nil { + return err + } + expected := map[string][]string(parse.Query()) + + if diff := cmp.Diff(gotQueryMap, expected); diff != "" { + return fmt.Errorf("(-got, +want)\n%s", diff) + } + return nil + }, + }, + { + name: "redacted", + expr: `grpc.federation.url.parse('https://example.com/path?query=1#fragment').redacted()`, + cmp: func(got ref.Val) error { + gotV, ok := got.(types.String) + if !ok { + return fmt.Errorf("invalid result type: %T", got) + } + parse, err := url.Parse("https://example.com/path?query=1#fragment") + if err != nil { + return err + } + expected := parse.Redacted() + if diff := cmp.Diff(string(gotV), expected); diff != "" { + return fmt.Errorf("(-got, +want)\n%s", diff) + } + return nil + }, + }, + { + name: "request uri", + expr: `grpc.federation.url.parse('https://example.com/path?query=1#fragment').requestURI()`, + cmp: func(got ref.Val) error { + gotV, ok := got.(types.String) + if !ok { + return fmt.Errorf("invalid result type: %T", got) + } + parse, err := url.Parse("https://example.com/path?query=1#fragment") + if err != nil { + return err + } + expected := parse.RequestURI() + if diff := cmp.Diff(string(gotV), expected); diff != "" { + return fmt.Errorf("(-got, +want)\n%s", diff) + } + return nil + }, + }, + { + name: "resolve reference", + expr: `grpc.federation.url.parse('https://example.com/path?query=1#fragment').resolveReference(grpc.federation.url.parse('/relativePath'))`, + cmp: func(got ref.Val) error { + gotV, ok := got.Value().(*cellib.URL) + if !ok { + return fmt.Errorf("invalid result type: %T", got) + } + gotURL := gotV.GoURL() + parse, err := url.Parse("https://example.com/path?query=1#fragment") + if err != nil { + return err + } + ref, err := url.Parse("/relativePath") + if err != nil { + return err + } + expected := parse.ResolveReference(ref) + if diff := cmp.Diff(gotURL, *expected, cmpopts.IgnoreUnexported(url.URL{})); diff != "" { + return fmt.Errorf("(-got, +want)\n%s", diff) + } + return nil + }, + }, + { + name: "string", + expr: `grpc.federation.url.parse('https://example.com/path?query=1#fragment').string()`, + cmp: func(got ref.Val) error { + gotV, ok := got.(types.String) + if !ok { + return fmt.Errorf("invalid result type: %T", got) + } + parse, err := url.Parse("https://example.com/path?query=1#fragment") + if err != nil { + return err + } + expected := parse.String() + if diff := cmp.Diff(string(gotV), expected); diff != "" { + return fmt.Errorf("(-got, +want)\n%s", diff) + } + return nil + }, + }, + { + name: "unmarshal binary", + expr: `grpc.federation.url.parse('https://example.com/path?query=1#fragment').unmarshalBinary(grpc.federation.url.parse('https://example.com/path?query=1#fragment').marshalBinary())`, + cmp: func(got ref.Val) error { + gotV, ok := got.Value().(*cellib.URL) + if !ok { + return fmt.Errorf("invalid result type: %T", got) + } + gotURL := gotV.GoURL() + parse, err := url.Parse("https://example.com/path?query=1#fragment") + if err != nil { + return err + } + expected := parse + if diff := cmp.Diff(gotURL, *expected, cmpopts.IgnoreUnexported(url.URL{})); diff != "" { + return fmt.Errorf("(-got, +want)\n%s", diff) + } + return nil + }, + }, + + // userinfo tests + { + name: "user", + expr: `grpc.federation.url.user('username')`, + cmp: func(got ref.Val) error { + gotV, ok := got.Value().(*cellib.Userinfo) + if !ok { + return fmt.Errorf("invalid result type: %T", got) + } + gotUser := gotV.GoUserinfo() + expected := url.User("username") + if diff := userinfoDiff(gotUser, expected); diff != "" { + return fmt.Errorf("(-got, +want)\n%s", diff) + } + return nil + }, + }, + { + name: "user password to user info", + expr: `grpc.federation.url.userPassword('username', 'password')`, + cmp: func(got ref.Val) error { + gotV, ok := got.Value().(*cellib.Userinfo) + if !ok { + return fmt.Errorf("invalid result type: %T", got) + } + gotUser := gotV.GoUserinfo() + expected := url.UserPassword("username", "password") + if diff := userinfoDiff(gotUser, expected); diff != "" { + return fmt.Errorf("(-got, +want)\n%s", diff) + } + return nil + }, + }, + { + name: "user username", + expr: `grpc.federation.url.parse('https://username:password@example.com/path?query=1#fragment').userinfo().username()`, + cmp: func(got ref.Val) error { + gotV, ok := got.(types.String) + if !ok { + return fmt.Errorf("invalid result type: %T", got) + } + user, err := url.Parse("https://username:password@example.com/path?query=1#fragment") + if err != nil { + return err + } + expected := user.User.Username() + if diff := cmp.Diff(string(gotV), expected); diff != "" { + return fmt.Errorf("(-got, +want)\n%s", diff) + } + return nil + }, + }, + { + name: "user password", + expr: `grpc.federation.url.parse('https://username:password@example.com/path?query=1#fragment').userinfo().password()`, + cmp: func(got ref.Val) error { + gotV, ok := got.(types.String) + if !ok { + return fmt.Errorf("invalid result type: %T", got) + } + user, err := url.Parse("https://username:password@example.com/path?query=1#fragment") + if err != nil { + return err + } + expected, _ := user.User.Password() + if diff := cmp.Diff(string(gotV), expected); diff != "" { + return fmt.Errorf("(-got, +want)\n%s", diff) + } + return nil + }, + }, + { + name: "user password set", + expr: `grpc.federation.url.parse('https://username:password@example.com/path?query=1#fragment').userinfo().passwordSet()`, + cmp: func(got ref.Val) error { + gotV, ok := got.(types.Bool) + if !ok { + return fmt.Errorf("invalid result type: %T", got) + } + user, err := url.Parse("https://username:password@example.com/path?query=1#fragment") + if err != nil { + return err + } + _, expected := user.User.Password() + if diff := cmp.Diff(bool(gotV), expected); diff != "" { + return fmt.Errorf("(-got, +want)\n%s", diff) + } + return nil + }, + }, + { + name: "user string", + expr: `grpc.federation.url.parse('https://username:password@example.com/path?query=1#fragment').userinfo().string()`, + cmp: func(got ref.Val) error { + gotV, ok := got.(types.String) + if !ok { + return fmt.Errorf("invalid result type: %T", got) + } + user, err := url.Parse("https://username:password@example.com/path?query=1#fragment") + if err != nil { + return err + } + expected := user.User.String() + if diff := cmp.Diff(string(gotV), expected); diff != "" { + return fmt.Errorf("(-got, +want)\n%s", diff) + } + return nil + }, + }, + } + + reg, err := types.NewRegistry(new(cellib.URL), new(cellib.Userinfo)) + if err != nil { + t.Fatal(err) + } + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + env, err := cel.NewEnv( + cel.Variable(cellib.ContextVariableName, cel.ObjectType(cellib.ContextTypeName)), + cel.Lib(cellib.NewURLLibrary(reg)), + ) + if err != nil { + t.Fatal(err) + } + ast, iss := env.Compile(test.expr) + if iss.Err() != nil { + t.Fatal(iss.Err()) + } + program, err := env.Program(ast) + if err != nil { + t.Fatal(err) + } + args := map[string]any{cellib.ContextVariableName: cellib.NewContextValue(context.Background())} + for k, v := range test.args { + args[k] = v + } + out, _, err := program.Eval(args) + if err != nil { + t.Fatal(err) + } + if err := test.cmp(out); err != nil { + t.Fatal(err) + } + }) + } +} + +// UserinfoDiff compares two Userinfo structs and returns a diff string similar to cmp.Diff. +func userinfoDiff(got, expected *url.Userinfo) string { + var diffs []string + + if got.Username() != expected.Username() { + diffs = append(diffs, fmt.Sprintf("username: got %q, want %q", got.Username(), expected.Username())) + } + + gotPassword, gotPasswordSet := got.Password() + expectedPassword, expectedPasswordSet := expected.Password() + if gotPasswordSet != expectedPasswordSet { + diffs = append(diffs, fmt.Sprintf("password set: got %t, want %t", gotPasswordSet, expectedPasswordSet)) + } + if gotPassword != expectedPassword { + diffs = append(diffs, fmt.Sprintf("password: got %q, want %q", gotPassword, expectedPassword)) + } + + if len(diffs) == 0 { + return "" + } + + return "(-got, +want)\n" + strings.Join(diffs, "\n") +} diff --git a/proto/grpc/federation/url.proto b/proto/grpc/federation/url.proto new file mode 100644 index 00000000..2b287195 --- /dev/null +++ b/proto/grpc/federation/url.proto @@ -0,0 +1,27 @@ +syntax = "proto3"; + +package grpc.federation.url; + +option go_package = "github.com/mercari/grpc-federation/grpc/federation/cel;cel"; + +// URL represents the structure of the URL in net/url package. +message URL { + string scheme = 1; + string opaque = 2; + Userinfo user = 3; + string host = 4; + string path = 5; + string raw_path = 6; + bool omit_host = 7; + bool force_query = 8; + string raw_query = 9; + string fragment = 10; + string raw_fragment = 11; +} + +// Userinfo represents username and password information. +message Userinfo { + string username = 1; + string password = 2; + bool password_set = 3; +}