Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in / Register
Toggle navigation
P
protobuf
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Packages
Packages
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
submodule
protobuf
Commits
61307b86
Commit
61307b86
authored
Apr 29, 2016
by
Jon Skeet
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Allow custom type URL prefixes in Any.Pack
(And likewise ignore the prefix in unpack.) Fixes issue #1459.
parent
b53417c7
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
88 additions
and
23 deletions
+88
-23
JsonFormatterTest.cs
csharp/src/Google.Protobuf.Test/JsonFormatterTest.cs
+9
-0
JsonParserTest.cs
csharp/src/Google.Protobuf.Test/JsonParserTest.cs
+11
-0
AnyTest.cs
csharp/src/Google.Protobuf.Test/WellKnownTypes/AnyTest.cs
+27
-0
JsonFormatter.cs
csharp/src/Google.Protobuf/JsonFormatter.cs
+2
-12
JsonParser.cs
csharp/src/Google.Protobuf/JsonParser.cs
+1
-1
AnyPartial.cs
csharp/src/Google.Protobuf/WellKnownTypes/AnyPartial.cs
+38
-10
No files found.
csharp/src/Google.Protobuf.Test/JsonFormatterTest.cs
View file @
61307b86
...
...
@@ -480,6 +480,15 @@ namespace Google.Protobuf
AssertJson
(
"{ '@type': 'type.googleapis.com/protobuf_unittest.TestAllTypes', 'singleInt32': 10, 'singleNestedMessage': { 'bb': 20 } }"
,
formatter
.
Format
(
any
));
}
[
Test
]
public
void
AnyMessageType_CustomPrefix
()
{
var
formatter
=
new
JsonFormatter
(
new
JsonFormatter
.
Settings
(
false
,
TypeRegistry
.
FromMessages
(
TestAllTypes
.
Descriptor
)));
var
message
=
new
TestAllTypes
{
SingleInt32
=
10
};
var
any
=
Any
.
Pack
(
message
,
"foo.bar/baz"
);
AssertJson
(
"{ '@type': 'foo.bar/baz/protobuf_unittest.TestAllTypes', 'singleInt32': 10 }"
,
formatter
.
Format
(
any
));
}
[
Test
]
public
void
AnyNested
()
{
...
...
csharp/src/Google.Protobuf.Test/JsonParserTest.cs
View file @
61307b86
...
...
@@ -810,6 +810,17 @@ namespace Google.Protobuf
Assert
.
AreEqual
(
original
,
parser
.
Parse
<
Any
>(
valueFirstJson
));
}
[
Test
]
public
void
Any_CustomPrefix
()
{
var
registry
=
TypeRegistry
.
FromMessages
(
TestAllTypes
.
Descriptor
);
var
message
=
new
TestAllTypes
{
SingleInt32
=
10
};
var
original
=
Any
.
Pack
(
message
,
"custom.prefix/middle-part"
);
var
parser
=
new
JsonParser
(
new
JsonParser
.
Settings
(
10
,
registry
));
string
json
=
"{ \"@type\": \"custom.prefix/middle-part/protobuf_unittest.TestAllTypes\", \"singleInt32\": 10 }"
;
Assert
.
AreEqual
(
original
,
parser
.
Parse
<
Any
>(
json
));
}
[
Test
]
public
void
Any_UnknownType
()
{
...
...
csharp/src/Google.Protobuf.Test/WellKnownTypes/AnyTest.cs
View file @
61307b86
...
...
@@ -46,6 +46,24 @@ namespace Google.Protobuf.WellKnownTypes
Assert
.
AreEqual
(
message
.
CalculateSize
(),
any
.
Value
.
Length
);
}
[
Test
]
public
void
Pack_WithCustomPrefix
()
{
var
message
=
SampleMessages
.
CreateFullTestAllTypes
();
var
any
=
Any
.
Pack
(
message
,
"foo.bar/baz"
);
Assert
.
AreEqual
(
"foo.bar/baz/protobuf_unittest.TestAllTypes"
,
any
.
TypeUrl
);
Assert
.
AreEqual
(
message
.
CalculateSize
(),
any
.
Value
.
Length
);
}
[
Test
]
public
void
Pack_WithCustomPrefixTrailingSlash
()
{
var
message
=
SampleMessages
.
CreateFullTestAllTypes
();
var
any
=
Any
.
Pack
(
message
,
"foo.bar/baz/"
);
Assert
.
AreEqual
(
"foo.bar/baz/protobuf_unittest.TestAllTypes"
,
any
.
TypeUrl
);
Assert
.
AreEqual
(
message
.
CalculateSize
(),
any
.
Value
.
Length
);
}
[
Test
]
public
void
Unpack_WrongType
()
{
...
...
@@ -63,6 +81,15 @@ namespace Google.Protobuf.WellKnownTypes
Assert
.
AreEqual
(
message
,
unpacked
);
}
[
Test
]
public
void
Unpack_CustomPrefix_Success
()
{
var
message
=
SampleMessages
.
CreateFullTestAllTypes
();
var
any
=
Any
.
Pack
(
message
,
"foo.bar/baz"
);
var
unpacked
=
any
.
Unpack
<
TestAllTypes
>();
Assert
.
AreEqual
(
message
,
unpacked
);
}
[
Test
]
public
void
ToString_WithValues
()
{
...
...
csharp/src/Google.Protobuf/JsonFormatter.cs
View file @
61307b86
...
...
@@ -567,7 +567,7 @@ namespace Google.Protobuf
string
typeUrl
=
(
string
)
value
.
Descriptor
.
Fields
[
Any
.
TypeUrlFieldNumber
].
Accessor
.
GetValue
(
value
);
ByteString
data
=
(
ByteString
)
value
.
Descriptor
.
Fields
[
Any
.
ValueFieldNumber
].
Accessor
.
GetValue
(
value
);
string
typeName
=
GetTypeName
(
typeUrl
);
string
typeName
=
Any
.
GetTypeName
(
typeUrl
);
MessageDescriptor
descriptor
=
settings
.
TypeRegistry
.
Find
(
typeName
);
if
(
descriptor
==
null
)
{
...
...
@@ -608,17 +608,7 @@ namespace Google.Protobuf
writer
.
Write
(
data
.
ToBase64
());
writer
.
Write
(
'"'
);
writer
.
Write
(
" }"
);
}
internal
static
string
GetTypeName
(
String
typeUrl
)
{
string
[]
parts
=
typeUrl
.
Split
(
'/'
);
if
(
parts
.
Length
!=
2
||
parts
[
0
]
!=
TypeUrlPrefix
)
{
throw
new
InvalidProtocolBufferException
(
$"Invalid type url:
{
typeUrl
}
"
);
}
return
parts
[
1
];
}
}
private
void
WriteStruct
(
TextWriter
writer
,
IMessage
message
)
{
...
...
csharp/src/Google.Protobuf/JsonParser.cs
View file @
61307b86
...
...
@@ -513,7 +513,7 @@ namespace Google.Protobuf
throw
new
InvalidProtocolBufferException
(
"Expected string value for Any.@type"
);
}
string
typeUrl
=
token
.
StringValue
;
string
typeName
=
JsonFormatter
.
GetTypeName
(
typeUrl
);
string
typeName
=
Any
.
GetTypeName
(
typeUrl
);
MessageDescriptor
descriptor
=
settings
.
TypeRegistry
.
Find
(
typeName
);
if
(
descriptor
==
null
)
...
...
csharp/src/Google.Protobuf/WellKnownTypes/AnyPartial.cs
View file @
61307b86
...
...
@@ -36,11 +36,27 @@ namespace Google.Protobuf.WellKnownTypes
{
public
partial
class
Any
{
private
const
string
DefaultPrefix
=
"type.googleapis.com"
;
// This could be moved to MessageDescriptor if we wanted to, but keeping it here means
// all the Any-specific code is in the same place.
private
static
string
GetTypeUrl
(
MessageDescriptor
descriptor
)
private
static
string
GetTypeUrl
(
MessageDescriptor
descriptor
,
string
prefix
)
=>
prefix
.
EndsWith
(
"/"
)
?
prefix
+
descriptor
.
FullName
:
prefix
+
"/"
+
descriptor
.
FullName
;
/// <summary>
/// Retrieves the type name for a type URL. This is always just the last part of the URL,
/// after the trailing slash. No validation of anything before the trailing slash is performed.
/// If the type URL does not include a slash, an empty string is returned rather than an exception
/// being thrown; this won't match any types, and the calling code is probably in a better position
/// to give a meaningful error.
/// There is no handling of fragments or queries at the moment.
/// </summary>
/// <param name="typeUrl">The URL to extract the type name from</param>
/// <returns>The type name</returns>
internal
static
string
GetTypeName
(
string
typeUrl
)
{
return
"type.googleapis.com/"
+
descriptor
.
FullName
;
int
lastSlash
=
typeUrl
.
LastIndexOf
(
'/'
);
return
lastSlash
==
-
1
?
""
:
typeUrl
.
Substring
(
lastSlash
+
1
);
}
/// <summary>
...
...
@@ -55,25 +71,37 @@ namespace Google.Protobuf.WellKnownTypes
// Note: this doesn't perform as well is it might. We could take a MessageParser<T> in an alternative overload,
// which would be expected to perform slightly better... although the difference is likely to be negligible.
T
target
=
new
T
();
string
targetTypeUrl
=
GetTypeUrl
(
target
.
Descriptor
);
if
(
TypeUrl
!=
targetTypeUrl
)
if
(
GetTypeName
(
TypeUrl
)
!=
target
.
Descriptor
.
FullName
)
{
throw
new
InvalidProtocolBufferException
(
string
.
Format
(
"Type url for {0} is {1}; Any message's type url is {2}"
,
target
.
Descriptor
.
Name
,
targetTypeUrl
,
TypeUrl
)
);
throw
new
InvalidProtocolBufferException
(
$"Full type name for
{
target
.
Descriptor
.
Name
}
is
{
target
.
Descriptor
.
FullName
}
; Any message's type url is
{
TypeUrl
}
"
);
}
target
.
MergeFrom
(
Value
);
return
target
;
}
/// <summary>
/// Packs the specified message into an Any message.
/// Packs the specified message into an Any message using a type URL prefix of "type.googleapis.com".
/// </summary>
/// <param name="message">The message to pack.</param>
/// <returns>An Any message with the content and type URL of <paramref name="message"/>.</returns>
public
static
Any
Pack
(
IMessage
message
)
=>
Pack
(
message
,
DefaultPrefix
);
/// <summary>
/// Packs the specified message into an Any message using the specified type URL prefix.
/// </summary>
/// <param name="message">The message to pack.</param>
/// <param name="typeUrlPrefix">The prefix for the type URL.</param>
/// <returns>An Any message with the content and type URL of <paramref name="message"/>.</returns>
public
static
Any
Pack
(
IMessage
message
)
public
static
Any
Pack
(
IMessage
message
,
string
typeUrlPrefix
)
{
ProtoPreconditions
.
CheckNotNull
(
message
,
"message"
);
return
new
Any
{
TypeUrl
=
GetTypeUrl
(
message
.
Descriptor
),
Value
=
message
.
ToByteString
()
};
ProtoPreconditions
.
CheckNotNull
(
message
,
nameof
(
message
));
ProtoPreconditions
.
CheckNotNull
(
typeUrlPrefix
,
nameof
(
typeUrlPrefix
));
return
new
Any
{
TypeUrl
=
GetTypeUrl
(
message
.
Descriptor
,
typeUrlPrefix
),
Value
=
message
.
ToByteString
()
};
}
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment