diff options
Diffstat (limited to 'csharp')
67 files changed, 4991 insertions, 1904 deletions
diff --git a/csharp/CHANGES.txt b/csharp/CHANGES.txt index b29debb8..a87cd4d5 100644 --- a/csharp/CHANGES.txt +++ b/csharp/CHANGES.txt @@ -128,7 +128,7 @@ Fixes: - Issue 12: default value for enumerate fields must be filled out Other: -- Rewrite of build using MSBbuild instead of NAnt +- Rewrite of build using MSbuild instead of NAnt - Moved to NUnit Version 2.2.8.0 - Changed to using secure .snk for releases diff --git a/csharp/README.md b/csharp/README.md index 305c44b6..8c3993e0 100644 --- a/csharp/README.md +++ b/csharp/README.md @@ -1,18 +1,7 @@ This directory contains the C# Protocol Buffers runtime library. -Status: Alpha - ready for early adopters -======================================== - -This code is still under significant churn. Unlike the original port, -it only supports proto3 (but not *all* of proto3 yet) - there are no -unknown fields or extensions, for example. protoc will (eventually) -deliberately fail if it is asked to generate C# code for proto2 -messages other than descriptor.proto, which is still required for -reflection. (It's currently exposed publicly, but won't be -eventually.) - -Also unlike the original port, the new version embraces mutability - -there are no builder types. +Status: Beta - ready for external testing +========================================= Usage ===== @@ -36,14 +25,25 @@ The runtime library is built as a portable class library, supporting: - Windows 8 - Windows Phone Silverlight 8 - Windows Phone 8.1 -- .NET Core (dnxcore) +- .NET Core + +You should be able to use Protocol Buffers in Visual Studio 2012 and +all later versions. This includes all code generated by `protoc`, +which only uses features from C# 3 and earlier. Building ======== -Open the `src/Google.Protobuf.sln` solution in Visual Studio. Click "Build solution" to build the solution. You should be able to run the NUnit test from Test Explorer (you might need to install NUnit Visual Studio add-in). +Open the `src/Google.Protobuf.sln` solution in Visual Studio 2015 or +later. You should be able to run the NUnit test from Test Explorer +(you might need to install NUnit Visual Studio add-in). -Supported Visual Studio versions are VS2013 (update 4) and VS2015. On Linux, you can also use Monodevelop 5.9 (older versions might work fine). +Although *users* of this project are only expected to have Visual +Studio 2012 or later, *developers* of the library are required to +have Visual Studio 2015 or later, as the library uses C# 6 features +in its implementation. These features have no impact when using the +compiled code - they're only relevant when building the +`Google.Protobuf` assembly. History of C# protobufs ======================= @@ -52,3 +52,19 @@ This subtree was originally imported from https://github.com/jskeet/protobuf-csh and represents the latest development version of C# protobufs, that will now be developed and maintained by Google. All the development will be done in open, under this repository (https://github.com/google/protobuf). + +The previous project differs from this project in a number of ways: + +- The old code only supported proto2; the new code only supports +proto3 (so no unknown fields, no required/optional distinction, no +extensions) +- The old code was based on immutable message types and builders for +them +- The old code did not support maps or `oneof` +- The old code had its own JSON representation, whereas the new code +uses the standard protobuf JSON representation +- The old code had no notion of the "well-known types" which have +special support in the new code +- The old project supported some older platforms (such as older +versions of Silverlight) which are not currently supported in the +new project diff --git a/csharp/generate_protos.sh b/csharp/generate_protos.sh index 3a556b0e..9899097d 100755 --- a/csharp/generate_protos.sh +++ b/csharp/generate_protos.sh @@ -3,16 +3,6 @@ # You first need to make sure protoc has been built (see instructions on # building protoc in root of this repository) -# This script performs a few fix-ups as part of generation. These are: -# - descriptor.proto is renamed to descriptor_proto_file.proto before -# generation, to avoid the naming collision between the class for the file -# descriptor and its Descriptor property -# - This change also impacts UnittestCustomOptions, which expects to -# use a class of Descriptor when it's actually been renamed to -# DescriptorProtoFile. -# - Issue 307 (codegen for double-nested types) breaks Unittest.proto and -# its lite equivalents. - set -ex # cd to repository root @@ -68,5 +58,5 @@ $PROTOC -Icsharp/protos --csharp_out=csharp/src/Google.Protobuf.Test \ $PROTOC -Iexamples --csharp_out=csharp/src/AddressBook \ examples/addressbook.proto -$PROTOC -Iconformance --csharp_out=csharp/src/Google.Protobuf.Conformance \ +$PROTOC -Iconformance -Isrc --csharp_out=csharp/src/Google.Protobuf.Conformance \ conformance/conformance.proto diff --git a/csharp/keys/Google.Protobuf.snk b/csharp/keys/Google.Protobuf.snk Binary files differnew file mode 100644 index 00000000..7515443c --- /dev/null +++ b/csharp/keys/Google.Protobuf.snk diff --git a/csharp/keys/README.md b/csharp/keys/README.md index 1a014198..ede67357 100644 --- a/csharp/keys/README.md +++ b/csharp/keys/README.md @@ -2,4 +2,8 @@ Contents -------- - Google.Protobuf.public.snk: - Public key to verify strong name of Google.Protobuf assemblies.
\ No newline at end of file + Public key to verify strong name of Google.Protobuf assemblies. +- Google.Protobuf.snk: + Signing key to provide strong name of Google.Protobuf assemblies. + As per [Microsoft guidance](https://msdn.microsoft.com/en-us/library/wd40t7ad(v=vs.110).aspx) + signing key should be checked into the repository. diff --git a/csharp/src/AddressBook/Addressbook.cs b/csharp/src/AddressBook/Addressbook.cs index 02dbc8e4..166dd49a 100644 --- a/csharp/src/AddressBook/Addressbook.cs +++ b/csharp/src/AddressBook/Addressbook.cs @@ -32,17 +32,20 @@ namespace Google.Protobuf.Examples.AddressBook { "GAEgAygLMhAudHV0b3JpYWwuUGVyc29uQlAKFGNvbS5leGFtcGxlLnR1dG9y", "aWFsQhFBZGRyZXNzQm9va1Byb3Rvc6oCJEdvb2dsZS5Qcm90b2J1Zi5FeGFt", "cGxlcy5BZGRyZXNzQm9va2IGcHJvdG8z")); - descriptor = pbr::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData, + descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, new pbr::FileDescriptor[] { }, - new pbr::GeneratedCodeInfo(null, new pbr::GeneratedCodeInfo[] { - new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.Examples.AddressBook.Person), global::Google.Protobuf.Examples.AddressBook.Person.Parser, new[]{ "Name", "Id", "Email", "Phones" }, null, new[]{ typeof(global::Google.Protobuf.Examples.AddressBook.Person.Types.PhoneType) }, new pbr::GeneratedCodeInfo[] { new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.Examples.AddressBook.Person.Types.PhoneNumber), global::Google.Protobuf.Examples.AddressBook.Person.Types.PhoneNumber.Parser, new[]{ "Number", "Type" }, null, null, null)}), - new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.Examples.AddressBook.AddressBook), global::Google.Protobuf.Examples.AddressBook.AddressBook.Parser, new[]{ "People" }, null, null, null) + new pbr::GeneratedClrTypeInfo(null, new pbr::GeneratedClrTypeInfo[] { + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Examples.AddressBook.Person), global::Google.Protobuf.Examples.AddressBook.Person.Parser, new[]{ "Name", "Id", "Email", "Phones" }, null, new[]{ typeof(global::Google.Protobuf.Examples.AddressBook.Person.Types.PhoneType) }, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Examples.AddressBook.Person.Types.PhoneNumber), global::Google.Protobuf.Examples.AddressBook.Person.Types.PhoneNumber.Parser, new[]{ "Number", "Type" }, null, null, null)}), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Examples.AddressBook.AddressBook), global::Google.Protobuf.Examples.AddressBook.AddressBook.Parser, new[]{ "People" }, null, null, null) })); } #endregion } #region Messages + /// <summary> + /// [START messages] + /// </summary> [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] public sealed partial class Person : pb::IMessage<Person> { private static readonly pb::MessageParser<Person> _parser = new pb::MessageParser<Person>(() => new Person()); @@ -79,7 +82,7 @@ namespace Google.Protobuf.Examples.AddressBook { public string Name { get { return name_; } set { - name_ = pb::Preconditions.CheckNotNull(value, "value"); + name_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } @@ -102,7 +105,7 @@ namespace Google.Protobuf.Examples.AddressBook { public string Email { get { return email_; } set { - email_ = pb::Preconditions.CheckNotNull(value, "value"); + email_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } @@ -143,7 +146,7 @@ namespace Google.Protobuf.Examples.AddressBook { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -264,7 +267,7 @@ namespace Google.Protobuf.Examples.AddressBook { public string Number { get { return number_; } set { - number_ = pb::Preconditions.CheckNotNull(value, "value"); + number_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } @@ -302,7 +305,7 @@ namespace Google.Protobuf.Examples.AddressBook { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -426,7 +429,7 @@ namespace Google.Protobuf.Examples.AddressBook { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { diff --git a/csharp/src/Google.Protobuf.Conformance/Conformance.cs b/csharp/src/Google.Protobuf.Conformance/Conformance.cs index b9ab4820..7d85d28c 100644 --- a/csharp/src/Google.Protobuf.Conformance/Conformance.cs +++ b/csharp/src/Google.Protobuf.Conformance/Conformance.cs @@ -23,125 +23,175 @@ namespace Conformance { static ConformanceReflection() { byte[] descriptorData = global::System.Convert.FromBase64String( string.Concat( - "ChFjb25mb3JtYW5jZS5wcm90bxILY29uZm9ybWFuY2UijQEKEkNvbmZvcm1h", - "bmNlUmVxdWVzdBIaChBwcm90b2J1Zl9wYXlsb2FkGAEgASgMSAASFgoManNv", - "bl9wYXlsb2FkGAIgASgJSAASOAoXcmVxdWVzdGVkX291dHB1dF9mb3JtYXQY", - "AyABKA4yFy5jb25mb3JtYW5jZS5XaXJlRm9ybWF0QgkKB3BheWxvYWQilgEK", - "E0NvbmZvcm1hbmNlUmVzcG9uc2USFQoLcGFyc2VfZXJyb3IYASABKAlIABIX", - "Cg1ydW50aW1lX2Vycm9yGAIgASgJSAASGgoQcHJvdG9idWZfcGF5bG9hZBgD", - "IAEoDEgAEhYKDGpzb25fcGF5bG9hZBgEIAEoCUgAEhEKB3NraXBwZWQYBSAB", - "KAlIAEIICgZyZXN1bHQi6yIKDFRlc3RBbGxUeXBlcxIWCg5vcHRpb25hbF9p", - "bnQzMhgBIAEoBRIWCg5vcHRpb25hbF9pbnQ2NBgCIAEoAxIXCg9vcHRpb25h", - "bF91aW50MzIYAyABKA0SFwoPb3B0aW9uYWxfdWludDY0GAQgASgEEhcKD29w", - "dGlvbmFsX3NpbnQzMhgFIAEoERIXCg9vcHRpb25hbF9zaW50NjQYBiABKBIS", - "GAoQb3B0aW9uYWxfZml4ZWQzMhgHIAEoBxIYChBvcHRpb25hbF9maXhlZDY0", - "GAggASgGEhkKEW9wdGlvbmFsX3NmaXhlZDMyGAkgASgPEhkKEW9wdGlvbmFs", - "X3NmaXhlZDY0GAogASgQEhYKDm9wdGlvbmFsX2Zsb2F0GAsgASgCEhcKD29w", - "dGlvbmFsX2RvdWJsZRgMIAEoARIVCg1vcHRpb25hbF9ib29sGA0gASgIEhcK", - "D29wdGlvbmFsX3N0cmluZxgOIAEoCRIWCg5vcHRpb25hbF9ieXRlcxgPIAEo", - "DBJIChdvcHRpb25hbF9uZXN0ZWRfbWVzc2FnZRgSIAEoCzInLmNvbmZvcm1h", - "bmNlLlRlc3RBbGxUeXBlcy5OZXN0ZWRNZXNzYWdlEj0KGG9wdGlvbmFsX2Zv", - "cmVpZ25fbWVzc2FnZRgTIAEoCzIbLmNvbmZvcm1hbmNlLkZvcmVpZ25NZXNz", - "YWdlEkIKFG9wdGlvbmFsX25lc3RlZF9lbnVtGBUgASgOMiQuY29uZm9ybWFu", - "Y2UuVGVzdEFsbFR5cGVzLk5lc3RlZEVudW0SNwoVb3B0aW9uYWxfZm9yZWln", - "bl9lbnVtGBYgASgOMhguY29uZm9ybWFuY2UuRm9yZWlnbkVudW0SIQoVb3B0", - "aW9uYWxfc3RyaW5nX3BpZWNlGBggASgJQgIIAhIZCg1vcHRpb25hbF9jb3Jk", - "GBkgASgJQgIIARI0ChFyZWN1cnNpdmVfbWVzc2FnZRgbIAEoCzIZLmNvbmZv", - "cm1hbmNlLlRlc3RBbGxUeXBlcxIWCg5yZXBlYXRlZF9pbnQzMhgfIAMoBRIW", - "Cg5yZXBlYXRlZF9pbnQ2NBggIAMoAxIXCg9yZXBlYXRlZF91aW50MzIYISAD", - "KA0SFwoPcmVwZWF0ZWRfdWludDY0GCIgAygEEhcKD3JlcGVhdGVkX3NpbnQz", - "MhgjIAMoERIXCg9yZXBlYXRlZF9zaW50NjQYJCADKBISGAoQcmVwZWF0ZWRf", - "Zml4ZWQzMhglIAMoBxIYChByZXBlYXRlZF9maXhlZDY0GCYgAygGEhkKEXJl", - "cGVhdGVkX3NmaXhlZDMyGCcgAygPEhkKEXJlcGVhdGVkX3NmaXhlZDY0GCgg", - "AygQEhYKDnJlcGVhdGVkX2Zsb2F0GCkgAygCEhcKD3JlcGVhdGVkX2RvdWJs", - "ZRgqIAMoARIVCg1yZXBlYXRlZF9ib29sGCsgAygIEhcKD3JlcGVhdGVkX3N0", - "cmluZxgsIAMoCRIWCg5yZXBlYXRlZF9ieXRlcxgtIAMoDBJIChdyZXBlYXRl", - "ZF9uZXN0ZWRfbWVzc2FnZRgwIAMoCzInLmNvbmZvcm1hbmNlLlRlc3RBbGxU", - "eXBlcy5OZXN0ZWRNZXNzYWdlEj0KGHJlcGVhdGVkX2ZvcmVpZ25fbWVzc2Fn", - "ZRgxIAMoCzIbLmNvbmZvcm1hbmNlLkZvcmVpZ25NZXNzYWdlEkIKFHJlcGVh", - "dGVkX25lc3RlZF9lbnVtGDMgAygOMiQuY29uZm9ybWFuY2UuVGVzdEFsbFR5", - "cGVzLk5lc3RlZEVudW0SNwoVcmVwZWF0ZWRfZm9yZWlnbl9lbnVtGDQgAygO", - "MhguY29uZm9ybWFuY2UuRm9yZWlnbkVudW0SIQoVcmVwZWF0ZWRfc3RyaW5n", - "X3BpZWNlGDYgAygJQgIIAhIZCg1yZXBlYXRlZF9jb3JkGDcgAygJQgIIARJF", - "Cg9tYXBfaW50MzJfaW50MzIYOCADKAsyLC5jb25mb3JtYW5jZS5UZXN0QWxs", - "VHlwZXMuTWFwSW50MzJJbnQzMkVudHJ5EkUKD21hcF9pbnQ2NF9pbnQ2NBg5", - "IAMoCzIsLmNvbmZvcm1hbmNlLlRlc3RBbGxUeXBlcy5NYXBJbnQ2NEludDY0", - "RW50cnkSSQoRbWFwX3VpbnQzMl91aW50MzIYOiADKAsyLi5jb25mb3JtYW5j", - "ZS5UZXN0QWxsVHlwZXMuTWFwVWludDMyVWludDMyRW50cnkSSQoRbWFwX3Vp", - "bnQ2NF91aW50NjQYOyADKAsyLi5jb25mb3JtYW5jZS5UZXN0QWxsVHlwZXMu", - "TWFwVWludDY0VWludDY0RW50cnkSSQoRbWFwX3NpbnQzMl9zaW50MzIYPCAD", - "KAsyLi5jb25mb3JtYW5jZS5UZXN0QWxsVHlwZXMuTWFwU2ludDMyU2ludDMy", - "RW50cnkSSQoRbWFwX3NpbnQ2NF9zaW50NjQYPSADKAsyLi5jb25mb3JtYW5j", - "ZS5UZXN0QWxsVHlwZXMuTWFwU2ludDY0U2ludDY0RW50cnkSTQoTbWFwX2Zp", - "eGVkMzJfZml4ZWQzMhg+IAMoCzIwLmNvbmZvcm1hbmNlLlRlc3RBbGxUeXBl", - "cy5NYXBGaXhlZDMyRml4ZWQzMkVudHJ5Ek0KE21hcF9maXhlZDY0X2ZpeGVk", - "NjQYPyADKAsyMC5jb25mb3JtYW5jZS5UZXN0QWxsVHlwZXMuTWFwRml4ZWQ2", - "NEZpeGVkNjRFbnRyeRJRChVtYXBfc2ZpeGVkMzJfc2ZpeGVkMzIYQCADKAsy", - "Mi5jb25mb3JtYW5jZS5UZXN0QWxsVHlwZXMuTWFwU2ZpeGVkMzJTZml4ZWQz", - "MkVudHJ5ElEKFW1hcF9zZml4ZWQ2NF9zZml4ZWQ2NBhBIAMoCzIyLmNvbmZv", - "cm1hbmNlLlRlc3RBbGxUeXBlcy5NYXBTZml4ZWQ2NFNmaXhlZDY0RW50cnkS", - "RQoPbWFwX2ludDMyX2Zsb2F0GEIgAygLMiwuY29uZm9ybWFuY2UuVGVzdEFs", - "bFR5cGVzLk1hcEludDMyRmxvYXRFbnRyeRJHChBtYXBfaW50MzJfZG91Ymxl", - "GEMgAygLMi0uY29uZm9ybWFuY2UuVGVzdEFsbFR5cGVzLk1hcEludDMyRG91", - "YmxlRW50cnkSQQoNbWFwX2Jvb2xfYm9vbBhEIAMoCzIqLmNvbmZvcm1hbmNl", - "LlRlc3RBbGxUeXBlcy5NYXBCb29sQm9vbEVudHJ5EkkKEW1hcF9zdHJpbmdf", - "c3RyaW5nGEUgAygLMi4uY29uZm9ybWFuY2UuVGVzdEFsbFR5cGVzLk1hcFN0", - "cmluZ1N0cmluZ0VudHJ5EkcKEG1hcF9zdHJpbmdfYnl0ZXMYRiADKAsyLS5j", - "b25mb3JtYW5jZS5UZXN0QWxsVHlwZXMuTWFwU3RyaW5nQnl0ZXNFbnRyeRJY", - "ChltYXBfc3RyaW5nX25lc3RlZF9tZXNzYWdlGEcgAygLMjUuY29uZm9ybWFu", - "Y2UuVGVzdEFsbFR5cGVzLk1hcFN0cmluZ05lc3RlZE1lc3NhZ2VFbnRyeRJa", - "ChptYXBfc3RyaW5nX2ZvcmVpZ25fbWVzc2FnZRhIIAMoCzI2LmNvbmZvcm1h", - "bmNlLlRlc3RBbGxUeXBlcy5NYXBTdHJpbmdGb3JlaWduTWVzc2FnZUVudHJ5", - "ElIKFm1hcF9zdHJpbmdfbmVzdGVkX2VudW0YSSADKAsyMi5jb25mb3JtYW5j", - "ZS5UZXN0QWxsVHlwZXMuTWFwU3RyaW5nTmVzdGVkRW51bUVudHJ5ElQKF21h", - "cF9zdHJpbmdfZm9yZWlnbl9lbnVtGEogAygLMjMuY29uZm9ybWFuY2UuVGVz", - "dEFsbFR5cGVzLk1hcFN0cmluZ0ZvcmVpZ25FbnVtRW50cnkSFgoMb25lb2Zf", - "dWludDMyGG8gASgNSAASRwoUb25lb2ZfbmVzdGVkX21lc3NhZ2UYcCABKAsy", - "Jy5jb25mb3JtYW5jZS5UZXN0QWxsVHlwZXMuTmVzdGVkTWVzc2FnZUgAEhYK", - "DG9uZW9mX3N0cmluZxhxIAEoCUgAEhUKC29uZW9mX2J5dGVzGHIgASgMSAAa", - "SgoNTmVzdGVkTWVzc2FnZRIJCgFhGAEgASgFEi4KC2NvcmVjdXJzaXZlGAIg", - "ASgLMhkuY29uZm9ybWFuY2UuVGVzdEFsbFR5cGVzGjQKEk1hcEludDMySW50", - "MzJFbnRyeRILCgNrZXkYASABKAUSDQoFdmFsdWUYAiABKAU6AjgBGjQKEk1h", - "cEludDY0SW50NjRFbnRyeRILCgNrZXkYASABKAMSDQoFdmFsdWUYAiABKAM6", - "AjgBGjYKFE1hcFVpbnQzMlVpbnQzMkVudHJ5EgsKA2tleRgBIAEoDRINCgV2", - "YWx1ZRgCIAEoDToCOAEaNgoUTWFwVWludDY0VWludDY0RW50cnkSCwoDa2V5", - "GAEgASgEEg0KBXZhbHVlGAIgASgEOgI4ARo2ChRNYXBTaW50MzJTaW50MzJF", - "bnRyeRILCgNrZXkYASABKBESDQoFdmFsdWUYAiABKBE6AjgBGjYKFE1hcFNp", - "bnQ2NFNpbnQ2NEVudHJ5EgsKA2tleRgBIAEoEhINCgV2YWx1ZRgCIAEoEjoC", - "OAEaOAoWTWFwRml4ZWQzMkZpeGVkMzJFbnRyeRILCgNrZXkYASABKAcSDQoF", - "dmFsdWUYAiABKAc6AjgBGjgKFk1hcEZpeGVkNjRGaXhlZDY0RW50cnkSCwoD", - "a2V5GAEgASgGEg0KBXZhbHVlGAIgASgGOgI4ARo6ChhNYXBTZml4ZWQzMlNm", - "aXhlZDMyRW50cnkSCwoDa2V5GAEgASgPEg0KBXZhbHVlGAIgASgPOgI4ARo6", - "ChhNYXBTZml4ZWQ2NFNmaXhlZDY0RW50cnkSCwoDa2V5GAEgASgQEg0KBXZh", - "bHVlGAIgASgQOgI4ARo0ChJNYXBJbnQzMkZsb2F0RW50cnkSCwoDa2V5GAEg", - "ASgFEg0KBXZhbHVlGAIgASgCOgI4ARo1ChNNYXBJbnQzMkRvdWJsZUVudHJ5", - "EgsKA2tleRgBIAEoBRINCgV2YWx1ZRgCIAEoAToCOAEaMgoQTWFwQm9vbEJv", - "b2xFbnRyeRILCgNrZXkYASABKAgSDQoFdmFsdWUYAiABKAg6AjgBGjYKFE1h", - "cFN0cmluZ1N0cmluZ0VudHJ5EgsKA2tleRgBIAEoCRINCgV2YWx1ZRgCIAEo", - "CToCOAEaNQoTTWFwU3RyaW5nQnl0ZXNFbnRyeRILCgNrZXkYASABKAkSDQoF", - "dmFsdWUYAiABKAw6AjgBGmYKG01hcFN0cmluZ05lc3RlZE1lc3NhZ2VFbnRy", - "eRILCgNrZXkYASABKAkSNgoFdmFsdWUYAiABKAsyJy5jb25mb3JtYW5jZS5U", - "ZXN0QWxsVHlwZXMuTmVzdGVkTWVzc2FnZToCOAEaWwocTWFwU3RyaW5nRm9y", - "ZWlnbk1lc3NhZ2VFbnRyeRILCgNrZXkYASABKAkSKgoFdmFsdWUYAiABKAsy", - "Gy5jb25mb3JtYW5jZS5Gb3JlaWduTWVzc2FnZToCOAEaYAoYTWFwU3RyaW5n", - "TmVzdGVkRW51bUVudHJ5EgsKA2tleRgBIAEoCRIzCgV2YWx1ZRgCIAEoDjIk", - "LmNvbmZvcm1hbmNlLlRlc3RBbGxUeXBlcy5OZXN0ZWRFbnVtOgI4ARpVChlN", - "YXBTdHJpbmdGb3JlaWduRW51bUVudHJ5EgsKA2tleRgBIAEoCRInCgV2YWx1", - "ZRgCIAEoDjIYLmNvbmZvcm1hbmNlLkZvcmVpZ25FbnVtOgI4ASI5CgpOZXN0", - "ZWRFbnVtEgcKA0ZPTxAAEgcKA0JBUhABEgcKA0JBWhACEhAKA05FRxD/////", - "//////8BQg0KC29uZW9mX2ZpZWxkIhsKDkZvcmVpZ25NZXNzYWdlEgkKAWMY", - "ASABKAUqNQoKV2lyZUZvcm1hdBIPCgtVTlNQRUNJRklFRBAAEgwKCFBST1RP", - "QlVGEAESCAoESlNPThACKkAKC0ZvcmVpZ25FbnVtEg8KC0ZPUkVJR05fRk9P", - "EAASDwoLRk9SRUlHTl9CQVIQARIPCgtGT1JFSUdOX0JBWhACQiEKH2NvbS5n", - "b29nbGUucHJvdG9idWYuY29uZm9ybWFuY2ViBnByb3RvMw==")); - descriptor = pbr::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData, - new pbr::FileDescriptor[] { }, - new pbr::GeneratedCodeInfo(new[] {typeof(global::Conformance.WireFormat), typeof(global::Conformance.ForeignEnum), }, new pbr::GeneratedCodeInfo[] { - new pbr::GeneratedCodeInfo(typeof(global::Conformance.ConformanceRequest), global::Conformance.ConformanceRequest.Parser, new[]{ "ProtobufPayload", "JsonPayload", "RequestedOutputFormat" }, new[]{ "Payload" }, null, null), - new pbr::GeneratedCodeInfo(typeof(global::Conformance.ConformanceResponse), global::Conformance.ConformanceResponse.Parser, new[]{ "ParseError", "RuntimeError", "ProtobufPayload", "JsonPayload", "Skipped" }, new[]{ "Result" }, null, null), - new pbr::GeneratedCodeInfo(typeof(global::Conformance.TestAllTypes), global::Conformance.TestAllTypes.Parser, new[]{ "OptionalInt32", "OptionalInt64", "OptionalUint32", "OptionalUint64", "OptionalSint32", "OptionalSint64", "OptionalFixed32", "OptionalFixed64", "OptionalSfixed32", "OptionalSfixed64", "OptionalFloat", "OptionalDouble", "OptionalBool", "OptionalString", "OptionalBytes", "OptionalNestedMessage", "OptionalForeignMessage", "OptionalNestedEnum", "OptionalForeignEnum", "OptionalStringPiece", "OptionalCord", "RecursiveMessage", "RepeatedInt32", "RepeatedInt64", "RepeatedUint32", "RepeatedUint64", "RepeatedSint32", "RepeatedSint64", "RepeatedFixed32", "RepeatedFixed64", "RepeatedSfixed32", "RepeatedSfixed64", "RepeatedFloat", "RepeatedDouble", "RepeatedBool", "RepeatedString", "RepeatedBytes", "RepeatedNestedMessage", "RepeatedForeignMessage", "RepeatedNestedEnum", "RepeatedForeignEnum", "RepeatedStringPiece", "RepeatedCord", "MapInt32Int32", "MapInt64Int64", "MapUint32Uint32", "MapUint64Uint64", "MapSint32Sint32", "MapSint64Sint64", "MapFixed32Fixed32", "MapFixed64Fixed64", "MapSfixed32Sfixed32", "MapSfixed64Sfixed64", "MapInt32Float", "MapInt32Double", "MapBoolBool", "MapStringString", "MapStringBytes", "MapStringNestedMessage", "MapStringForeignMessage", "MapStringNestedEnum", "MapStringForeignEnum", "OneofUint32", "OneofNestedMessage", "OneofString", "OneofBytes" }, new[]{ "OneofField" }, new[]{ typeof(global::Conformance.TestAllTypes.Types.NestedEnum) }, new pbr::GeneratedCodeInfo[] { new pbr::GeneratedCodeInfo(typeof(global::Conformance.TestAllTypes.Types.NestedMessage), global::Conformance.TestAllTypes.Types.NestedMessage.Parser, new[]{ "A", "Corecursive" }, null, null, null), + "ChFjb25mb3JtYW5jZS5wcm90bxILY29uZm9ybWFuY2UaGWdvb2dsZS9wcm90", + "b2J1Zi9hbnkucHJvdG8aHmdvb2dsZS9wcm90b2J1Zi9kdXJhdGlvbi5wcm90", + "bxogZ29vZ2xlL3Byb3RvYnVmL2ZpZWxkX21hc2sucHJvdG8aHGdvb2dsZS9w", + "cm90b2J1Zi9zdHJ1Y3QucHJvdG8aH2dvb2dsZS9wcm90b2J1Zi90aW1lc3Rh", + "bXAucHJvdG8aHmdvb2dsZS9wcm90b2J1Zi93cmFwcGVycy5wcm90byKNAQoS", + "Q29uZm9ybWFuY2VSZXF1ZXN0EhoKEHByb3RvYnVmX3BheWxvYWQYASABKAxI", + "ABIWCgxqc29uX3BheWxvYWQYAiABKAlIABI4ChdyZXF1ZXN0ZWRfb3V0cHV0", + "X2Zvcm1hdBgDIAEoDjIXLmNvbmZvcm1hbmNlLldpcmVGb3JtYXRCCQoHcGF5", + "bG9hZCKxAQoTQ29uZm9ybWFuY2VSZXNwb25zZRIVCgtwYXJzZV9lcnJvchgB", + "IAEoCUgAEhkKD3NlcmlhbGl6ZV9lcnJvchgGIAEoCUgAEhcKDXJ1bnRpbWVf", + "ZXJyb3IYAiABKAlIABIaChBwcm90b2J1Zl9wYXlsb2FkGAMgASgMSAASFgoM", + "anNvbl9wYXlsb2FkGAQgASgJSAASEQoHc2tpcHBlZBgFIAEoCUgAQggKBnJl", + "c3VsdCLVMgoMVGVzdEFsbFR5cGVzEhYKDm9wdGlvbmFsX2ludDMyGAEgASgF", + "EhYKDm9wdGlvbmFsX2ludDY0GAIgASgDEhcKD29wdGlvbmFsX3VpbnQzMhgD", + "IAEoDRIXCg9vcHRpb25hbF91aW50NjQYBCABKAQSFwoPb3B0aW9uYWxfc2lu", + "dDMyGAUgASgREhcKD29wdGlvbmFsX3NpbnQ2NBgGIAEoEhIYChBvcHRpb25h", + "bF9maXhlZDMyGAcgASgHEhgKEG9wdGlvbmFsX2ZpeGVkNjQYCCABKAYSGQoR", + "b3B0aW9uYWxfc2ZpeGVkMzIYCSABKA8SGQoRb3B0aW9uYWxfc2ZpeGVkNjQY", + "CiABKBASFgoOb3B0aW9uYWxfZmxvYXQYCyABKAISFwoPb3B0aW9uYWxfZG91", + "YmxlGAwgASgBEhUKDW9wdGlvbmFsX2Jvb2wYDSABKAgSFwoPb3B0aW9uYWxf", + "c3RyaW5nGA4gASgJEhYKDm9wdGlvbmFsX2J5dGVzGA8gASgMEkgKF29wdGlv", + "bmFsX25lc3RlZF9tZXNzYWdlGBIgASgLMicuY29uZm9ybWFuY2UuVGVzdEFs", + "bFR5cGVzLk5lc3RlZE1lc3NhZ2USPQoYb3B0aW9uYWxfZm9yZWlnbl9tZXNz", + "YWdlGBMgASgLMhsuY29uZm9ybWFuY2UuRm9yZWlnbk1lc3NhZ2USQgoUb3B0", + "aW9uYWxfbmVzdGVkX2VudW0YFSABKA4yJC5jb25mb3JtYW5jZS5UZXN0QWxs", + "VHlwZXMuTmVzdGVkRW51bRI3ChVvcHRpb25hbF9mb3JlaWduX2VudW0YFiAB", + "KA4yGC5jb25mb3JtYW5jZS5Gb3JlaWduRW51bRIhChVvcHRpb25hbF9zdHJp", + "bmdfcGllY2UYGCABKAlCAggCEhkKDW9wdGlvbmFsX2NvcmQYGSABKAlCAggB", + "EjQKEXJlY3Vyc2l2ZV9tZXNzYWdlGBsgASgLMhkuY29uZm9ybWFuY2UuVGVz", + "dEFsbFR5cGVzEhYKDnJlcGVhdGVkX2ludDMyGB8gAygFEhYKDnJlcGVhdGVk", + "X2ludDY0GCAgAygDEhcKD3JlcGVhdGVkX3VpbnQzMhghIAMoDRIXCg9yZXBl", + "YXRlZF91aW50NjQYIiADKAQSFwoPcmVwZWF0ZWRfc2ludDMyGCMgAygREhcK", + "D3JlcGVhdGVkX3NpbnQ2NBgkIAMoEhIYChByZXBlYXRlZF9maXhlZDMyGCUg", + "AygHEhgKEHJlcGVhdGVkX2ZpeGVkNjQYJiADKAYSGQoRcmVwZWF0ZWRfc2Zp", + "eGVkMzIYJyADKA8SGQoRcmVwZWF0ZWRfc2ZpeGVkNjQYKCADKBASFgoOcmVw", + "ZWF0ZWRfZmxvYXQYKSADKAISFwoPcmVwZWF0ZWRfZG91YmxlGCogAygBEhUK", + "DXJlcGVhdGVkX2Jvb2wYKyADKAgSFwoPcmVwZWF0ZWRfc3RyaW5nGCwgAygJ", + "EhYKDnJlcGVhdGVkX2J5dGVzGC0gAygMEkgKF3JlcGVhdGVkX25lc3RlZF9t", + "ZXNzYWdlGDAgAygLMicuY29uZm9ybWFuY2UuVGVzdEFsbFR5cGVzLk5lc3Rl", + "ZE1lc3NhZ2USPQoYcmVwZWF0ZWRfZm9yZWlnbl9tZXNzYWdlGDEgAygLMhsu", + "Y29uZm9ybWFuY2UuRm9yZWlnbk1lc3NhZ2USQgoUcmVwZWF0ZWRfbmVzdGVk", + "X2VudW0YMyADKA4yJC5jb25mb3JtYW5jZS5UZXN0QWxsVHlwZXMuTmVzdGVk", + "RW51bRI3ChVyZXBlYXRlZF9mb3JlaWduX2VudW0YNCADKA4yGC5jb25mb3Jt", + "YW5jZS5Gb3JlaWduRW51bRIhChVyZXBlYXRlZF9zdHJpbmdfcGllY2UYNiAD", + "KAlCAggCEhkKDXJlcGVhdGVkX2NvcmQYNyADKAlCAggBEkUKD21hcF9pbnQz", + "Ml9pbnQzMhg4IAMoCzIsLmNvbmZvcm1hbmNlLlRlc3RBbGxUeXBlcy5NYXBJ", + "bnQzMkludDMyRW50cnkSRQoPbWFwX2ludDY0X2ludDY0GDkgAygLMiwuY29u", + "Zm9ybWFuY2UuVGVzdEFsbFR5cGVzLk1hcEludDY0SW50NjRFbnRyeRJJChFt", + "YXBfdWludDMyX3VpbnQzMhg6IAMoCzIuLmNvbmZvcm1hbmNlLlRlc3RBbGxU", + "eXBlcy5NYXBVaW50MzJVaW50MzJFbnRyeRJJChFtYXBfdWludDY0X3VpbnQ2", + "NBg7IAMoCzIuLmNvbmZvcm1hbmNlLlRlc3RBbGxUeXBlcy5NYXBVaW50NjRV", + "aW50NjRFbnRyeRJJChFtYXBfc2ludDMyX3NpbnQzMhg8IAMoCzIuLmNvbmZv", + "cm1hbmNlLlRlc3RBbGxUeXBlcy5NYXBTaW50MzJTaW50MzJFbnRyeRJJChFt", + "YXBfc2ludDY0X3NpbnQ2NBg9IAMoCzIuLmNvbmZvcm1hbmNlLlRlc3RBbGxU", + "eXBlcy5NYXBTaW50NjRTaW50NjRFbnRyeRJNChNtYXBfZml4ZWQzMl9maXhl", + "ZDMyGD4gAygLMjAuY29uZm9ybWFuY2UuVGVzdEFsbFR5cGVzLk1hcEZpeGVk", + "MzJGaXhlZDMyRW50cnkSTQoTbWFwX2ZpeGVkNjRfZml4ZWQ2NBg/IAMoCzIw", + "LmNvbmZvcm1hbmNlLlRlc3RBbGxUeXBlcy5NYXBGaXhlZDY0Rml4ZWQ2NEVu", + "dHJ5ElEKFW1hcF9zZml4ZWQzMl9zZml4ZWQzMhhAIAMoCzIyLmNvbmZvcm1h", + "bmNlLlRlc3RBbGxUeXBlcy5NYXBTZml4ZWQzMlNmaXhlZDMyRW50cnkSUQoV", + "bWFwX3NmaXhlZDY0X3NmaXhlZDY0GEEgAygLMjIuY29uZm9ybWFuY2UuVGVz", + "dEFsbFR5cGVzLk1hcFNmaXhlZDY0U2ZpeGVkNjRFbnRyeRJFCg9tYXBfaW50", + "MzJfZmxvYXQYQiADKAsyLC5jb25mb3JtYW5jZS5UZXN0QWxsVHlwZXMuTWFw", + "SW50MzJGbG9hdEVudHJ5EkcKEG1hcF9pbnQzMl9kb3VibGUYQyADKAsyLS5j", + "b25mb3JtYW5jZS5UZXN0QWxsVHlwZXMuTWFwSW50MzJEb3VibGVFbnRyeRJB", + "Cg1tYXBfYm9vbF9ib29sGEQgAygLMiouY29uZm9ybWFuY2UuVGVzdEFsbFR5", + "cGVzLk1hcEJvb2xCb29sRW50cnkSSQoRbWFwX3N0cmluZ19zdHJpbmcYRSAD", + "KAsyLi5jb25mb3JtYW5jZS5UZXN0QWxsVHlwZXMuTWFwU3RyaW5nU3RyaW5n", + "RW50cnkSRwoQbWFwX3N0cmluZ19ieXRlcxhGIAMoCzItLmNvbmZvcm1hbmNl", + "LlRlc3RBbGxUeXBlcy5NYXBTdHJpbmdCeXRlc0VudHJ5ElgKGW1hcF9zdHJp", + "bmdfbmVzdGVkX21lc3NhZ2UYRyADKAsyNS5jb25mb3JtYW5jZS5UZXN0QWxs", + "VHlwZXMuTWFwU3RyaW5nTmVzdGVkTWVzc2FnZUVudHJ5EloKGm1hcF9zdHJp", + "bmdfZm9yZWlnbl9tZXNzYWdlGEggAygLMjYuY29uZm9ybWFuY2UuVGVzdEFs", + "bFR5cGVzLk1hcFN0cmluZ0ZvcmVpZ25NZXNzYWdlRW50cnkSUgoWbWFwX3N0", + "cmluZ19uZXN0ZWRfZW51bRhJIAMoCzIyLmNvbmZvcm1hbmNlLlRlc3RBbGxU", + "eXBlcy5NYXBTdHJpbmdOZXN0ZWRFbnVtRW50cnkSVAoXbWFwX3N0cmluZ19m", + "b3JlaWduX2VudW0YSiADKAsyMy5jb25mb3JtYW5jZS5UZXN0QWxsVHlwZXMu", + "TWFwU3RyaW5nRm9yZWlnbkVudW1FbnRyeRIWCgxvbmVvZl91aW50MzIYbyAB", + "KA1IABJHChRvbmVvZl9uZXN0ZWRfbWVzc2FnZRhwIAEoCzInLmNvbmZvcm1h", + "bmNlLlRlc3RBbGxUeXBlcy5OZXN0ZWRNZXNzYWdlSAASFgoMb25lb2Zfc3Ry", + "aW5nGHEgASgJSAASFQoLb25lb2ZfYnl0ZXMYciABKAxIABI6ChVvcHRpb25h", + "bF9ib29sX3dyYXBwZXIYyQEgASgLMhouZ29vZ2xlLnByb3RvYnVmLkJvb2xW", + "YWx1ZRI8ChZvcHRpb25hbF9pbnQzMl93cmFwcGVyGMoBIAEoCzIbLmdvb2ds", + "ZS5wcm90b2J1Zi5JbnQzMlZhbHVlEjwKFm9wdGlvbmFsX2ludDY0X3dyYXBw", + "ZXIYywEgASgLMhsuZ29vZ2xlLnByb3RvYnVmLkludDY0VmFsdWUSPgoXb3B0", + "aW9uYWxfdWludDMyX3dyYXBwZXIYzAEgASgLMhwuZ29vZ2xlLnByb3RvYnVm", + "LlVJbnQzMlZhbHVlEj4KF29wdGlvbmFsX3VpbnQ2NF93cmFwcGVyGM0BIAEo", + "CzIcLmdvb2dsZS5wcm90b2J1Zi5VSW50NjRWYWx1ZRI8ChZvcHRpb25hbF9m", + "bG9hdF93cmFwcGVyGM4BIAEoCzIbLmdvb2dsZS5wcm90b2J1Zi5GbG9hdFZh", + "bHVlEj4KF29wdGlvbmFsX2RvdWJsZV93cmFwcGVyGM8BIAEoCzIcLmdvb2ds", + "ZS5wcm90b2J1Zi5Eb3VibGVWYWx1ZRI+ChdvcHRpb25hbF9zdHJpbmdfd3Jh", + "cHBlchjQASABKAsyHC5nb29nbGUucHJvdG9idWYuU3RyaW5nVmFsdWUSPAoW", + "b3B0aW9uYWxfYnl0ZXNfd3JhcHBlchjRASABKAsyGy5nb29nbGUucHJvdG9i", + "dWYuQnl0ZXNWYWx1ZRI6ChVyZXBlYXRlZF9ib29sX3dyYXBwZXIY0wEgAygL", + "MhouZ29vZ2xlLnByb3RvYnVmLkJvb2xWYWx1ZRI8ChZyZXBlYXRlZF9pbnQz", + "Ml93cmFwcGVyGNQBIAMoCzIbLmdvb2dsZS5wcm90b2J1Zi5JbnQzMlZhbHVl", + "EjwKFnJlcGVhdGVkX2ludDY0X3dyYXBwZXIY1QEgAygLMhsuZ29vZ2xlLnBy", + "b3RvYnVmLkludDY0VmFsdWUSPgoXcmVwZWF0ZWRfdWludDMyX3dyYXBwZXIY", + "1gEgAygLMhwuZ29vZ2xlLnByb3RvYnVmLlVJbnQzMlZhbHVlEj4KF3JlcGVh", + "dGVkX3VpbnQ2NF93cmFwcGVyGNcBIAMoCzIcLmdvb2dsZS5wcm90b2J1Zi5V", + "SW50NjRWYWx1ZRI8ChZyZXBlYXRlZF9mbG9hdF93cmFwcGVyGNgBIAMoCzIb", + "Lmdvb2dsZS5wcm90b2J1Zi5GbG9hdFZhbHVlEj4KF3JlcGVhdGVkX2RvdWJs", + "ZV93cmFwcGVyGNkBIAMoCzIcLmdvb2dsZS5wcm90b2J1Zi5Eb3VibGVWYWx1", + "ZRI+ChdyZXBlYXRlZF9zdHJpbmdfd3JhcHBlchjaASADKAsyHC5nb29nbGUu", + "cHJvdG9idWYuU3RyaW5nVmFsdWUSPAoWcmVwZWF0ZWRfYnl0ZXNfd3JhcHBl", + "chjbASADKAsyGy5nb29nbGUucHJvdG9idWYuQnl0ZXNWYWx1ZRI1ChFvcHRp", + "b25hbF9kdXJhdGlvbhitAiABKAsyGS5nb29nbGUucHJvdG9idWYuRHVyYXRp", + "b24SNwoSb3B0aW9uYWxfdGltZXN0YW1wGK4CIAEoCzIaLmdvb2dsZS5wcm90", + "b2J1Zi5UaW1lc3RhbXASOAoTb3B0aW9uYWxfZmllbGRfbWFzaxivAiABKAsy", + "Gi5nb29nbGUucHJvdG9idWYuRmllbGRNYXNrEjEKD29wdGlvbmFsX3N0cnVj", + "dBiwAiABKAsyFy5nb29nbGUucHJvdG9idWYuU3RydWN0EisKDG9wdGlvbmFs", + "X2FueRixAiABKAsyFC5nb29nbGUucHJvdG9idWYuQW55Ei8KDm9wdGlvbmFs", + "X3ZhbHVlGLICIAEoCzIWLmdvb2dsZS5wcm90b2J1Zi5WYWx1ZRI1ChFyZXBl", + "YXRlZF9kdXJhdGlvbhi3AiADKAsyGS5nb29nbGUucHJvdG9idWYuRHVyYXRp", + "b24SNwoScmVwZWF0ZWRfdGltZXN0YW1wGLgCIAMoCzIaLmdvb2dsZS5wcm90", + "b2J1Zi5UaW1lc3RhbXASNwoScmVwZWF0ZWRfZmllbGRtYXNrGLkCIAMoCzIa", + "Lmdvb2dsZS5wcm90b2J1Zi5GaWVsZE1hc2sSMQoPcmVwZWF0ZWRfc3RydWN0", + "GMQCIAMoCzIXLmdvb2dsZS5wcm90b2J1Zi5TdHJ1Y3QSKwoMcmVwZWF0ZWRf", + "YW55GLsCIAMoCzIULmdvb2dsZS5wcm90b2J1Zi5BbnkSLwoOcmVwZWF0ZWRf", + "dmFsdWUYvAIgAygLMhYuZ29vZ2xlLnByb3RvYnVmLlZhbHVlEhMKCmZpZWxk", + "bmFtZTEYkQMgASgFEhQKC2ZpZWxkX25hbWUyGJIDIAEoBRIVCgxfZmllbGRf", + "bmFtZTMYkwMgASgFEhYKDWZpZWxkX19uYW1lNF8YlAMgASgFEhQKC2ZpZWxk", + "MG5hbWU1GJUDIAEoBRIWCg1maWVsZF8wX25hbWU2GJYDIAEoBRITCgpmaWVs", + "ZE5hbWU3GJcDIAEoBRITCgpGaWVsZE5hbWU4GJgDIAEoBRIUCgtmaWVsZF9O", + "YW1lORiZAyABKAUSFQoMRmllbGRfTmFtZTEwGJoDIAEoBRIVCgxGSUVMRF9O", + "QU1FMTEYmwMgASgFEhUKDEZJRUxEX25hbWUxMhicAyABKAUaSgoNTmVzdGVk", + "TWVzc2FnZRIJCgFhGAEgASgFEi4KC2NvcmVjdXJzaXZlGAIgASgLMhkuY29u", + "Zm9ybWFuY2UuVGVzdEFsbFR5cGVzGjQKEk1hcEludDMySW50MzJFbnRyeRIL", + "CgNrZXkYASABKAUSDQoFdmFsdWUYAiABKAU6AjgBGjQKEk1hcEludDY0SW50", + "NjRFbnRyeRILCgNrZXkYASABKAMSDQoFdmFsdWUYAiABKAM6AjgBGjYKFE1h", + "cFVpbnQzMlVpbnQzMkVudHJ5EgsKA2tleRgBIAEoDRINCgV2YWx1ZRgCIAEo", + "DToCOAEaNgoUTWFwVWludDY0VWludDY0RW50cnkSCwoDa2V5GAEgASgEEg0K", + "BXZhbHVlGAIgASgEOgI4ARo2ChRNYXBTaW50MzJTaW50MzJFbnRyeRILCgNr", + "ZXkYASABKBESDQoFdmFsdWUYAiABKBE6AjgBGjYKFE1hcFNpbnQ2NFNpbnQ2", + "NEVudHJ5EgsKA2tleRgBIAEoEhINCgV2YWx1ZRgCIAEoEjoCOAEaOAoWTWFw", + "Rml4ZWQzMkZpeGVkMzJFbnRyeRILCgNrZXkYASABKAcSDQoFdmFsdWUYAiAB", + "KAc6AjgBGjgKFk1hcEZpeGVkNjRGaXhlZDY0RW50cnkSCwoDa2V5GAEgASgG", + "Eg0KBXZhbHVlGAIgASgGOgI4ARo6ChhNYXBTZml4ZWQzMlNmaXhlZDMyRW50", + "cnkSCwoDa2V5GAEgASgPEg0KBXZhbHVlGAIgASgPOgI4ARo6ChhNYXBTZml4", + "ZWQ2NFNmaXhlZDY0RW50cnkSCwoDa2V5GAEgASgQEg0KBXZhbHVlGAIgASgQ", + "OgI4ARo0ChJNYXBJbnQzMkZsb2F0RW50cnkSCwoDa2V5GAEgASgFEg0KBXZh", + "bHVlGAIgASgCOgI4ARo1ChNNYXBJbnQzMkRvdWJsZUVudHJ5EgsKA2tleRgB", + "IAEoBRINCgV2YWx1ZRgCIAEoAToCOAEaMgoQTWFwQm9vbEJvb2xFbnRyeRIL", + "CgNrZXkYASABKAgSDQoFdmFsdWUYAiABKAg6AjgBGjYKFE1hcFN0cmluZ1N0", + "cmluZ0VudHJ5EgsKA2tleRgBIAEoCRINCgV2YWx1ZRgCIAEoCToCOAEaNQoT", + "TWFwU3RyaW5nQnl0ZXNFbnRyeRILCgNrZXkYASABKAkSDQoFdmFsdWUYAiAB", + "KAw6AjgBGmYKG01hcFN0cmluZ05lc3RlZE1lc3NhZ2VFbnRyeRILCgNrZXkY", + "ASABKAkSNgoFdmFsdWUYAiABKAsyJy5jb25mb3JtYW5jZS5UZXN0QWxsVHlw", + "ZXMuTmVzdGVkTWVzc2FnZToCOAEaWwocTWFwU3RyaW5nRm9yZWlnbk1lc3Nh", + "Z2VFbnRyeRILCgNrZXkYASABKAkSKgoFdmFsdWUYAiABKAsyGy5jb25mb3Jt", + "YW5jZS5Gb3JlaWduTWVzc2FnZToCOAEaYAoYTWFwU3RyaW5nTmVzdGVkRW51", + "bUVudHJ5EgsKA2tleRgBIAEoCRIzCgV2YWx1ZRgCIAEoDjIkLmNvbmZvcm1h", + "bmNlLlRlc3RBbGxUeXBlcy5OZXN0ZWRFbnVtOgI4ARpVChlNYXBTdHJpbmdG", + "b3JlaWduRW51bUVudHJ5EgsKA2tleRgBIAEoCRInCgV2YWx1ZRgCIAEoDjIY", + "LmNvbmZvcm1hbmNlLkZvcmVpZ25FbnVtOgI4ASI5CgpOZXN0ZWRFbnVtEgcK", + "A0ZPTxAAEgcKA0JBUhABEgcKA0JBWhACEhAKA05FRxD///////////8BQg0K", + "C29uZW9mX2ZpZWxkIhsKDkZvcmVpZ25NZXNzYWdlEgkKAWMYASABKAUqNQoK", + "V2lyZUZvcm1hdBIPCgtVTlNQRUNJRklFRBAAEgwKCFBST1RPQlVGEAESCAoE", + "SlNPThACKkAKC0ZvcmVpZ25FbnVtEg8KC0ZPUkVJR05fRk9PEAASDwoLRk9S", + "RUlHTl9CQVIQARIPCgtGT1JFSUdOX0JBWhACQiEKH2NvbS5nb29nbGUucHJv", + "dG9idWYuY29uZm9ybWFuY2ViBnByb3RvMw==")); + descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, + new pbr::FileDescriptor[] { global::Google.Protobuf.WellKnownTypes.AnyReflection.Descriptor, global::Google.Protobuf.WellKnownTypes.DurationReflection.Descriptor, global::Google.Protobuf.WellKnownTypes.FieldMaskReflection.Descriptor, global::Google.Protobuf.WellKnownTypes.StructReflection.Descriptor, global::Google.Protobuf.WellKnownTypes.TimestampReflection.Descriptor, global::Google.Protobuf.WellKnownTypes.WrappersReflection.Descriptor, }, + new pbr::GeneratedClrTypeInfo(new[] {typeof(global::Conformance.WireFormat), typeof(global::Conformance.ForeignEnum), }, new pbr::GeneratedClrTypeInfo[] { + new pbr::GeneratedClrTypeInfo(typeof(global::Conformance.ConformanceRequest), global::Conformance.ConformanceRequest.Parser, new[]{ "ProtobufPayload", "JsonPayload", "RequestedOutputFormat" }, new[]{ "Payload" }, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Conformance.ConformanceResponse), global::Conformance.ConformanceResponse.Parser, new[]{ "ParseError", "SerializeError", "RuntimeError", "ProtobufPayload", "JsonPayload", "Skipped" }, new[]{ "Result" }, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Conformance.TestAllTypes), global::Conformance.TestAllTypes.Parser, new[]{ "OptionalInt32", "OptionalInt64", "OptionalUint32", "OptionalUint64", "OptionalSint32", "OptionalSint64", "OptionalFixed32", "OptionalFixed64", "OptionalSfixed32", "OptionalSfixed64", "OptionalFloat", "OptionalDouble", "OptionalBool", "OptionalString", "OptionalBytes", "OptionalNestedMessage", "OptionalForeignMessage", "OptionalNestedEnum", "OptionalForeignEnum", "OptionalStringPiece", "OptionalCord", "RecursiveMessage", "RepeatedInt32", "RepeatedInt64", "RepeatedUint32", "RepeatedUint64", "RepeatedSint32", "RepeatedSint64", "RepeatedFixed32", "RepeatedFixed64", "RepeatedSfixed32", "RepeatedSfixed64", "RepeatedFloat", "RepeatedDouble", "RepeatedBool", "RepeatedString", "RepeatedBytes", "RepeatedNestedMessage", "RepeatedForeignMessage", "RepeatedNestedEnum", "RepeatedForeignEnum", "RepeatedStringPiece", "RepeatedCord", "MapInt32Int32", "MapInt64Int64", "MapUint32Uint32", "MapUint64Uint64", "MapSint32Sint32", "MapSint64Sint64", "MapFixed32Fixed32", "MapFixed64Fixed64", "MapSfixed32Sfixed32", "MapSfixed64Sfixed64", "MapInt32Float", "MapInt32Double", "MapBoolBool", "MapStringString", "MapStringBytes", "MapStringNestedMessage", "MapStringForeignMessage", "MapStringNestedEnum", "MapStringForeignEnum", "OneofUint32", "OneofNestedMessage", "OneofString", "OneofBytes", "OptionalBoolWrapper", "OptionalInt32Wrapper", "OptionalInt64Wrapper", "OptionalUint32Wrapper", "OptionalUint64Wrapper", "OptionalFloatWrapper", "OptionalDoubleWrapper", "OptionalStringWrapper", "OptionalBytesWrapper", "RepeatedBoolWrapper", "RepeatedInt32Wrapper", "RepeatedInt64Wrapper", "RepeatedUint32Wrapper", "RepeatedUint64Wrapper", "RepeatedFloatWrapper", "RepeatedDoubleWrapper", "RepeatedStringWrapper", "RepeatedBytesWrapper", "OptionalDuration", "OptionalTimestamp", "OptionalFieldMask", "OptionalStruct", "OptionalAny", "OptionalValue", "RepeatedDuration", "RepeatedTimestamp", "RepeatedFieldmask", "RepeatedStruct", "RepeatedAny", "RepeatedValue", "Fieldname1", "FieldName2", "FieldName3", "FieldName4", "Field0Name5", "Field0Name6", "FieldName7", "FieldName8", "FieldName9", "FieldName10", "FIELDNAME11", "FIELDName12" }, new[]{ "OneofField" }, new[]{ typeof(global::Conformance.TestAllTypes.Types.NestedEnum) }, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::Conformance.TestAllTypes.Types.NestedMessage), global::Conformance.TestAllTypes.Types.NestedMessage.Parser, new[]{ "A", "Corecursive" }, null, null, null), null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, }), - new pbr::GeneratedCodeInfo(typeof(global::Conformance.ForeignMessage), global::Conformance.ForeignMessage.Parser, new[]{ "C" }, null, null, null) + new pbr::GeneratedClrTypeInfo(typeof(global::Conformance.ForeignMessage), global::Conformance.ForeignMessage.Parser, new[]{ "C" }, null, null, null) })); } #endregion @@ -211,7 +261,7 @@ namespace Conformance { public pb::ByteString ProtobufPayload { get { return payloadCase_ == PayloadOneofCase.ProtobufPayload ? (pb::ByteString) payload_ : pb::ByteString.Empty; } set { - payload_ = pb::Preconditions.CheckNotNull(value, "value"); + payload_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); payloadCase_ = PayloadOneofCase.ProtobufPayload; } } @@ -221,7 +271,7 @@ namespace Conformance { public string JsonPayload { get { return payloadCase_ == PayloadOneofCase.JsonPayload ? (string) payload_ : ""; } set { - payload_ = pb::Preconditions.CheckNotNull(value, "value"); + payload_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); payloadCase_ = PayloadOneofCase.JsonPayload; } } @@ -284,7 +334,7 @@ namespace Conformance { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -386,6 +436,9 @@ namespace Conformance { case ResultOneofCase.ParseError: ParseError = other.ParseError; break; + case ResultOneofCase.SerializeError: + SerializeError = other.SerializeError; + break; case ResultOneofCase.RuntimeError: RuntimeError = other.RuntimeError; break; @@ -418,11 +471,26 @@ namespace Conformance { public string ParseError { get { return resultCase_ == ResultOneofCase.ParseError ? (string) result_ : ""; } set { - result_ = pb::Preconditions.CheckNotNull(value, "value"); + result_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); resultCase_ = ResultOneofCase.ParseError; } } + /// <summary>Field number for the "serialize_error" field.</summary> + public const int SerializeErrorFieldNumber = 6; + /// <summary> + /// If the input was successfully parsed but errors occurred when + /// serializing it to the requested output format, set the error message in + /// this field. + /// </summary> + public string SerializeError { + get { return resultCase_ == ResultOneofCase.SerializeError ? (string) result_ : ""; } + set { + result_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + resultCase_ = ResultOneofCase.SerializeError; + } + } + /// <summary>Field number for the "runtime_error" field.</summary> public const int RuntimeErrorFieldNumber = 2; /// <summary> @@ -433,7 +501,7 @@ namespace Conformance { public string RuntimeError { get { return resultCase_ == ResultOneofCase.RuntimeError ? (string) result_ : ""; } set { - result_ = pb::Preconditions.CheckNotNull(value, "value"); + result_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); resultCase_ = ResultOneofCase.RuntimeError; } } @@ -447,7 +515,7 @@ namespace Conformance { public pb::ByteString ProtobufPayload { get { return resultCase_ == ResultOneofCase.ProtobufPayload ? (pb::ByteString) result_ : pb::ByteString.Empty; } set { - result_ = pb::Preconditions.CheckNotNull(value, "value"); + result_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); resultCase_ = ResultOneofCase.ProtobufPayload; } } @@ -461,7 +529,7 @@ namespace Conformance { public string JsonPayload { get { return resultCase_ == ResultOneofCase.JsonPayload ? (string) result_ : ""; } set { - result_ = pb::Preconditions.CheckNotNull(value, "value"); + result_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); resultCase_ = ResultOneofCase.JsonPayload; } } @@ -475,7 +543,7 @@ namespace Conformance { public string Skipped { get { return resultCase_ == ResultOneofCase.Skipped ? (string) result_ : ""; } set { - result_ = pb::Preconditions.CheckNotNull(value, "value"); + result_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); resultCase_ = ResultOneofCase.Skipped; } } @@ -485,6 +553,7 @@ namespace Conformance { public enum ResultOneofCase { None = 0, ParseError = 1, + SerializeError = 6, RuntimeError = 2, ProtobufPayload = 3, JsonPayload = 4, @@ -512,6 +581,7 @@ namespace Conformance { return true; } if (ParseError != other.ParseError) return false; + if (SerializeError != other.SerializeError) return false; if (RuntimeError != other.RuntimeError) return false; if (ProtobufPayload != other.ProtobufPayload) return false; if (JsonPayload != other.JsonPayload) return false; @@ -523,6 +593,7 @@ namespace Conformance { public override int GetHashCode() { int hash = 1; if (resultCase_ == ResultOneofCase.ParseError) hash ^= ParseError.GetHashCode(); + if (resultCase_ == ResultOneofCase.SerializeError) hash ^= SerializeError.GetHashCode(); if (resultCase_ == ResultOneofCase.RuntimeError) hash ^= RuntimeError.GetHashCode(); if (resultCase_ == ResultOneofCase.ProtobufPayload) hash ^= ProtobufPayload.GetHashCode(); if (resultCase_ == ResultOneofCase.JsonPayload) hash ^= JsonPayload.GetHashCode(); @@ -532,7 +603,7 @@ namespace Conformance { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -556,6 +627,10 @@ namespace Conformance { output.WriteRawTag(42); output.WriteString(Skipped); } + if (resultCase_ == ResultOneofCase.SerializeError) { + output.WriteRawTag(50); + output.WriteString(SerializeError); + } } public int CalculateSize() { @@ -563,6 +638,9 @@ namespace Conformance { if (resultCase_ == ResultOneofCase.ParseError) { size += 1 + pb::CodedOutputStream.ComputeStringSize(ParseError); } + if (resultCase_ == ResultOneofCase.SerializeError) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(SerializeError); + } if (resultCase_ == ResultOneofCase.RuntimeError) { size += 1 + pb::CodedOutputStream.ComputeStringSize(RuntimeError); } @@ -586,6 +664,9 @@ namespace Conformance { case ResultOneofCase.ParseError: ParseError = other.ParseError; break; + case ResultOneofCase.SerializeError: + SerializeError = other.SerializeError; + break; case ResultOneofCase.RuntimeError: RuntimeError = other.RuntimeError; break; @@ -629,6 +710,10 @@ namespace Conformance { Skipped = input.ReadString(); break; } + case 50: { + SerializeError = input.ReadString(); + break; + } } } } @@ -721,6 +806,48 @@ namespace Conformance { mapStringForeignMessage_ = other.mapStringForeignMessage_.Clone(); mapStringNestedEnum_ = other.mapStringNestedEnum_.Clone(); mapStringForeignEnum_ = other.mapStringForeignEnum_.Clone(); + OptionalBoolWrapper = other.OptionalBoolWrapper; + OptionalInt32Wrapper = other.OptionalInt32Wrapper; + OptionalInt64Wrapper = other.OptionalInt64Wrapper; + OptionalUint32Wrapper = other.OptionalUint32Wrapper; + OptionalUint64Wrapper = other.OptionalUint64Wrapper; + OptionalFloatWrapper = other.OptionalFloatWrapper; + OptionalDoubleWrapper = other.OptionalDoubleWrapper; + OptionalStringWrapper = other.OptionalStringWrapper; + OptionalBytesWrapper = other.OptionalBytesWrapper; + repeatedBoolWrapper_ = other.repeatedBoolWrapper_.Clone(); + repeatedInt32Wrapper_ = other.repeatedInt32Wrapper_.Clone(); + repeatedInt64Wrapper_ = other.repeatedInt64Wrapper_.Clone(); + repeatedUint32Wrapper_ = other.repeatedUint32Wrapper_.Clone(); + repeatedUint64Wrapper_ = other.repeatedUint64Wrapper_.Clone(); + repeatedFloatWrapper_ = other.repeatedFloatWrapper_.Clone(); + repeatedDoubleWrapper_ = other.repeatedDoubleWrapper_.Clone(); + repeatedStringWrapper_ = other.repeatedStringWrapper_.Clone(); + repeatedBytesWrapper_ = other.repeatedBytesWrapper_.Clone(); + OptionalDuration = other.optionalDuration_ != null ? other.OptionalDuration.Clone() : null; + OptionalTimestamp = other.optionalTimestamp_ != null ? other.OptionalTimestamp.Clone() : null; + OptionalFieldMask = other.optionalFieldMask_ != null ? other.OptionalFieldMask.Clone() : null; + OptionalStruct = other.optionalStruct_ != null ? other.OptionalStruct.Clone() : null; + OptionalAny = other.optionalAny_ != null ? other.OptionalAny.Clone() : null; + OptionalValue = other.optionalValue_ != null ? other.OptionalValue.Clone() : null; + repeatedDuration_ = other.repeatedDuration_.Clone(); + repeatedTimestamp_ = other.repeatedTimestamp_.Clone(); + repeatedFieldmask_ = other.repeatedFieldmask_.Clone(); + repeatedStruct_ = other.repeatedStruct_.Clone(); + repeatedAny_ = other.repeatedAny_.Clone(); + repeatedValue_ = other.repeatedValue_.Clone(); + fieldname1_ = other.fieldname1_; + fieldName2_ = other.fieldName2_; + FieldName3_ = other.FieldName3_; + fieldName4_ = other.fieldName4_; + field0Name5_ = other.field0Name5_; + field0Name6_ = other.field0Name6_; + fieldName7_ = other.fieldName7_; + fieldName8_ = other.fieldName8_; + fieldName9_ = other.fieldName9_; + fieldName10_ = other.fieldName10_; + fIELDNAME11_ = other.fIELDNAME11_; + fIELDName12_ = other.fIELDName12_; switch (other.OneofFieldCase) { case OneofFieldOneofCase.OneofUint32: OneofUint32 = other.OneofUint32; @@ -881,7 +1008,7 @@ namespace Conformance { public string OptionalString { get { return optionalString_; } set { - optionalString_ = pb::Preconditions.CheckNotNull(value, "value"); + optionalString_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } @@ -891,7 +1018,7 @@ namespace Conformance { public pb::ByteString OptionalBytes { get { return optionalBytes_; } set { - optionalBytes_ = pb::Preconditions.CheckNotNull(value, "value"); + optionalBytes_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } @@ -941,7 +1068,7 @@ namespace Conformance { public string OptionalStringPiece { get { return optionalStringPiece_; } set { - optionalStringPiece_ = pb::Preconditions.CheckNotNull(value, "value"); + optionalStringPiece_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } @@ -951,7 +1078,7 @@ namespace Conformance { public string OptionalCord { get { return optionalCord_; } set { - optionalCord_ = pb::Preconditions.CheckNotNull(value, "value"); + optionalCord_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } @@ -1356,7 +1483,7 @@ namespace Conformance { public string OneofString { get { return oneofFieldCase_ == OneofFieldOneofCase.OneofString ? (string) oneofField_ : ""; } set { - oneofField_ = pb::Preconditions.CheckNotNull(value, "value"); + oneofField_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); oneofFieldCase_ = OneofFieldOneofCase.OneofString; } } @@ -1366,11 +1493,431 @@ namespace Conformance { public pb::ByteString OneofBytes { get { return oneofFieldCase_ == OneofFieldOneofCase.OneofBytes ? (pb::ByteString) oneofField_ : pb::ByteString.Empty; } set { - oneofField_ = pb::Preconditions.CheckNotNull(value, "value"); + oneofField_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); oneofFieldCase_ = OneofFieldOneofCase.OneofBytes; } } + /// <summary>Field number for the "optional_bool_wrapper" field.</summary> + public const int OptionalBoolWrapperFieldNumber = 201; + private static readonly pb::FieldCodec<bool?> _single_optionalBoolWrapper_codec = pb::FieldCodec.ForStructWrapper<bool>(1610); + private bool? optionalBoolWrapper_; + /// <summary> + /// Well-known types + /// </summary> + public bool? OptionalBoolWrapper { + get { return optionalBoolWrapper_; } + set { + optionalBoolWrapper_ = value; + } + } + + /// <summary>Field number for the "optional_int32_wrapper" field.</summary> + public const int OptionalInt32WrapperFieldNumber = 202; + private static readonly pb::FieldCodec<int?> _single_optionalInt32Wrapper_codec = pb::FieldCodec.ForStructWrapper<int>(1618); + private int? optionalInt32Wrapper_; + public int? OptionalInt32Wrapper { + get { return optionalInt32Wrapper_; } + set { + optionalInt32Wrapper_ = value; + } + } + + /// <summary>Field number for the "optional_int64_wrapper" field.</summary> + public const int OptionalInt64WrapperFieldNumber = 203; + private static readonly pb::FieldCodec<long?> _single_optionalInt64Wrapper_codec = pb::FieldCodec.ForStructWrapper<long>(1626); + private long? optionalInt64Wrapper_; + public long? OptionalInt64Wrapper { + get { return optionalInt64Wrapper_; } + set { + optionalInt64Wrapper_ = value; + } + } + + /// <summary>Field number for the "optional_uint32_wrapper" field.</summary> + public const int OptionalUint32WrapperFieldNumber = 204; + private static readonly pb::FieldCodec<uint?> _single_optionalUint32Wrapper_codec = pb::FieldCodec.ForStructWrapper<uint>(1634); + private uint? optionalUint32Wrapper_; + public uint? OptionalUint32Wrapper { + get { return optionalUint32Wrapper_; } + set { + optionalUint32Wrapper_ = value; + } + } + + /// <summary>Field number for the "optional_uint64_wrapper" field.</summary> + public const int OptionalUint64WrapperFieldNumber = 205; + private static readonly pb::FieldCodec<ulong?> _single_optionalUint64Wrapper_codec = pb::FieldCodec.ForStructWrapper<ulong>(1642); + private ulong? optionalUint64Wrapper_; + public ulong? OptionalUint64Wrapper { + get { return optionalUint64Wrapper_; } + set { + optionalUint64Wrapper_ = value; + } + } + + /// <summary>Field number for the "optional_float_wrapper" field.</summary> + public const int OptionalFloatWrapperFieldNumber = 206; + private static readonly pb::FieldCodec<float?> _single_optionalFloatWrapper_codec = pb::FieldCodec.ForStructWrapper<float>(1650); + private float? optionalFloatWrapper_; + public float? OptionalFloatWrapper { + get { return optionalFloatWrapper_; } + set { + optionalFloatWrapper_ = value; + } + } + + /// <summary>Field number for the "optional_double_wrapper" field.</summary> + public const int OptionalDoubleWrapperFieldNumber = 207; + private static readonly pb::FieldCodec<double?> _single_optionalDoubleWrapper_codec = pb::FieldCodec.ForStructWrapper<double>(1658); + private double? optionalDoubleWrapper_; + public double? OptionalDoubleWrapper { + get { return optionalDoubleWrapper_; } + set { + optionalDoubleWrapper_ = value; + } + } + + /// <summary>Field number for the "optional_string_wrapper" field.</summary> + public const int OptionalStringWrapperFieldNumber = 208; + private static readonly pb::FieldCodec<string> _single_optionalStringWrapper_codec = pb::FieldCodec.ForClassWrapper<string>(1666); + private string optionalStringWrapper_; + public string OptionalStringWrapper { + get { return optionalStringWrapper_; } + set { + optionalStringWrapper_ = value; + } + } + + /// <summary>Field number for the "optional_bytes_wrapper" field.</summary> + public const int OptionalBytesWrapperFieldNumber = 209; + private static readonly pb::FieldCodec<pb::ByteString> _single_optionalBytesWrapper_codec = pb::FieldCodec.ForClassWrapper<pb::ByteString>(1674); + private pb::ByteString optionalBytesWrapper_; + public pb::ByteString OptionalBytesWrapper { + get { return optionalBytesWrapper_; } + set { + optionalBytesWrapper_ = value; + } + } + + /// <summary>Field number for the "repeated_bool_wrapper" field.</summary> + public const int RepeatedBoolWrapperFieldNumber = 211; + private static readonly pb::FieldCodec<bool?> _repeated_repeatedBoolWrapper_codec + = pb::FieldCodec.ForStructWrapper<bool>(1690); + private readonly pbc::RepeatedField<bool?> repeatedBoolWrapper_ = new pbc::RepeatedField<bool?>(); + public pbc::RepeatedField<bool?> RepeatedBoolWrapper { + get { return repeatedBoolWrapper_; } + } + + /// <summary>Field number for the "repeated_int32_wrapper" field.</summary> + public const int RepeatedInt32WrapperFieldNumber = 212; + private static readonly pb::FieldCodec<int?> _repeated_repeatedInt32Wrapper_codec + = pb::FieldCodec.ForStructWrapper<int>(1698); + private readonly pbc::RepeatedField<int?> repeatedInt32Wrapper_ = new pbc::RepeatedField<int?>(); + public pbc::RepeatedField<int?> RepeatedInt32Wrapper { + get { return repeatedInt32Wrapper_; } + } + + /// <summary>Field number for the "repeated_int64_wrapper" field.</summary> + public const int RepeatedInt64WrapperFieldNumber = 213; + private static readonly pb::FieldCodec<long?> _repeated_repeatedInt64Wrapper_codec + = pb::FieldCodec.ForStructWrapper<long>(1706); + private readonly pbc::RepeatedField<long?> repeatedInt64Wrapper_ = new pbc::RepeatedField<long?>(); + public pbc::RepeatedField<long?> RepeatedInt64Wrapper { + get { return repeatedInt64Wrapper_; } + } + + /// <summary>Field number for the "repeated_uint32_wrapper" field.</summary> + public const int RepeatedUint32WrapperFieldNumber = 214; + private static readonly pb::FieldCodec<uint?> _repeated_repeatedUint32Wrapper_codec + = pb::FieldCodec.ForStructWrapper<uint>(1714); + private readonly pbc::RepeatedField<uint?> repeatedUint32Wrapper_ = new pbc::RepeatedField<uint?>(); + public pbc::RepeatedField<uint?> RepeatedUint32Wrapper { + get { return repeatedUint32Wrapper_; } + } + + /// <summary>Field number for the "repeated_uint64_wrapper" field.</summary> + public const int RepeatedUint64WrapperFieldNumber = 215; + private static readonly pb::FieldCodec<ulong?> _repeated_repeatedUint64Wrapper_codec + = pb::FieldCodec.ForStructWrapper<ulong>(1722); + private readonly pbc::RepeatedField<ulong?> repeatedUint64Wrapper_ = new pbc::RepeatedField<ulong?>(); + public pbc::RepeatedField<ulong?> RepeatedUint64Wrapper { + get { return repeatedUint64Wrapper_; } + } + + /// <summary>Field number for the "repeated_float_wrapper" field.</summary> + public const int RepeatedFloatWrapperFieldNumber = 216; + private static readonly pb::FieldCodec<float?> _repeated_repeatedFloatWrapper_codec + = pb::FieldCodec.ForStructWrapper<float>(1730); + private readonly pbc::RepeatedField<float?> repeatedFloatWrapper_ = new pbc::RepeatedField<float?>(); + public pbc::RepeatedField<float?> RepeatedFloatWrapper { + get { return repeatedFloatWrapper_; } + } + + /// <summary>Field number for the "repeated_double_wrapper" field.</summary> + public const int RepeatedDoubleWrapperFieldNumber = 217; + private static readonly pb::FieldCodec<double?> _repeated_repeatedDoubleWrapper_codec + = pb::FieldCodec.ForStructWrapper<double>(1738); + private readonly pbc::RepeatedField<double?> repeatedDoubleWrapper_ = new pbc::RepeatedField<double?>(); + public pbc::RepeatedField<double?> RepeatedDoubleWrapper { + get { return repeatedDoubleWrapper_; } + } + + /// <summary>Field number for the "repeated_string_wrapper" field.</summary> + public const int RepeatedStringWrapperFieldNumber = 218; + private static readonly pb::FieldCodec<string> _repeated_repeatedStringWrapper_codec + = pb::FieldCodec.ForClassWrapper<string>(1746); + private readonly pbc::RepeatedField<string> repeatedStringWrapper_ = new pbc::RepeatedField<string>(); + public pbc::RepeatedField<string> RepeatedStringWrapper { + get { return repeatedStringWrapper_; } + } + + /// <summary>Field number for the "repeated_bytes_wrapper" field.</summary> + public const int RepeatedBytesWrapperFieldNumber = 219; + private static readonly pb::FieldCodec<pb::ByteString> _repeated_repeatedBytesWrapper_codec + = pb::FieldCodec.ForClassWrapper<pb::ByteString>(1754); + private readonly pbc::RepeatedField<pb::ByteString> repeatedBytesWrapper_ = new pbc::RepeatedField<pb::ByteString>(); + public pbc::RepeatedField<pb::ByteString> RepeatedBytesWrapper { + get { return repeatedBytesWrapper_; } + } + + /// <summary>Field number for the "optional_duration" field.</summary> + public const int OptionalDurationFieldNumber = 301; + private global::Google.Protobuf.WellKnownTypes.Duration optionalDuration_; + public global::Google.Protobuf.WellKnownTypes.Duration OptionalDuration { + get { return optionalDuration_; } + set { + optionalDuration_ = value; + } + } + + /// <summary>Field number for the "optional_timestamp" field.</summary> + public const int OptionalTimestampFieldNumber = 302; + private global::Google.Protobuf.WellKnownTypes.Timestamp optionalTimestamp_; + public global::Google.Protobuf.WellKnownTypes.Timestamp OptionalTimestamp { + get { return optionalTimestamp_; } + set { + optionalTimestamp_ = value; + } + } + + /// <summary>Field number for the "optional_field_mask" field.</summary> + public const int OptionalFieldMaskFieldNumber = 303; + private global::Google.Protobuf.WellKnownTypes.FieldMask optionalFieldMask_; + public global::Google.Protobuf.WellKnownTypes.FieldMask OptionalFieldMask { + get { return optionalFieldMask_; } + set { + optionalFieldMask_ = value; + } + } + + /// <summary>Field number for the "optional_struct" field.</summary> + public const int OptionalStructFieldNumber = 304; + private global::Google.Protobuf.WellKnownTypes.Struct optionalStruct_; + public global::Google.Protobuf.WellKnownTypes.Struct OptionalStruct { + get { return optionalStruct_; } + set { + optionalStruct_ = value; + } + } + + /// <summary>Field number for the "optional_any" field.</summary> + public const int OptionalAnyFieldNumber = 305; + private global::Google.Protobuf.WellKnownTypes.Any optionalAny_; + public global::Google.Protobuf.WellKnownTypes.Any OptionalAny { + get { return optionalAny_; } + set { + optionalAny_ = value; + } + } + + /// <summary>Field number for the "optional_value" field.</summary> + public const int OptionalValueFieldNumber = 306; + private global::Google.Protobuf.WellKnownTypes.Value optionalValue_; + public global::Google.Protobuf.WellKnownTypes.Value OptionalValue { + get { return optionalValue_; } + set { + optionalValue_ = value; + } + } + + /// <summary>Field number for the "repeated_duration" field.</summary> + public const int RepeatedDurationFieldNumber = 311; + private static readonly pb::FieldCodec<global::Google.Protobuf.WellKnownTypes.Duration> _repeated_repeatedDuration_codec + = pb::FieldCodec.ForMessage(2490, global::Google.Protobuf.WellKnownTypes.Duration.Parser); + private readonly pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Duration> repeatedDuration_ = new pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Duration>(); + public pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Duration> RepeatedDuration { + get { return repeatedDuration_; } + } + + /// <summary>Field number for the "repeated_timestamp" field.</summary> + public const int RepeatedTimestampFieldNumber = 312; + private static readonly pb::FieldCodec<global::Google.Protobuf.WellKnownTypes.Timestamp> _repeated_repeatedTimestamp_codec + = pb::FieldCodec.ForMessage(2498, global::Google.Protobuf.WellKnownTypes.Timestamp.Parser); + private readonly pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Timestamp> repeatedTimestamp_ = new pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Timestamp>(); + public pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Timestamp> RepeatedTimestamp { + get { return repeatedTimestamp_; } + } + + /// <summary>Field number for the "repeated_fieldmask" field.</summary> + public const int RepeatedFieldmaskFieldNumber = 313; + private static readonly pb::FieldCodec<global::Google.Protobuf.WellKnownTypes.FieldMask> _repeated_repeatedFieldmask_codec + = pb::FieldCodec.ForMessage(2506, global::Google.Protobuf.WellKnownTypes.FieldMask.Parser); + private readonly pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.FieldMask> repeatedFieldmask_ = new pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.FieldMask>(); + public pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.FieldMask> RepeatedFieldmask { + get { return repeatedFieldmask_; } + } + + /// <summary>Field number for the "repeated_struct" field.</summary> + public const int RepeatedStructFieldNumber = 324; + private static readonly pb::FieldCodec<global::Google.Protobuf.WellKnownTypes.Struct> _repeated_repeatedStruct_codec + = pb::FieldCodec.ForMessage(2594, global::Google.Protobuf.WellKnownTypes.Struct.Parser); + private readonly pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Struct> repeatedStruct_ = new pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Struct>(); + public pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Struct> RepeatedStruct { + get { return repeatedStruct_; } + } + + /// <summary>Field number for the "repeated_any" field.</summary> + public const int RepeatedAnyFieldNumber = 315; + private static readonly pb::FieldCodec<global::Google.Protobuf.WellKnownTypes.Any> _repeated_repeatedAny_codec + = pb::FieldCodec.ForMessage(2522, global::Google.Protobuf.WellKnownTypes.Any.Parser); + private readonly pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Any> repeatedAny_ = new pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Any>(); + public pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Any> RepeatedAny { + get { return repeatedAny_; } + } + + /// <summary>Field number for the "repeated_value" field.</summary> + public const int RepeatedValueFieldNumber = 316; + private static readonly pb::FieldCodec<global::Google.Protobuf.WellKnownTypes.Value> _repeated_repeatedValue_codec + = pb::FieldCodec.ForMessage(2530, global::Google.Protobuf.WellKnownTypes.Value.Parser); + private readonly pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Value> repeatedValue_ = new pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Value>(); + public pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Value> RepeatedValue { + get { return repeatedValue_; } + } + + /// <summary>Field number for the "fieldname1" field.</summary> + public const int Fieldname1FieldNumber = 401; + private int fieldname1_; + /// <summary> + /// Test field-name-to-JSON-name convention. + /// </summary> + public int Fieldname1 { + get { return fieldname1_; } + set { + fieldname1_ = value; + } + } + + /// <summary>Field number for the "field_name2" field.</summary> + public const int FieldName2FieldNumber = 402; + private int fieldName2_; + public int FieldName2 { + get { return fieldName2_; } + set { + fieldName2_ = value; + } + } + + /// <summary>Field number for the "_field_name3" field.</summary> + public const int FieldName3FieldNumber = 403; + private int FieldName3_; + public int FieldName3 { + get { return FieldName3_; } + set { + FieldName3_ = value; + } + } + + /// <summary>Field number for the "field__name4_" field.</summary> + public const int FieldName4FieldNumber = 404; + private int fieldName4_; + public int FieldName4 { + get { return fieldName4_; } + set { + fieldName4_ = value; + } + } + + /// <summary>Field number for the "field0name5" field.</summary> + public const int Field0Name5FieldNumber = 405; + private int field0Name5_; + public int Field0Name5 { + get { return field0Name5_; } + set { + field0Name5_ = value; + } + } + + /// <summary>Field number for the "field_0_name6" field.</summary> + public const int Field0Name6FieldNumber = 406; + private int field0Name6_; + public int Field0Name6 { + get { return field0Name6_; } + set { + field0Name6_ = value; + } + } + + /// <summary>Field number for the "fieldName7" field.</summary> + public const int FieldName7FieldNumber = 407; + private int fieldName7_; + public int FieldName7 { + get { return fieldName7_; } + set { + fieldName7_ = value; + } + } + + /// <summary>Field number for the "FieldName8" field.</summary> + public const int FieldName8FieldNumber = 408; + private int fieldName8_; + public int FieldName8 { + get { return fieldName8_; } + set { + fieldName8_ = value; + } + } + + /// <summary>Field number for the "field_Name9" field.</summary> + public const int FieldName9FieldNumber = 409; + private int fieldName9_; + public int FieldName9 { + get { return fieldName9_; } + set { + fieldName9_ = value; + } + } + + /// <summary>Field number for the "Field_Name10" field.</summary> + public const int FieldName10FieldNumber = 410; + private int fieldName10_; + public int FieldName10 { + get { return fieldName10_; } + set { + fieldName10_ = value; + } + } + + /// <summary>Field number for the "FIELD_NAME11" field.</summary> + public const int FIELDNAME11FieldNumber = 411; + private int fIELDNAME11_; + public int FIELDNAME11 { + get { return fIELDNAME11_; } + set { + fIELDNAME11_ = value; + } + } + + /// <summary>Field number for the "FIELD_name12" field.</summary> + public const int FIELDName12FieldNumber = 412; + private int fIELDName12_; + public int FIELDName12 { + get { return fIELDName12_; } + set { + fIELDName12_ = value; + } + } + private object oneofField_; /// <summary>Enum of possible cases for the "oneof_field" oneof.</summary> public enum OneofFieldOneofCase { @@ -1467,6 +2014,48 @@ namespace Conformance { if (!object.Equals(OneofNestedMessage, other.OneofNestedMessage)) return false; if (OneofString != other.OneofString) return false; if (OneofBytes != other.OneofBytes) return false; + if (OptionalBoolWrapper != other.OptionalBoolWrapper) return false; + if (OptionalInt32Wrapper != other.OptionalInt32Wrapper) return false; + if (OptionalInt64Wrapper != other.OptionalInt64Wrapper) return false; + if (OptionalUint32Wrapper != other.OptionalUint32Wrapper) return false; + if (OptionalUint64Wrapper != other.OptionalUint64Wrapper) return false; + if (OptionalFloatWrapper != other.OptionalFloatWrapper) return false; + if (OptionalDoubleWrapper != other.OptionalDoubleWrapper) return false; + if (OptionalStringWrapper != other.OptionalStringWrapper) return false; + if (OptionalBytesWrapper != other.OptionalBytesWrapper) return false; + if(!repeatedBoolWrapper_.Equals(other.repeatedBoolWrapper_)) return false; + if(!repeatedInt32Wrapper_.Equals(other.repeatedInt32Wrapper_)) return false; + if(!repeatedInt64Wrapper_.Equals(other.repeatedInt64Wrapper_)) return false; + if(!repeatedUint32Wrapper_.Equals(other.repeatedUint32Wrapper_)) return false; + if(!repeatedUint64Wrapper_.Equals(other.repeatedUint64Wrapper_)) return false; + if(!repeatedFloatWrapper_.Equals(other.repeatedFloatWrapper_)) return false; + if(!repeatedDoubleWrapper_.Equals(other.repeatedDoubleWrapper_)) return false; + if(!repeatedStringWrapper_.Equals(other.repeatedStringWrapper_)) return false; + if(!repeatedBytesWrapper_.Equals(other.repeatedBytesWrapper_)) return false; + if (!object.Equals(OptionalDuration, other.OptionalDuration)) return false; + if (!object.Equals(OptionalTimestamp, other.OptionalTimestamp)) return false; + if (!object.Equals(OptionalFieldMask, other.OptionalFieldMask)) return false; + if (!object.Equals(OptionalStruct, other.OptionalStruct)) return false; + if (!object.Equals(OptionalAny, other.OptionalAny)) return false; + if (!object.Equals(OptionalValue, other.OptionalValue)) return false; + if(!repeatedDuration_.Equals(other.repeatedDuration_)) return false; + if(!repeatedTimestamp_.Equals(other.repeatedTimestamp_)) return false; + if(!repeatedFieldmask_.Equals(other.repeatedFieldmask_)) return false; + if(!repeatedStruct_.Equals(other.repeatedStruct_)) return false; + if(!repeatedAny_.Equals(other.repeatedAny_)) return false; + if(!repeatedValue_.Equals(other.repeatedValue_)) return false; + if (Fieldname1 != other.Fieldname1) return false; + if (FieldName2 != other.FieldName2) return false; + if (FieldName3 != other.FieldName3) return false; + if (FieldName4 != other.FieldName4) return false; + if (Field0Name5 != other.Field0Name5) return false; + if (Field0Name6 != other.Field0Name6) return false; + if (FieldName7 != other.FieldName7) return false; + if (FieldName8 != other.FieldName8) return false; + if (FieldName9 != other.FieldName9) return false; + if (FieldName10 != other.FieldName10) return false; + if (FIELDNAME11 != other.FIELDNAME11) return false; + if (FIELDName12 != other.FIELDName12) return false; if (OneofFieldCase != other.OneofFieldCase) return false; return true; } @@ -1539,12 +2128,54 @@ namespace Conformance { if (oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage) hash ^= OneofNestedMessage.GetHashCode(); if (oneofFieldCase_ == OneofFieldOneofCase.OneofString) hash ^= OneofString.GetHashCode(); if (oneofFieldCase_ == OneofFieldOneofCase.OneofBytes) hash ^= OneofBytes.GetHashCode(); + if (optionalBoolWrapper_ != null) hash ^= OptionalBoolWrapper.GetHashCode(); + if (optionalInt32Wrapper_ != null) hash ^= OptionalInt32Wrapper.GetHashCode(); + if (optionalInt64Wrapper_ != null) hash ^= OptionalInt64Wrapper.GetHashCode(); + if (optionalUint32Wrapper_ != null) hash ^= OptionalUint32Wrapper.GetHashCode(); + if (optionalUint64Wrapper_ != null) hash ^= OptionalUint64Wrapper.GetHashCode(); + if (optionalFloatWrapper_ != null) hash ^= OptionalFloatWrapper.GetHashCode(); + if (optionalDoubleWrapper_ != null) hash ^= OptionalDoubleWrapper.GetHashCode(); + if (optionalStringWrapper_ != null) hash ^= OptionalStringWrapper.GetHashCode(); + if (optionalBytesWrapper_ != null) hash ^= OptionalBytesWrapper.GetHashCode(); + hash ^= repeatedBoolWrapper_.GetHashCode(); + hash ^= repeatedInt32Wrapper_.GetHashCode(); + hash ^= repeatedInt64Wrapper_.GetHashCode(); + hash ^= repeatedUint32Wrapper_.GetHashCode(); + hash ^= repeatedUint64Wrapper_.GetHashCode(); + hash ^= repeatedFloatWrapper_.GetHashCode(); + hash ^= repeatedDoubleWrapper_.GetHashCode(); + hash ^= repeatedStringWrapper_.GetHashCode(); + hash ^= repeatedBytesWrapper_.GetHashCode(); + if (optionalDuration_ != null) hash ^= OptionalDuration.GetHashCode(); + if (optionalTimestamp_ != null) hash ^= OptionalTimestamp.GetHashCode(); + if (optionalFieldMask_ != null) hash ^= OptionalFieldMask.GetHashCode(); + if (optionalStruct_ != null) hash ^= OptionalStruct.GetHashCode(); + if (optionalAny_ != null) hash ^= OptionalAny.GetHashCode(); + if (optionalValue_ != null) hash ^= OptionalValue.GetHashCode(); + hash ^= repeatedDuration_.GetHashCode(); + hash ^= repeatedTimestamp_.GetHashCode(); + hash ^= repeatedFieldmask_.GetHashCode(); + hash ^= repeatedStruct_.GetHashCode(); + hash ^= repeatedAny_.GetHashCode(); + hash ^= repeatedValue_.GetHashCode(); + if (Fieldname1 != 0) hash ^= Fieldname1.GetHashCode(); + if (FieldName2 != 0) hash ^= FieldName2.GetHashCode(); + if (FieldName3 != 0) hash ^= FieldName3.GetHashCode(); + if (FieldName4 != 0) hash ^= FieldName4.GetHashCode(); + if (Field0Name5 != 0) hash ^= Field0Name5.GetHashCode(); + if (Field0Name6 != 0) hash ^= Field0Name6.GetHashCode(); + if (FieldName7 != 0) hash ^= FieldName7.GetHashCode(); + if (FieldName8 != 0) hash ^= FieldName8.GetHashCode(); + if (FieldName9 != 0) hash ^= FieldName9.GetHashCode(); + if (FieldName10 != 0) hash ^= FieldName10.GetHashCode(); + if (FIELDNAME11 != 0) hash ^= FIELDNAME11.GetHashCode(); + if (FIELDName12 != 0) hash ^= FIELDName12.GetHashCode(); hash ^= (int) oneofFieldCase_; return hash; } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -1692,6 +2323,120 @@ namespace Conformance { output.WriteRawTag(146, 7); output.WriteBytes(OneofBytes); } + if (optionalBoolWrapper_ != null) { + _single_optionalBoolWrapper_codec.WriteTagAndValue(output, OptionalBoolWrapper); + } + if (optionalInt32Wrapper_ != null) { + _single_optionalInt32Wrapper_codec.WriteTagAndValue(output, OptionalInt32Wrapper); + } + if (optionalInt64Wrapper_ != null) { + _single_optionalInt64Wrapper_codec.WriteTagAndValue(output, OptionalInt64Wrapper); + } + if (optionalUint32Wrapper_ != null) { + _single_optionalUint32Wrapper_codec.WriteTagAndValue(output, OptionalUint32Wrapper); + } + if (optionalUint64Wrapper_ != null) { + _single_optionalUint64Wrapper_codec.WriteTagAndValue(output, OptionalUint64Wrapper); + } + if (optionalFloatWrapper_ != null) { + _single_optionalFloatWrapper_codec.WriteTagAndValue(output, OptionalFloatWrapper); + } + if (optionalDoubleWrapper_ != null) { + _single_optionalDoubleWrapper_codec.WriteTagAndValue(output, OptionalDoubleWrapper); + } + if (optionalStringWrapper_ != null) { + _single_optionalStringWrapper_codec.WriteTagAndValue(output, OptionalStringWrapper); + } + if (optionalBytesWrapper_ != null) { + _single_optionalBytesWrapper_codec.WriteTagAndValue(output, OptionalBytesWrapper); + } + repeatedBoolWrapper_.WriteTo(output, _repeated_repeatedBoolWrapper_codec); + repeatedInt32Wrapper_.WriteTo(output, _repeated_repeatedInt32Wrapper_codec); + repeatedInt64Wrapper_.WriteTo(output, _repeated_repeatedInt64Wrapper_codec); + repeatedUint32Wrapper_.WriteTo(output, _repeated_repeatedUint32Wrapper_codec); + repeatedUint64Wrapper_.WriteTo(output, _repeated_repeatedUint64Wrapper_codec); + repeatedFloatWrapper_.WriteTo(output, _repeated_repeatedFloatWrapper_codec); + repeatedDoubleWrapper_.WriteTo(output, _repeated_repeatedDoubleWrapper_codec); + repeatedStringWrapper_.WriteTo(output, _repeated_repeatedStringWrapper_codec); + repeatedBytesWrapper_.WriteTo(output, _repeated_repeatedBytesWrapper_codec); + if (optionalDuration_ != null) { + output.WriteRawTag(234, 18); + output.WriteMessage(OptionalDuration); + } + if (optionalTimestamp_ != null) { + output.WriteRawTag(242, 18); + output.WriteMessage(OptionalTimestamp); + } + if (optionalFieldMask_ != null) { + output.WriteRawTag(250, 18); + output.WriteMessage(OptionalFieldMask); + } + if (optionalStruct_ != null) { + output.WriteRawTag(130, 19); + output.WriteMessage(OptionalStruct); + } + if (optionalAny_ != null) { + output.WriteRawTag(138, 19); + output.WriteMessage(OptionalAny); + } + if (optionalValue_ != null) { + output.WriteRawTag(146, 19); + output.WriteMessage(OptionalValue); + } + repeatedDuration_.WriteTo(output, _repeated_repeatedDuration_codec); + repeatedTimestamp_.WriteTo(output, _repeated_repeatedTimestamp_codec); + repeatedFieldmask_.WriteTo(output, _repeated_repeatedFieldmask_codec); + repeatedAny_.WriteTo(output, _repeated_repeatedAny_codec); + repeatedValue_.WriteTo(output, _repeated_repeatedValue_codec); + repeatedStruct_.WriteTo(output, _repeated_repeatedStruct_codec); + if (Fieldname1 != 0) { + output.WriteRawTag(136, 25); + output.WriteInt32(Fieldname1); + } + if (FieldName2 != 0) { + output.WriteRawTag(144, 25); + output.WriteInt32(FieldName2); + } + if (FieldName3 != 0) { + output.WriteRawTag(152, 25); + output.WriteInt32(FieldName3); + } + if (FieldName4 != 0) { + output.WriteRawTag(160, 25); + output.WriteInt32(FieldName4); + } + if (Field0Name5 != 0) { + output.WriteRawTag(168, 25); + output.WriteInt32(Field0Name5); + } + if (Field0Name6 != 0) { + output.WriteRawTag(176, 25); + output.WriteInt32(Field0Name6); + } + if (FieldName7 != 0) { + output.WriteRawTag(184, 25); + output.WriteInt32(FieldName7); + } + if (FieldName8 != 0) { + output.WriteRawTag(192, 25); + output.WriteInt32(FieldName8); + } + if (FieldName9 != 0) { + output.WriteRawTag(200, 25); + output.WriteInt32(FieldName9); + } + if (FieldName10 != 0) { + output.WriteRawTag(208, 25); + output.WriteInt32(FieldName10); + } + if (FIELDNAME11 != 0) { + output.WriteRawTag(216, 25); + output.WriteInt32(FIELDNAME11); + } + if (FIELDName12 != 0) { + output.WriteRawTag(224, 25); + output.WriteInt32(FIELDName12); + } } public int CalculateSize() { @@ -1814,6 +2559,102 @@ namespace Conformance { if (oneofFieldCase_ == OneofFieldOneofCase.OneofBytes) { size += 2 + pb::CodedOutputStream.ComputeBytesSize(OneofBytes); } + if (optionalBoolWrapper_ != null) { + size += _single_optionalBoolWrapper_codec.CalculateSizeWithTag(OptionalBoolWrapper); + } + if (optionalInt32Wrapper_ != null) { + size += _single_optionalInt32Wrapper_codec.CalculateSizeWithTag(OptionalInt32Wrapper); + } + if (optionalInt64Wrapper_ != null) { + size += _single_optionalInt64Wrapper_codec.CalculateSizeWithTag(OptionalInt64Wrapper); + } + if (optionalUint32Wrapper_ != null) { + size += _single_optionalUint32Wrapper_codec.CalculateSizeWithTag(OptionalUint32Wrapper); + } + if (optionalUint64Wrapper_ != null) { + size += _single_optionalUint64Wrapper_codec.CalculateSizeWithTag(OptionalUint64Wrapper); + } + if (optionalFloatWrapper_ != null) { + size += _single_optionalFloatWrapper_codec.CalculateSizeWithTag(OptionalFloatWrapper); + } + if (optionalDoubleWrapper_ != null) { + size += _single_optionalDoubleWrapper_codec.CalculateSizeWithTag(OptionalDoubleWrapper); + } + if (optionalStringWrapper_ != null) { + size += _single_optionalStringWrapper_codec.CalculateSizeWithTag(OptionalStringWrapper); + } + if (optionalBytesWrapper_ != null) { + size += _single_optionalBytesWrapper_codec.CalculateSizeWithTag(OptionalBytesWrapper); + } + size += repeatedBoolWrapper_.CalculateSize(_repeated_repeatedBoolWrapper_codec); + size += repeatedInt32Wrapper_.CalculateSize(_repeated_repeatedInt32Wrapper_codec); + size += repeatedInt64Wrapper_.CalculateSize(_repeated_repeatedInt64Wrapper_codec); + size += repeatedUint32Wrapper_.CalculateSize(_repeated_repeatedUint32Wrapper_codec); + size += repeatedUint64Wrapper_.CalculateSize(_repeated_repeatedUint64Wrapper_codec); + size += repeatedFloatWrapper_.CalculateSize(_repeated_repeatedFloatWrapper_codec); + size += repeatedDoubleWrapper_.CalculateSize(_repeated_repeatedDoubleWrapper_codec); + size += repeatedStringWrapper_.CalculateSize(_repeated_repeatedStringWrapper_codec); + size += repeatedBytesWrapper_.CalculateSize(_repeated_repeatedBytesWrapper_codec); + if (optionalDuration_ != null) { + size += 2 + pb::CodedOutputStream.ComputeMessageSize(OptionalDuration); + } + if (optionalTimestamp_ != null) { + size += 2 + pb::CodedOutputStream.ComputeMessageSize(OptionalTimestamp); + } + if (optionalFieldMask_ != null) { + size += 2 + pb::CodedOutputStream.ComputeMessageSize(OptionalFieldMask); + } + if (optionalStruct_ != null) { + size += 2 + pb::CodedOutputStream.ComputeMessageSize(OptionalStruct); + } + if (optionalAny_ != null) { + size += 2 + pb::CodedOutputStream.ComputeMessageSize(OptionalAny); + } + if (optionalValue_ != null) { + size += 2 + pb::CodedOutputStream.ComputeMessageSize(OptionalValue); + } + size += repeatedDuration_.CalculateSize(_repeated_repeatedDuration_codec); + size += repeatedTimestamp_.CalculateSize(_repeated_repeatedTimestamp_codec); + size += repeatedFieldmask_.CalculateSize(_repeated_repeatedFieldmask_codec); + size += repeatedStruct_.CalculateSize(_repeated_repeatedStruct_codec); + size += repeatedAny_.CalculateSize(_repeated_repeatedAny_codec); + size += repeatedValue_.CalculateSize(_repeated_repeatedValue_codec); + if (Fieldname1 != 0) { + size += 2 + pb::CodedOutputStream.ComputeInt32Size(Fieldname1); + } + if (FieldName2 != 0) { + size += 2 + pb::CodedOutputStream.ComputeInt32Size(FieldName2); + } + if (FieldName3 != 0) { + size += 2 + pb::CodedOutputStream.ComputeInt32Size(FieldName3); + } + if (FieldName4 != 0) { + size += 2 + pb::CodedOutputStream.ComputeInt32Size(FieldName4); + } + if (Field0Name5 != 0) { + size += 2 + pb::CodedOutputStream.ComputeInt32Size(Field0Name5); + } + if (Field0Name6 != 0) { + size += 2 + pb::CodedOutputStream.ComputeInt32Size(Field0Name6); + } + if (FieldName7 != 0) { + size += 2 + pb::CodedOutputStream.ComputeInt32Size(FieldName7); + } + if (FieldName8 != 0) { + size += 2 + pb::CodedOutputStream.ComputeInt32Size(FieldName8); + } + if (FieldName9 != 0) { + size += 2 + pb::CodedOutputStream.ComputeInt32Size(FieldName9); + } + if (FieldName10 != 0) { + size += 2 + pb::CodedOutputStream.ComputeInt32Size(FieldName10); + } + if (FIELDNAME11 != 0) { + size += 2 + pb::CodedOutputStream.ComputeInt32Size(FIELDNAME11); + } + if (FIELDName12 != 0) { + size += 2 + pb::CodedOutputStream.ComputeInt32Size(FIELDName12); + } return size; } @@ -1936,6 +2777,138 @@ namespace Conformance { mapStringForeignMessage_.Add(other.mapStringForeignMessage_); mapStringNestedEnum_.Add(other.mapStringNestedEnum_); mapStringForeignEnum_.Add(other.mapStringForeignEnum_); + if (other.optionalBoolWrapper_ != null) { + if (optionalBoolWrapper_ == null || other.OptionalBoolWrapper != false) { + OptionalBoolWrapper = other.OptionalBoolWrapper; + } + } + if (other.optionalInt32Wrapper_ != null) { + if (optionalInt32Wrapper_ == null || other.OptionalInt32Wrapper != 0) { + OptionalInt32Wrapper = other.OptionalInt32Wrapper; + } + } + if (other.optionalInt64Wrapper_ != null) { + if (optionalInt64Wrapper_ == null || other.OptionalInt64Wrapper != 0L) { + OptionalInt64Wrapper = other.OptionalInt64Wrapper; + } + } + if (other.optionalUint32Wrapper_ != null) { + if (optionalUint32Wrapper_ == null || other.OptionalUint32Wrapper != 0) { + OptionalUint32Wrapper = other.OptionalUint32Wrapper; + } + } + if (other.optionalUint64Wrapper_ != null) { + if (optionalUint64Wrapper_ == null || other.OptionalUint64Wrapper != 0UL) { + OptionalUint64Wrapper = other.OptionalUint64Wrapper; + } + } + if (other.optionalFloatWrapper_ != null) { + if (optionalFloatWrapper_ == null || other.OptionalFloatWrapper != 0F) { + OptionalFloatWrapper = other.OptionalFloatWrapper; + } + } + if (other.optionalDoubleWrapper_ != null) { + if (optionalDoubleWrapper_ == null || other.OptionalDoubleWrapper != 0D) { + OptionalDoubleWrapper = other.OptionalDoubleWrapper; + } + } + if (other.optionalStringWrapper_ != null) { + if (optionalStringWrapper_ == null || other.OptionalStringWrapper != "") { + OptionalStringWrapper = other.OptionalStringWrapper; + } + } + if (other.optionalBytesWrapper_ != null) { + if (optionalBytesWrapper_ == null || other.OptionalBytesWrapper != pb::ByteString.Empty) { + OptionalBytesWrapper = other.OptionalBytesWrapper; + } + } + repeatedBoolWrapper_.Add(other.repeatedBoolWrapper_); + repeatedInt32Wrapper_.Add(other.repeatedInt32Wrapper_); + repeatedInt64Wrapper_.Add(other.repeatedInt64Wrapper_); + repeatedUint32Wrapper_.Add(other.repeatedUint32Wrapper_); + repeatedUint64Wrapper_.Add(other.repeatedUint64Wrapper_); + repeatedFloatWrapper_.Add(other.repeatedFloatWrapper_); + repeatedDoubleWrapper_.Add(other.repeatedDoubleWrapper_); + repeatedStringWrapper_.Add(other.repeatedStringWrapper_); + repeatedBytesWrapper_.Add(other.repeatedBytesWrapper_); + if (other.optionalDuration_ != null) { + if (optionalDuration_ == null) { + optionalDuration_ = new global::Google.Protobuf.WellKnownTypes.Duration(); + } + OptionalDuration.MergeFrom(other.OptionalDuration); + } + if (other.optionalTimestamp_ != null) { + if (optionalTimestamp_ == null) { + optionalTimestamp_ = new global::Google.Protobuf.WellKnownTypes.Timestamp(); + } + OptionalTimestamp.MergeFrom(other.OptionalTimestamp); + } + if (other.optionalFieldMask_ != null) { + if (optionalFieldMask_ == null) { + optionalFieldMask_ = new global::Google.Protobuf.WellKnownTypes.FieldMask(); + } + OptionalFieldMask.MergeFrom(other.OptionalFieldMask); + } + if (other.optionalStruct_ != null) { + if (optionalStruct_ == null) { + optionalStruct_ = new global::Google.Protobuf.WellKnownTypes.Struct(); + } + OptionalStruct.MergeFrom(other.OptionalStruct); + } + if (other.optionalAny_ != null) { + if (optionalAny_ == null) { + optionalAny_ = new global::Google.Protobuf.WellKnownTypes.Any(); + } + OptionalAny.MergeFrom(other.OptionalAny); + } + if (other.optionalValue_ != null) { + if (optionalValue_ == null) { + optionalValue_ = new global::Google.Protobuf.WellKnownTypes.Value(); + } + OptionalValue.MergeFrom(other.OptionalValue); + } + repeatedDuration_.Add(other.repeatedDuration_); + repeatedTimestamp_.Add(other.repeatedTimestamp_); + repeatedFieldmask_.Add(other.repeatedFieldmask_); + repeatedStruct_.Add(other.repeatedStruct_); + repeatedAny_.Add(other.repeatedAny_); + repeatedValue_.Add(other.repeatedValue_); + if (other.Fieldname1 != 0) { + Fieldname1 = other.Fieldname1; + } + if (other.FieldName2 != 0) { + FieldName2 = other.FieldName2; + } + if (other.FieldName3 != 0) { + FieldName3 = other.FieldName3; + } + if (other.FieldName4 != 0) { + FieldName4 = other.FieldName4; + } + if (other.Field0Name5 != 0) { + Field0Name5 = other.Field0Name5; + } + if (other.Field0Name6 != 0) { + Field0Name6 = other.Field0Name6; + } + if (other.FieldName7 != 0) { + FieldName7 = other.FieldName7; + } + if (other.FieldName8 != 0) { + FieldName8 = other.FieldName8; + } + if (other.FieldName9 != 0) { + FieldName9 = other.FieldName9; + } + if (other.FieldName10 != 0) { + FieldName10 = other.FieldName10; + } + if (other.FIELDNAME11 != 0) { + FIELDNAME11 = other.FIELDNAME11; + } + if (other.FIELDName12 != 0) { + FIELDName12 = other.FIELDName12; + } switch (other.OneofFieldCase) { case OneofFieldOneofCase.OneofUint32: OneofUint32 = other.OneofUint32; @@ -2253,6 +3226,219 @@ namespace Conformance { OneofBytes = input.ReadBytes(); break; } + case 1610: { + bool? value = _single_optionalBoolWrapper_codec.Read(input); + if (optionalBoolWrapper_ == null || value != false) { + OptionalBoolWrapper = value; + } + break; + } + case 1618: { + int? value = _single_optionalInt32Wrapper_codec.Read(input); + if (optionalInt32Wrapper_ == null || value != 0) { + OptionalInt32Wrapper = value; + } + break; + } + case 1626: { + long? value = _single_optionalInt64Wrapper_codec.Read(input); + if (optionalInt64Wrapper_ == null || value != 0L) { + OptionalInt64Wrapper = value; + } + break; + } + case 1634: { + uint? value = _single_optionalUint32Wrapper_codec.Read(input); + if (optionalUint32Wrapper_ == null || value != 0) { + OptionalUint32Wrapper = value; + } + break; + } + case 1642: { + ulong? value = _single_optionalUint64Wrapper_codec.Read(input); + if (optionalUint64Wrapper_ == null || value != 0UL) { + OptionalUint64Wrapper = value; + } + break; + } + case 1650: { + float? value = _single_optionalFloatWrapper_codec.Read(input); + if (optionalFloatWrapper_ == null || value != 0F) { + OptionalFloatWrapper = value; + } + break; + } + case 1658: { + double? value = _single_optionalDoubleWrapper_codec.Read(input); + if (optionalDoubleWrapper_ == null || value != 0D) { + OptionalDoubleWrapper = value; + } + break; + } + case 1666: { + string value = _single_optionalStringWrapper_codec.Read(input); + if (optionalStringWrapper_ == null || value != "") { + OptionalStringWrapper = value; + } + break; + } + case 1674: { + pb::ByteString value = _single_optionalBytesWrapper_codec.Read(input); + if (optionalBytesWrapper_ == null || value != pb::ByteString.Empty) { + OptionalBytesWrapper = value; + } + break; + } + case 1690: { + repeatedBoolWrapper_.AddEntriesFrom(input, _repeated_repeatedBoolWrapper_codec); + break; + } + case 1698: { + repeatedInt32Wrapper_.AddEntriesFrom(input, _repeated_repeatedInt32Wrapper_codec); + break; + } + case 1706: { + repeatedInt64Wrapper_.AddEntriesFrom(input, _repeated_repeatedInt64Wrapper_codec); + break; + } + case 1714: { + repeatedUint32Wrapper_.AddEntriesFrom(input, _repeated_repeatedUint32Wrapper_codec); + break; + } + case 1722: { + repeatedUint64Wrapper_.AddEntriesFrom(input, _repeated_repeatedUint64Wrapper_codec); + break; + } + case 1730: { + repeatedFloatWrapper_.AddEntriesFrom(input, _repeated_repeatedFloatWrapper_codec); + break; + } + case 1738: { + repeatedDoubleWrapper_.AddEntriesFrom(input, _repeated_repeatedDoubleWrapper_codec); + break; + } + case 1746: { + repeatedStringWrapper_.AddEntriesFrom(input, _repeated_repeatedStringWrapper_codec); + break; + } + case 1754: { + repeatedBytesWrapper_.AddEntriesFrom(input, _repeated_repeatedBytesWrapper_codec); + break; + } + case 2410: { + if (optionalDuration_ == null) { + optionalDuration_ = new global::Google.Protobuf.WellKnownTypes.Duration(); + } + input.ReadMessage(optionalDuration_); + break; + } + case 2418: { + if (optionalTimestamp_ == null) { + optionalTimestamp_ = new global::Google.Protobuf.WellKnownTypes.Timestamp(); + } + input.ReadMessage(optionalTimestamp_); + break; + } + case 2426: { + if (optionalFieldMask_ == null) { + optionalFieldMask_ = new global::Google.Protobuf.WellKnownTypes.FieldMask(); + } + input.ReadMessage(optionalFieldMask_); + break; + } + case 2434: { + if (optionalStruct_ == null) { + optionalStruct_ = new global::Google.Protobuf.WellKnownTypes.Struct(); + } + input.ReadMessage(optionalStruct_); + break; + } + case 2442: { + if (optionalAny_ == null) { + optionalAny_ = new global::Google.Protobuf.WellKnownTypes.Any(); + } + input.ReadMessage(optionalAny_); + break; + } + case 2450: { + if (optionalValue_ == null) { + optionalValue_ = new global::Google.Protobuf.WellKnownTypes.Value(); + } + input.ReadMessage(optionalValue_); + break; + } + case 2490: { + repeatedDuration_.AddEntriesFrom(input, _repeated_repeatedDuration_codec); + break; + } + case 2498: { + repeatedTimestamp_.AddEntriesFrom(input, _repeated_repeatedTimestamp_codec); + break; + } + case 2506: { + repeatedFieldmask_.AddEntriesFrom(input, _repeated_repeatedFieldmask_codec); + break; + } + case 2522: { + repeatedAny_.AddEntriesFrom(input, _repeated_repeatedAny_codec); + break; + } + case 2530: { + repeatedValue_.AddEntriesFrom(input, _repeated_repeatedValue_codec); + break; + } + case 2594: { + repeatedStruct_.AddEntriesFrom(input, _repeated_repeatedStruct_codec); + break; + } + case 3208: { + Fieldname1 = input.ReadInt32(); + break; + } + case 3216: { + FieldName2 = input.ReadInt32(); + break; + } + case 3224: { + FieldName3 = input.ReadInt32(); + break; + } + case 3232: { + FieldName4 = input.ReadInt32(); + break; + } + case 3240: { + Field0Name5 = input.ReadInt32(); + break; + } + case 3248: { + Field0Name6 = input.ReadInt32(); + break; + } + case 3256: { + FieldName7 = input.ReadInt32(); + break; + } + case 3264: { + FieldName8 = input.ReadInt32(); + break; + } + case 3272: { + FieldName9 = input.ReadInt32(); + break; + } + case 3280: { + FieldName10 = input.ReadInt32(); + break; + } + case 3288: { + FIELDNAME11 = input.ReadInt32(); + break; + } + case 3296: { + FIELDName12 = input.ReadInt32(); + break; + } } } } @@ -2343,7 +3529,7 @@ namespace Conformance { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -2471,7 +3657,7 @@ namespace Conformance { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { diff --git a/csharp/src/Google.Protobuf.Conformance/Program.cs b/csharp/src/Google.Protobuf.Conformance/Program.cs index af92da9f..f3f7e295 100644 --- a/csharp/src/Google.Protobuf.Conformance/Program.cs +++ b/csharp/src/Google.Protobuf.Conformance/Program.cs @@ -31,6 +31,7 @@ #endregion using Conformance; +using Google.Protobuf.Reflection; using System; using System.IO; @@ -47,16 +48,17 @@ namespace Google.Protobuf.Conformance // This way we get the binary streams instead of readers/writers. var input = new BinaryReader(Console.OpenStandardInput()); var output = new BinaryWriter(Console.OpenStandardOutput()); + var typeRegistry = TypeRegistry.FromMessages(TestAllTypes.Descriptor); int count = 0; - while (RunTest(input, output)) + while (RunTest(input, output, typeRegistry)) { count++; } Console.Error.WriteLine("Received EOF after {0} tests", count); } - private static bool RunTest(BinaryReader input, BinaryWriter output) + private static bool RunTest(BinaryReader input, BinaryWriter output, TypeRegistry typeRegistry) { int? size = ReadInt32(input); if (size == null) @@ -69,7 +71,7 @@ namespace Google.Protobuf.Conformance throw new EndOfStreamException("Read " + inputData.Length + " bytes of data when expecting " + size); } ConformanceRequest request = ConformanceRequest.Parser.ParseFrom(inputData); - ConformanceResponse response = PerformRequest(request); + ConformanceResponse response = PerformRequest(request, typeRegistry); byte[] outputData = response.ToByteArray(); output.Write(outputData.Length); output.Write(outputData); @@ -77,34 +79,48 @@ namespace Google.Protobuf.Conformance return true; } - private static ConformanceResponse PerformRequest(ConformanceRequest request) + private static ConformanceResponse PerformRequest(ConformanceRequest request, TypeRegistry typeRegistry) { TestAllTypes message; - switch (request.PayloadCase) + try { - case ConformanceRequest.PayloadOneofCase.JsonPayload: - return new ConformanceResponse { Skipped = "JSON parsing not implemented in C# yet" }; - case ConformanceRequest.PayloadOneofCase.ProtobufPayload: - try - { + switch (request.PayloadCase) + { + case ConformanceRequest.PayloadOneofCase.JsonPayload: + var parser = new JsonParser(new JsonParser.Settings(20, typeRegistry)); + message = parser.Parse<TestAllTypes>(request.JsonPayload); + break; + case ConformanceRequest.PayloadOneofCase.ProtobufPayload: message = TestAllTypes.Parser.ParseFrom(request.ProtobufPayload); - } - catch (InvalidProtocolBufferException e) - { - return new ConformanceResponse { ParseError = e.Message }; - } - break; - default: - throw new Exception("Unsupported request payload: " + request.PayloadCase); + break; + default: + throw new Exception("Unsupported request payload: " + request.PayloadCase); + } } - switch (request.RequestedOutputFormat) + catch (InvalidProtocolBufferException e) { - case global::Conformance.WireFormat.JSON: - return new ConformanceResponse { JsonPayload = JsonFormatter.Default.Format(message) }; - case global::Conformance.WireFormat.PROTOBUF: - return new ConformanceResponse { ProtobufPayload = message.ToByteString() }; - default: - throw new Exception("Unsupported request output format: " + request.PayloadCase); + return new ConformanceResponse { ParseError = e.Message }; + } + catch (InvalidJsonException e) + { + return new ConformanceResponse { ParseError = e.Message }; + } + try + { + switch (request.RequestedOutputFormat) + { + case global::Conformance.WireFormat.JSON: + var formatter = new JsonFormatter(new JsonFormatter.Settings(false, typeRegistry)); + return new ConformanceResponse { JsonPayload = formatter.Format(message) }; + case global::Conformance.WireFormat.PROTOBUF: + return new ConformanceResponse { ProtobufPayload = message.ToByteString() }; + default: + throw new Exception("Unsupported request output format: " + request.PayloadCase); + } + } + catch (InvalidOperationException e) + { + return new ConformanceResponse { SerializeError = e.Message }; } } diff --git a/csharp/src/Google.Protobuf.Test/Collections/MapFieldTest.cs b/csharp/src/Google.Protobuf.Test/Collections/MapFieldTest.cs index ba82c0e8..9c845907 100644 --- a/csharp/src/Google.Protobuf.Test/Collections/MapFieldTest.cs +++ b/csharp/src/Google.Protobuf.Test/Collections/MapFieldTest.cs @@ -56,7 +56,7 @@ namespace Google.Protobuf.Collections } [Test] - public void NullValues() + public void NullValuesProhibited() { TestNullValues<int?>(0); TestNullValues(""); @@ -65,19 +65,12 @@ namespace Google.Protobuf.Collections private void TestNullValues<T>(T nonNullValue) { - var map = new MapField<int, T>(false); + var map = new MapField<int, T>(); var nullValue = (T) (object) null; Assert.Throws<ArgumentNullException>(() => map.Add(0, nullValue)); Assert.Throws<ArgumentNullException>(() => map[0] = nullValue); map.Add(1, nonNullValue); map[1] = nonNullValue; - - // Doesn't throw... - map = new MapField<int, T>(true); - map.Add(0, nullValue); - map[0] = nullValue; - map.Add(1, nonNullValue); - map[1] = nonNullValue; } [Test] @@ -161,27 +154,6 @@ namespace Google.Protobuf.Collections } [Test] - public void EqualityHandlesNullValues() - { - var map1 = new MapField<string, ForeignMessage>(); - map1.Add("a", new ForeignMessage { C = 10 }); - map1.Add("b", null); - - var map2 = new MapField<string, ForeignMessage>(); - map2.Add("a", new ForeignMessage { C = 10 }); - map2.Add("b", null); - - EqualityTester.AssertEquality(map1, map2); - // Check the null value isn't ignored entirely... - Assert.IsTrue(map1.Remove("b")); - EqualityTester.AssertInequality(map1, map2); - map1.Add("b", new ForeignMessage()); - EqualityTester.AssertInequality(map1, map2); - map1["b"] = null; - EqualityTester.AssertEquality(map1, map2); - } - - [Test] public void Add_Dictionary() { var map1 = new MapField<string, string> @@ -454,30 +426,6 @@ namespace Google.Protobuf.Collections } [Test] - public void AllowNullValues_Property() - { - // Non-message reference type values are non-nullable by default, but can be overridden - Assert.IsFalse(new MapField<int, string>().AllowsNullValues); - Assert.IsFalse(new MapField<int, string>(false).AllowsNullValues); - Assert.IsTrue(new MapField<int, string>(true).AllowsNullValues); - - // Non-nullable value type values are never nullable - Assert.IsFalse(new MapField<int, int>().AllowsNullValues); - Assert.IsFalse(new MapField<int, int>(false).AllowsNullValues); - Assert.Throws<ArgumentException>(() => new MapField<int, int>(true)); - - // Message type values are nullable by default, but can be overridden - Assert.IsTrue(new MapField<int, TestAllTypes>().AllowsNullValues); - Assert.IsFalse(new MapField<int, TestAllTypes>(false).AllowsNullValues); - Assert.IsTrue(new MapField<int, TestAllTypes>(true).AllowsNullValues); - - // Nullable value type values are nullable by default, but can be overridden - Assert.IsTrue(new MapField<int, int?>().AllowsNullValues); - Assert.IsFalse(new MapField<int, int?>(false).AllowsNullValues); - Assert.IsTrue(new MapField<int, int?>(true).AllowsNullValues); - } - - [Test] public void KeysReturnsLiveView() { var map = new MapField<string, string>(); diff --git a/csharp/src/Google.Protobuf.Test/GeneratedMessageTest.cs b/csharp/src/Google.Protobuf.Test/GeneratedMessageTest.cs index 1163f524..14cc6d19 100644 --- a/csharp/src/Google.Protobuf.Test/GeneratedMessageTest.cs +++ b/csharp/src/Google.Protobuf.Test/GeneratedMessageTest.cs @@ -221,7 +221,7 @@ namespace Google.Protobuf },
MapInt32ForeignMessage = {
{ 0, new ForeignMessage { C = 10 } },
- { 5, null },
+ { 5, new ForeignMessage() },
},
MapInt32Enum = {
{ 1, MapEnum.MAP_ENUM_BAR },
@@ -269,6 +269,40 @@ namespace Google.Protobuf }
[Test]
+ public void MapWithOnlyKey_PrimitiveValue()
+ {
+ // Hand-craft the stream to contain a single entry with just a key.
+ var memoryStream = new MemoryStream();
+ var output = new CodedOutputStream(memoryStream);
+ output.WriteTag(TestMap.MapInt32DoubleFieldNumber, WireFormat.WireType.LengthDelimited);
+ int key = 10;
+ output.WriteLength(1 + CodedOutputStream.ComputeInt32Size(key));
+ output.WriteTag(1, WireFormat.WireType.Varint);
+ output.WriteInt32(key);
+ output.Flush();
+
+ var parsed = TestMap.Parser.ParseFrom(memoryStream.ToArray());
+ Assert.AreEqual(0.0, parsed.MapInt32Double[key]);
+ }
+
+ [Test]
+ public void MapWithOnlyKey_MessageValue()
+ {
+ // Hand-craft the stream to contain a single entry with just a key.
+ var memoryStream = new MemoryStream();
+ var output = new CodedOutputStream(memoryStream);
+ output.WriteTag(TestMap.MapInt32ForeignMessageFieldNumber, WireFormat.WireType.LengthDelimited);
+ int key = 10;
+ output.WriteLength(1 + CodedOutputStream.ComputeInt32Size(key));
+ output.WriteTag(1, WireFormat.WireType.Varint);
+ output.WriteInt32(key);
+ output.Flush();
+
+ var parsed = TestMap.Parser.ParseFrom(memoryStream.ToArray());
+ Assert.AreEqual(new ForeignMessage(), parsed.MapInt32ForeignMessage[key]);
+ }
+
+ [Test]
public void MapIgnoresExtraFieldsWithinEntryMessages()
{
// Hand-craft the stream to contain a single entry with three fields
@@ -661,5 +695,21 @@ namespace Google.Protobuf var parsed = TestAllTypes.Parser.ParseFrom(stream);
Assert.AreEqual(new TestAllTypes { SingleFixed32 = 123 }, parsed);
}
+
+ [Test]
+ public void CustomDiagnosticMessage_DirectToStringCall()
+ {
+ var message = new ForeignMessage { C = 31 };
+ Assert.AreEqual("{ \"c\": 31, \"@cInHex\": \"1f\" }", message.ToString());
+ Assert.AreEqual("{ \"c\": 31 }", JsonFormatter.Default.Format(message));
+ }
+
+ [Test]
+ public void CustomDiagnosticMessage_Nested()
+ {
+ var message = new TestAllTypes { SingleForeignMessage = new ForeignMessage { C = 16 } };
+ Assert.AreEqual("{ \"singleForeignMessage\": { \"c\": 16, \"@cInHex\": \"10\" } }", message.ToString());
+ Assert.AreEqual("{ \"singleForeignMessage\": { \"c\": 16 } }", JsonFormatter.Default.Format(message));
+ }
}
}
diff --git a/csharp/src/Google.Protobuf.Test/Google.Protobuf.Test.csproj b/csharp/src/Google.Protobuf.Test/Google.Protobuf.Test.csproj index cd15b968..4f37c5e2 100644 --- a/csharp/src/Google.Protobuf.Test/Google.Protobuf.Test.csproj +++ b/csharp/src/Google.Protobuf.Test/Google.Protobuf.Test.csproj @@ -55,7 +55,7 @@ <GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
<Prefer32Bit>false</Prefer32Bit>
<SignAssembly>True</SignAssembly>
- <AssemblyOriginatorKeyFile>C:\keys\Google.Protobuf.snk</AssemblyOriginatorKeyFile>
+ <AssemblyOriginatorKeyFile>..\..\keys\Google.Protobuf.snk</AssemblyOriginatorKeyFile>
</PropertyGroup>
<ItemGroup>
<Reference Include="mscorlib" />
@@ -99,8 +99,10 @@ <Compile Include="JsonTokenizerTest.cs" />
<Compile Include="Reflection\DescriptorsTest.cs" />
<Compile Include="Reflection\FieldAccessTest.cs" />
+ <Compile Include="Reflection\TypeRegistryTest.cs" />
<Compile Include="SampleEnum.cs" />
<Compile Include="SampleMessages.cs" />
+ <Compile Include="TestProtos\ForeignMessagePartial.cs" />
<Compile Include="TestProtos\MapUnittestProto3.cs" />
<Compile Include="TestProtos\UnittestImportProto3.cs" />
<Compile Include="TestProtos\UnittestImportPublicProto3.cs" />
@@ -113,6 +115,7 @@ <Compile Include="TestProtos\UnittestWellKnownTypes.cs" />
<Compile Include="WellKnownTypes\AnyTest.cs" />
<Compile Include="WellKnownTypes\DurationTest.cs" />
+ <Compile Include="WellKnownTypes\FieldMaskTest.cs" />
<Compile Include="WellKnownTypes\TimestampTest.cs" />
<Compile Include="WellKnownTypes\WrappersTest.cs" />
</ItemGroup>
diff --git a/csharp/src/Google.Protobuf.Test/JsonFormatterTest.cs b/csharp/src/Google.Protobuf.Test/JsonFormatterTest.cs index 08cedad8..42455043 100644 --- a/csharp/src/Google.Protobuf.Test/JsonFormatterTest.cs +++ b/csharp/src/Google.Protobuf.Test/JsonFormatterTest.cs @@ -35,6 +35,9 @@ using Google.Protobuf.TestProtos; using NUnit.Framework; using UnitTest.Issues.TestProtos; using Google.Protobuf.WellKnownTypes; +using Google.Protobuf.Reflection; + +using static Google.Protobuf.JsonParserTest; // For WrapInQuotes namespace Google.Protobuf { @@ -162,41 +165,31 @@ namespace Google.Protobuf } [Test] - public void UnknownEnumValueOmitted_SingleField() + public void UnknownEnumValueNumeric_SingleField() { var message = new TestAllTypes { SingleForeignEnum = (ForeignEnum) 100 }; - AssertJson("{ }", JsonFormatter.Default.Format(message)); + AssertJson("{ 'singleForeignEnum': 100 }", JsonFormatter.Default.Format(message)); } [Test] - public void UnknownEnumValueOmitted_RepeatedField() + public void UnknownEnumValueNumeric_RepeatedField() { var message = new TestAllTypes { RepeatedForeignEnum = { ForeignEnum.FOREIGN_BAZ, (ForeignEnum) 100, ForeignEnum.FOREIGN_FOO } }; - AssertJson("{ 'repeatedForeignEnum': [ 'FOREIGN_BAZ', 'FOREIGN_FOO' ] }", JsonFormatter.Default.Format(message)); + AssertJson("{ 'repeatedForeignEnum': [ 'FOREIGN_BAZ', 100, 'FOREIGN_FOO' ] }", JsonFormatter.Default.Format(message)); } [Test] - public void UnknownEnumValueOmitted_MapField() + public void UnknownEnumValueNumeric_MapField() { - // This matches the C++ behaviour. var message = new TestMap { MapInt32Enum = { { 1, MapEnum.MAP_ENUM_FOO }, { 2, (MapEnum) 100 }, { 3, MapEnum.MAP_ENUM_BAR } } }; - AssertJson("{ 'mapInt32Enum': { '1': 'MAP_ENUM_FOO', '3': 'MAP_ENUM_BAR' } }", JsonFormatter.Default.Format(message)); + AssertJson("{ 'mapInt32Enum': { '1': 'MAP_ENUM_FOO', '2': 100, '3': 'MAP_ENUM_BAR' } }", JsonFormatter.Default.Format(message)); } [Test] - public void UnknownEnumValueOmitted_RepeatedField_AllEntriesUnknown() + public void UnknownEnumValue_RepeatedField_AllEntriesUnknown() { - // *Maybe* we should hold off on writing the "[" until we find that we've got at least one value to write... - // but this is what happens at the moment, and it doesn't seem too awful. var message = new TestAllTypes { RepeatedForeignEnum = { (ForeignEnum) 200, (ForeignEnum) 100 } }; - AssertJson("{ 'repeatedForeignEnum': [ ] }", JsonFormatter.Default.Format(message)); - } - - [Test] - public void NullValueForMessage() - { - var message = new TestMap { MapInt32ForeignMessage = { { 10, null } } }; - AssertJson("{ 'mapInt32ForeignMessage': { '10': null } }", JsonFormatter.Default.Format(message)); + AssertJson("{ 'repeatedForeignEnum': [ 200, 100 ] }", JsonFormatter.Default.Format(message)); } [Test] @@ -318,27 +311,52 @@ namespace Google.Protobuf } [Test] - public void TimestampStandalone() - { - Assert.AreEqual("1970-01-01T00:00:00Z", new Timestamp().ToString()); - Assert.AreEqual("1970-01-01T00:00:00.100Z", new Timestamp { Nanos = 100000000 }.ToString()); - Assert.AreEqual("1970-01-01T00:00:00.120Z", new Timestamp { Nanos = 120000000 }.ToString()); - Assert.AreEqual("1970-01-01T00:00:00.123Z", new Timestamp { Nanos = 123000000 }.ToString()); - Assert.AreEqual("1970-01-01T00:00:00.123400Z", new Timestamp { Nanos = 123400000 }.ToString()); - Assert.AreEqual("1970-01-01T00:00:00.123450Z", new Timestamp { Nanos = 123450000 }.ToString()); - Assert.AreEqual("1970-01-01T00:00:00.123456Z", new Timestamp { Nanos = 123456000 }.ToString()); - Assert.AreEqual("1970-01-01T00:00:00.123456700Z", new Timestamp { Nanos = 123456700 }.ToString()); - Assert.AreEqual("1970-01-01T00:00:00.123456780Z", new Timestamp { Nanos = 123456780 }.ToString()); - Assert.AreEqual("1970-01-01T00:00:00.123456789Z", new Timestamp { Nanos = 123456789 }.ToString()); + [TestCase("1970-01-01T00:00:00Z", 0)] + [TestCase("1970-01-01T00:00:00.000000001Z", 1)] + [TestCase("1970-01-01T00:00:00.000000010Z", 10)] + [TestCase("1970-01-01T00:00:00.000000100Z", 100)] + [TestCase("1970-01-01T00:00:00.000001Z", 1000)] + [TestCase("1970-01-01T00:00:00.000010Z", 10000)] + [TestCase("1970-01-01T00:00:00.000100Z", 100000)] + [TestCase("1970-01-01T00:00:00.001Z", 1000000)] + [TestCase("1970-01-01T00:00:00.010Z", 10000000)] + [TestCase("1970-01-01T00:00:00.100Z", 100000000)] + [TestCase("1970-01-01T00:00:00.100Z", 100000000)] + [TestCase("1970-01-01T00:00:00.120Z", 120000000)] + [TestCase("1970-01-01T00:00:00.123Z", 123000000)] + [TestCase("1970-01-01T00:00:00.123400Z", 123400000)] + [TestCase("1970-01-01T00:00:00.123450Z", 123450000)] + [TestCase("1970-01-01T00:00:00.123456Z", 123456000)] + [TestCase("1970-01-01T00:00:00.123456700Z", 123456700)] + [TestCase("1970-01-01T00:00:00.123456780Z", 123456780)] + [TestCase("1970-01-01T00:00:00.123456789Z", 123456789)] + public void TimestampStandalone(string expected, int nanos) + { + Assert.AreEqual(WrapInQuotes(expected), new Timestamp { Nanos = nanos }.ToString()); + } - // One before and one after the Unix epoch - Assert.AreEqual("1673-06-19T12:34:56Z", + [Test] + public void TimestampStandalone_FromDateTime() + { + // One before and one after the Unix epoch, more easily represented via DateTime. + Assert.AreEqual("\"1673-06-19T12:34:56Z\"", new DateTime(1673, 6, 19, 12, 34, 56, DateTimeKind.Utc).ToTimestamp().ToString()); - Assert.AreEqual("2015-07-31T10:29:34Z", + Assert.AreEqual("\"2015-07-31T10:29:34Z\"", new DateTime(2015, 7, 31, 10, 29, 34, DateTimeKind.Utc).ToTimestamp().ToString()); } [Test] + [TestCase(-1, -1)] // Would be valid as duration + [TestCase(1, Timestamp.MaxNanos + 1)] + [TestCase(Timestamp.UnixSecondsAtBclMaxValue + 1, 0)] + [TestCase(Timestamp.UnixSecondsAtBclMinValue - 1, 0)] + public void TimestampStandalone_NonNormalized(long seconds, int nanoseconds) + { + var timestamp = new Timestamp { Seconds = seconds, Nanos = nanoseconds }; + Assert.Throws<InvalidOperationException>(() => JsonFormatter.Default.Format(timestamp)); + } + + [Test] public void TimestampField() { var message = new TestWellKnownTypes { TimestampField = new Timestamp() }; @@ -349,6 +367,14 @@ namespace Google.Protobuf [TestCase(0, 0, "0s")] [TestCase(1, 0, "1s")] [TestCase(-1, 0, "-1s")] + [TestCase(0, 1, "0.000000001s")] + [TestCase(0, 10, "0.000000010s")] + [TestCase(0, 100, "0.000000100s")] + [TestCase(0, 1000, "0.000001s")] + [TestCase(0, 10000, "0.000010s")] + [TestCase(0, 100000, "0.000100s")] + [TestCase(0, 1000000, "0.001s")] + [TestCase(0, 10000000, "0.010s")] [TestCase(0, 100000000, "0.100s")] [TestCase(0, 120000000, "0.120s")] [TestCase(0, 123000000, "0.123s")] @@ -361,12 +387,19 @@ namespace Google.Protobuf [TestCase(0, -100000000, "-0.100s")] [TestCase(1, 100000000, "1.100s")] [TestCase(-1, -100000000, "-1.100s")] - // Non-normalized examples - [TestCase(1, 2123456789, "3.123456789s")] - [TestCase(1, -100000000, "0.900s")] public void DurationStandalone(long seconds, int nanoseconds, string expected) { - Assert.AreEqual(expected, new Duration { Seconds = seconds, Nanos = nanoseconds }.ToString()); + var json = JsonFormatter.Default.Format(new Duration { Seconds = seconds, Nanos = nanoseconds }); + Assert.AreEqual(WrapInQuotes(expected), json); + } + + [Test] + [TestCase(1, 2123456789)] + [TestCase(1, -100000000)] + public void DurationStandalone_NonNormalized(long seconds, int nanoseconds) + { + var duration = new Duration { Seconds = seconds, Nanos = nanoseconds }; + Assert.Throws<InvalidOperationException>(() => JsonFormatter.Default.Format(duration)); } [Test] @@ -395,14 +428,24 @@ namespace Google.Protobuf } [Test] + [TestCase("foo__bar")] + [TestCase("foo_3_ar")] + [TestCase("fooBar")] + public void FieldMaskInvalid(string input) + { + var mask = new FieldMask { Paths = { input } }; + Assert.Throws<InvalidOperationException>(() => JsonFormatter.Default.Format(mask)); + } + + [Test] public void FieldMaskStandalone() { var fieldMask = new FieldMask { Paths = { "", "single", "with_underscore", "nested.field.name", "nested..double_dot" } }; - Assert.AreEqual(",single,withUnderscore,nested.field.name,nested..doubleDot", fieldMask.ToString()); + Assert.AreEqual("\",single,withUnderscore,nested.field.name,nested..doubleDot\"", fieldMask.ToString()); // Invalid, but we shouldn't create broken JSON... fieldMask = new FieldMask { Paths = { "x\\y" } }; - Assert.AreEqual(@"x\\y", fieldMask.ToString()); + Assert.AreEqual(@"""x\\y""", fieldMask.ToString()); } [Test] @@ -420,6 +463,47 @@ namespace Google.Protobuf AssertJson("{ 'fileName': 'foo.proto' }", JsonFormatter.Default.Format(message)); } + [Test] + public void AnyWellKnownType() + { + var formatter = new JsonFormatter(new JsonFormatter.Settings(false, TypeRegistry.FromMessages(Timestamp.Descriptor))); + var timestamp = new DateTime(1673, 6, 19, 12, 34, 56, DateTimeKind.Utc).ToTimestamp(); + var any = Any.Pack(timestamp); + AssertJson("{ '@type': 'type.googleapis.com/google.protobuf.Timestamp', 'value': '1673-06-19T12:34:56Z' }", formatter.Format(any)); + } + + [Test] + public void AnyMessageType() + { + var formatter = new JsonFormatter(new JsonFormatter.Settings(false, TypeRegistry.FromMessages(TestAllTypes.Descriptor))); + var message = new TestAllTypes { SingleInt32 = 10, SingleNestedMessage = new TestAllTypes.Types.NestedMessage { Bb = 20 } }; + var any = Any.Pack(message); + AssertJson("{ '@type': 'type.googleapis.com/protobuf_unittest.TestAllTypes', 'singleInt32': 10, 'singleNestedMessage': { 'bb': 20 } }", formatter.Format(any)); + } + + [Test] + public void AnyNested() + { + var registry = TypeRegistry.FromMessages(TestWellKnownTypes.Descriptor, TestAllTypes.Descriptor); + var formatter = new JsonFormatter(new JsonFormatter.Settings(false, registry)); + + // Nest an Any as the value of an Any. + var doubleNestedMessage = new TestAllTypes { SingleInt32 = 20 }; + var nestedMessage = Any.Pack(doubleNestedMessage); + var message = new TestWellKnownTypes { AnyField = Any.Pack(nestedMessage) }; + AssertJson("{ 'anyField': { '@type': 'type.googleapis.com/google.protobuf.Any', 'value': { '@type': 'type.googleapis.com/protobuf_unittest.TestAllTypes', 'singleInt32': 20 } } }", + formatter.Format(message)); + } + + [Test] + public void AnyUnknownType() + { + // The default type registry doesn't have any types in it. + var message = new TestAllTypes(); + var any = Any.Pack(message); + Assert.Throws<InvalidOperationException>(() => JsonFormatter.Default.Format(any)); + } + /// <summary> /// Checks that the actual JSON is the same as the expected JSON - but after replacing /// all apostrophes in the expected JSON with double quotes. This basically makes the tests easier diff --git a/csharp/src/Google.Protobuf.Test/JsonParserTest.cs b/csharp/src/Google.Protobuf.Test/JsonParserTest.cs index b3664770..d21da58a 100644 --- a/csharp/src/Google.Protobuf.Test/JsonParserTest.cs +++ b/csharp/src/Google.Protobuf.Test/JsonParserTest.cs @@ -30,6 +30,7 @@ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion +using Google.Protobuf.Reflection; using Google.Protobuf.TestProtos; using Google.Protobuf.WellKnownTypes; using NUnit.Framework; @@ -38,9 +39,7 @@ using System; namespace Google.Protobuf { /// <summary> - /// Unit tests for JSON parsing. Some tests are ignored at the moment as the desired behaviour - /// isn't fully known, either in terms of which exceptions should be thrown or whether they should - /// count as valid values. + /// Unit tests for JSON parsing. /// </summary> public class JsonParserTest { @@ -73,6 +72,14 @@ namespace Google.Protobuf } [Test] + public void OriginalFieldNameAccepted() + { + var json = "{ \"single_int32\": 10 }"; + var expected = new TestAllTypes { SingleInt32 = 10 }; + Assert.AreEqual(expected, TestAllTypes.Parser.ParseJson(json)); + } + + [Test] public void SourceContextRoundtrip() { AssertRoundtrip(new SourceContext { FileName = "foo.proto" }); @@ -117,7 +124,9 @@ namespace Google.Protobuf [Test] public void SingularWrappers_ExplicitNulls() { - var message = new TestWellKnownTypes(); + // When we parse the "valueField": null part, we remember it... basically, it's one case + // where explicit default values don't fully roundtrip. + var message = new TestWellKnownTypes { ValueField = Value.ForNull() }; var json = new JsonFormatter(new JsonFormatter.Settings(true)).Format(message); var parsed = JsonParser.Default.Parse<TestWellKnownTypes>(json); Assert.AreEqual(message, parsed); @@ -144,11 +153,19 @@ namespace Google.Protobuf } [Test] + public void ExplicitNullValue() + { + string json = "{\"valueField\": null}"; + var message = JsonParser.Default.Parse<TestWellKnownTypes>(json); + Assert.AreEqual(new TestWellKnownTypes { ValueField = Value.ForNull() }, message); + } + + [Test] public void BytesWrapper_Standalone() { ByteString data = ByteString.CopyFrom(1, 2, 3); // Can't do this with attributes... - var parsed = JsonParser.Default.Parse<BytesValue>("\"" + data.ToBase64() + "\""); + var parsed = JsonParser.Default.Parse<BytesValue>(WrapInQuotes(data.ToBase64())); var expected = new BytesValue { Value = data }; Assert.AreEqual(expected, parsed); } @@ -172,6 +189,36 @@ namespace Google.Protobuf } [Test] + public void RepeatedField_NullElementProhibited() + { + string json = "{ \"repeated_foreign_message\": [null] }"; + Assert.Throws<InvalidProtocolBufferException>(() => TestAllTypes.Parser.ParseJson(json)); + } + + [Test] + public void RepeatedField_NullOverallValueAllowed() + { + string json = "{ \"repeated_foreign_message\": null }"; + Assert.AreEqual(new TestAllTypes(), TestAllTypes.Parser.ParseJson(json)); + } + + [Test] + [TestCase("{ \"mapInt32Int32\": { \"10\": null }")] + [TestCase("{ \"mapStringString\": { \"abc\": null }")] + [TestCase("{ \"mapInt32ForeignMessage\": { \"10\": null }")] + public void MapField_NullValueProhibited(string json) + { + Assert.Throws<InvalidProtocolBufferException>(() => TestMap.Parser.ParseJson(json)); + } + + [Test] + public void MapField_NullOverallValueAllowed() + { + string json = "{ \"mapInt32Int32\": null }"; + Assert.AreEqual(new TestMap(), TestMap.Parser.ParseJson(json)); + } + + [Test] public void IndividualWrapperTypes() { Assert.AreEqual(new StringValue { Value = "foo" }, StringValue.Parser.ParseJson("\"foo\"")); @@ -183,7 +230,7 @@ namespace Google.Protobuf private static void AssertRoundtrip<T>(T message) where T : IMessage<T>, new() { var clone = message.Clone(); - var json = message.ToString(); + var json = JsonFormatter.Default.Format(message); var parsed = JsonParser.Default.Parse<T>(json); Assert.AreEqual(clone, parsed); } @@ -204,6 +251,8 @@ namespace Google.Protobuf [Test] [TestCase("+0")] + [TestCase(" 1")] + [TestCase("1 ")] [TestCase("00")] [TestCase("-00")] [TestCase("--1")] @@ -317,7 +366,18 @@ namespace Google.Protobuf [TestCase("1.0.0")] [TestCase("+1")] [TestCase("00")] + [TestCase("01")] + [TestCase("-00")] + [TestCase("-01")] [TestCase("--1")] + [TestCase(" Infinity")] + [TestCase(" -Infinity")] + [TestCase("NaN ")] + [TestCase("Infinity ")] + [TestCase("-Infinity ")] + [TestCase(" NaN")] + [TestCase("INFINITY")] + [TestCase("nan")] [TestCase("\u00BD")] // 1/2 as a single Unicode character. Just sanity checking... public void StringToDouble_Invalid(string jsonValue) { @@ -362,6 +422,10 @@ namespace Google.Protobuf [TestCase("-1", -1)] [TestCase("2147483647", 2147483647)] [TestCase("-2147483648", -2147483648)] + [TestCase("1e1", 10)] + [TestCase("-1e1", -10)] + [TestCase("10.00", 10)] + [TestCase("-10.00", -10)] public void NumberToInt32_Valid(string jsonValue, int expectedParsedValue) { string json = "{ \"singleInt32\": " + jsonValue + "}"; @@ -375,7 +439,8 @@ namespace Google.Protobuf [TestCase("-00", typeof(InvalidJsonException))] [TestCase("--1", typeof(InvalidJsonException))] [TestCase("+1", typeof(InvalidJsonException))] - [TestCase("1.5", typeof(InvalidProtocolBufferException), Ignore = true, Reason = "Desired behaviour unclear")] + [TestCase("1.5", typeof(InvalidProtocolBufferException))] + // Value is out of range [TestCase("1e10", typeof(InvalidProtocolBufferException))] [TestCase("2147483648", typeof(InvalidProtocolBufferException))] [TestCase("-2147483649", typeof(InvalidProtocolBufferException))] @@ -410,8 +475,10 @@ namespace Google.Protobuf [TestCase("0", 0L)] [TestCase("1", 1L)] [TestCase("-1", -1L)] - [TestCase("9223372036854775807", 9223372036854775807, Ignore = true, Reason = "Desired behaviour unclear")] - [TestCase("-9223372036854775808", -9223372036854775808, Ignore = true, Reason = "Desired behaviour unclear")] + // long.MaxValue isn't actually representable as a double. This string value is the highest + // representable value which isn't greater than long.MaxValue. + [TestCase("9223372036854774784", 9223372036854774784)] + [TestCase("-9223372036854775808", -9223372036854775808)] public void NumberToInt64_Valid(string jsonValue, long expectedParsedValue) { string json = "{ \"singleInt64\": " + jsonValue + "}"; @@ -421,8 +488,11 @@ namespace Google.Protobuf // Assume that anything non-bounds-related is covered in the Int32 case [Test] - [TestCase("-9223372036854775809", Ignore = true, Reason = "Desired behaviour unclear")] - [TestCase("9223372036854775808", Ignore = true, Reason = "Desired behaviour unclear")] + [TestCase("9223372036854775808")] + // Theoretical bound would be -9223372036854775809, but when that is parsed to a double + // we end up with the exact value of long.MinValue due to lack of precision. The value here + // is the "next double down". + [TestCase("-9223372036854780000")] public void NumberToInt64_Invalid(string jsonValue) { string json = "{ \"singleInt64\": " + jsonValue + "}"; @@ -432,7 +502,9 @@ namespace Google.Protobuf [Test] [TestCase("0", 0UL)] [TestCase("1", 1UL)] - [TestCase("18446744073709551615", 18446744073709551615, Ignore = true, Reason = "Desired behaviour unclear")] + // ulong.MaxValue isn't representable as a double. This value is the largest double within + // the range of ulong. + [TestCase("18446744073709549568", 18446744073709549568UL)] public void NumberToUInt64_Valid(string jsonValue, ulong expectedParsedValue) { string json = "{ \"singleUint64\": " + jsonValue + "}"; @@ -474,9 +546,9 @@ namespace Google.Protobuf } [Test] - [TestCase("1.7977e308", Ignore = true, Reason = "Desired behaviour unclear")] - [TestCase("-1.7977e308", Ignore = true, Reason = "Desired behaviour unclear")] - [TestCase("1e309", Ignore = true, Reason = "Desired behaviour unclear")] + [TestCase("1.7977e308")] + [TestCase("-1.7977e308")] + [TestCase("1e309")] [TestCase("1,0")] [TestCase("1.0.0")] [TestCase("+1")] @@ -564,9 +636,9 @@ namespace Google.Protobuf public void Timestamp_Valid(string jsonValue, string expectedFormatted) { expectedFormatted = expectedFormatted ?? jsonValue; - string json = "\"" + jsonValue + "\""; + string json = WrapInQuotes(jsonValue); var parsed = Timestamp.Parser.ParseJson(json); - Assert.AreEqual(expectedFormatted, parsed.ToString()); + Assert.AreEqual(WrapInQuotes(expectedFormatted), parsed.ToString()); } [Test] @@ -591,7 +663,7 @@ namespace Google.Protobuf [TestCase("2100-02-29T14:46:23.123456789Z", Description = "Feb 29th on a non-leap-year")] public void Timestamp_Invalid(string jsonValue) { - string json = "\"" + jsonValue + "\""; + string json = WrapInQuotes(jsonValue); Assert.Throws<InvalidProtocolBufferException>(() => Timestamp.Parser.ParseJson(json)); } @@ -665,9 +737,9 @@ namespace Google.Protobuf public void Duration_Valid(string jsonValue, string expectedFormatted) { expectedFormatted = expectedFormatted ?? jsonValue; - string json = "\"" + jsonValue + "\""; + string json = WrapInQuotes(jsonValue); var parsed = Duration.Parser.ParseJson(json); - Assert.AreEqual(expectedFormatted, parsed.ToString()); + Assert.AreEqual(WrapInQuotes(expectedFormatted), parsed.ToString()); } // The simplest way of testing that the value has parsed correctly is to reformat it, @@ -691,12 +763,11 @@ namespace Google.Protobuf [TestCase("--0.123456789s", Description = "Double minus sign")] // Violate upper/lower bounds in various ways [TestCase("315576000001s", Description = "Integer part too large")] - [TestCase("315576000000.000000001s", Description = "Integer part is upper bound; non-zero fraction")] [TestCase("3155760000000s", Description = "Integer part too long (positive)")] [TestCase("-3155760000000s", Description = "Integer part too long (negative)")] public void Duration_Invalid(string jsonValue) { - string json = "\"" + jsonValue + "\""; + string json = WrapInQuotes(jsonValue); Assert.Throws<InvalidProtocolBufferException>(() => Duration.Parser.ParseJson(json)); } @@ -712,12 +783,76 @@ namespace Google.Protobuf [TestCase("fooBar.bazQux", "foo_bar.baz_qux")] public void FieldMask_Valid(string jsonValue, params string[] expectedPaths) { - string json = "\"" + jsonValue + "\""; + string json = WrapInQuotes(jsonValue); var parsed = FieldMask.Parser.ParseJson(json); CollectionAssert.AreEqual(expectedPaths, parsed.Paths); } [Test] + [TestCase("foo_bar")] + public void FieldMask_Invalid(string jsonValue) + { + string json = WrapInQuotes(jsonValue); + Assert.Throws<InvalidProtocolBufferException>(() => FieldMask.Parser.ParseJson(json)); + } + + [Test] + public void Any_RegularMessage() + { + var registry = TypeRegistry.FromMessages(TestAllTypes.Descriptor); + var formatter = new JsonFormatter(new JsonFormatter.Settings(false, TypeRegistry.FromMessages(TestAllTypes.Descriptor))); + var message = new TestAllTypes { SingleInt32 = 10, SingleNestedMessage = new TestAllTypes.Types.NestedMessage { Bb = 20 } }; + var original = Any.Pack(message); + var json = formatter.Format(original); // This is tested in JsonFormatterTest + var parser = new JsonParser(new JsonParser.Settings(10, registry)); + Assert.AreEqual(original, parser.Parse<Any>(json)); + string valueFirstJson = "{ \"singleInt32\": 10, \"singleNestedMessage\": { \"bb\": 20 }, \"@type\": \"type.googleapis.com/protobuf_unittest.TestAllTypes\" }"; + Assert.AreEqual(original, parser.Parse<Any>(valueFirstJson)); + } + + [Test] + public void Any_UnknownType() + { + string json = "{ \"@type\": \"type.googleapis.com/bogus\" }"; + Assert.Throws<InvalidOperationException>(() => Any.Parser.ParseJson(json)); + } + + [Test] + public void Any_NoTypeUrl() + { + string json = "{ \"foo\": \"bar\" }"; + Assert.Throws<InvalidProtocolBufferException>(() => Any.Parser.ParseJson(json)); + } + + [Test] + public void Any_WellKnownType() + { + var registry = TypeRegistry.FromMessages(Timestamp.Descriptor); + var formatter = new JsonFormatter(new JsonFormatter.Settings(false, registry)); + var timestamp = new DateTime(1673, 6, 19, 12, 34, 56, DateTimeKind.Utc).ToTimestamp(); + var original = Any.Pack(timestamp); + var json = formatter.Format(original); // This is tested in JsonFormatterTest + var parser = new JsonParser(new JsonParser.Settings(10, registry)); + Assert.AreEqual(original, parser.Parse<Any>(json)); + string valueFirstJson = "{ \"value\": \"1673-06-19T12:34:56Z\", \"@type\": \"type.googleapis.com/google.protobuf.Timestamp\" }"; + Assert.AreEqual(original, parser.Parse<Any>(valueFirstJson)); + } + + [Test] + public void Any_Nested() + { + var registry = TypeRegistry.FromMessages(TestWellKnownTypes.Descriptor, TestAllTypes.Descriptor); + var formatter = new JsonFormatter(new JsonFormatter.Settings(false, registry)); + var parser = new JsonParser(new JsonParser.Settings(10, registry)); + var doubleNestedMessage = new TestAllTypes { SingleInt32 = 20 }; + var nestedMessage = Any.Pack(doubleNestedMessage); + var message = new TestWellKnownTypes { AnyField = Any.Pack(nestedMessage) }; + var json = formatter.Format(message); + // Use the descriptor-based parser just for a change. + Assert.AreEqual(message, parser.Parse(json, TestWellKnownTypes.Descriptor)); + } + + [Test] public void DataAfterObject() { string json = "{} 10"; @@ -739,7 +874,52 @@ namespace Google.Protobuf var parser63 = new JsonParser(new JsonParser.Settings(63)); Assert.Throws<InvalidProtocolBufferException>(() => parser63.Parse<TestRecursiveMessage>(data64)); + } + [Test] + [TestCase("AQI")] + [TestCase("_-==")] + public void Bytes_InvalidBase64(string badBase64) + { + string json = "{ \"singleBytes\": \"" + badBase64 + "\" }"; + Assert.Throws<InvalidProtocolBufferException>(() => TestAllTypes.Parser.ParseJson(json)); + } + + [Test] + [TestCase("\"FOREIGN_BAR\"", ForeignEnum.FOREIGN_BAR)] + [TestCase("5", ForeignEnum.FOREIGN_BAR)] + [TestCase("100", (ForeignEnum) 100)] + public void EnumValid(string value, ForeignEnum expectedValue) + { + string json = "{ \"singleForeignEnum\": " + value + " }"; + var parsed = TestAllTypes.Parser.ParseJson(json); + Assert.AreEqual(new TestAllTypes { SingleForeignEnum = expectedValue }, parsed); + } + + [Test] + [TestCase("\"NOT_A_VALID_VALUE\"")] + [TestCase("5.5")] + public void Enum_Invalid(string value) + { + string json = "{ \"singleForeignEnum\": " + value + " }"; + Assert.Throws<InvalidProtocolBufferException>(() => TestAllTypes.Parser.ParseJson(json)); + } + + [Test] + public void OneofDuplicate_Invalid() + { + string json = "{ \"oneofString\": \"x\", \"oneofUint32\": 10 }"; + Assert.Throws<InvalidProtocolBufferException>(() => TestAllTypes.Parser.ParseJson(json)); + } + + /// <summary> + /// Various tests use strings which have quotes round them for parsing or as the result + /// of formatting, but without those quotes being specified in the tests (for the sake of readability). + /// This method simply returns the input, wrapped in double quotes. + /// </summary> + internal static string WrapInQuotes(string text) + { + return '"' + text + '"'; } } } diff --git a/csharp/src/Google.Protobuf.Test/JsonTokenizerTest.cs b/csharp/src/Google.Protobuf.Test/JsonTokenizerTest.cs index a38efeed..a0a62227 100644 --- a/csharp/src/Google.Protobuf.Test/JsonTokenizerTest.cs +++ b/csharp/src/Google.Protobuf.Test/JsonTokenizerTest.cs @@ -85,7 +85,7 @@ namespace Google.Protobuf public void ObjectDepth() { string json = "{ \"foo\": { \"x\": 1, \"y\": [ 0 ] } }"; - var tokenizer = new JsonTokenizer(new StringReader(json)); + var tokenizer = JsonTokenizer.FromTextReader(new StringReader(json)); // If we had more tests like this, I'd introduce a helper method... but for one test, it's not worth it. Assert.AreEqual(0, tokenizer.ObjectDepth); Assert.AreEqual(JsonToken.StartObject, tokenizer.Next()); @@ -118,7 +118,7 @@ namespace Google.Protobuf public void ObjectDepth_WithPushBack() { string json = "{}"; - var tokenizer = new JsonTokenizer(new StringReader(json)); + var tokenizer = JsonTokenizer.FromTextReader(new StringReader(json)); Assert.AreEqual(0, tokenizer.ObjectDepth); var token = tokenizer.Next(); Assert.AreEqual(1, tokenizer.ObjectDepth); @@ -275,7 +275,7 @@ namespace Google.Protobuf // Note: we don't test that the earlier tokens are exactly as expected, // partly because that's hard to parameterize. var reader = new StringReader(json.Replace('\'', '"')); - var tokenizer = new JsonTokenizer(reader); + var tokenizer = JsonTokenizer.FromTextReader(reader); for (int i = 0; i < expectedValidTokens; i++) { Assert.IsNotNull(tokenizer.Next()); @@ -334,7 +334,7 @@ namespace Google.Protobuf [Test] public void NextAfterEndDocumentThrows() { - var tokenizer = new JsonTokenizer(new StringReader("null")); + var tokenizer = JsonTokenizer.FromTextReader(new StringReader("null")); Assert.AreEqual(JsonToken.Null, tokenizer.Next()); Assert.AreEqual(JsonToken.EndDocument, tokenizer.Next()); Assert.Throws<InvalidOperationException>(() => tokenizer.Next()); @@ -343,7 +343,7 @@ namespace Google.Protobuf [Test] public void CanPushBackEndDocument() { - var tokenizer = new JsonTokenizer(new StringReader("null")); + var tokenizer = JsonTokenizer.FromTextReader(new StringReader("null")); Assert.AreEqual(JsonToken.Null, tokenizer.Next()); Assert.AreEqual(JsonToken.EndDocument, tokenizer.Next()); tokenizer.PushBack(JsonToken.EndDocument); @@ -373,7 +373,7 @@ namespace Google.Protobuf private static void AssertTokensNoReplacement(string json, params JsonToken[] expectedTokens) { var reader = new StringReader(json); - var tokenizer = new JsonTokenizer(reader); + var tokenizer = JsonTokenizer.FromTextReader(reader); for (int i = 0; i < expectedTokens.Length; i++) { var actualToken = tokenizer.Next(); @@ -393,7 +393,7 @@ namespace Google.Protobuf private static void AssertThrowsAfter(string json, params JsonToken[] expectedTokens) { var reader = new StringReader(json); - var tokenizer = new JsonTokenizer(reader); + var tokenizer = JsonTokenizer.FromTextReader(reader); for (int i = 0; i < expectedTokens.Length; i++) { var actualToken = tokenizer.Next(); diff --git a/csharp/src/Google.Protobuf.Test/Reflection/DescriptorsTest.cs b/csharp/src/Google.Protobuf.Test/Reflection/DescriptorsTest.cs index 51eff053..086a4e98 100644 --- a/csharp/src/Google.Protobuf.Test/Reflection/DescriptorsTest.cs +++ b/csharp/src/Google.Protobuf.Test/Reflection/DescriptorsTest.cs @@ -63,7 +63,7 @@ namespace Google.Protobuf.Reflection Assert.AreEqual(UnittestImportProto3Reflection.Descriptor, file.Dependencies[0]); MessageDescriptor messageType = TestAllTypes.Descriptor; - Assert.AreSame(typeof(TestAllTypes), messageType.GeneratedType); + Assert.AreSame(typeof(TestAllTypes), messageType.ClrType); Assert.AreSame(TestAllTypes.Parser, messageType.Parser); Assert.AreEqual(messageType, file.MessageTypes[0]); Assert.AreEqual(messageType, file.FindTypeByName<MessageDescriptor>("TestAllTypes")); @@ -227,18 +227,12 @@ namespace Google.Protobuf.Reflection } [Test] - public void ConstructionWithoutGeneratedCodeInfo() + public void MapEntryMessageDescriptor() { - var data = UnittestIssuesReflection.Descriptor.Proto.ToByteArray(); - var newDescriptor = Google.Protobuf.Reflection.FileDescriptor.InternalBuildGeneratedFileFrom(data, new Reflection.FileDescriptor[] { }, null); - - // We should still be able to get at a field... - var messageDescriptor = newDescriptor.FindTypeByName<MessageDescriptor>("ItemField"); - var fieldDescriptor = messageDescriptor.FindFieldByName("item"); - // But there shouldn't be an accessor (or a generated type for the message, or parser) - Assert.IsNull(fieldDescriptor.Accessor); - Assert.IsNull(messageDescriptor.GeneratedType); - Assert.IsNull(messageDescriptor.Parser); + var descriptor = MapWellKnownTypes.Descriptor.NestedTypes[0]; + Assert.IsNull(descriptor.Parser); + Assert.IsNull(descriptor.ClrType); + Assert.IsNull(descriptor.Fields[1].Accessor); } // From TestFieldOrdering: diff --git a/csharp/src/Google.Protobuf.Test/Reflection/TypeRegistryTest.cs b/csharp/src/Google.Protobuf.Test/Reflection/TypeRegistryTest.cs new file mode 100644 index 00000000..5be7ca23 --- /dev/null +++ b/csharp/src/Google.Protobuf.Test/Reflection/TypeRegistryTest.cs @@ -0,0 +1,94 @@ +#region Copyright notice and license +// Protocol Buffers - Google's data interchange format +// Copyright 2015 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#endregion + +using Google.Protobuf.TestProtos; +using Google.Protobuf.WellKnownTypes; +using NUnit.Framework; + +namespace Google.Protobuf.Reflection +{ + public class TypeRegistryTest + { + // Most of our tests use messages. Simple test that we really can use files... + [Test] + public void CreateWithFileDescriptor() + { + var registry = TypeRegistry.FromFiles(DurationReflection.Descriptor, StructReflection.Descriptor); + AssertDescriptorPresent(registry, Duration.Descriptor); + AssertDescriptorPresent(registry, ListValue.Descriptor); + AssertDescriptorAbsent(registry, Timestamp.Descriptor); + } + + [Test] + public void TypesFromSameFile() + { + // Just for kicks, let's start with a nested type + var registry = TypeRegistry.FromMessages(TestAllTypes.Types.NestedMessage.Descriptor); + // Top-level... + AssertDescriptorPresent(registry, TestFieldOrderings.Descriptor); + // ... and nested (not the same as the original NestedMessage!) + AssertDescriptorPresent(registry, TestFieldOrderings.Types.NestedMessage.Descriptor); + } + + [Test] + public void DependenciesAreIncluded() + { + var registry = TypeRegistry.FromMessages(TestAllTypes.Descriptor); + // Direct dependencies + AssertDescriptorPresent(registry, ImportMessage.Descriptor); + // Public dependencies + AssertDescriptorPresent(registry, PublicImportMessage.Descriptor); + } + + [Test] + public void DuplicateFiles() + { + // Duplicates via dependencies and simply via repetition + var registry = TypeRegistry.FromFiles( + UnittestProto3Reflection.Descriptor, UnittestImportProto3Reflection.Descriptor, + TimestampReflection.Descriptor, TimestampReflection.Descriptor); + AssertDescriptorPresent(registry, TestAllTypes.Descriptor); + AssertDescriptorPresent(registry, ImportMessage.Descriptor); + AssertDescriptorPresent(registry, Timestamp.Descriptor); + } + + private static void AssertDescriptorPresent(TypeRegistry registry, MessageDescriptor descriptor) + { + Assert.AreSame(descriptor, registry.Find(descriptor.FullName)); + } + + private static void AssertDescriptorAbsent(TypeRegistry registry, MessageDescriptor descriptor) + { + Assert.IsNull(registry.Find(descriptor.FullName)); + } + } +} diff --git a/csharp/src/Google.Protobuf.Test/TestProtos/ForeignMessagePartial.cs b/csharp/src/Google.Protobuf.Test/TestProtos/ForeignMessagePartial.cs new file mode 100644 index 00000000..5663a699 --- /dev/null +++ b/csharp/src/Google.Protobuf.Test/TestProtos/ForeignMessagePartial.cs @@ -0,0 +1,45 @@ +#region Copyright notice and license +// Protocol Buffers - Google's data interchange format +// Copyright 2016 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#endregion + +namespace Google.Protobuf.TestProtos +{ + /// <summary> + /// A message with custom diagnostics (to test that they work). + /// </summary> + public partial class ForeignMessage : ICustomDiagnosticMessage + { + public string ToDiagnosticString() + { + return $"{{ \"c\": {C}, \"@cInHex\": \"{C:x}\" }}"; + } + } +} diff --git a/csharp/src/Google.Protobuf.Test/TestProtos/MapUnittestProto3.cs b/csharp/src/Google.Protobuf.Test/TestProtos/MapUnittestProto3.cs index 66b9d842..27c04787 100644 --- a/csharp/src/Google.Protobuf.Test/TestProtos/MapUnittestProto3.cs +++ b/csharp/src/Google.Protobuf.Test/TestProtos/MapUnittestProto3.cs @@ -147,16 +147,16 @@ namespace Google.Protobuf.TestProtos { "dmFsdWUYAiABKAU6AjgBKj8KB01hcEVudW0SEAoMTUFQX0VOVU1fRk9PEAAS", "EAoMTUFQX0VOVU1fQkFSEAESEAoMTUFQX0VOVU1fQkFaEAJCIPgBAaoCGkdv", "b2dsZS5Qcm90b2J1Zi5UZXN0UHJvdG9zYgZwcm90bzM=")); - descriptor = pbr::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData, + descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, new pbr::FileDescriptor[] { global::Google.Protobuf.TestProtos.UnittestProto3Reflection.Descriptor, }, - new pbr::GeneratedCodeInfo(new[] {typeof(global::Google.Protobuf.TestProtos.MapEnum), }, new pbr::GeneratedCodeInfo[] { - new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.TestMap), global::Google.Protobuf.TestProtos.TestMap.Parser, new[]{ "MapInt32Int32", "MapInt64Int64", "MapUint32Uint32", "MapUint64Uint64", "MapSint32Sint32", "MapSint64Sint64", "MapFixed32Fixed32", "MapFixed64Fixed64", "MapSfixed32Sfixed32", "MapSfixed64Sfixed64", "MapInt32Float", "MapInt32Double", "MapBoolBool", "MapStringString", "MapInt32Bytes", "MapInt32Enum", "MapInt32ForeignMessage" }, null, null, new pbr::GeneratedCodeInfo[] { null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, }), - new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.TestMapSubmessage), global::Google.Protobuf.TestProtos.TestMapSubmessage.Parser, new[]{ "TestMap" }, null, null, null), - new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.TestMessageMap), global::Google.Protobuf.TestProtos.TestMessageMap.Parser, new[]{ "MapInt32Message" }, null, null, new pbr::GeneratedCodeInfo[] { null, }), - new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.TestSameTypeMap), global::Google.Protobuf.TestProtos.TestSameTypeMap.Parser, new[]{ "Map1", "Map2" }, null, null, new pbr::GeneratedCodeInfo[] { null, null, }), - new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.TestArenaMap), global::Google.Protobuf.TestProtos.TestArenaMap.Parser, new[]{ "MapInt32Int32", "MapInt64Int64", "MapUint32Uint32", "MapUint64Uint64", "MapSint32Sint32", "MapSint64Sint64", "MapFixed32Fixed32", "MapFixed64Fixed64", "MapSfixed32Sfixed32", "MapSfixed64Sfixed64", "MapInt32Float", "MapInt32Double", "MapBoolBool", "MapInt32Enum", "MapInt32ForeignMessage" }, null, null, new pbr::GeneratedCodeInfo[] { null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, }), - new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.MessageContainingEnumCalledType), global::Google.Protobuf.TestProtos.MessageContainingEnumCalledType.Parser, new[]{ "Type" }, null, new[]{ typeof(global::Google.Protobuf.TestProtos.MessageContainingEnumCalledType.Types.Type) }, new pbr::GeneratedCodeInfo[] { null, }), - new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.MessageContainingMapCalledEntry), global::Google.Protobuf.TestProtos.MessageContainingMapCalledEntry.Parser, new[]{ "Entry" }, null, null, new pbr::GeneratedCodeInfo[] { null, }) + new pbr::GeneratedClrTypeInfo(new[] {typeof(global::Google.Protobuf.TestProtos.MapEnum), }, new pbr::GeneratedClrTypeInfo[] { + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.TestMap), global::Google.Protobuf.TestProtos.TestMap.Parser, new[]{ "MapInt32Int32", "MapInt64Int64", "MapUint32Uint32", "MapUint64Uint64", "MapSint32Sint32", "MapSint64Sint64", "MapFixed32Fixed32", "MapFixed64Fixed64", "MapSfixed32Sfixed32", "MapSfixed64Sfixed64", "MapInt32Float", "MapInt32Double", "MapBoolBool", "MapStringString", "MapInt32Bytes", "MapInt32Enum", "MapInt32ForeignMessage" }, null, null, new pbr::GeneratedClrTypeInfo[] { null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, }), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.TestMapSubmessage), global::Google.Protobuf.TestProtos.TestMapSubmessage.Parser, new[]{ "TestMap" }, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.TestMessageMap), global::Google.Protobuf.TestProtos.TestMessageMap.Parser, new[]{ "MapInt32Message" }, null, null, new pbr::GeneratedClrTypeInfo[] { null, }), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.TestSameTypeMap), global::Google.Protobuf.TestProtos.TestSameTypeMap.Parser, new[]{ "Map1", "Map2" }, null, null, new pbr::GeneratedClrTypeInfo[] { null, null, }), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.TestArenaMap), global::Google.Protobuf.TestProtos.TestArenaMap.Parser, new[]{ "MapInt32Int32", "MapInt64Int64", "MapUint32Uint32", "MapUint64Uint64", "MapSint32Sint32", "MapSint64Sint64", "MapFixed32Fixed32", "MapFixed64Fixed64", "MapSfixed32Sfixed32", "MapSfixed64Sfixed64", "MapInt32Float", "MapInt32Double", "MapBoolBool", "MapInt32Enum", "MapInt32ForeignMessage" }, null, null, new pbr::GeneratedClrTypeInfo[] { null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, }), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.MessageContainingEnumCalledType), global::Google.Protobuf.TestProtos.MessageContainingEnumCalledType.Parser, new[]{ "Type" }, null, new[]{ typeof(global::Google.Protobuf.TestProtos.MessageContainingEnumCalledType.Types.Type) }, new pbr::GeneratedClrTypeInfo[] { null, }), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.MessageContainingMapCalledEntry), global::Google.Protobuf.TestProtos.MessageContainingMapCalledEntry.Parser, new[]{ "Entry" }, null, null, new pbr::GeneratedClrTypeInfo[] { null, }) })); } #endregion @@ -425,7 +425,7 @@ namespace Google.Protobuf.TestProtos { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -633,7 +633,7 @@ namespace Google.Protobuf.TestProtos { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -741,7 +741,7 @@ namespace Google.Protobuf.TestProtos { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -851,7 +851,7 @@ namespace Google.Protobuf.TestProtos { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -1121,7 +1121,7 @@ namespace Google.Protobuf.TestProtos { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -1318,7 +1318,7 @@ namespace Google.Protobuf.TestProtos { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -1427,7 +1427,7 @@ namespace Google.Protobuf.TestProtos { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { diff --git a/csharp/src/Google.Protobuf.Test/TestProtos/UnittestImportProto3.cs b/csharp/src/Google.Protobuf.Test/TestProtos/UnittestImportProto3.cs index 78a6bc14..7b824dc7 100644 --- a/csharp/src/Google.Protobuf.Test/TestProtos/UnittestImportProto3.cs +++ b/csharp/src/Google.Protobuf.Test/TestProtos/UnittestImportProto3.cs @@ -31,10 +31,10 @@ namespace Google.Protobuf.TestProtos { "UhAIEg4KCklNUE9SVF9CQVoQCUI8Chhjb20uZ29vZ2xlLnByb3RvYnVmLnRl", "c3RIAfgBAaoCGkdvb2dsZS5Qcm90b2J1Zi5UZXN0UHJvdG9zUABiBnByb3Rv", "Mw==")); - descriptor = pbr::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData, + descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, new pbr::FileDescriptor[] { global::Google.Protobuf.TestProtos.UnittestImportPublicProto3Reflection.Descriptor, }, - new pbr::GeneratedCodeInfo(new[] {typeof(global::Google.Protobuf.TestProtos.ImportEnum), }, new pbr::GeneratedCodeInfo[] { - new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.ImportMessage), global::Google.Protobuf.TestProtos.ImportMessage.Parser, new[]{ "D" }, null, null, null) + new pbr::GeneratedClrTypeInfo(new[] {typeof(global::Google.Protobuf.TestProtos.ImportEnum), }, new pbr::GeneratedClrTypeInfo[] { + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.ImportMessage), global::Google.Protobuf.TestProtos.ImportMessage.Parser, new[]{ "D" }, null, null, null) })); } #endregion @@ -110,7 +110,7 @@ namespace Google.Protobuf.TestProtos { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { diff --git a/csharp/src/Google.Protobuf.Test/TestProtos/UnittestImportPublicProto3.cs b/csharp/src/Google.Protobuf.Test/TestProtos/UnittestImportPublicProto3.cs index d69b37e4..b471a8cf 100644 --- a/csharp/src/Google.Protobuf.Test/TestProtos/UnittestImportPublicProto3.cs +++ b/csharp/src/Google.Protobuf.Test/TestProtos/UnittestImportPublicProto3.cs @@ -27,10 +27,10 @@ namespace Google.Protobuf.TestProtos { "bzMucHJvdG8SGHByb3RvYnVmX3VuaXR0ZXN0X2ltcG9ydCIgChNQdWJsaWNJ", "bXBvcnRNZXNzYWdlEgkKAWUYASABKAVCNwoYY29tLmdvb2dsZS5wcm90b2J1", "Zi50ZXN0qgIaR29vZ2xlLlByb3RvYnVmLlRlc3RQcm90b3NiBnByb3RvMw==")); - descriptor = pbr::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData, + descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, new pbr::FileDescriptor[] { }, - new pbr::GeneratedCodeInfo(null, new pbr::GeneratedCodeInfo[] { - new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.PublicImportMessage), global::Google.Protobuf.TestProtos.PublicImportMessage.Parser, new[]{ "E" }, null, null, null) + new pbr::GeneratedClrTypeInfo(null, new pbr::GeneratedClrTypeInfo[] { + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.PublicImportMessage), global::Google.Protobuf.TestProtos.PublicImportMessage.Parser, new[]{ "E" }, null, null, null) })); } #endregion @@ -96,7 +96,7 @@ namespace Google.Protobuf.TestProtos { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { diff --git a/csharp/src/Google.Protobuf.Test/TestProtos/UnittestIssues.cs b/csharp/src/Google.Protobuf.Test/TestProtos/UnittestIssues.cs index 5709b65c..16176a33 100644 --- a/csharp/src/Google.Protobuf.Test/TestProtos/UnittestIssues.cs +++ b/csharp/src/Google.Protobuf.Test/TestProtos/UnittestIssues.cs @@ -46,16 +46,16 @@ namespace UnitTest.Issues.TestProtos { "aXZlQmVsb3cQ+///////////ARIVCghNaW51c09uZRD///////////8BKi4K", "DkRlcHJlY2F0ZWRFbnVtEhMKD0RFUFJFQ0FURURfWkVSTxAAEgcKA29uZRAB", "Qh9IAaoCGlVuaXRUZXN0Lklzc3Vlcy5UZXN0UHJvdG9zYgZwcm90bzM=")); - descriptor = pbr::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData, + descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, new pbr::FileDescriptor[] { }, - new pbr::GeneratedCodeInfo(new[] {typeof(global::UnitTest.Issues.TestProtos.NegativeEnum), typeof(global::UnitTest.Issues.TestProtos.DeprecatedEnum), }, new pbr::GeneratedCodeInfo[] { - new pbr::GeneratedCodeInfo(typeof(global::UnitTest.Issues.TestProtos.Issue307), global::UnitTest.Issues.TestProtos.Issue307.Parser, null, null, null, new pbr::GeneratedCodeInfo[] { new pbr::GeneratedCodeInfo(typeof(global::UnitTest.Issues.TestProtos.Issue307.Types.NestedOnce), global::UnitTest.Issues.TestProtos.Issue307.Types.NestedOnce.Parser, null, null, null, new pbr::GeneratedCodeInfo[] { new pbr::GeneratedCodeInfo(typeof(global::UnitTest.Issues.TestProtos.Issue307.Types.NestedOnce.Types.NestedTwice), global::UnitTest.Issues.TestProtos.Issue307.Types.NestedOnce.Types.NestedTwice.Parser, null, null, null, null)})}), - new pbr::GeneratedCodeInfo(typeof(global::UnitTest.Issues.TestProtos.NegativeEnumMessage), global::UnitTest.Issues.TestProtos.NegativeEnumMessage.Parser, new[]{ "Value", "Values", "PackedValues" }, null, null, null), - new pbr::GeneratedCodeInfo(typeof(global::UnitTest.Issues.TestProtos.DeprecatedChild), global::UnitTest.Issues.TestProtos.DeprecatedChild.Parser, null, null, null, null), - new pbr::GeneratedCodeInfo(typeof(global::UnitTest.Issues.TestProtos.DeprecatedFieldsMessage), global::UnitTest.Issues.TestProtos.DeprecatedFieldsMessage.Parser, new[]{ "PrimitiveValue", "PrimitiveArray", "MessageValue", "MessageArray", "EnumValue", "EnumArray" }, null, null, null), - new pbr::GeneratedCodeInfo(typeof(global::UnitTest.Issues.TestProtos.ItemField), global::UnitTest.Issues.TestProtos.ItemField.Parser, new[]{ "Item" }, null, null, null), - new pbr::GeneratedCodeInfo(typeof(global::UnitTest.Issues.TestProtos.ReservedNames), global::UnitTest.Issues.TestProtos.ReservedNames.Parser, new[]{ "Types_", "Descriptor_" }, null, null, new pbr::GeneratedCodeInfo[] { new pbr::GeneratedCodeInfo(typeof(global::UnitTest.Issues.TestProtos.ReservedNames.Types.SomeNestedType), global::UnitTest.Issues.TestProtos.ReservedNames.Types.SomeNestedType.Parser, null, null, null, null)}), - new pbr::GeneratedCodeInfo(typeof(global::UnitTest.Issues.TestProtos.TestJsonFieldOrdering), global::UnitTest.Issues.TestProtos.TestJsonFieldOrdering.Parser, new[]{ "PlainInt32", "O1String", "O1Int32", "PlainString", "O2Int32", "O2String" }, new[]{ "O1", "O2" }, null, null) + new pbr::GeneratedClrTypeInfo(new[] {typeof(global::UnitTest.Issues.TestProtos.NegativeEnum), typeof(global::UnitTest.Issues.TestProtos.DeprecatedEnum), }, new pbr::GeneratedClrTypeInfo[] { + new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.Issue307), global::UnitTest.Issues.TestProtos.Issue307.Parser, null, null, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.Issue307.Types.NestedOnce), global::UnitTest.Issues.TestProtos.Issue307.Types.NestedOnce.Parser, null, null, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.Issue307.Types.NestedOnce.Types.NestedTwice), global::UnitTest.Issues.TestProtos.Issue307.Types.NestedOnce.Types.NestedTwice.Parser, null, null, null, null)})}), + new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.NegativeEnumMessage), global::UnitTest.Issues.TestProtos.NegativeEnumMessage.Parser, new[]{ "Value", "Values", "PackedValues" }, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.DeprecatedChild), global::UnitTest.Issues.TestProtos.DeprecatedChild.Parser, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.DeprecatedFieldsMessage), global::UnitTest.Issues.TestProtos.DeprecatedFieldsMessage.Parser, new[]{ "PrimitiveValue", "PrimitiveArray", "MessageValue", "MessageArray", "EnumValue", "EnumArray" }, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.ItemField), global::UnitTest.Issues.TestProtos.ItemField.Parser, new[]{ "Item" }, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.ReservedNames), global::UnitTest.Issues.TestProtos.ReservedNames.Parser, new[]{ "Types_", "Descriptor_" }, null, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.ReservedNames.Types.SomeNestedType), global::UnitTest.Issues.TestProtos.ReservedNames.Types.SomeNestedType.Parser, null, null, null, null)}), + new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.TestJsonFieldOrdering), global::UnitTest.Issues.TestProtos.TestJsonFieldOrdering.Parser, new[]{ "PlainInt32", "O1String", "O1Int32", "PlainString", "O2Int32", "O2String" }, new[]{ "O1", "O2" }, null, null) })); } #endregion @@ -126,7 +126,7 @@ namespace UnitTest.Issues.TestProtos { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -204,7 +204,7 @@ namespace UnitTest.Issues.TestProtos { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -282,7 +282,7 @@ namespace UnitTest.Issues.TestProtos { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -405,7 +405,7 @@ namespace UnitTest.Issues.TestProtos { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -511,7 +511,7 @@ namespace UnitTest.Issues.TestProtos { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -668,7 +668,7 @@ namespace UnitTest.Issues.TestProtos { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -831,7 +831,7 @@ namespace UnitTest.Issues.TestProtos { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -947,7 +947,7 @@ namespace UnitTest.Issues.TestProtos { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -1056,7 +1056,7 @@ namespace UnitTest.Issues.TestProtos { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -1164,7 +1164,7 @@ namespace UnitTest.Issues.TestProtos { public string O1String { get { return o1Case_ == O1OneofCase.O1String ? (string) o1_ : ""; } set { - o1_ = pb::Preconditions.CheckNotNull(value, "value"); + o1_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); o1Case_ = O1OneofCase.O1String; } } @@ -1185,7 +1185,7 @@ namespace UnitTest.Issues.TestProtos { public string PlainString { get { return plainString_; } set { - plainString_ = pb::Preconditions.CheckNotNull(value, "value"); + plainString_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } @@ -1204,7 +1204,7 @@ namespace UnitTest.Issues.TestProtos { public string O2String { get { return o2Case_ == O2OneofCase.O2String ? (string) o2_ : ""; } set { - o2_ = pb::Preconditions.CheckNotNull(value, "value"); + o2_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); o2Case_ = O2OneofCase.O2String; } } @@ -1279,7 +1279,7 @@ namespace UnitTest.Issues.TestProtos { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { diff --git a/csharp/src/Google.Protobuf.Test/TestProtos/UnittestProto3.cs b/csharp/src/Google.Protobuf.Test/TestProtos/UnittestProto3.cs index f027c4ee..d8465448 100644 --- a/csharp/src/Google.Protobuf.Test/TestProtos/UnittestProto3.cs +++ b/csharp/src/Google.Protobuf.Test/TestProtos/UnittestProto3.cs @@ -150,42 +150,42 @@ namespace Google.Protobuf.TestProtos { "HS5wcm90b2J1Zl91bml0dGVzdC5CYXJSZXF1ZXN0Gh4ucHJvdG9idWZfdW5p", "dHRlc3QuQmFyUmVzcG9uc2VCOkINVW5pdHRlc3RQcm90b0gBgAEBiAEBkAEB", "+AEBqgIaR29vZ2xlLlByb3RvYnVmLlRlc3RQcm90b3NiBnByb3RvMw==")); - descriptor = pbr::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData, + descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, new pbr::FileDescriptor[] { global::Google.Protobuf.TestProtos.UnittestImportProto3Reflection.Descriptor, }, - new pbr::GeneratedCodeInfo(new[] {typeof(global::Google.Protobuf.TestProtos.ForeignEnum), typeof(global::Google.Protobuf.TestProtos.TestEnumWithDupValue), typeof(global::Google.Protobuf.TestProtos.TestSparseEnum), }, new pbr::GeneratedCodeInfo[] { - new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.TestAllTypes), global::Google.Protobuf.TestProtos.TestAllTypes.Parser, new[]{ "SingleInt32", "SingleInt64", "SingleUint32", "SingleUint64", "SingleSint32", "SingleSint64", "SingleFixed32", "SingleFixed64", "SingleSfixed32", "SingleSfixed64", "SingleFloat", "SingleDouble", "SingleBool", "SingleString", "SingleBytes", "SingleNestedMessage", "SingleForeignMessage", "SingleImportMessage", "SingleNestedEnum", "SingleForeignEnum", "SingleImportEnum", "SinglePublicImportMessage", "RepeatedInt32", "RepeatedInt64", "RepeatedUint32", "RepeatedUint64", "RepeatedSint32", "RepeatedSint64", "RepeatedFixed32", "RepeatedFixed64", "RepeatedSfixed32", "RepeatedSfixed64", "RepeatedFloat", "RepeatedDouble", "RepeatedBool", "RepeatedString", "RepeatedBytes", "RepeatedNestedMessage", "RepeatedForeignMessage", "RepeatedImportMessage", "RepeatedNestedEnum", "RepeatedForeignEnum", "RepeatedImportEnum", "RepeatedPublicImportMessage", "OneofUint32", "OneofNestedMessage", "OneofString", "OneofBytes" }, new[]{ "OneofField" }, new[]{ typeof(global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedEnum) }, new pbr::GeneratedCodeInfo[] { new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedMessage), global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedMessage.Parser, new[]{ "Bb" }, null, null, null)}), - new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.NestedTestAllTypes), global::Google.Protobuf.TestProtos.NestedTestAllTypes.Parser, new[]{ "Child", "Payload", "RepeatedChild" }, null, null, null), - new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.TestDeprecatedFields), global::Google.Protobuf.TestProtos.TestDeprecatedFields.Parser, new[]{ "DeprecatedInt32" }, null, null, null), - new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.ForeignMessage), global::Google.Protobuf.TestProtos.ForeignMessage.Parser, new[]{ "C" }, null, null, null), - new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.TestReservedFields), global::Google.Protobuf.TestProtos.TestReservedFields.Parser, null, null, null, null), - new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.TestForeignNested), global::Google.Protobuf.TestProtos.TestForeignNested.Parser, new[]{ "ForeignNested" }, null, null, null), - new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.TestReallyLargeTagNumber), global::Google.Protobuf.TestProtos.TestReallyLargeTagNumber.Parser, new[]{ "A", "Bb" }, null, null, null), - new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.TestRecursiveMessage), global::Google.Protobuf.TestProtos.TestRecursiveMessage.Parser, new[]{ "A", "I" }, null, null, null), - new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.TestMutualRecursionA), global::Google.Protobuf.TestProtos.TestMutualRecursionA.Parser, new[]{ "Bb" }, null, null, null), - new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.TestMutualRecursionB), global::Google.Protobuf.TestProtos.TestMutualRecursionB.Parser, new[]{ "A", "OptionalInt32" }, null, null, null), - new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.TestCamelCaseFieldNames), global::Google.Protobuf.TestProtos.TestCamelCaseFieldNames.Parser, new[]{ "PrimitiveField", "StringField", "EnumField", "MessageField", "RepeatedPrimitiveField", "RepeatedStringField", "RepeatedEnumField", "RepeatedMessageField" }, null, null, null), - new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.TestFieldOrderings), global::Google.Protobuf.TestProtos.TestFieldOrderings.Parser, new[]{ "MyString", "MyInt", "MyFloat", "SingleNestedMessage" }, null, null, new pbr::GeneratedCodeInfo[] { new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.TestFieldOrderings.Types.NestedMessage), global::Google.Protobuf.TestProtos.TestFieldOrderings.Types.NestedMessage.Parser, new[]{ "Oo", "Bb" }, null, null, null)}), - new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.SparseEnumMessage), global::Google.Protobuf.TestProtos.SparseEnumMessage.Parser, new[]{ "SparseEnum" }, null, null, null), - new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.OneString), global::Google.Protobuf.TestProtos.OneString.Parser, new[]{ "Data" }, null, null, null), - new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.MoreString), global::Google.Protobuf.TestProtos.MoreString.Parser, new[]{ "Data" }, null, null, null), - new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.OneBytes), global::Google.Protobuf.TestProtos.OneBytes.Parser, new[]{ "Data" }, null, null, null), - new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.MoreBytes), global::Google.Protobuf.TestProtos.MoreBytes.Parser, new[]{ "Data" }, null, null, null), - new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.Int32Message), global::Google.Protobuf.TestProtos.Int32Message.Parser, new[]{ "Data" }, null, null, null), - new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.Uint32Message), global::Google.Protobuf.TestProtos.Uint32Message.Parser, new[]{ "Data" }, null, null, null), - new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.Int64Message), global::Google.Protobuf.TestProtos.Int64Message.Parser, new[]{ "Data" }, null, null, null), - new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.Uint64Message), global::Google.Protobuf.TestProtos.Uint64Message.Parser, new[]{ "Data" }, null, null, null), - new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.BoolMessage), global::Google.Protobuf.TestProtos.BoolMessage.Parser, new[]{ "Data" }, null, null, null), - new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.TestOneof), global::Google.Protobuf.TestProtos.TestOneof.Parser, new[]{ "FooInt", "FooString", "FooMessage" }, new[]{ "Foo" }, null, null), - new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.TestPackedTypes), global::Google.Protobuf.TestProtos.TestPackedTypes.Parser, new[]{ "PackedInt32", "PackedInt64", "PackedUint32", "PackedUint64", "PackedSint32", "PackedSint64", "PackedFixed32", "PackedFixed64", "PackedSfixed32", "PackedSfixed64", "PackedFloat", "PackedDouble", "PackedBool", "PackedEnum" }, null, null, null), - new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.TestUnpackedTypes), global::Google.Protobuf.TestProtos.TestUnpackedTypes.Parser, new[]{ "UnpackedInt32", "UnpackedInt64", "UnpackedUint32", "UnpackedUint64", "UnpackedSint32", "UnpackedSint64", "UnpackedFixed32", "UnpackedFixed64", "UnpackedSfixed32", "UnpackedSfixed64", "UnpackedFloat", "UnpackedDouble", "UnpackedBool", "UnpackedEnum" }, null, null, null), - new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.TestRepeatedScalarDifferentTagSizes), global::Google.Protobuf.TestProtos.TestRepeatedScalarDifferentTagSizes.Parser, new[]{ "RepeatedFixed32", "RepeatedInt32", "RepeatedFixed64", "RepeatedInt64", "RepeatedFloat", "RepeatedUint64" }, null, null, null), - new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.TestCommentInjectionMessage), global::Google.Protobuf.TestProtos.TestCommentInjectionMessage.Parser, new[]{ "A" }, null, null, null), - new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.FooRequest), global::Google.Protobuf.TestProtos.FooRequest.Parser, null, null, null, null), - new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.FooResponse), global::Google.Protobuf.TestProtos.FooResponse.Parser, null, null, null, null), - new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.FooClientMessage), global::Google.Protobuf.TestProtos.FooClientMessage.Parser, null, null, null, null), - new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.FooServerMessage), global::Google.Protobuf.TestProtos.FooServerMessage.Parser, null, null, null, null), - new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.BarRequest), global::Google.Protobuf.TestProtos.BarRequest.Parser, null, null, null, null), - new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.BarResponse), global::Google.Protobuf.TestProtos.BarResponse.Parser, null, null, null, null) + new pbr::GeneratedClrTypeInfo(new[] {typeof(global::Google.Protobuf.TestProtos.ForeignEnum), typeof(global::Google.Protobuf.TestProtos.TestEnumWithDupValue), typeof(global::Google.Protobuf.TestProtos.TestSparseEnum), }, new pbr::GeneratedClrTypeInfo[] { + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.TestAllTypes), global::Google.Protobuf.TestProtos.TestAllTypes.Parser, new[]{ "SingleInt32", "SingleInt64", "SingleUint32", "SingleUint64", "SingleSint32", "SingleSint64", "SingleFixed32", "SingleFixed64", "SingleSfixed32", "SingleSfixed64", "SingleFloat", "SingleDouble", "SingleBool", "SingleString", "SingleBytes", "SingleNestedMessage", "SingleForeignMessage", "SingleImportMessage", "SingleNestedEnum", "SingleForeignEnum", "SingleImportEnum", "SinglePublicImportMessage", "RepeatedInt32", "RepeatedInt64", "RepeatedUint32", "RepeatedUint64", "RepeatedSint32", "RepeatedSint64", "RepeatedFixed32", "RepeatedFixed64", "RepeatedSfixed32", "RepeatedSfixed64", "RepeatedFloat", "RepeatedDouble", "RepeatedBool", "RepeatedString", "RepeatedBytes", "RepeatedNestedMessage", "RepeatedForeignMessage", "RepeatedImportMessage", "RepeatedNestedEnum", "RepeatedForeignEnum", "RepeatedImportEnum", "RepeatedPublicImportMessage", "OneofUint32", "OneofNestedMessage", "OneofString", "OneofBytes" }, new[]{ "OneofField" }, new[]{ typeof(global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedEnum) }, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedMessage), global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedMessage.Parser, new[]{ "Bb" }, null, null, null)}), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.NestedTestAllTypes), global::Google.Protobuf.TestProtos.NestedTestAllTypes.Parser, new[]{ "Child", "Payload", "RepeatedChild" }, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.TestDeprecatedFields), global::Google.Protobuf.TestProtos.TestDeprecatedFields.Parser, new[]{ "DeprecatedInt32" }, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.ForeignMessage), global::Google.Protobuf.TestProtos.ForeignMessage.Parser, new[]{ "C" }, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.TestReservedFields), global::Google.Protobuf.TestProtos.TestReservedFields.Parser, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.TestForeignNested), global::Google.Protobuf.TestProtos.TestForeignNested.Parser, new[]{ "ForeignNested" }, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.TestReallyLargeTagNumber), global::Google.Protobuf.TestProtos.TestReallyLargeTagNumber.Parser, new[]{ "A", "Bb" }, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.TestRecursiveMessage), global::Google.Protobuf.TestProtos.TestRecursiveMessage.Parser, new[]{ "A", "I" }, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.TestMutualRecursionA), global::Google.Protobuf.TestProtos.TestMutualRecursionA.Parser, new[]{ "Bb" }, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.TestMutualRecursionB), global::Google.Protobuf.TestProtos.TestMutualRecursionB.Parser, new[]{ "A", "OptionalInt32" }, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.TestCamelCaseFieldNames), global::Google.Protobuf.TestProtos.TestCamelCaseFieldNames.Parser, new[]{ "PrimitiveField", "StringField", "EnumField", "MessageField", "RepeatedPrimitiveField", "RepeatedStringField", "RepeatedEnumField", "RepeatedMessageField" }, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.TestFieldOrderings), global::Google.Protobuf.TestProtos.TestFieldOrderings.Parser, new[]{ "MyString", "MyInt", "MyFloat", "SingleNestedMessage" }, null, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.TestFieldOrderings.Types.NestedMessage), global::Google.Protobuf.TestProtos.TestFieldOrderings.Types.NestedMessage.Parser, new[]{ "Oo", "Bb" }, null, null, null)}), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.SparseEnumMessage), global::Google.Protobuf.TestProtos.SparseEnumMessage.Parser, new[]{ "SparseEnum" }, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.OneString), global::Google.Protobuf.TestProtos.OneString.Parser, new[]{ "Data" }, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.MoreString), global::Google.Protobuf.TestProtos.MoreString.Parser, new[]{ "Data" }, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.OneBytes), global::Google.Protobuf.TestProtos.OneBytes.Parser, new[]{ "Data" }, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.MoreBytes), global::Google.Protobuf.TestProtos.MoreBytes.Parser, new[]{ "Data" }, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.Int32Message), global::Google.Protobuf.TestProtos.Int32Message.Parser, new[]{ "Data" }, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.Uint32Message), global::Google.Protobuf.TestProtos.Uint32Message.Parser, new[]{ "Data" }, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.Int64Message), global::Google.Protobuf.TestProtos.Int64Message.Parser, new[]{ "Data" }, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.Uint64Message), global::Google.Protobuf.TestProtos.Uint64Message.Parser, new[]{ "Data" }, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.BoolMessage), global::Google.Protobuf.TestProtos.BoolMessage.Parser, new[]{ "Data" }, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.TestOneof), global::Google.Protobuf.TestProtos.TestOneof.Parser, new[]{ "FooInt", "FooString", "FooMessage" }, new[]{ "Foo" }, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.TestPackedTypes), global::Google.Protobuf.TestProtos.TestPackedTypes.Parser, new[]{ "PackedInt32", "PackedInt64", "PackedUint32", "PackedUint64", "PackedSint32", "PackedSint64", "PackedFixed32", "PackedFixed64", "PackedSfixed32", "PackedSfixed64", "PackedFloat", "PackedDouble", "PackedBool", "PackedEnum" }, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.TestUnpackedTypes), global::Google.Protobuf.TestProtos.TestUnpackedTypes.Parser, new[]{ "UnpackedInt32", "UnpackedInt64", "UnpackedUint32", "UnpackedUint64", "UnpackedSint32", "UnpackedSint64", "UnpackedFixed32", "UnpackedFixed64", "UnpackedSfixed32", "UnpackedSfixed64", "UnpackedFloat", "UnpackedDouble", "UnpackedBool", "UnpackedEnum" }, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.TestRepeatedScalarDifferentTagSizes), global::Google.Protobuf.TestProtos.TestRepeatedScalarDifferentTagSizes.Parser, new[]{ "RepeatedFixed32", "RepeatedInt32", "RepeatedFixed64", "RepeatedInt64", "RepeatedFloat", "RepeatedUint64" }, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.TestCommentInjectionMessage), global::Google.Protobuf.TestProtos.TestCommentInjectionMessage.Parser, new[]{ "A" }, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.FooRequest), global::Google.Protobuf.TestProtos.FooRequest.Parser, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.FooResponse), global::Google.Protobuf.TestProtos.FooResponse.Parser, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.FooClientMessage), global::Google.Protobuf.TestProtos.FooClientMessage.Parser, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.FooServerMessage), global::Google.Protobuf.TestProtos.FooServerMessage.Parser, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.BarRequest), global::Google.Protobuf.TestProtos.BarRequest.Parser, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.BarResponse), global::Google.Protobuf.TestProtos.BarResponse.Parser, null, null, null, null) })); } #endregion @@ -459,7 +459,7 @@ namespace Google.Protobuf.TestProtos { public string SingleString { get { return singleString_; } set { - singleString_ = pb::Preconditions.CheckNotNull(value, "value"); + singleString_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } @@ -469,7 +469,7 @@ namespace Google.Protobuf.TestProtos { public pb::ByteString SingleBytes { get { return singleBytes_; } set { - singleBytes_ = pb::Preconditions.CheckNotNull(value, "value"); + singleBytes_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } @@ -775,7 +775,7 @@ namespace Google.Protobuf.TestProtos { public string OneofString { get { return oneofFieldCase_ == OneofFieldOneofCase.OneofString ? (string) oneofField_ : ""; } set { - oneofField_ = pb::Preconditions.CheckNotNull(value, "value"); + oneofField_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); oneofFieldCase_ = OneofFieldOneofCase.OneofString; } } @@ -785,7 +785,7 @@ namespace Google.Protobuf.TestProtos { public pb::ByteString OneofBytes { get { return oneofFieldCase_ == OneofFieldOneofCase.OneofBytes ? (pb::ByteString) oneofField_ : pb::ByteString.Empty; } set { - oneofField_ = pb::Preconditions.CheckNotNull(value, "value"); + oneofField_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); oneofFieldCase_ = OneofFieldOneofCase.OneofBytes; } } @@ -927,7 +927,7 @@ namespace Google.Protobuf.TestProtos { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -1600,7 +1600,7 @@ namespace Google.Protobuf.TestProtos { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -1736,7 +1736,7 @@ namespace Google.Protobuf.TestProtos { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -1873,7 +1873,7 @@ namespace Google.Protobuf.TestProtos { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -1980,7 +1980,7 @@ namespace Google.Protobuf.TestProtos { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -2070,7 +2070,7 @@ namespace Google.Protobuf.TestProtos { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -2162,7 +2162,7 @@ namespace Google.Protobuf.TestProtos { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -2291,7 +2291,7 @@ namespace Google.Protobuf.TestProtos { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -2421,7 +2421,7 @@ namespace Google.Protobuf.TestProtos { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -2547,7 +2547,7 @@ namespace Google.Protobuf.TestProtos { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -2669,7 +2669,7 @@ namespace Google.Protobuf.TestProtos { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -2787,7 +2787,7 @@ namespace Google.Protobuf.TestProtos { public string StringField { get { return stringField_; } set { - stringField_ = pb::Preconditions.CheckNotNull(value, "value"); + stringField_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } @@ -2883,7 +2883,7 @@ namespace Google.Protobuf.TestProtos { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -3045,7 +3045,7 @@ namespace Google.Protobuf.TestProtos { public string MyString { get { return myString_; } set { - myString_ = pb::Preconditions.CheckNotNull(value, "value"); + myString_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } @@ -3107,7 +3107,7 @@ namespace Google.Protobuf.TestProtos { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -3278,7 +3278,7 @@ namespace Google.Protobuf.TestProtos { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -3400,7 +3400,7 @@ namespace Google.Protobuf.TestProtos { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -3480,7 +3480,7 @@ namespace Google.Protobuf.TestProtos { public string Data { get { return data_; } set { - data_ = pb::Preconditions.CheckNotNull(value, "value"); + data_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } @@ -3506,7 +3506,7 @@ namespace Google.Protobuf.TestProtos { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -3608,7 +3608,7 @@ namespace Google.Protobuf.TestProtos { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -3678,7 +3678,7 @@ namespace Google.Protobuf.TestProtos { public pb::ByteString Data { get { return data_; } set { - data_ = pb::Preconditions.CheckNotNull(value, "value"); + data_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } @@ -3704,7 +3704,7 @@ namespace Google.Protobuf.TestProtos { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -3781,7 +3781,7 @@ namespace Google.Protobuf.TestProtos { public pb::ByteString Data { get { return data_; } set { - data_ = pb::Preconditions.CheckNotNull(value, "value"); + data_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } @@ -3807,7 +3807,7 @@ namespace Google.Protobuf.TestProtos { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -3913,7 +3913,7 @@ namespace Google.Protobuf.TestProtos { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -4016,7 +4016,7 @@ namespace Google.Protobuf.TestProtos { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -4119,7 +4119,7 @@ namespace Google.Protobuf.TestProtos { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -4222,7 +4222,7 @@ namespace Google.Protobuf.TestProtos { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -4325,7 +4325,7 @@ namespace Google.Protobuf.TestProtos { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -4425,7 +4425,7 @@ namespace Google.Protobuf.TestProtos { public string FooString { get { return fooCase_ == FooOneofCase.FooString ? (string) foo_ : ""; } set { - foo_ = pb::Preconditions.CheckNotNull(value, "value"); + foo_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); fooCase_ = FooOneofCase.FooString; } } @@ -4486,7 +4486,7 @@ namespace Google.Protobuf.TestProtos { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -4780,7 +4780,7 @@ namespace Google.Protobuf.TestProtos { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -5140,7 +5140,7 @@ namespace Google.Protobuf.TestProtos { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -5414,7 +5414,7 @@ namespace Google.Protobuf.TestProtos { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -5528,7 +5528,7 @@ namespace Google.Protobuf.TestProtos { public string A { get { return a_; } set { - a_ = pb::Preconditions.CheckNotNull(value, "value"); + a_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } @@ -5554,7 +5554,7 @@ namespace Google.Protobuf.TestProtos { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -5647,7 +5647,7 @@ namespace Google.Protobuf.TestProtos { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -5723,7 +5723,7 @@ namespace Google.Protobuf.TestProtos { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -5799,7 +5799,7 @@ namespace Google.Protobuf.TestProtos { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -5875,7 +5875,7 @@ namespace Google.Protobuf.TestProtos { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -5951,7 +5951,7 @@ namespace Google.Protobuf.TestProtos { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -6027,7 +6027,7 @@ namespace Google.Protobuf.TestProtos { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { diff --git a/csharp/src/Google.Protobuf.Test/TestProtos/UnittestWellKnownTypes.cs b/csharp/src/Google.Protobuf.Test/TestProtos/UnittestWellKnownTypes.cs index 3cad3e7a..ae12f4a4 100644 --- a/csharp/src/Google.Protobuf.Test/TestProtos/UnittestWellKnownTypes.cs +++ b/csharp/src/Google.Protobuf.Test/TestProtos/UnittestWellKnownTypes.cs @@ -31,7 +31,7 @@ namespace Google.Protobuf.TestProtos { "L3Byb3RvYnVmL3NvdXJjZV9jb250ZXh0LnByb3RvGhxnb29nbGUvcHJvdG9i", "dWYvc3RydWN0LnByb3RvGh9nb29nbGUvcHJvdG9idWYvdGltZXN0YW1wLnBy", "b3RvGhpnb29nbGUvcHJvdG9idWYvdHlwZS5wcm90bxoeZ29vZ2xlL3Byb3Rv", - "YnVmL3dyYXBwZXJzLnByb3RvIpEHChJUZXN0V2VsbEtub3duVHlwZXMSJwoJ", + "YnVmL3dyYXBwZXJzLnByb3RvIr4HChJUZXN0V2VsbEtub3duVHlwZXMSJwoJ", "YW55X2ZpZWxkGAEgASgLMhQuZ29vZ2xlLnByb3RvYnVmLkFueRInCglhcGlf", "ZmllbGQYAiABKAsyFC5nb29nbGUucHJvdG9idWYuQXBpEjEKDmR1cmF0aW9u", "X2ZpZWxkGAMgASgLMhkuZ29vZ2xlLnByb3RvYnVmLkR1cmF0aW9uEisKC2Vt", @@ -51,7 +51,8 @@ namespace Google.Protobuf.TestProtos { "cm90b2J1Zi5VSW50MzJWYWx1ZRIuCgpib29sX2ZpZWxkGBAgASgLMhouZ29v", "Z2xlLnByb3RvYnVmLkJvb2xWYWx1ZRIyCgxzdHJpbmdfZmllbGQYESABKAsy", "HC5nb29nbGUucHJvdG9idWYuU3RyaW5nVmFsdWUSMAoLYnl0ZXNfZmllbGQY", - "EiABKAsyGy5nb29nbGUucHJvdG9idWYuQnl0ZXNWYWx1ZSKVBwoWUmVwZWF0", + "EiABKAsyGy5nb29nbGUucHJvdG9idWYuQnl0ZXNWYWx1ZRIrCgt2YWx1ZV9m", + "aWVsZBgTIAEoCzIWLmdvb2dsZS5wcm90b2J1Zi5WYWx1ZSKVBwoWUmVwZWF0", "ZWRXZWxsS25vd25UeXBlcxInCglhbnlfZmllbGQYASADKAsyFC5nb29nbGUu", "cHJvdG9idWYuQW55EicKCWFwaV9maWVsZBgCIAMoCzIULmdvb2dsZS5wcm90", "b2J1Zi5BcGkSMQoOZHVyYXRpb25fZmllbGQYAyADKAsyGS5nb29nbGUucHJv", @@ -159,13 +160,13 @@ namespace Google.Protobuf.TestProtos { "AiABKAsyGy5nb29nbGUucHJvdG9idWYuQnl0ZXNWYWx1ZToCOAFCOQoYY29t", "Lmdvb2dsZS5wcm90b2J1Zi50ZXN0UAGqAhpHb29nbGUuUHJvdG9idWYuVGVz", "dFByb3Rvc2IGcHJvdG8z")); - descriptor = pbr::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData, + descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, new pbr::FileDescriptor[] { global::Google.Protobuf.WellKnownTypes.AnyReflection.Descriptor, global::Google.Protobuf.WellKnownTypes.ApiReflection.Descriptor, global::Google.Protobuf.WellKnownTypes.DurationReflection.Descriptor, global::Google.Protobuf.WellKnownTypes.EmptyReflection.Descriptor, global::Google.Protobuf.WellKnownTypes.FieldMaskReflection.Descriptor, global::Google.Protobuf.WellKnownTypes.SourceContextReflection.Descriptor, global::Google.Protobuf.WellKnownTypes.StructReflection.Descriptor, global::Google.Protobuf.WellKnownTypes.TimestampReflection.Descriptor, global::Google.Protobuf.WellKnownTypes.TypeReflection.Descriptor, global::Google.Protobuf.WellKnownTypes.WrappersReflection.Descriptor, }, - new pbr::GeneratedCodeInfo(null, new pbr::GeneratedCodeInfo[] { - new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.TestWellKnownTypes), global::Google.Protobuf.TestProtos.TestWellKnownTypes.Parser, new[]{ "AnyField", "ApiField", "DurationField", "EmptyField", "FieldMaskField", "SourceContextField", "StructField", "TimestampField", "TypeField", "DoubleField", "FloatField", "Int64Field", "Uint64Field", "Int32Field", "Uint32Field", "BoolField", "StringField", "BytesField" }, null, null, null), - new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.RepeatedWellKnownTypes), global::Google.Protobuf.TestProtos.RepeatedWellKnownTypes.Parser, new[]{ "AnyField", "ApiField", "DurationField", "EmptyField", "FieldMaskField", "SourceContextField", "StructField", "TimestampField", "TypeField", "DoubleField", "FloatField", "Int64Field", "Uint64Field", "Int32Field", "Uint32Field", "BoolField", "StringField", "BytesField" }, null, null, null), - new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.OneofWellKnownTypes), global::Google.Protobuf.TestProtos.OneofWellKnownTypes.Parser, new[]{ "AnyField", "ApiField", "DurationField", "EmptyField", "FieldMaskField", "SourceContextField", "StructField", "TimestampField", "TypeField", "DoubleField", "FloatField", "Int64Field", "Uint64Field", "Int32Field", "Uint32Field", "BoolField", "StringField", "BytesField" }, new[]{ "OneofField" }, null, null), - new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.MapWellKnownTypes), global::Google.Protobuf.TestProtos.MapWellKnownTypes.Parser, new[]{ "AnyField", "ApiField", "DurationField", "EmptyField", "FieldMaskField", "SourceContextField", "StructField", "TimestampField", "TypeField", "DoubleField", "FloatField", "Int64Field", "Uint64Field", "Int32Field", "Uint32Field", "BoolField", "StringField", "BytesField" }, null, null, new pbr::GeneratedCodeInfo[] { null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, }) + new pbr::GeneratedClrTypeInfo(null, new pbr::GeneratedClrTypeInfo[] { + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.TestWellKnownTypes), global::Google.Protobuf.TestProtos.TestWellKnownTypes.Parser, new[]{ "AnyField", "ApiField", "DurationField", "EmptyField", "FieldMaskField", "SourceContextField", "StructField", "TimestampField", "TypeField", "DoubleField", "FloatField", "Int64Field", "Uint64Field", "Int32Field", "Uint32Field", "BoolField", "StringField", "BytesField", "ValueField" }, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.RepeatedWellKnownTypes), global::Google.Protobuf.TestProtos.RepeatedWellKnownTypes.Parser, new[]{ "AnyField", "ApiField", "DurationField", "EmptyField", "FieldMaskField", "SourceContextField", "StructField", "TimestampField", "TypeField", "DoubleField", "FloatField", "Int64Field", "Uint64Field", "Int32Field", "Uint32Field", "BoolField", "StringField", "BytesField" }, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.OneofWellKnownTypes), global::Google.Protobuf.TestProtos.OneofWellKnownTypes.Parser, new[]{ "AnyField", "ApiField", "DurationField", "EmptyField", "FieldMaskField", "SourceContextField", "StructField", "TimestampField", "TypeField", "DoubleField", "FloatField", "Int64Field", "Uint64Field", "Int32Field", "Uint32Field", "BoolField", "StringField", "BytesField" }, new[]{ "OneofField" }, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.MapWellKnownTypes), global::Google.Protobuf.TestProtos.MapWellKnownTypes.Parser, new[]{ "AnyField", "ApiField", "DurationField", "EmptyField", "FieldMaskField", "SourceContextField", "StructField", "TimestampField", "TypeField", "DoubleField", "FloatField", "Int64Field", "Uint64Field", "Int32Field", "Uint32Field", "BoolField", "StringField", "BytesField" }, null, null, new pbr::GeneratedClrTypeInfo[] { null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, }) })); } #endregion @@ -215,6 +216,7 @@ namespace Google.Protobuf.TestProtos { BoolField = other.BoolField; StringField = other.StringField; BytesField = other.BytesField; + ValueField = other.valueField_ != null ? other.ValueField.Clone() : null; } public TestWellKnownTypes Clone() { @@ -410,6 +412,19 @@ namespace Google.Protobuf.TestProtos { } } + /// <summary>Field number for the "value_field" field.</summary> + public const int ValueFieldFieldNumber = 19; + private global::Google.Protobuf.WellKnownTypes.Value valueField_; + /// <summary> + /// Part of struct, but useful to be able to test separately + /// </summary> + public global::Google.Protobuf.WellKnownTypes.Value ValueField { + get { return valueField_; } + set { + valueField_ = value; + } + } + public override bool Equals(object other) { return Equals(other as TestWellKnownTypes); } @@ -439,6 +454,7 @@ namespace Google.Protobuf.TestProtos { if (BoolField != other.BoolField) return false; if (StringField != other.StringField) return false; if (BytesField != other.BytesField) return false; + if (!object.Equals(ValueField, other.ValueField)) return false; return true; } @@ -462,11 +478,12 @@ namespace Google.Protobuf.TestProtos { if (boolField_ != null) hash ^= BoolField.GetHashCode(); if (stringField_ != null) hash ^= StringField.GetHashCode(); if (bytesField_ != null) hash ^= BytesField.GetHashCode(); + if (valueField_ != null) hash ^= ValueField.GetHashCode(); return hash; } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -533,6 +550,10 @@ namespace Google.Protobuf.TestProtos { if (bytesField_ != null) { _single_bytesField_codec.WriteTagAndValue(output, BytesField); } + if (valueField_ != null) { + output.WriteRawTag(154, 1); + output.WriteMessage(ValueField); + } } public int CalculateSize() { @@ -591,6 +612,9 @@ namespace Google.Protobuf.TestProtos { if (bytesField_ != null) { size += _single_bytesField_codec.CalculateSizeWithTag(BytesField); } + if (valueField_ != null) { + size += 2 + pb::CodedOutputStream.ComputeMessageSize(ValueField); + } return size; } @@ -697,6 +721,12 @@ namespace Google.Protobuf.TestProtos { BytesField = other.BytesField; } } + if (other.valueField_ != null) { + if (valueField_ == null) { + valueField_ = new global::Google.Protobuf.WellKnownTypes.Value(); + } + ValueField.MergeFrom(other.ValueField); + } } public void MergeFrom(pb::CodedInputStream input) { @@ -832,6 +862,13 @@ namespace Google.Protobuf.TestProtos { } break; } + case 154: { + if (valueField_ == null) { + valueField_ = new global::Google.Protobuf.WellKnownTypes.Value(); + } + input.ReadMessage(valueField_); + break; + } } } } @@ -1106,7 +1143,7 @@ namespace Google.Protobuf.TestProtos { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -1625,7 +1662,7 @@ namespace Google.Protobuf.TestProtos { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -2080,7 +2117,7 @@ namespace Google.Protobuf.TestProtos { public const int DoubleFieldFieldNumber = 10; private static readonly pbc::MapField<int, double?>.Codec _map_doubleField_codec = new pbc::MapField<int, double?>.Codec(pb::FieldCodec.ForInt32(8), pb::FieldCodec.ForStructWrapper<double>(18), 82); - private readonly pbc::MapField<int, double?> doubleField_ = new pbc::MapField<int, double?>(true); + private readonly pbc::MapField<int, double?> doubleField_ = new pbc::MapField<int, double?>(); public pbc::MapField<int, double?> DoubleField { get { return doubleField_; } } @@ -2089,7 +2126,7 @@ namespace Google.Protobuf.TestProtos { public const int FloatFieldFieldNumber = 11; private static readonly pbc::MapField<int, float?>.Codec _map_floatField_codec = new pbc::MapField<int, float?>.Codec(pb::FieldCodec.ForInt32(8), pb::FieldCodec.ForStructWrapper<float>(18), 90); - private readonly pbc::MapField<int, float?> floatField_ = new pbc::MapField<int, float?>(true); + private readonly pbc::MapField<int, float?> floatField_ = new pbc::MapField<int, float?>(); public pbc::MapField<int, float?> FloatField { get { return floatField_; } } @@ -2098,7 +2135,7 @@ namespace Google.Protobuf.TestProtos { public const int Int64FieldFieldNumber = 12; private static readonly pbc::MapField<int, long?>.Codec _map_int64Field_codec = new pbc::MapField<int, long?>.Codec(pb::FieldCodec.ForInt32(8), pb::FieldCodec.ForStructWrapper<long>(18), 98); - private readonly pbc::MapField<int, long?> int64Field_ = new pbc::MapField<int, long?>(true); + private readonly pbc::MapField<int, long?> int64Field_ = new pbc::MapField<int, long?>(); public pbc::MapField<int, long?> Int64Field { get { return int64Field_; } } @@ -2107,7 +2144,7 @@ namespace Google.Protobuf.TestProtos { public const int Uint64FieldFieldNumber = 13; private static readonly pbc::MapField<int, ulong?>.Codec _map_uint64Field_codec = new pbc::MapField<int, ulong?>.Codec(pb::FieldCodec.ForInt32(8), pb::FieldCodec.ForStructWrapper<ulong>(18), 106); - private readonly pbc::MapField<int, ulong?> uint64Field_ = new pbc::MapField<int, ulong?>(true); + private readonly pbc::MapField<int, ulong?> uint64Field_ = new pbc::MapField<int, ulong?>(); public pbc::MapField<int, ulong?> Uint64Field { get { return uint64Field_; } } @@ -2116,7 +2153,7 @@ namespace Google.Protobuf.TestProtos { public const int Int32FieldFieldNumber = 14; private static readonly pbc::MapField<int, int?>.Codec _map_int32Field_codec = new pbc::MapField<int, int?>.Codec(pb::FieldCodec.ForInt32(8), pb::FieldCodec.ForStructWrapper<int>(18), 114); - private readonly pbc::MapField<int, int?> int32Field_ = new pbc::MapField<int, int?>(true); + private readonly pbc::MapField<int, int?> int32Field_ = new pbc::MapField<int, int?>(); public pbc::MapField<int, int?> Int32Field { get { return int32Field_; } } @@ -2125,7 +2162,7 @@ namespace Google.Protobuf.TestProtos { public const int Uint32FieldFieldNumber = 15; private static readonly pbc::MapField<int, uint?>.Codec _map_uint32Field_codec = new pbc::MapField<int, uint?>.Codec(pb::FieldCodec.ForInt32(8), pb::FieldCodec.ForStructWrapper<uint>(18), 122); - private readonly pbc::MapField<int, uint?> uint32Field_ = new pbc::MapField<int, uint?>(true); + private readonly pbc::MapField<int, uint?> uint32Field_ = new pbc::MapField<int, uint?>(); public pbc::MapField<int, uint?> Uint32Field { get { return uint32Field_; } } @@ -2134,7 +2171,7 @@ namespace Google.Protobuf.TestProtos { public const int BoolFieldFieldNumber = 16; private static readonly pbc::MapField<int, bool?>.Codec _map_boolField_codec = new pbc::MapField<int, bool?>.Codec(pb::FieldCodec.ForInt32(8), pb::FieldCodec.ForStructWrapper<bool>(18), 130); - private readonly pbc::MapField<int, bool?> boolField_ = new pbc::MapField<int, bool?>(true); + private readonly pbc::MapField<int, bool?> boolField_ = new pbc::MapField<int, bool?>(); public pbc::MapField<int, bool?> BoolField { get { return boolField_; } } @@ -2143,7 +2180,7 @@ namespace Google.Protobuf.TestProtos { public const int StringFieldFieldNumber = 17; private static readonly pbc::MapField<int, string>.Codec _map_stringField_codec = new pbc::MapField<int, string>.Codec(pb::FieldCodec.ForInt32(8), pb::FieldCodec.ForClassWrapper<string>(18), 138); - private readonly pbc::MapField<int, string> stringField_ = new pbc::MapField<int, string>(true); + private readonly pbc::MapField<int, string> stringField_ = new pbc::MapField<int, string>(); public pbc::MapField<int, string> StringField { get { return stringField_; } } @@ -2152,7 +2189,7 @@ namespace Google.Protobuf.TestProtos { public const int BytesFieldFieldNumber = 18; private static readonly pbc::MapField<int, pb::ByteString>.Codec _map_bytesField_codec = new pbc::MapField<int, pb::ByteString>.Codec(pb::FieldCodec.ForInt32(8), pb::FieldCodec.ForClassWrapper<pb::ByteString>(18), 146); - private readonly pbc::MapField<int, pb::ByteString> bytesField_ = new pbc::MapField<int, pb::ByteString>(true); + private readonly pbc::MapField<int, pb::ByteString> bytesField_ = new pbc::MapField<int, pb::ByteString>(); public pbc::MapField<int, pb::ByteString> BytesField { get { return bytesField_; } } @@ -2213,7 +2250,7 @@ namespace Google.Protobuf.TestProtos { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { diff --git a/csharp/src/Google.Protobuf.Test/WellKnownTypes/AnyTest.cs b/csharp/src/Google.Protobuf.Test/WellKnownTypes/AnyTest.cs index 0a2b8b32..f3593e5f 100644 --- a/csharp/src/Google.Protobuf.Test/WellKnownTypes/AnyTest.cs +++ b/csharp/src/Google.Protobuf.Test/WellKnownTypes/AnyTest.cs @@ -62,5 +62,28 @@ namespace Google.Protobuf.WellKnownTypes var unpacked = any.Unpack<TestAllTypes>(); Assert.AreEqual(message, unpacked); } + + [Test] + public void ToString_WithValues() + { + var message = SampleMessages.CreateFullTestAllTypes(); + var any = Any.Pack(message); + var text = any.ToString(); + Assert.That(text, Is.StringContaining("\"@value\": \"" + message.ToByteString().ToBase64() + "\"")); + } + + [Test] + public void ToString_Empty() + { + var any = new Any(); + Assert.AreEqual("{ \"@type\": \"\", \"@value\": \"\" }", any.ToString()); + } + + [Test] + public void ToString_MessageContainingAny() + { + var message = new TestWellKnownTypes { AnyField = new Any() }; + Assert.AreEqual("{ \"anyField\": { \"@type\": \"\", \"@value\": \"\" } }", message.ToString()); + } } } diff --git a/csharp/src/Google.Protobuf.Test/WellKnownTypes/DurationTest.cs b/csharp/src/Google.Protobuf.Test/WellKnownTypes/DurationTest.cs index 36012e63..141faf80 100644 --- a/csharp/src/Google.Protobuf.Test/WellKnownTypes/DurationTest.cs +++ b/csharp/src/Google.Protobuf.Test/WellKnownTypes/DurationTest.cs @@ -50,11 +50,6 @@ namespace Google.Protobuf.WellKnownTypes // Rounding is towards 0 Assert.AreEqual(TimeSpan.FromTicks(2), new Duration { Nanos = 250 }.ToTimeSpan()); Assert.AreEqual(TimeSpan.FromTicks(-2), new Duration { Nanos = -250 }.ToTimeSpan()); - - // Non-normalized durations - Assert.AreEqual(TimeSpan.FromSeconds(3), new Duration { Seconds = 1, Nanos = 2 * Duration.NanosecondsPerSecond }.ToTimeSpan()); - Assert.AreEqual(TimeSpan.FromSeconds(1), new Duration { Seconds = 3, Nanos = -2 * Duration.NanosecondsPerSecond }.ToTimeSpan()); - Assert.AreEqual(TimeSpan.FromSeconds(-1), new Duration { Seconds = 1, Nanos = -2 * Duration.NanosecondsPerSecond }.ToTimeSpan()); } [Test] @@ -100,5 +95,38 @@ namespace Google.Protobuf.WellKnownTypes Assert.AreEqual(new Duration { Seconds = 1 }, Duration.FromTimeSpan(TimeSpan.FromSeconds(1))); Assert.AreEqual(new Duration { Nanos = Duration.NanosecondsPerTick }, Duration.FromTimeSpan(TimeSpan.FromTicks(1))); } + + [Test] + [TestCase(0, Duration.MaxNanoseconds + 1)] + [TestCase(0, Duration.MinNanoseconds - 1)] + [TestCase(Duration.MinSeconds - 1, 0)] + [TestCase(Duration.MaxSeconds + 1, 0)] + [TestCase(1, -1)] + [TestCase(-1, 1)] + public void ToTimeSpan_Invalid(long seconds, int nanoseconds) + { + var duration = new Duration { Seconds = seconds, Nanos = nanoseconds }; + Assert.Throws<InvalidOperationException>(() => duration.ToTimeSpan()); + } + + [Test] + [TestCase(0, Duration.MaxNanoseconds)] + [TestCase(0, Duration.MinNanoseconds)] + [TestCase(Duration.MinSeconds, Duration.MinNanoseconds)] + [TestCase(Duration.MaxSeconds, Duration.MaxNanoseconds)] + public void ToTimeSpan_Valid(long seconds, int nanoseconds) + { + // Only testing that these values don't throw, unlike their similar tests in ToTimeSpan_Invalid + var duration = new Duration { Seconds = seconds, Nanos = nanoseconds }; + duration.ToTimeSpan(); + } + + [Test] + public void ToString_NonNormalized() + { + // Just a single example should be sufficient... + var duration = new Duration { Seconds = 1, Nanos = -1 }; + Assert.AreEqual("{ \"@warning\": \"Invalid Duration\", \"seconds\": \"1\", \"nanos\": -1 }", duration.ToString()); + } } } diff --git a/csharp/src/Google.Protobuf.Test/WellKnownTypes/FieldMaskTest.cs b/csharp/src/Google.Protobuf.Test/WellKnownTypes/FieldMaskTest.cs new file mode 100644 index 00000000..89bc8275 --- /dev/null +++ b/csharp/src/Google.Protobuf.Test/WellKnownTypes/FieldMaskTest.cs @@ -0,0 +1,62 @@ +#region Copyright notice and license +// Protocol Buffers - Google's data interchange format +// Copyright 2016 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#endregion + + +using NUnit.Framework; + +namespace Google.Protobuf.WellKnownTypes +{ + public class FieldMaskTest + { + [Test] + [TestCase("foo__bar")] + [TestCase("foo_3_ar")] + [TestCase("fooBar")] + public void ToString_Invalid(string input) + { + var mask = new FieldMask { Paths = { input } }; + var text = mask.ToString(); + // More specific test below + Assert.That(text, Is.StringContaining("@warning")); + Assert.That(text, Is.StringContaining(input)); + } + + [Test] + public void ToString_Invalid_Precise() + { + var mask = new FieldMask { Paths = { "x", "foo__bar", @"x\y" } }; + Assert.AreEqual( + "{ \"@warning\": \"Invalid FieldMask\", \"paths\": [ \"x\", \"foo__bar\", \"x\\\\y\" ] }", + mask.ToString()); + } + } +} diff --git a/csharp/src/Google.Protobuf.Test/WellKnownTypes/TimestampTest.cs b/csharp/src/Google.Protobuf.Test/WellKnownTypes/TimestampTest.cs index 597539eb..9ecd24c6 100644 --- a/csharp/src/Google.Protobuf.Test/WellKnownTypes/TimestampTest.cs +++ b/csharp/src/Google.Protobuf.Test/WellKnownTypes/TimestampTest.cs @@ -61,6 +61,29 @@ namespace Google.Protobuf.WellKnownTypes Assert.AreEqual(new DateTime(1969, 12, 31, 23, 59, 59).AddMilliseconds(1), t2.ToDateTime()); } + [Test] + [TestCase(Timestamp.UnixSecondsAtBclMinValue - 1, Timestamp.MaxNanos)] + [TestCase(Timestamp.UnixSecondsAtBclMaxValue + 1, 0)] + [TestCase(0, -1)] + [TestCase(0, Timestamp.MaxNanos + 1)] + public void ToDateTime_OutOfRange(long seconds, int nanoseconds) + { + var value = new Timestamp { Seconds = seconds, Nanos = nanoseconds }; + Assert.Throws<InvalidOperationException>(() => value.ToDateTime()); + } + + // 1ns larger or smaller than the above values + [Test] + [TestCase(Timestamp.UnixSecondsAtBclMinValue, 0)] + [TestCase(Timestamp.UnixSecondsAtBclMaxValue, Timestamp.MaxNanos)] + [TestCase(0, 0)] + [TestCase(0, Timestamp.MaxNanos)] + public void ToDateTime_ValidBoundaries(long seconds, int nanoseconds) + { + var value = new Timestamp { Seconds = seconds, Nanos = nanoseconds }; + value.ToDateTime(); + } + private static void AssertRoundtrip(Timestamp timestamp, DateTime dateTime) { Assert.AreEqual(timestamp, Timestamp.FromDateTime(dateTime)); @@ -80,5 +103,13 @@ namespace Google.Protobuf.WellKnownTypes Assert.AreEqual(t1, t2 + difference); Assert.AreEqual(t2, t1 - difference); } + + [Test] + public void ToString_NonNormalized() + { + // Just a single example should be sufficient... + var duration = new Timestamp { Seconds = 1, Nanos = -1 }; + Assert.AreEqual("{ \"@warning\": \"Invalid Timestamp\", \"seconds\": \"1\", \"nanos\": -1 }", duration.ToString()); + } } } diff --git a/csharp/src/Google.Protobuf.Test/WellKnownTypes/WrappersTest.cs b/csharp/src/Google.Protobuf.Test/WellKnownTypes/WrappersTest.cs index c87ceb2f..a2c833fe 100644 --- a/csharp/src/Google.Protobuf.Test/WellKnownTypes/WrappersTest.cs +++ b/csharp/src/Google.Protobuf.Test/WellKnownTypes/WrappersTest.cs @@ -149,8 +149,34 @@ namespace Google.Protobuf.WellKnownTypes } [Test] + public void RepeatedWrappersBinaryFormat() + { + // At one point we accidentally used a packed format for repeated wrappers, which is wrong (and weird). + // This test is just to prove that we use the right format. + + var rawOutput = new MemoryStream(); + var output = new CodedOutputStream(rawOutput); + // Write a value of 5 + output.WriteTag(RepeatedWellKnownTypes.Int32FieldFieldNumber, WireFormat.WireType.LengthDelimited); + output.WriteLength(2); + output.WriteTag(WrappersReflection.WrapperValueFieldNumber, WireFormat.WireType.Varint); + output.WriteInt32(5); + // Write a value of 0 (empty message) + output.WriteTag(RepeatedWellKnownTypes.Int32FieldFieldNumber, WireFormat.WireType.LengthDelimited); + output.WriteLength(0); + output.Flush(); + var expectedBytes = rawOutput.ToArray(); + + var message = new RepeatedWellKnownTypes { Int32Field = { 5, 0 } }; + var actualBytes = message.ToByteArray(); + Assert.AreEqual(expectedBytes, actualBytes); + } + + [Test] public void MapWrappersSerializeDeserialize() { + // Note: no null values here, as they are prohibited in map fields + // (despite being representable). var message = new MapWellKnownTypes { BoolField = { { 10, false }, { 20, true } }, @@ -158,13 +184,12 @@ namespace Google.Protobuf.WellKnownTypes { -1, ByteString.CopyFrom(1, 2, 3) }, { 10, ByteString.CopyFrom(4, 5, 6) }, { 1000, ByteString.Empty }, - { 10000, null } }, DoubleField = { { 1, 12.5 }, { 10, -1.5 }, { 20, 0d } }, FloatField = { { 2, 123.25f }, { 3, -20f }, { 4, 0f } }, Int32Field = { { 5, int.MaxValue }, { 6, int.MinValue }, { 7, 0 } }, Int64Field = { { 8, long.MaxValue }, { 9, long.MinValue }, { 10, 0L } }, - StringField = { { 11, "First" }, { 12, "Second" }, { 13, "" }, { 14, null } }, + StringField = { { 11, "First" }, { 12, "Second" }, { 13, "" } }, Uint32Field = { { 15, uint.MaxValue }, { 16, uint.MinValue }, { 17, 0U } }, Uint64Field = { { 18, ulong.MaxValue }, { 19, ulong.MinValue }, { 20, 0UL } }, }; @@ -224,13 +249,11 @@ namespace Google.Protobuf.WellKnownTypes [Test] public void Reflection_MapFields() { - // Just a single example... note that we can't have a null value here - var message = new MapWellKnownTypes { Int32Field = { { 1, 2 }, { 3, null } } }; + // Just a single example... note that we can't have a null value here despite the value type being int? + var message = new MapWellKnownTypes { Int32Field = { { 1, 2 } } }; var fields = MapWellKnownTypes.Descriptor.Fields; var dictionary = (IDictionary) fields[MapWellKnownTypes.Int32FieldFieldNumber].Accessor.GetValue(message); Assert.AreEqual(2, dictionary[1]); - Assert.IsNull(dictionary[3]); - Assert.IsTrue(dictionary.Contains(3)); } [Test] diff --git a/csharp/src/Google.Protobuf/CodedInputStream.cs b/csharp/src/Google.Protobuf/CodedInputStream.cs index 65d0e710..91bed8e3 100644 --- a/csharp/src/Google.Protobuf/CodedInputStream.cs +++ b/csharp/src/Google.Protobuf/CodedInputStream.cs @@ -115,7 +115,7 @@ namespace Google.Protobuf /// <summary>
/// Creates a new CodedInputStream reading data from the given byte array.
/// </summary>
- public CodedInputStream(byte[] buffer) : this(null, Preconditions.CheckNotNull(buffer, "buffer"), 0, buffer.Length)
+ public CodedInputStream(byte[] buffer) : this(null, ProtoPreconditions.CheckNotNull(buffer, "buffer"), 0, buffer.Length)
{
}
@@ -123,7 +123,7 @@ namespace Google.Protobuf /// Creates a new CodedInputStream that reads from the given byte array slice.
/// </summary>
public CodedInputStream(byte[] buffer, int offset, int length)
- : this(null, Preconditions.CheckNotNull(buffer, "buffer"), offset, offset + length)
+ : this(null, ProtoPreconditions.CheckNotNull(buffer, "buffer"), offset, offset + length)
{
if (offset < 0 || offset > buffer.Length)
{
@@ -140,7 +140,7 @@ namespace Google.Protobuf /// </summary>
public CodedInputStream(Stream input) : this(input, new byte[BufferSize], 0, 0)
{
- Preconditions.CheckNotNull(input, "input");
+ ProtoPreconditions.CheckNotNull(input, "input");
}
/// <summary>
diff --git a/csharp/src/Google.Protobuf/Collections/MapField.cs b/csharp/src/Google.Protobuf/Collections/MapField.cs index c0ed28ae..90a5ff1a 100644 --- a/csharp/src/Google.Protobuf/Collections/MapField.cs +++ b/csharp/src/Google.Protobuf/Collections/MapField.cs @@ -53,6 +53,13 @@ namespace Google.Protobuf.Collections /// For string keys, the equality comparison is provided by <see cref="StringComparer.Ordinal" />. /// </para> /// <para> + /// Null values are not permitted in the map, either for wrapper types or regular messages. + /// If a map is deserialized from a data stream and the value is missing from an entry, a default value + /// is created instead. For primitive types, that is the regular default value (0, the empty string and so + /// on); for message types, an empty instance of the message is created, as if the map entry contained a 0-length + /// encoded value for the field. + /// </para> + /// <para> /// This implementation does not generally prohibit the use of key/value types which are not /// supported by Protocol Buffers (e.g. using a key type of <code>byte</code>) but nor does it guarantee /// that all operations will work in such cases. @@ -61,35 +68,11 @@ namespace Google.Protobuf.Collections public sealed class MapField<TKey, TValue> : IDeepCloneable<MapField<TKey, TValue>>, IDictionary<TKey, TValue>, IEquatable<MapField<TKey, TValue>>, IDictionary { // TODO: Don't create the map/list until we have an entry. (Assume many maps will be empty.) - private readonly bool allowNullValues; private readonly Dictionary<TKey, LinkedListNode<KeyValuePair<TKey, TValue>>> map = new Dictionary<TKey, LinkedListNode<KeyValuePair<TKey, TValue>>>(); private readonly LinkedList<KeyValuePair<TKey, TValue>> list = new LinkedList<KeyValuePair<TKey, TValue>>(); /// <summary> - /// Constructs a new map field, defaulting the value nullability to only allow null values for message types - /// and non-nullable value types. - /// </summary> - public MapField() : this(typeof(IMessage).IsAssignableFrom(typeof(TValue)) || Nullable.GetUnderlyingType(typeof(TValue)) != null) - { - } - - /// <summary> - /// Constructs a new map field, overriding the choice of whether null values are permitted in the map. - /// This is used by wrapper types, where maps with string and bytes wrappers as the value types - /// support null values. - /// </summary> - /// <param name="allowNullValues">Whether null values are permitted in the map or not.</param> - public MapField(bool allowNullValues) - { - if (allowNullValues && typeof(TValue).IsValueType() && Nullable.GetUnderlyingType(typeof(TValue)) == null) - { - throw new ArgumentException("allowNullValues", "Non-nullable value types do not support null values"); - } - this.allowNullValues = allowNullValues; - } - - /// <summary> /// Creates a deep clone of this object. /// </summary> /// <returns> @@ -97,13 +80,13 @@ namespace Google.Protobuf.Collections /// </returns> public MapField<TKey, TValue> Clone() { - var clone = new MapField<TKey, TValue>(allowNullValues); + var clone = new MapField<TKey, TValue>(); // Keys are never cloneable. Values might be. if (typeof(IDeepCloneable<TValue>).IsAssignableFrom(typeof(TValue))) { foreach (var pair in list) { - clone.Add(pair.Key, pair.Value == null ? pair.Value : ((IDeepCloneable<TValue>)pair.Value).Clone()); + clone.Add(pair.Key, ((IDeepCloneable<TValue>)pair.Value).Clone()); } } else @@ -140,7 +123,7 @@ namespace Google.Protobuf.Collections /// <returns><c>true</c> if the map contains the given key; <c>false</c> otherwise.</returns> public bool ContainsKey(TKey key) { - Preconditions.CheckNotNullUnconstrained(key, "key"); + ProtoPreconditions.CheckNotNullUnconstrained(key, "key"); return map.ContainsKey(key); } @@ -157,7 +140,7 @@ namespace Google.Protobuf.Collections /// <returns><c>true</c> if the map contained the given key before the entry was removed; <c>false</c> otherwise.</returns> public bool Remove(TKey key) { - Preconditions.CheckNotNullUnconstrained(key, "key"); + ProtoPreconditions.CheckNotNullUnconstrained(key, "key"); LinkedListNode<KeyValuePair<TKey, TValue>> node; if (map.TryGetValue(key, out node)) { @@ -205,7 +188,7 @@ namespace Google.Protobuf.Collections { get { - Preconditions.CheckNotNullUnconstrained(key, "key"); + ProtoPreconditions.CheckNotNullUnconstrained(key, "key"); TValue value; if (TryGetValue(key, out value)) { @@ -215,11 +198,11 @@ namespace Google.Protobuf.Collections } set { - Preconditions.CheckNotNullUnconstrained(key, "key"); + ProtoPreconditions.CheckNotNullUnconstrained(key, "key"); // value == null check here is redundant, but avoids boxing. - if (value == null && !allowNullValues) + if (value == null) { - Preconditions.CheckNotNullUnconstrained(value, "value"); + ProtoPreconditions.CheckNotNullUnconstrained(value, "value"); } LinkedListNode<KeyValuePair<TKey, TValue>> node; var pair = new KeyValuePair<TKey, TValue>(key, value); @@ -246,12 +229,12 @@ namespace Google.Protobuf.Collections public ICollection<TValue> Values { get { return new MapView<TValue>(this, pair => pair.Value, ContainsValue); } } /// <summary> - /// Adds the specified entries to the map. + /// Adds the specified entries to the map. The keys and values are not automatically cloned. /// </summary> /// <param name="entries">The entries to add to the map.</param> public void Add(IDictionary<TKey, TValue> entries) { - Preconditions.CheckNotNull(entries, "entries"); + ProtoPreconditions.CheckNotNull(entries, "entries"); foreach (var pair in entries) { Add(pair.Key, pair.Value); @@ -347,11 +330,6 @@ namespace Google.Protobuf.Collections } /// <summary> - /// Returns whether or not this map allows values to be null. - /// </summary> - public bool AllowsNullValues { get { return allowNullValues; } } - - /// <summary> /// Gets the number of elements contained in the map. /// </summary> public int Count { get { return list.Count; } } @@ -523,7 +501,7 @@ namespace Google.Protobuf.Collections void IDictionary.Remove(object key) { - Preconditions.CheckNotNull(key, "key"); + ProtoPreconditions.CheckNotNull(key, "key"); if (!(key is TKey)) { return; @@ -552,7 +530,7 @@ namespace Google.Protobuf.Collections { get { - Preconditions.CheckNotNull(key, "key"); + ProtoPreconditions.CheckNotNull(key, "key"); if (!(key is TKey)) { return null; @@ -632,6 +610,8 @@ namespace Google.Protobuf.Collections /// </summary> internal class MessageAdapter : IMessage { + private static readonly byte[] ZeroLengthMessageStreamData = new byte[] { 0 }; + private readonly Codec codec; internal TKey Key { get; set; } internal TValue Value { get; set; } @@ -665,6 +645,13 @@ namespace Google.Protobuf.Collections input.SkipLastField(); } } + + // Corner case: a map entry with a key but no value, where the value type is a message. + // Read it as if we'd seen an input stream with no data (i.e. create a "default" message). + if (Value == null) + { + Value = codec.valueCodec.Read(new CodedInputStream(ZeroLengthMessageStreamData)); + } } public void WriteTo(CodedOutputStream output) diff --git a/csharp/src/Google.Protobuf/Collections/RepeatedField.cs b/csharp/src/Google.Protobuf/Collections/RepeatedField.cs index e3f65afe..1cde03bc 100644 --- a/csharp/src/Google.Protobuf/Collections/RepeatedField.cs +++ b/csharp/src/Google.Protobuf/Collections/RepeatedField.cs @@ -34,7 +34,6 @@ using System; using System.Collections; using System.Collections.Generic; using System.Text; -using Google.Protobuf.Compatibility; namespace Google.Protobuf.Collections { @@ -96,8 +95,8 @@ namespace Google.Protobuf.Collections // iteration. uint tag = input.LastTag; var reader = codec.ValueReader; - // Value types can be packed or not. - if (typeof(T).IsValueType() && WireFormat.GetTagWireType(tag) == WireFormat.WireType.LengthDelimited) + // Non-nullable value types can be packed or not. + if (FieldCodec<T>.IsPackedRepeatedField(tag)) { int length = input.ReadLength(); if (length > 0) @@ -134,7 +133,7 @@ namespace Google.Protobuf.Collections return 0; } uint tag = codec.Tag; - if (typeof(T).IsValueType() && WireFormat.GetTagWireType(tag) == WireFormat.WireType.LengthDelimited) + if (codec.PackedRepeatedField) { int dataSize = CalculatePackedDataSize(codec); return CodedOutputStream.ComputeRawVarint32Size(tag) + @@ -186,7 +185,7 @@ namespace Google.Protobuf.Collections } var writer = codec.ValueWriter; var tag = codec.Tag; - if (typeof(T).IsValueType() && WireFormat.GetTagWireType(tag) == WireFormat.WireType.LengthDelimited) + if (codec.PackedRepeatedField) { // Packed primitive type uint size = (uint)CalculatePackedDataSize(codec); diff --git a/csharp/src/Google.Protobuf/FieldCodec.cs b/csharp/src/Google.Protobuf/FieldCodec.cs index 6ee8e2f9..98313088 100644 --- a/csharp/src/Google.Protobuf/FieldCodec.cs +++ b/csharp/src/Google.Protobuf/FieldCodec.cs @@ -30,6 +30,7 @@ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion +using Google.Protobuf.Compatibility; using Google.Protobuf.WellKnownTypes; using System; using System.Collections.Generic; @@ -329,17 +330,24 @@ namespace Google.Protobuf } /// <summary> + /// <para> /// An encode/decode pair for a single field. This effectively encapsulates /// all the information needed to read or write the field value from/to a coded /// stream. + /// </para> + /// <para> + /// This class is public and has to be as it is used by generated code, but its public + /// API is very limited - just what the generated code needs to call directly. + /// </para> /// </summary> /// <remarks> - /// This never writes default values to the stream, and is not currently designed - /// to play well with packed arrays. + /// This never writes default values to the stream, and does not address "packedness" + /// in repeated fields itself, other than to know whether or not the field *should* be packed. /// </remarks> public sealed class FieldCodec<T> { private static readonly T DefaultDefault; + private static readonly bool TypeSupportsPacking = typeof(T).IsValueType() && Nullable.GetUnderlyingType(typeof(T)) == null; static FieldCodec() { @@ -354,80 +362,31 @@ namespace Google.Protobuf // Otherwise it's the default value of the CLR type } - private static Func<T, bool> CreateDefaultValueCheck<TTmp>(Func<TTmp, bool> check) - { - return (Func<T, bool>)(object)check; - } - - private readonly Func<CodedInputStream, T> reader; - private readonly Action<CodedOutputStream, T> writer; - private readonly Func<T, int> sizeCalculator; - private readonly uint tag; - private readonly int tagSize; - private readonly int fixedSize; - // Default value for this codec. Usually the same for every instance of the same type, but - // for string/ByteString wrapper fields the codec's default value is null, whereas for - // other string/ByteString fields it's "" or ByteString.Empty. - private readonly T defaultValue; + internal static bool IsPackedRepeatedField(uint tag) => + TypeSupportsPacking && WireFormat.GetTagWireType(tag) == WireFormat.WireType.LengthDelimited; - internal FieldCodec( - Func<CodedInputStream, T> reader, - Action<CodedOutputStream, T> writer, - Func<T, int> sizeCalculator, - uint tag) : this(reader, writer, sizeCalculator, tag, DefaultDefault) - { - } - - internal FieldCodec( - Func<CodedInputStream, T> reader, - Action<CodedOutputStream, T> writer, - Func<T, int> sizeCalculator, - uint tag, - T defaultValue) - { - this.reader = reader; - this.writer = writer; - this.sizeCalculator = sizeCalculator; - this.fixedSize = 0; - this.tag = tag; - this.defaultValue = defaultValue; - tagSize = CodedOutputStream.ComputeRawVarint32Size(tag); - } - - internal FieldCodec( - Func<CodedInputStream, T> reader, - Action<CodedOutputStream, T> writer, - int fixedSize, - uint tag) - { - this.reader = reader; - this.writer = writer; - this.sizeCalculator = _ => fixedSize; - this.fixedSize = fixedSize; - this.tag = tag; - tagSize = CodedOutputStream.ComputeRawVarint32Size(tag); - } + internal bool PackedRepeatedField { get; } /// <summary> - /// Returns the size calculator for just a value. + /// Returns a delegate to write a value (unconditionally) to a coded output stream. /// </summary> - internal Func<T, int> ValueSizeCalculator { get { return sizeCalculator; } } + internal Action<CodedOutputStream, T> ValueWriter { get; } /// <summary> - /// Returns a delegate to write a value (unconditionally) to a coded output stream. + /// Returns the size calculator for just a value. /// </summary> - internal Action<CodedOutputStream, T> ValueWriter { get { return writer; } } + internal Func<T, int> ValueSizeCalculator { get; } /// <summary> /// Returns a delegate to read a value from a coded input stream. It is assumed that /// the stream is already positioned on the appropriate tag. /// </summary> - internal Func<CodedInputStream, T> ValueReader { get { return reader; } } + internal Func<CodedInputStream, T> ValueReader { get; } /// <summary> /// Returns the fixed size for an entry, or 0 if sizes vary. /// </summary> - internal int FixedSize { get { return fixedSize; } } + internal int FixedSize { get; } /// <summary> /// Gets the tag of the codec. @@ -435,15 +394,54 @@ namespace Google.Protobuf /// <value> /// The tag of the codec. /// </value> - public uint Tag { get { return tag; } } + internal uint Tag { get; } /// <summary> - /// Gets the default value of the codec's type. + /// Default value for this codec. Usually the same for every instance of the same type, but + /// for string/ByteString wrapper fields the codec's default value is null, whereas for + /// other string/ByteString fields it's "" or ByteString.Empty. /// </summary> /// <value> /// The default value of the codec's type. /// </value> - public T DefaultValue { get { return defaultValue; } } + internal T DefaultValue { get; } + + private readonly int tagSize; + + internal FieldCodec( + Func<CodedInputStream, T> reader, + Action<CodedOutputStream, T> writer, + int fixedSize, + uint tag) : this(reader, writer, _ => fixedSize, tag) + { + FixedSize = fixedSize; + } + + internal FieldCodec( + Func<CodedInputStream, T> reader, + Action<CodedOutputStream, T> writer, + Func<T, int> sizeCalculator, + uint tag) : this(reader, writer, sizeCalculator, tag, DefaultDefault) + { + } + + internal FieldCodec( + Func<CodedInputStream, T> reader, + Action<CodedOutputStream, T> writer, + Func<T, int> sizeCalculator, + uint tag, + T defaultValue) + { + ValueReader = reader; + ValueWriter = writer; + ValueSizeCalculator = sizeCalculator; + FixedSize = 0; + Tag = tag; + DefaultValue = defaultValue; + tagSize = CodedOutputStream.ComputeRawVarint32Size(tag); + // Detect packed-ness once, so we can check for it within RepeatedField<T>. + PackedRepeatedField = IsPackedRepeatedField(tag); + } /// <summary> /// Write a tag and the given value, *if* the value is not the default. @@ -452,8 +450,8 @@ namespace Google.Protobuf { if (!IsDefault(value)) { - output.WriteTag(tag); - writer(output, value); + output.WriteTag(Tag); + ValueWriter(output, value); } } @@ -462,23 +460,14 @@ namespace Google.Protobuf /// </summary> /// <param name="input">The input stream to read from.</param> /// <returns>The value read from the stream.</returns> - public T Read(CodedInputStream input) - { - return reader(input); - } + public T Read(CodedInputStream input) => ValueReader(input); /// <summary> /// Calculates the size required to write the given value, with a tag, /// if the value is not the default. /// </summary> - public int CalculateSizeWithTag(T value) - { - return IsDefault(value) ? 0 : sizeCalculator(value) + tagSize; - } + public int CalculateSizeWithTag(T value) => IsDefault(value) ? 0 : ValueSizeCalculator(value) + tagSize; - private bool IsDefault(T value) - { - return EqualityComparer<T>.Default.Equals(value, defaultValue); - } + private bool IsDefault(T value) => EqualityComparer<T>.Default.Equals(value, DefaultValue); } } diff --git a/csharp/src/Google.Protobuf/Google.Protobuf.csproj b/csharp/src/Google.Protobuf/Google.Protobuf.csproj index 9179ab17..ef524baf 100644 --- a/csharp/src/Google.Protobuf/Google.Protobuf.csproj +++ b/csharp/src/Google.Protobuf/Google.Protobuf.csproj @@ -16,6 +16,8 @@ <FileAlignment>512</FileAlignment>
<OldToolsVersion>3.5</OldToolsVersion>
<MinimumVisualStudioVersion>10.0</MinimumVisualStudioVersion>
+ <NuGetPackageImportStamp>
+ </NuGetPackageImportStamp>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
@@ -62,7 +64,7 @@ <NoStdLib>true</NoStdLib>
<GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
<SignAssembly>True</SignAssembly>
- <AssemblyOriginatorKeyFile>C:\keys\Google.Protobuf.snk</AssemblyOriginatorKeyFile>
+ <AssemblyOriginatorKeyFile>..\..\keys\Google.Protobuf.snk</AssemblyOriginatorKeyFile>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
</PropertyGroup>
<ItemGroup>
@@ -83,6 +85,7 @@ <Compile Include="Compatibility\TypeExtensions.cs" />
<Compile Include="FieldCodec.cs" />
<Compile Include="FrameworkPortability.cs" />
+ <Compile Include="ICustomDiagnosticMessage.cs" />
<Compile Include="IDeepCloneable.cs" />
<Compile Include="InvalidJsonException.cs" />
<Compile Include="JsonFormatter.cs" />
@@ -106,7 +109,7 @@ <Compile Include="Reflection\FieldDescriptor.cs" />
<Compile Include="Reflection\FieldType.cs" />
<Compile Include="Reflection\FileDescriptor.cs" />
- <Compile Include="Reflection\GeneratedCodeInfo.cs" />
+ <Compile Include="Reflection\GeneratedClrTypeInfo.cs" />
<Compile Include="Reflection\IDescriptor.cs" />
<Compile Include="Reflection\IFieldAccessor.cs" />
<Compile Include="Reflection\MapFieldAccessor.cs" />
@@ -120,7 +123,8 @@ <Compile Include="Reflection\RepeatedFieldAccessor.cs" />
<Compile Include="Reflection\ServiceDescriptor.cs" />
<Compile Include="Reflection\SingleFieldAccessor.cs" />
- <Compile Include="Preconditions.cs" />
+ <Compile Include="ProtoPreconditions.cs" />
+ <Compile Include="Reflection\TypeRegistry.cs" />
<Compile Include="WellKnownTypes\Any.cs" />
<Compile Include="WellKnownTypes\AnyPartial.cs" />
<Compile Include="WellKnownTypes\Api.cs" />
@@ -128,6 +132,7 @@ <Compile Include="WellKnownTypes\DurationPartial.cs" />
<Compile Include="WellKnownTypes\Empty.cs" />
<Compile Include="WellKnownTypes\FieldMask.cs" />
+ <Compile Include="WellKnownTypes\FieldMaskPartial.cs" />
<Compile Include="WellKnownTypes\SourceContext.cs" />
<Compile Include="WellKnownTypes\Struct.cs" />
<Compile Include="WellKnownTypes\TimeExtensions.cs" />
@@ -141,9 +146,17 @@ </ItemGroup>
<ItemGroup>
<None Include="Google.Protobuf.nuspec" />
+ <None Include="packages.config" />
</ItemGroup>
<ItemGroup />
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\Portable\$(TargetFrameworkVersion)\Microsoft.Portable.CSharp.targets" />
+ <Import Project="..\packages\NuSpec.ReferenceGenerator.1.4.1\build\portable-net45+win+wpa81+wp80+MonoAndroid10+xamarinios10+MonoTouch10\NuSpec.ReferenceGenerator.targets" Condition="Exists('..\packages\NuSpec.ReferenceGenerator.1.4.1\build\portable-net45+win+wpa81+wp80+MonoAndroid10+xamarinios10+MonoTouch10\NuSpec.ReferenceGenerator.targets')" />
+ <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
+ <PropertyGroup>
+ <ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
+ </PropertyGroup>
+ <Error Condition="!Exists('..\packages\NuSpec.ReferenceGenerator.1.4.1\build\portable-net45+win+wpa81+wp80+MonoAndroid10+xamarinios10+MonoTouch10\NuSpec.ReferenceGenerator.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\NuSpec.ReferenceGenerator.1.4.1\build\portable-net45+win+wpa81+wp80+MonoAndroid10+xamarinios10+MonoTouch10\NuSpec.ReferenceGenerator.targets'))" />
+ </Target>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
diff --git a/csharp/src/Google.Protobuf/Google.Protobuf.nuspec b/csharp/src/Google.Protobuf/Google.Protobuf.nuspec index 9542138a..d5302544 100644 --- a/csharp/src/Google.Protobuf/Google.Protobuf.nuspec +++ b/csharp/src/Google.Protobuf/Google.Protobuf.nuspec @@ -1,11 +1,11 @@ -<?xml version="1.0" encoding="utf-8"?> +<?xml version="1.0" encoding="utf-8"?> <package> <metadata> <id>Google.Protobuf</id> <title>Google Protocol Buffers C#</title> <summary>C# runtime library for Protocol Buffers - Google's data interchange format.</summary> <description>See project site for more info.</description> - <version>3.0.0-alpha4</version> + <version>3.0.0-beta2</version> <authors>Google Inc.</authors> <owners>protobuf-packages</owners> <licenseUrl>https://github.com/google/protobuf/blob/master/LICENSE</licenseUrl> @@ -14,24 +14,53 @@ <releaseNotes>C# proto3 support</releaseNotes> <copyright>Copyright 2015, Google Inc.</copyright> <tags>Protocol Buffers Binary Serialization Format Google proto proto3</tags> + <dependencies> + <!-- Dependencies for older, monolithic-assembly platforms --> + <group targetFramework="net45" /> + <group targetFramework="wp8" /> + <group targetFramework="win8" /> + <group targetFramework="wpa81" /> + <group targetFramework="xamarin.ios" /> + <group targetFramework="monotouch" /> + <group targetFramework="monoandroid" /> + + <!-- Dependencies for newer, more granular platforms (.NET Core etc) --> + <group targetFramework="dotnet"> + <dependency id="System.Collections" version="4.0.0" /> + <dependency id="System.Diagnostics.Debug" version="4.0.0" /> + <dependency id="System.Globalization" version="4.0.0" /> + <dependency id="System.IO" version="4.0.0" /> + <dependency id="System.Linq" version="4.0.0" /> + <dependency id="System.Linq.Expressions" version="4.0.0" /> + <dependency id="System.ObjectModel" version="4.0.0" /> + <dependency id="System.Reflection" version="4.0.0" /> + <dependency id="System.Runtime" version="4.0.0" /> + <dependency id="System.Runtime.Extensions" version="4.0.0" /> + <dependency id="System.Text.Encoding" version="4.0.0" /> + <dependency id="System.Text.RegularExpressions" version="4.0.0" /> + </group> + </dependencies> </metadata> <files> <file src="bin/ReleaseSigned/Google.Protobuf.dll" target="lib/portable-net45+netcore45+wpa81+wp8" /> - <file src="bin/ReleaseSigned/Google.Protobuf.pdb" target="lib/portable-net45+netcore45+wpa81+wp8" /> - <file src="bin/ReleaseSigned/Google.Protobuf.xml" target="lib/portable-net45+netcore45+wpa81+wp8" /> - <file src="**\*.cs" target="src" /> - <file src="..\..\..\cmake\Release\protoc.exe" target="tools" /> - <file src="..\..\..\src\google\protobuf\any.proto" target="tools\google\protobuf" /> - <file src="..\..\..\src\google\protobuf\api.proto" target="tools\google\protobuf" /> - <file src="..\..\..\src\google\protobuf\descriptor.proto" target="tools\google\protobuf" /> - <file src="..\..\..\src\google\protobuf\duration.proto" target="tools\google\protobuf" /> - <file src="..\..\..\src\google\protobuf\empty.proto" target="tools\google\protobuf" /> - <file src="..\..\..\src\google\protobuf\field_mask.proto" target="tools\google\protobuf" /> - <file src="..\..\..\src\google\protobuf\source_context.proto" target="tools\google\protobuf" /> - <file src="..\..\..\src\google\protobuf\struct.proto" target="tools\google\protobuf" /> - <file src="..\..\..\src\google\protobuf\timestamp.proto" target="tools\google\protobuf" /> - <file src="..\..\..\src\google\protobuf\any.proto" target="tools\google\protobuf" /> - <file src="..\..\..\src\google\protobuf\type.proto" target="tools\google\protobuf" /> - <file src="..\..\..\src\google\protobuf\wrappers.proto" target="tools\google\protobuf" /> + <file src="bin/ReleaseSigned/Google.Protobuf.pdb" target="lib/portable-net45+netcore45+wpa81+wp8" /> + <file src="bin/ReleaseSigned/Google.Protobuf.xml" target="lib/portable-net45+netcore45+wpa81+wp8" /> + <file src="bin/ReleaseSigned/Google.Protobuf.dll" target="lib/dotnet" /> + <file src="bin/ReleaseSigned/Google.Protobuf.pdb" target="lib/dotnet" /> + <file src="bin/ReleaseSigned/Google.Protobuf.xml" target="lib/dotnet" /> + <file src="**\*.cs" target="src" /> + <file src="..\..\..\cmake\Release\protoc.exe" target="tools" /> + <file src="..\..\..\src\google\protobuf\any.proto" target="tools\google\protobuf" /> + <file src="..\..\..\src\google\protobuf\api.proto" target="tools\google\protobuf" /> + <file src="..\..\..\src\google\protobuf\descriptor.proto" target="tools\google\protobuf" /> + <file src="..\..\..\src\google\protobuf\duration.proto" target="tools\google\protobuf" /> + <file src="..\..\..\src\google\protobuf\empty.proto" target="tools\google\protobuf" /> + <file src="..\..\..\src\google\protobuf\field_mask.proto" target="tools\google\protobuf" /> + <file src="..\..\..\src\google\protobuf\source_context.proto" target="tools\google\protobuf" /> + <file src="..\..\..\src\google\protobuf\struct.proto" target="tools\google\protobuf" /> + <file src="..\..\..\src\google\protobuf\timestamp.proto" target="tools\google\protobuf" /> + <file src="..\..\..\src\google\protobuf\any.proto" target="tools\google\protobuf" /> + <file src="..\..\..\src\google\protobuf\type.proto" target="tools\google\protobuf" /> + <file src="..\..\..\src\google\protobuf\wrappers.proto" target="tools\google\protobuf" /> </files> -</package> +</package>
\ No newline at end of file diff --git a/csharp/src/Google.Protobuf/ICustomDiagnosticMessage.cs b/csharp/src/Google.Protobuf/ICustomDiagnosticMessage.cs new file mode 100644 index 00000000..a0090569 --- /dev/null +++ b/csharp/src/Google.Protobuf/ICustomDiagnosticMessage.cs @@ -0,0 +1,69 @@ +#region Copyright notice and license +// Protocol Buffers - Google's data interchange format +// Copyright 2016 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#endregion + +namespace Google.Protobuf +{ + /// <summary> + /// A message type that has a custom string format for diagnostic purposes. + /// </summary> + /// <remarks> + /// <para> + /// Calling <see cref="object.ToString"/> on a generated message type normally + /// returns the JSON representation. If a message type implements this interface, + /// then the <see cref="ToDiagnosticString"/> method will be called instead of the regular + /// JSON formatting code, but only when <c>ToString()</c> is called either on the message itself + /// or on another message which contains it. This does not affect the normal JSON formatting of + /// the message. + /// </para> + /// <para> + /// For example, if you create a proto message representing a GUID, the internal + /// representation may be a <c>bytes</c> field or four <c>fixed32</c> fields. However, when debugging + /// it may be more convenient to see a result in the same format as <see cref="System.Guid"/> provides. + /// </para> + /// <para>This interface extends <see cref="IMessage"/> to avoid it accidentally being implemented + /// on types other than messages, where it would not be used by anything in the framework.</para> + /// </remarks> + public interface ICustomDiagnosticMessage : IMessage + { + /// <summary> + /// Returns a string representation of this object, for diagnostic purposes. + /// </summary> + /// <remarks> + /// This method is called when a message is formatted as part of a <see cref="object.ToString"/> + /// call. It does not affect the JSON representation used by <see cref="JsonFormatter"/> other than + /// in calls to <see cref="JsonFormatter.ToDiagnosticString(IMessage)"/>. While it is recommended + /// that the result is valid JSON, this is never assumed by the Protobuf library. + /// </remarks> + /// <returns>A string representation of this object, for diagnostic purposes.</returns> + string ToDiagnosticString(); + } +} diff --git a/csharp/src/Google.Protobuf/InvalidProtocolBufferException.cs b/csharp/src/Google.Protobuf/InvalidProtocolBufferException.cs index cacda648..eeb0f13a 100644 --- a/csharp/src/Google.Protobuf/InvalidProtocolBufferException.cs +++ b/csharp/src/Google.Protobuf/InvalidProtocolBufferException.cs @@ -30,6 +30,7 @@ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#endregion
+using System;
using System.IO;
namespace Google.Protobuf
@@ -45,6 +46,11 @@ namespace Google.Protobuf {
}
+ internal InvalidProtocolBufferException(string message, Exception innerException)
+ : base(message, innerException)
+ {
+ }
+
internal static InvalidProtocolBufferException MoreDataAvailable()
{
return new InvalidProtocolBufferException(
@@ -82,6 +88,11 @@ namespace Google.Protobuf "Protocol message contained an invalid tag (zero).");
}
+ internal static InvalidProtocolBufferException InvalidBase64(Exception innerException)
+ {
+ return new InvalidProtocolBufferException("Invalid base64 data", innerException);
+ }
+
internal static InvalidProtocolBufferException InvalidEndTag()
{
return new InvalidProtocolBufferException(
diff --git a/csharp/src/Google.Protobuf/JsonFormatter.cs b/csharp/src/Google.Protobuf/JsonFormatter.cs index 08e3142e..60f61fc8 100644 --- a/csharp/src/Google.Protobuf/JsonFormatter.cs +++ b/csharp/src/Google.Protobuf/JsonFormatter.cs @@ -37,6 +37,7 @@ using System.Text; using Google.Protobuf.Reflection; using Google.Protobuf.WellKnownTypes; using System.Linq; +using System.Collections.Generic; namespace Google.Protobuf { @@ -55,12 +56,20 @@ namespace Google.Protobuf /// </remarks> public sealed class JsonFormatter { - private static JsonFormatter defaultInstance = new JsonFormatter(Settings.Default); + internal const string AnyTypeUrlField = "@type"; + internal const string AnyDiagnosticValueField = "@value"; + internal const string AnyWellKnownTypeValueField = "value"; + private const string TypeUrlPrefix = "type.googleapis.com"; + private const string NameValueSeparator = ": "; + private const string PropertySeparator = ", "; /// <summary> /// Returns a formatter using the default settings. /// </summary> - public static JsonFormatter Default { get { return defaultInstance; } } + public static JsonFormatter Default { get; } = new JsonFormatter(Settings.Default); + + // A JSON formatter which *only* exists + private static readonly JsonFormatter diagnosticFormatter = new JsonFormatter(Settings.Default); /// <summary> /// The JSON representation of the first 160 characters of Unicode. @@ -114,6 +123,8 @@ namespace Google.Protobuf private readonly Settings settings; + private bool DiagnosticOnly => ReferenceEquals(this, diagnosticFormatter); + /// <summary> /// Creates a new formatted with the given settings. /// </summary> @@ -130,11 +141,11 @@ namespace Google.Protobuf /// <returns>The formatted message.</returns> public string Format(IMessage message) { - Preconditions.CheckNotNull(message, "message"); + ProtoPreconditions.CheckNotNull(message, nameof(message)); StringBuilder builder = new StringBuilder(); if (message.Descriptor.IsWellKnownType) { - WriteWellKnownTypeValue(builder, message.Descriptor, message, false); + WriteWellKnownTypeValue(builder, message.Descriptor, message); } else { @@ -143,6 +154,29 @@ namespace Google.Protobuf return builder.ToString(); } + /// <summary> + /// Converts a message to JSON for diagnostic purposes with no extra context. + /// </summary> + /// <remarks> + /// <para> + /// This differs from calling <see cref="Format(IMessage)"/> on the default JSON + /// formatter in its handling of <see cref="Any"/>. As no type registry is available + /// in <see cref="object.ToString"/> calls, the normal way of resolving the type of + /// an <c>Any</c> message cannot be applied. Instead, a JSON property named <c>@value</c> + /// is included with the base64 data from the <see cref="Any.Value"/> property of the message. + /// </para> + /// <para>The value returned by this method is only designed to be used for diagnostic + /// purposes. It may not be parsable by <see cref="JsonParser"/>, and may not be parsable + /// by other Protocol Buffer implementations.</para> + /// </remarks> + /// <param name="message">The message to format for diagnostic purposes.</param> + /// <returns>The diagnostic-only JSON representation of the message</returns> + public static string ToDiagnosticString(IMessage message) + { + ProtoPreconditions.CheckNotNull(message, nameof(message)); + return diagnosticFormatter.Format(message); + } + private void WriteMessage(StringBuilder builder, IMessage message) { if (message == null) @@ -150,14 +184,28 @@ namespace Google.Protobuf WriteNull(builder); return; } + if (DiagnosticOnly) + { + ICustomDiagnosticMessage customDiagnosticMessage = message as ICustomDiagnosticMessage; + if (customDiagnosticMessage != null) + { + builder.Append(customDiagnosticMessage.ToDiagnosticString()); + return; + } + } builder.Append("{ "); + bool writtenFields = WriteMessageFields(builder, message, false); + builder.Append(writtenFields ? " }" : "}"); + } + + private bool WriteMessageFields(StringBuilder builder, IMessage message, bool assumeFirstFieldWritten) + { var fields = message.Descriptor.Fields; - bool first = true; + bool first = !assumeFirstFieldWritten; // First non-oneof fields foreach (var field in fields.InFieldNumberOrder()) { var accessor = field.Accessor; - // Oneofs are written later if (field.ContainingOneof != null && field.ContainingOneof.Accessor.GetCaseFieldDescriptor(message) != field) { continue; @@ -169,23 +217,43 @@ namespace Google.Protobuf { continue; } - // Omit awkward (single) values such as unknown enum values - if (!field.IsRepeated && !field.IsMap && !CanWriteSingleValue(value)) - { - continue; - } // Okay, all tests complete: let's write the field value... if (!first) { - builder.Append(", "); + builder.Append(PropertySeparator); } WriteString(builder, ToCamelCase(accessor.Descriptor.Name)); - builder.Append(": "); + builder.Append(NameValueSeparator); WriteValue(builder, value); first = false; } - builder.Append(first ? "}" : " }"); + return !first; + } + + /// <summary> + /// Camel-case converter with added strictness for field mask formatting. + /// </summary> + /// <exception cref="InvalidOperationException">The field mask is invalid for JSON representation</exception> + private static string ToCamelCaseForFieldMask(string input) + { + for (int i = 0; i < input.Length; i++) + { + char c = input[i]; + if (c >= 'A' && c <= 'Z') + { + throw new InvalidOperationException($"Invalid field mask to be converted to JSON: {input}"); + } + if (c == '_' && i < input.Length - 1) + { + char next = input[i + 1]; + if (next < 'a' || next > 'z') + { + throw new InvalidOperationException($"Invalid field mask to be converted to JSON: {input}"); + } + } + } + return ToCamelCase(input); } // Converted from src/google/protobuf/util/internal/utility.cc ToCamelCase @@ -336,7 +404,14 @@ namespace Google.Protobuf } else if (value is System.Enum) { - WriteString(builder, value.ToString()); + if (System.Enum.IsDefined(value.GetType(), value)) + { + WriteString(builder, value.ToString()); + } + else + { + WriteValue(builder, (int) value); + } } else if (value is float || value is double) { @@ -357,7 +432,7 @@ namespace Google.Protobuf IMessage message = (IMessage) value; if (message.Descriptor.IsWellKnownType) { - WriteWellKnownTypeValue(builder, message.Descriptor, value, true); + WriteWellKnownTypeValue(builder, message.Descriptor, value); } else { @@ -376,8 +451,10 @@ namespace Google.Protobuf /// values are using the embedded well-known types, in order to allow for dynamic messages /// in the future. /// </summary> - private void WriteWellKnownTypeValue(StringBuilder builder, MessageDescriptor descriptor, object value, bool inField) + private void WriteWellKnownTypeValue(StringBuilder builder, MessageDescriptor descriptor, object value) { + // Currently, we can never actually get here, because null values are always handled by the caller. But if we *could*, + // this would do the right thing. if (value == null) { WriteNull(builder); @@ -388,8 +465,7 @@ namespace Google.Protobuf // If it's the message form, we can extract the value first, which *will* be the (possibly boxed) native value, // and then proceed, writing it as if we were definitely in a field. (We never need to wrap it in an extra string... // WriteValue will do the right thing.) - // TODO: Detect this differently when we have dynamic messages. - if (descriptor.File == Int32Value.Descriptor.File) + if (descriptor.IsWrapperType) { if (value is IMessage) { @@ -401,17 +477,17 @@ namespace Google.Protobuf } if (descriptor.FullName == Timestamp.Descriptor.FullName) { - MaybeWrapInString(builder, value, WriteTimestamp, inField); + WriteTimestamp(builder, (IMessage) value); return; } if (descriptor.FullName == Duration.Descriptor.FullName) { - MaybeWrapInString(builder, value, WriteDuration, inField); + WriteDuration(builder, (IMessage) value); return; } if (descriptor.FullName == FieldMask.Descriptor.FullName) { - MaybeWrapInString(builder, value, WriteFieldMask, inField); + WriteFieldMask(builder, (IMessage) value); return; } if (descriptor.FullName == Struct.Descriptor.FullName) @@ -430,25 +506,12 @@ namespace Google.Protobuf WriteStructFieldValue(builder, (IMessage) value); return; } - WriteMessage(builder, (IMessage) value); - } - - /// <summary> - /// Some well-known types end up as string values... so they need wrapping in quotes, but only - /// when they're being used as fields within another message. - /// </summary> - private void MaybeWrapInString(StringBuilder builder, object value, Action<StringBuilder, IMessage> action, bool inField) - { - if (inField) + if (descriptor.FullName == Any.Descriptor.FullName) { - builder.Append('"'); - action(builder, (IMessage) value); - builder.Append('"'); - } - else - { - action(builder, (IMessage) value); + WriteAny(builder, (IMessage) value); + return; } + WriteMessage(builder, (IMessage) value); } private void WriteTimestamp(StringBuilder builder, IMessage value) @@ -459,15 +522,7 @@ namespace Google.Protobuf // it still works in that case. int nanos = (int) value.Descriptor.Fields[Timestamp.NanosFieldNumber].Accessor.GetValue(value); long seconds = (long) value.Descriptor.Fields[Timestamp.SecondsFieldNumber].Accessor.GetValue(value); - - // Even if the original message isn't using the built-in classes, we can still build one... and then - // rely on it being normalized. - Timestamp normalized = Timestamp.Normalize(seconds, nanos); - // Use .NET's formatting for the value down to the second, including an opening double quote (as it's a string value) - DateTime dateTime = normalized.ToDateTime(); - builder.Append(dateTime.ToString("yyyy'-'MM'-'dd'T'HH:mm:ss", CultureInfo.InvariantCulture)); - AppendNanoseconds(builder, Math.Abs(normalized.Nanos)); - builder.Append('Z'); + builder.Append(Timestamp.ToJson(seconds, nanos, DiagnosticOnly)); } private void WriteDuration(StringBuilder builder, IMessage value) @@ -475,51 +530,76 @@ namespace Google.Protobuf // TODO: Same as for WriteTimestamp int nanos = (int) value.Descriptor.Fields[Duration.NanosFieldNumber].Accessor.GetValue(value); long seconds = (long) value.Descriptor.Fields[Duration.SecondsFieldNumber].Accessor.GetValue(value); + builder.Append(Duration.ToJson(seconds, nanos, DiagnosticOnly)); + } - // Even if the original message isn't using the built-in classes, we can still build one... and then - // rely on it being normalized. - Duration normalized = Duration.Normalize(seconds, nanos); + private void WriteFieldMask(StringBuilder builder, IMessage value) + { + var paths = (IList<string>) value.Descriptor.Fields[FieldMask.PathsFieldNumber].Accessor.GetValue(value); + builder.Append(FieldMask.ToJson(paths, DiagnosticOnly)); + } + + private void WriteAny(StringBuilder builder, IMessage value) + { + if (DiagnosticOnly) + { + WriteDiagnosticOnlyAny(builder, value); + return; + } - // The seconds part will normally provide the minus sign if we need it, but not if it's 0... - if (normalized.Seconds == 0 && normalized.Nanos < 0) + 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); + MessageDescriptor descriptor = settings.TypeRegistry.Find(typeName); + if (descriptor == null) { - builder.Append('-'); + throw new InvalidOperationException($"Type registry has no descriptor for type name '{typeName}'"); } + IMessage message = descriptor.Parser.ParseFrom(data); + builder.Append("{ "); + WriteString(builder, AnyTypeUrlField); + builder.Append(NameValueSeparator); + WriteString(builder, typeUrl); - builder.Append(normalized.Seconds.ToString("d", CultureInfo.InvariantCulture)); - AppendNanoseconds(builder, Math.Abs(normalized.Nanos)); - builder.Append('s'); + if (descriptor.IsWellKnownType) + { + builder.Append(PropertySeparator); + WriteString(builder, AnyWellKnownTypeValueField); + builder.Append(NameValueSeparator); + WriteWellKnownTypeValue(builder, descriptor, message); + } + else + { + WriteMessageFields(builder, message, true); + } + builder.Append(" }"); } - private void WriteFieldMask(StringBuilder builder, IMessage value) + private void WriteDiagnosticOnlyAny(StringBuilder builder, IMessage value) { - IList paths = (IList) value.Descriptor.Fields[FieldMask.PathsFieldNumber].Accessor.GetValue(value); - AppendEscapedString(builder, string.Join(",", paths.Cast<string>().Select(ToCamelCase))); + string typeUrl = (string) value.Descriptor.Fields[Any.TypeUrlFieldNumber].Accessor.GetValue(value); + ByteString data = (ByteString) value.Descriptor.Fields[Any.ValueFieldNumber].Accessor.GetValue(value); + builder.Append("{ "); + WriteString(builder, AnyTypeUrlField); + builder.Append(NameValueSeparator); + WriteString(builder, typeUrl); + builder.Append(PropertySeparator); + WriteString(builder, AnyDiagnosticValueField); + builder.Append(NameValueSeparator); + builder.Append('"'); + builder.Append(data.ToBase64()); + builder.Append('"'); + builder.Append(" }"); } - /// <summary> - /// Appends a number of nanoseconds to a StringBuilder. Either 0 digits are added (in which - /// case no "." is appended), or 3 6 or 9 digits. - /// </summary> - private static void AppendNanoseconds(StringBuilder builder, int nanos) + internal static string GetTypeName(String typeUrl) { - if (nanos != 0) + string[] parts = typeUrl.Split('/'); + if (parts.Length != 2 || parts[0] != TypeUrlPrefix) { - builder.Append('.'); - // Output to 3, 6 or 9 digits. - if (nanos % 1000000 == 0) - { - builder.Append((nanos / 1000000).ToString("d", CultureInfo.InvariantCulture)); - } - else if (nanos % 1000 == 0) - { - builder.Append((nanos / 1000).ToString("d", CultureInfo.InvariantCulture)); - } - else - { - builder.Append(nanos.ToString("d", CultureInfo.InvariantCulture)); - } + throw new InvalidProtocolBufferException($"Invalid type url: {typeUrl}"); } + return parts[1]; } private void WriteStruct(StringBuilder builder, IMessage message) @@ -538,10 +618,10 @@ namespace Google.Protobuf if (!first) { - builder.Append(", "); + builder.Append(PropertySeparator); } WriteString(builder, key); - builder.Append(": "); + builder.Append(NameValueSeparator); WriteStructFieldValue(builder, value); first = false; } @@ -569,7 +649,7 @@ namespace Google.Protobuf case Value.ListValueFieldNumber: // Structs and ListValues are nested messages, and already well-known types. var nestedMessage = (IMessage) specifiedField.Accessor.GetValue(message); - WriteWellKnownTypeValue(builder, nestedMessage.Descriptor, nestedMessage, true); + WriteWellKnownTypeValue(builder, nestedMessage.Descriptor, nestedMessage); return; case Value.NullValueFieldNumber: WriteNull(builder); @@ -585,13 +665,9 @@ namespace Google.Protobuf bool first = true; foreach (var value in list) { - if (!CanWriteSingleValue(value)) - { - continue; - } if (!first) { - builder.Append(", "); + builder.Append(PropertySeparator); } WriteValue(builder, value); first = false; @@ -606,13 +682,9 @@ namespace Google.Protobuf // This will box each pair. Could use IDictionaryEnumerator, but that's ugly in terms of disposal. foreach (DictionaryEntry pair in dictionary) { - if (!CanWriteSingleValue(pair.Value)) - { - continue; - } if (!first) { - builder.Append(", "); + builder.Append(PropertySeparator); } string keyText; if (pair.Key is string) @@ -636,7 +708,7 @@ namespace Google.Protobuf throw new ArgumentException("Unhandled dictionary key type: " + pair.Key.GetType()); } WriteString(builder, keyText); - builder.Append(": "); + builder.Append(NameValueSeparator); WriteValue(builder, pair.Value); first = false; } @@ -663,18 +735,9 @@ namespace Google.Protobuf /// <remarks> /// Other than surrogate pair handling, this code is mostly taken from src/google/protobuf/util/internal/json_escaping.cc. /// </remarks> - private void WriteString(StringBuilder builder, string text) + internal static void WriteString(StringBuilder builder, string text) { builder.Append('"'); - AppendEscapedString(builder, text); - builder.Append('"'); - } - - /// <summary> - /// Appends the given text to the string builder, escaping as required. - /// </summary> - private void AppendEscapedString(StringBuilder builder, string text) - { for (int i = 0; i < text.Length; i++) { char c = text[i]; @@ -734,6 +797,7 @@ namespace Google.Protobuf break; } } + builder.Append('"'); } private const string Hex = "0123456789abcdef"; @@ -751,28 +815,50 @@ namespace Google.Protobuf /// </summary> public sealed class Settings { - private static readonly Settings defaultInstance = new Settings(false); - /// <summary> /// Default settings, as used by <see cref="JsonFormatter.Default"/> /// </summary> - public static Settings Default { get { return defaultInstance; } } + public static Settings Default { get; } - private readonly bool formatDefaultValues; + // Workaround for the Mono compiler complaining about XML comments not being on + // valid language elements. + static Settings() + { + Default = new Settings(false); + } /// <summary> /// Whether fields whose values are the default for the field type (e.g. 0 for integers) /// should be formatted (true) or omitted (false). /// </summary> - public bool FormatDefaultValues { get { return formatDefaultValues; } } + public bool FormatDefaultValues { get; } + + /// <summary> + /// The type registry used to format <see cref="Any"/> messages. + /// </summary> + public TypeRegistry TypeRegistry { get; } + + // TODO: Work out how we're going to scale this to multiple settings. "WithXyz" methods? + + /// <summary> + /// Creates a new <see cref="Settings"/> object with the specified formatting of default values + /// and an empty type registry. + /// </summary> + /// <param name="formatDefaultValues"><c>true</c> if default values (0, empty strings etc) should be formatted; <c>false</c> otherwise.</param> + public Settings(bool formatDefaultValues) : this(formatDefaultValues, TypeRegistry.Empty) + { + } /// <summary> - /// Creates a new <see cref="Settings"/> object with the specified formatting of default values. + /// Creates a new <see cref="Settings"/> object with the specified formatting of default values + /// and type registry. /// </summary> /// <param name="formatDefaultValues"><c>true</c> if default values (0, empty strings etc) should be formatted; <c>false</c> otherwise.</param> - public Settings(bool formatDefaultValues) + /// <param name="typeRegistry">The <see cref="TypeRegistry"/> to use when formatting <see cref="Any"/> messages.</param> + public Settings(bool formatDefaultValues, TypeRegistry typeRegistry) { - this.formatDefaultValues = formatDefaultValues; + FormatDefaultValues = formatDefaultValues; + TypeRegistry = ProtoPreconditions.CheckNotNull(typeRegistry, nameof(typeRegistry)); } } } diff --git a/csharp/src/Google.Protobuf/JsonParser.cs b/csharp/src/Google.Protobuf/JsonParser.cs index b4a35d7c..80d3013d 100644 --- a/csharp/src/Google.Protobuf/JsonParser.cs +++ b/csharp/src/Google.Protobuf/JsonParser.cs @@ -77,6 +77,7 @@ namespace Google.Protobuf { ListValue.Descriptor.FullName, (parser, message, tokenizer) => parser.MergeRepeatedField(message, message.Descriptor.Fields[ListValue.ValuesFieldNumber], tokenizer) }, { Struct.Descriptor.FullName, (parser, message, tokenizer) => parser.MergeStruct(message, tokenizer) }, + { Any.Descriptor.FullName, (parser, message, tokenizer) => parser.MergeAny(message, tokenizer) }, { FieldMask.Descriptor.FullName, (parser, message, tokenizer) => MergeFieldMask(message, tokenizer.Next()) }, { Int32Value.Descriptor.FullName, MergeWrapperField }, { Int64Value.Descriptor.FullName, MergeWrapperField }, @@ -128,7 +129,7 @@ namespace Google.Protobuf /// <param name="jsonReader">Reader providing the JSON to parse.</param> internal void Merge(IMessage message, TextReader jsonReader) { - var tokenizer = new JsonTokenizer(jsonReader); + var tokenizer = JsonTokenizer.FromTextReader(jsonReader); Merge(message, tokenizer); var lastToken = tokenizer.Next(); if (lastToken != JsonToken.EndDocument) @@ -167,6 +168,10 @@ namespace Google.Protobuf } var descriptor = message.Descriptor; var jsonFieldMap = descriptor.Fields.ByJsonName(); + // All the oneof fields we've already accounted for - we can only see each of them once. + // The set is created lazily to avoid the overhead of creating a set for every message + // we parsed, when oneofs are relatively rare. + HashSet<OneofDescriptor> seenOneofs = null; while (true) { token = tokenizer.Next(); @@ -182,6 +187,17 @@ namespace Google.Protobuf FieldDescriptor field; if (jsonFieldMap.TryGetValue(name, out field)) { + if (field.ContainingOneof != null) + { + if (seenOneofs == null) + { + seenOneofs = new HashSet<OneofDescriptor>(); + } + if (!seenOneofs.Add(field.ContainingOneof)) + { + throw new InvalidProtocolBufferException($"Multiple values specified for oneof {field.ContainingOneof.Name}"); + } + } MergeField(message, field, tokenizer); } else @@ -199,10 +215,15 @@ namespace Google.Protobuf var token = tokenizer.Next(); if (token.Type == JsonToken.TokenType.Null) { + // Clear the field if we see a null token, unless it's for a singular field of type + // google.protobuf.Value. // Note: different from Java API, which just ignores it. // TODO: Bring it more in line? Discuss... - field.Accessor.Clear(message); - return; + if (field.IsMap || field.IsRepeated || !IsGoogleProtobufValueField(field)) + { + field.Accessor.Clear(message); + return; + } } tokenizer.PushBack(token); @@ -238,6 +259,10 @@ namespace Google.Protobuf return; } tokenizer.PushBack(token); + if (token.Type == JsonToken.TokenType.Null) + { + throw new InvalidProtocolBufferException("Repeated field elements cannot be null"); + } list.Add(ParseSingleValue(field, tokenizer)); } } @@ -269,19 +294,30 @@ namespace Google.Protobuf } object key = ParseMapKey(keyField, token.StringValue); object value = ParseSingleValue(valueField, tokenizer); - // TODO: Null handling + if (value == null) + { + throw new InvalidProtocolBufferException("Map values must not be null"); + } dictionary[key] = value; } } + private static bool IsGoogleProtobufValueField(FieldDescriptor field) + { + return field.FieldType == FieldType.Message && + field.MessageType.FullName == Value.Descriptor.FullName; + } + private object ParseSingleValue(FieldDescriptor field, JsonTokenizer tokenizer) { var token = tokenizer.Next(); if (token.Type == JsonToken.TokenType.Null) { - if (field.FieldType == FieldType.Message && field.MessageType.FullName == Value.Descriptor.FullName) + // TODO: In order to support dynamic messages, we should really build this up + // dynamically. + if (IsGoogleProtobufValueField(field)) { - return new Value { NullValue = NullValue.NULL_VALUE }; + return Value.ForNull(); } return null; } @@ -291,8 +327,7 @@ namespace Google.Protobuf { // Parse wrapper types as their constituent types. // TODO: What does this mean for null? - // TODO: Detect this differently when we have dynamic messages, and put it in one place... - if (field.MessageType.IsWellKnownType && field.MessageType.File == Int32Value.Descriptor.File) + if (field.MessageType.IsWrapperType) { field = field.MessageType.Fields[WrappersReflection.WrapperValueFieldNumber]; fieldType = field.FieldType; @@ -339,6 +374,7 @@ namespace Google.Protobuf /// <exception cref="InvalidProtocolBufferException">The JSON does not represent a Protocol Buffers message correctly</exception> public T Parse<T>(string json) where T : IMessage, new() { + ProtoPreconditions.CheckNotNull(json, nameof(json)); return Parse<T>(new StringReader(json)); } @@ -351,11 +387,42 @@ namespace Google.Protobuf /// <exception cref="InvalidProtocolBufferException">The JSON does not represent a Protocol Buffers message correctly</exception> public T Parse<T>(TextReader jsonReader) where T : IMessage, new() { + ProtoPreconditions.CheckNotNull(jsonReader, nameof(jsonReader)); T message = new T(); Merge(message, jsonReader); return message; } + /// <summary> + /// Parses <paramref name="json"/> into a new message. + /// </summary> + /// <param name="json">The JSON to parse.</param> + /// <param name="descriptor">Descriptor of message type to parse.</param> + /// <exception cref="InvalidJsonException">The JSON does not comply with RFC 7159</exception> + /// <exception cref="InvalidProtocolBufferException">The JSON does not represent a Protocol Buffers message correctly</exception> + public IMessage Parse(string json, MessageDescriptor descriptor) + { + ProtoPreconditions.CheckNotNull(json, nameof(json)); + ProtoPreconditions.CheckNotNull(descriptor, nameof(descriptor)); + return Parse(new StringReader(json), descriptor); + } + + /// <summary> + /// Parses JSON read from <paramref name="jsonReader"/> into a new message. + /// </summary> + /// <param name="jsonReader">Reader providing the JSON to parse.</param> + /// <param name="descriptor">Descriptor of message type to parse.</param> + /// <exception cref="InvalidJsonException">The JSON does not comply with RFC 7159</exception> + /// <exception cref="InvalidProtocolBufferException">The JSON does not represent a Protocol Buffers message correctly</exception> + public IMessage Parse(TextReader jsonReader, MessageDescriptor descriptor) + { + ProtoPreconditions.CheckNotNull(jsonReader, nameof(jsonReader)); + ProtoPreconditions.CheckNotNull(descriptor, nameof(descriptor)); + IMessage message = descriptor.Parser.CreateTemplate(); + Merge(message, jsonReader); + return message; + } + private void MergeStructValue(IMessage message, JsonTokenizer tokenizer) { var firstToken = tokenizer.Next(); @@ -411,6 +478,88 @@ namespace Google.Protobuf MergeMapField(message, field, tokenizer); } + private void MergeAny(IMessage message, JsonTokenizer tokenizer) + { + // Record the token stream until we see the @type property. At that point, we can take the value, consult + // the type registry for the relevant message, and replay the stream, omitting the @type property. + var tokens = new List<JsonToken>(); + + var token = tokenizer.Next(); + if (token.Type != JsonToken.TokenType.StartObject) + { + throw new InvalidProtocolBufferException("Expected object value for Any"); + } + int typeUrlObjectDepth = tokenizer.ObjectDepth; + + // The check for the property depth protects us from nested Any values which occur before the type URL + // for *this* Any. + while (token.Type != JsonToken.TokenType.Name || + token.StringValue != JsonFormatter.AnyTypeUrlField || + tokenizer.ObjectDepth != typeUrlObjectDepth) + { + tokens.Add(token); + token = tokenizer.Next(); + + if (tokenizer.ObjectDepth < typeUrlObjectDepth) + { + throw new InvalidProtocolBufferException("Any message with no @type"); + } + } + + // Don't add the @type property or its value to the recorded token list + token = tokenizer.Next(); + if (token.Type != JsonToken.TokenType.StringValue) + { + throw new InvalidProtocolBufferException("Expected string value for Any.@type"); + } + string typeUrl = token.StringValue; + string typeName = JsonFormatter.GetTypeName(typeUrl); + + MessageDescriptor descriptor = settings.TypeRegistry.Find(typeName); + if (descriptor == null) + { + throw new InvalidOperationException($"Type registry has no descriptor for type name '{typeName}'"); + } + + // Now replay the token stream we've already read and anything that remains of the object, just parsing it + // as normal. Our original tokenizer should end up at the end of the object. + var replay = JsonTokenizer.FromReplayedTokens(tokens, tokenizer); + var body = descriptor.Parser.CreateTemplate(); + if (descriptor.IsWellKnownType) + { + MergeWellKnownTypeAnyBody(body, replay); + } + else + { + Merge(body, replay); + } + var data = body.ToByteString(); + + // Now that we have the message data, we can pack it into an Any (the message received as a parameter). + message.Descriptor.Fields[Any.TypeUrlFieldNumber].Accessor.SetValue(message, typeUrl); + message.Descriptor.Fields[Any.ValueFieldNumber].Accessor.SetValue(message, data); + } + + // Well-known types end up in a property called "value" in the JSON. As there's no longer a @type property + // in the given JSON token stream, we should *only* have tokens of start-object, name("value"), the value + // itself, and then end-object. + private void MergeWellKnownTypeAnyBody(IMessage body, JsonTokenizer tokenizer) + { + var token = tokenizer.Next(); // Definitely start-object; checked in previous method + token = tokenizer.Next(); + // TODO: What about an absent Int32Value, for example? + if (token.Type != JsonToken.TokenType.Name || token.StringValue != JsonFormatter.AnyWellKnownTypeValueField) + { + throw new InvalidProtocolBufferException($"Expected '{JsonFormatter.AnyWellKnownTypeValueField}' property for well-known type Any body"); + } + Merge(body, tokenizer); + token = tokenizer.Next(); + if (token.Type != JsonToken.TokenType.EndObject) + { + throw new InvalidProtocolBufferException($"Expected end-object token after @type/value for well-known type"); + } + } + #region Utility methods which don't depend on the state (or settings) of the parser. private static object ParseMapKey(FieldDescriptor field, string keyText) { @@ -431,17 +580,17 @@ namespace Google.Protobuf case FieldType.Int32: case FieldType.SInt32: case FieldType.SFixed32: - return ParseNumericString(keyText, int.Parse, false); + return ParseNumericString(keyText, int.Parse); case FieldType.UInt32: case FieldType.Fixed32: - return ParseNumericString(keyText, uint.Parse, false); + return ParseNumericString(keyText, uint.Parse); case FieldType.Int64: case FieldType.SInt64: case FieldType.SFixed64: - return ParseNumericString(keyText, long.Parse, false); + return ParseNumericString(keyText, long.Parse); case FieldType.UInt64: case FieldType.Fixed64: - return ParseNumericString(keyText, ulong.Parse, false); + return ParseNumericString(keyText, ulong.Parse); default: throw new InvalidProtocolBufferException("Invalid field type for map: " + field.FieldType); } @@ -452,7 +601,6 @@ namespace Google.Protobuf double value = token.NumberValue; checked { - // TODO: Validate that it's actually an integer, possibly in terms of the textual representation? try { switch (field.FieldType) @@ -460,16 +608,20 @@ namespace Google.Protobuf case FieldType.Int32: case FieldType.SInt32: case FieldType.SFixed32: + CheckInteger(value); return (int) value; case FieldType.UInt32: case FieldType.Fixed32: + CheckInteger(value); return (uint) value; case FieldType.Int64: case FieldType.SInt64: case FieldType.SFixed64: + CheckInteger(value); return (long) value; case FieldType.UInt64: case FieldType.Fixed64: + CheckInteger(value); return (ulong) value; case FieldType.Double: return value; @@ -488,20 +640,37 @@ namespace Google.Protobuf { return float.NegativeInfinity; } - throw new InvalidProtocolBufferException("Value out of range: " + value); + throw new InvalidProtocolBufferException($"Value out of range: {value}"); } return (float) value; + case FieldType.Enum: + CheckInteger(value); + // Just return it as an int, and let the CLR convert it. + // Note that we deliberately don't check that it's a known value. + return (int) value; default: - throw new InvalidProtocolBufferException("Unsupported conversion from JSON number for field type " + field.FieldType); + throw new InvalidProtocolBufferException($"Unsupported conversion from JSON number for field type {field.FieldType}"); } } catch (OverflowException) { - throw new InvalidProtocolBufferException("Value out of range: " + value); + throw new InvalidProtocolBufferException($"Value out of range: {value}"); } } } + private static void CheckInteger(double value) + { + if (double.IsInfinity(value) || double.IsNaN(value)) + { + throw new InvalidProtocolBufferException($"Value not an integer: {value}"); + } + if (value != Math.Floor(value)) + { + throw new InvalidProtocolBufferException($"Value not an integer: {value}"); + } + } + private static object ParseSingleStringValue(FieldDescriptor field, string text) { switch (field.FieldType) @@ -509,47 +678,46 @@ namespace Google.Protobuf case FieldType.String: return text; case FieldType.Bytes: - return ByteString.FromBase64(text); + try + { + return ByteString.FromBase64(text); + } + catch (FormatException e) + { + throw InvalidProtocolBufferException.InvalidBase64(e); + } case FieldType.Int32: case FieldType.SInt32: case FieldType.SFixed32: - return ParseNumericString(text, int.Parse, false); + return ParseNumericString(text, int.Parse); case FieldType.UInt32: case FieldType.Fixed32: - return ParseNumericString(text, uint.Parse, false); + return ParseNumericString(text, uint.Parse); case FieldType.Int64: case FieldType.SInt64: case FieldType.SFixed64: - return ParseNumericString(text, long.Parse, false); + return ParseNumericString(text, long.Parse); case FieldType.UInt64: case FieldType.Fixed64: - return ParseNumericString(text, ulong.Parse, false); + return ParseNumericString(text, ulong.Parse); case FieldType.Double: - double d = ParseNumericString(text, double.Parse, true); - // double.Parse can return +/- infinity on Mono for non-infinite values which are out of range for double. - if (double.IsInfinity(d) && !text.Contains("Infinity")) - { - throw new InvalidProtocolBufferException("Invalid numeric value: " + text); - } + double d = ParseNumericString(text, double.Parse); + ValidateInfinityAndNan(text, double.IsPositiveInfinity(d), double.IsNegativeInfinity(d), double.IsNaN(d)); return d; case FieldType.Float: - float f = ParseNumericString(text, float.Parse, true); - // float.Parse can return +/- infinity on Mono for non-infinite values which are out of range for float. - if (float.IsInfinity(f) && !text.Contains("Infinity")) - { - throw new InvalidProtocolBufferException("Invalid numeric value: " + text); - } + float f = ParseNumericString(text, float.Parse); + ValidateInfinityAndNan(text, float.IsPositiveInfinity(f), float.IsNegativeInfinity(f), float.IsNaN(f)); return f; case FieldType.Enum: var enumValue = field.EnumType.FindValueByName(text); if (enumValue == null) { - throw new InvalidProtocolBufferException("Invalid enum value: " + text + " for enum type: " + field.EnumType.FullName); + throw new InvalidProtocolBufferException($"Invalid enum value: {text} for enum type: {field.EnumType.FullName}"); } // Just return it as an int, and let the CLR convert it. return enumValue.Number; default: - throw new InvalidProtocolBufferException("Unsupported conversion from JSON string for field type " + field.FieldType); + throw new InvalidProtocolBufferException($"Unsupported conversion from JSON string for field type {field.FieldType}"); } } @@ -561,43 +729,53 @@ namespace Google.Protobuf return field.MessageType.Parser.CreateTemplate(); } - private static T ParseNumericString<T>(string text, Func<string, NumberStyles, IFormatProvider, T> parser, bool floatingPoint) + private static T ParseNumericString<T>(string text, Func<string, NumberStyles, IFormatProvider, T> parser) { - // TODO: Prohibit leading zeroes (but allow 0!) - // TODO: Validate handling of "Infinity" etc. (Should be case sensitive, no leading whitespace etc) // Can't prohibit this with NumberStyles. if (text.StartsWith("+")) { - throw new InvalidProtocolBufferException("Invalid numeric value: " + text); + throw new InvalidProtocolBufferException($"Invalid numeric value: {text}"); } if (text.StartsWith("0") && text.Length > 1) { if (text[1] >= '0' && text[1] <= '9') { - throw new InvalidProtocolBufferException("Invalid numeric value: " + text); + throw new InvalidProtocolBufferException($"Invalid numeric value: {text}"); } } else if (text.StartsWith("-0") && text.Length > 2) { if (text[2] >= '0' && text[2] <= '9') { - throw new InvalidProtocolBufferException("Invalid numeric value: " + text); + throw new InvalidProtocolBufferException($"Invalid numeric value: {text}"); } } try { - var styles = floatingPoint - ? NumberStyles.AllowLeadingSign | NumberStyles.AllowDecimalPoint | NumberStyles.AllowExponent - : NumberStyles.AllowLeadingSign; - return parser(text, styles, CultureInfo.InvariantCulture); + return parser(text, NumberStyles.AllowLeadingSign | NumberStyles.AllowDecimalPoint | NumberStyles.AllowExponent, CultureInfo.InvariantCulture); } catch (FormatException) { - throw new InvalidProtocolBufferException("Invalid numeric value for type: " + text); + throw new InvalidProtocolBufferException($"Invalid numeric value for type: {text}"); } catch (OverflowException) { - throw new InvalidProtocolBufferException("Value out of range: " + text); + throw new InvalidProtocolBufferException($"Value out of range: {text}"); + } + } + + /// <summary> + /// Checks that any infinite/NaN values originated from the correct text. + /// This corrects the lenient whitespace handling of double.Parse/float.Parse, as well as the + /// way that Mono parses out-of-range values as infinity. + /// </summary> + private static void ValidateInfinityAndNan(string text, bool isPositiveInfinity, bool isNegativeInfinity, bool isNaN) + { + if ((isPositiveInfinity && text != "Infinity") || + (isNegativeInfinity && text != "-Infinity") || + (isNaN && text != "NaN")) + { + throw new InvalidProtocolBufferException($"Invalid numeric value: {text}"); } } @@ -610,7 +788,7 @@ namespace Google.Protobuf var match = TimestampRegex.Match(token.StringValue); if (!match.Success) { - throw new InvalidProtocolBufferException("Invalid Timestamp value: " + token.StringValue); + throw new InvalidProtocolBufferException($"Invalid Timestamp value: {token.StringValue}"); } var dateTime = match.Groups["datetime"].Value; var subseconds = match.Groups["subseconds"].Value; @@ -700,28 +878,24 @@ namespace Google.Protobuf try { - long seconds = long.Parse(secondsText, CultureInfo.InvariantCulture); + long seconds = long.Parse(secondsText, CultureInfo.InvariantCulture) * multiplier; int nanos = 0; if (subseconds != "") { // This should always work, as we've got 1-9 digits. int parsedFraction = int.Parse(subseconds.Substring(1)); - nanos = parsedFraction * SubsecondScalingFactors[subseconds.Length]; + nanos = parsedFraction * SubsecondScalingFactors[subseconds.Length] * multiplier; } - if (seconds >= Duration.MaxSeconds) + if (!Duration.IsNormalized(seconds, nanos)) { - // Allow precisely 315576000000 seconds, but prohibit even 1ns more. - if (seconds > Duration.MaxSeconds || nanos > 0) - { - throw new InvalidProtocolBufferException("Invalid Duration value: " + token.StringValue); - } + throw new InvalidProtocolBufferException($"Invalid Duration value: {token.StringValue}"); } - message.Descriptor.Fields[Duration.SecondsFieldNumber].Accessor.SetValue(message, seconds * multiplier); - message.Descriptor.Fields[Duration.NanosFieldNumber].Accessor.SetValue(message, nanos * multiplier); + message.Descriptor.Fields[Duration.SecondsFieldNumber].Accessor.SetValue(message, seconds); + message.Descriptor.Fields[Duration.NanosFieldNumber].Accessor.SetValue(message, nanos); } catch (FormatException) { - throw new InvalidProtocolBufferException("Invalid Duration value: " + token.StringValue); + throw new InvalidProtocolBufferException($"Invalid Duration value: {token.StringValue}"); } } @@ -744,6 +918,8 @@ namespace Google.Protobuf private static string ToSnakeCase(string text) { var builder = new StringBuilder(text.Length * 2); + // Note: this is probably unnecessary now, but currently retained to be as close as possible to the + // C++, whilst still throwing an exception on underscores. bool wasNotUnderscore = false; // Initialize to false for case 1 (below) bool wasNotCap = false; @@ -777,7 +953,11 @@ namespace Google.Protobuf else { builder.Append(c); - wasNotUnderscore = c != '_'; + if (c == '_') + { + throw new InvalidProtocolBufferException($"Invalid field mask: {text}"); + } + wasNotUnderscore = true; wasNotCap = true; } } @@ -790,29 +970,48 @@ namespace Google.Protobuf /// </summary> public sealed class Settings { - private static readonly Settings defaultInstance = new Settings(CodedInputStream.DefaultRecursionLimit); - - private readonly int recursionLimit; - /// <summary> - /// Default settings, as used by <see cref="JsonParser.Default"/> + /// Default settings, as used by <see cref="JsonParser.Default"/>. This has the same default + /// recursion limit as <see cref="CodedInputStream"/>, and an empty type registry. /// </summary> - public static Settings Default { get { return defaultInstance; } } + public static Settings Default { get; } + + // Workaround for the Mono compiler complaining about XML comments not being on + // valid language elements. + static Settings() + { + Default = new Settings(CodedInputStream.DefaultRecursionLimit); + } /// <summary> /// The maximum depth of messages to parse. Note that this limit only applies to parsing /// messages, not collections - so a message within a collection within a message only counts as /// depth 2, not 3. /// </summary> - public int RecursionLimit { get { return recursionLimit; } } + public int RecursionLimit { get; } + + /// <summary> + /// The type registry used to parse <see cref="Any"/> messages. + /// </summary> + public TypeRegistry TypeRegistry { get; } /// <summary> /// Creates a new <see cref="Settings"/> object with the specified recursion limit. /// </summary> /// <param name="recursionLimit">The maximum depth of messages to parse</param> - public Settings(int recursionLimit) + public Settings(int recursionLimit) : this(recursionLimit, TypeRegistry.Empty) + { + } + + /// <summary> + /// Creates a new <see cref="Settings"/> object with the specified recursion limit and type registry. + /// </summary> + /// <param name="recursionLimit">The maximum depth of messages to parse</param> + /// <param name="typeRegistry">The type registry used to parse <see cref="Any"/> messages</param> + public Settings(int recursionLimit, TypeRegistry typeRegistry) { - this.recursionLimit = recursionLimit; + RecursionLimit = recursionLimit; + TypeRegistry = ProtoPreconditions.CheckNotNull(typeRegistry, nameof(typeRegistry)); } } } diff --git a/csharp/src/Google.Protobuf/JsonTokenizer.cs b/csharp/src/Google.Protobuf/JsonTokenizer.cs index 6589427a..09a6d43b 100644 --- a/csharp/src/Google.Protobuf/JsonTokenizer.cs +++ b/csharp/src/Google.Protobuf/JsonTokenizer.cs @@ -47,32 +47,38 @@ namespace Google.Protobuf /// between values. It validates the token stream as it goes - so callers can assume that the /// tokens it produces are appropriate. For example, it would never produce "start object, end array." /// </para> + /// <para>Implementation details: the base class handles single token push-back and </para> /// <para>Not thread-safe.</para> /// </remarks> - internal sealed class JsonTokenizer + internal abstract class JsonTokenizer { - // The set of states in which a value is valid next token. - private static readonly State ValueStates = State.ArrayStart | State.ArrayAfterComma | State.ObjectAfterColon | State.StartOfDocument; - - private readonly Stack<ContainerType> containerStack = new Stack<ContainerType>(); - private readonly PushBackReader reader; private JsonToken bufferedToken; - private State state; - private int objectDepth = 0; /// <summary> - /// Returns the depth of the stack, purely in objects (not collections). - /// Informally, this is the number of remaining unclosed '{' characters we have. + /// Creates a tokenizer that reads from the given text reader. /// </summary> - internal int ObjectDepth { get { return objectDepth; } } + internal static JsonTokenizer FromTextReader(TextReader reader) + { + return new JsonTextTokenizer(reader); + } - internal JsonTokenizer(TextReader reader) + /// <summary> + /// Creates a tokenizer that first replays the given list of tokens, then continues reading + /// from another tokenizer. Note that if the returned tokenizer is "pushed back", that does not push back + /// on the continuation tokenizer, or vice versa. Care should be taken when using this method - it was + /// created for the sake of Any parsing. + /// </summary> + internal static JsonTokenizer FromReplayedTokens(IList<JsonToken> tokens, JsonTokenizer continuation) { - this.reader = new PushBackReader(reader); - state = State.StartOfDocument; - containerStack.Push(ContainerType.Document); + return new JsonReplayTokenizer(tokens, continuation); } + /// <summary> + /// Returns the depth of the stack, purely in objects (not collections). + /// Informally, this is the number of remaining unclosed '{' characters we have. + /// </summary> + internal int ObjectDepth { get; private set; } + // TODO: Why do we allow a different token to be pushed back? It might be better to always remember the previous // token returned, and allow a parameterless Rewind() method (which could only be called once, just like the current PushBack). internal void PushBack(JsonToken token) @@ -84,11 +90,11 @@ namespace Google.Protobuf bufferedToken = token; if (token.Type == JsonToken.TokenType.StartObject) { - objectDepth--; + ObjectDepth--; } else if (token.Type == JsonToken.TokenType.EndObject) { - objectDepth++; + ObjectDepth++; } } @@ -96,574 +102,636 @@ namespace Google.Protobuf /// Returns the next JSON token in the stream. An EndDocument token is returned to indicate the end of the stream, /// after which point <c>Next()</c> should not be called again. /// </summary> - /// <remarks> - /// This method essentially just loops through characters skipping whitespace, validating and - /// changing state (e.g. from ObjectBeforeColon to ObjectAfterColon) - /// until it reaches something which will be a genuine token (e.g. a start object, or a value) at which point - /// it returns the token. Although the method is large, it would be relatively hard to break down further... most - /// of it is the large switch statement, which sometimes returns and sometimes doesn't. - /// </remarks> + /// <remarks>This implementation provides single-token buffering, and calls <see cref="NextImpl"/> if there is no buffered token.</remarks> /// <returns>The next token in the stream. This is never null.</returns> /// <exception cref="InvalidOperationException">This method is called after an EndDocument token has been returned</exception> /// <exception cref="InvalidJsonException">The input text does not comply with RFC 7159</exception> internal JsonToken Next() { + JsonToken tokenToReturn; if (bufferedToken != null) { - var ret = bufferedToken; + tokenToReturn = bufferedToken; bufferedToken = null; - if (ret.Type == JsonToken.TokenType.StartObject) - { - objectDepth++; - } - else if (ret.Type == JsonToken.TokenType.EndObject) - { - objectDepth--; - } - return ret; } - if (state == State.ReaderExhausted) + else { - throw new InvalidOperationException("Next() called after end of document"); + tokenToReturn = NextImpl(); } - while (true) + if (tokenToReturn.Type == JsonToken.TokenType.StartObject) { - var next = reader.Read(); - if (next == null) - { - ValidateState(State.ExpectedEndOfDocument, "Unexpected end of document in state: "); - state = State.ReaderExhausted; - return JsonToken.EndDocument; - } - switch (next.Value) - { - // Skip whitespace between tokens - case ' ': - case '\t': - case '\r': - case '\n': - break; - case ':': - ValidateState(State.ObjectBeforeColon, "Invalid state to read a colon: "); - state = State.ObjectAfterColon; - break; - case ',': - ValidateState(State.ObjectAfterProperty | State.ArrayAfterValue, "Invalid state to read a colon: "); - state = state == State.ObjectAfterProperty ? State.ObjectAfterComma : State.ArrayAfterComma; - break; - case '"': - string stringValue = ReadString(); - if ((state & (State.ObjectStart | State.ObjectAfterComma)) != 0) - { - state = State.ObjectBeforeColon; - return JsonToken.Name(stringValue); - } - else - { - ValidateAndModifyStateForValue("Invalid state to read a double quote: "); - return JsonToken.Value(stringValue); - } - case '{': - ValidateState(ValueStates, "Invalid state to read an open brace: "); - state = State.ObjectStart; - containerStack.Push(ContainerType.Object); - objectDepth++; - return JsonToken.StartObject; - case '}': - ValidateState(State.ObjectAfterProperty | State.ObjectStart, "Invalid state to read a close brace: "); - PopContainer(); - objectDepth--; - return JsonToken.EndObject; - case '[': - ValidateState(ValueStates, "Invalid state to read an open square bracket: "); - state = State.ArrayStart; - containerStack.Push(ContainerType.Array); - return JsonToken.StartArray; - case ']': - ValidateState(State.ArrayAfterValue | State.ArrayStart, "Invalid state to read a close square bracket: "); - PopContainer(); - return JsonToken.EndArray; - case 'n': // Start of null - ConsumeLiteral("null"); - ValidateAndModifyStateForValue("Invalid state to read a null literal: "); - return JsonToken.Null; - case 't': // Start of true - ConsumeLiteral("true"); - ValidateAndModifyStateForValue("Invalid state to read a true literal: "); - return JsonToken.True; - case 'f': // Start of false - ConsumeLiteral("false"); - ValidateAndModifyStateForValue("Invalid state to read a false literal: "); - return JsonToken.False; - case '-': // Start of a number - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - double number = ReadNumber(next.Value); - ValidateAndModifyStateForValue("Invalid state to read a number token: "); - return JsonToken.Value(number); - default: - throw new InvalidJsonException("Invalid first character of token: " + next.Value); - } + ObjectDepth++; } - } - - private void ValidateState(State validStates, string errorPrefix) - { - if ((validStates & state) == 0) + else if (tokenToReturn.Type == JsonToken.TokenType.EndObject) { - throw reader.CreateException(errorPrefix + state); + ObjectDepth--; } + return tokenToReturn; } /// <summary> - /// Reads a string token. It is assumed that the opening " has already been read. + /// Returns the next JSON token in the stream, when requested by the base class. (The <see cref="Next"/> method delegates + /// to this if it doesn't have a buffered token.) /// </summary> - private string ReadString() - { - var value = new StringBuilder(); - bool haveHighSurrogate = false; - while (true) - { - char c = reader.ReadOrFail("Unexpected end of text while reading string"); - if (c < ' ') - { - throw reader.CreateException(string.Format(CultureInfo.InvariantCulture, "Invalid character in string literal: U+{0:x4}", (int) c)); - } - if (c == '"') - { - if (haveHighSurrogate) - { - throw reader.CreateException("Invalid use of surrogate pair code units"); - } - return value.ToString(); - } - if (c == '\\') - { - c = ReadEscapedCharacter(); - } - // TODO: Consider only allowing surrogate pairs that are either both escaped, - // or both not escaped. It would be a very odd text stream that contained a "lone" high surrogate - // followed by an escaped low surrogate or vice versa... and that couldn't even be represented in UTF-8. - if (haveHighSurrogate != char.IsLowSurrogate(c)) - { - throw reader.CreateException("Invalid use of surrogate pair code units"); - } - haveHighSurrogate = char.IsHighSurrogate(c); - value.Append(c); - } - } + /// <exception cref="InvalidOperationException">This method is called after an EndDocument token has been returned</exception> + /// <exception cref="InvalidJsonException">The input text does not comply with RFC 7159</exception> + protected abstract JsonToken NextImpl(); /// <summary> - /// Reads an escaped character. It is assumed that the leading backslash has already been read. + /// Tokenizer which first exhausts a list of tokens, then consults another tokenizer. /// </summary> - private char ReadEscapedCharacter() + private class JsonReplayTokenizer : JsonTokenizer { - char c = reader.ReadOrFail("Unexpected end of text while reading character escape sequence"); - switch (c) + private readonly IList<JsonToken> tokens; + private readonly JsonTokenizer nextTokenizer; + private int nextTokenIndex; + + internal JsonReplayTokenizer(IList<JsonToken> tokens, JsonTokenizer nextTokenizer) { - case 'n': - return '\n'; - case '\\': - return '\\'; - case 'b': - return '\b'; - case 'f': - return '\f'; - case 'r': - return '\r'; - case 't': - return '\t'; - case '"': - return '"'; - case '/': - return '/'; - case 'u': - return ReadUnicodeEscape(); - default: - throw reader.CreateException(string.Format(CultureInfo.InvariantCulture, "Invalid character in character escape sequence: U+{0:x4}", (int) c)); + this.tokens = tokens; + this.nextTokenizer = nextTokenizer; } - } - /// <summary> - /// Reads an escaped Unicode 4-nybble hex sequence. It is assumed that the leading \u has already been read. - /// </summary> - private char ReadUnicodeEscape() - { - int result = 0; - for (int i = 0; i < 4; i++) + // FIXME: Object depth not maintained... + protected override JsonToken NextImpl() { - char c = reader.ReadOrFail("Unexpected end of text while reading Unicode escape sequence"); - int nybble; - if (c >= '0' && c <= '9') + if (nextTokenIndex >= tokens.Count) { - nybble = c - '0'; + return nextTokenizer.Next(); } - else if (c >= 'a' && c <= 'f') - { - nybble = c - 'a' + 10; - } - else if (c >= 'A' && c <= 'F') - { - nybble = c - 'A' + 10; - } - else - { - throw reader.CreateException(string.Format(CultureInfo.InvariantCulture, "Invalid character in character escape sequence: U+{0:x4}", (int) c)); - } - result = (result << 4) + nybble; + return tokens[nextTokenIndex++]; } - return (char) result; } /// <summary> - /// Consumes a text-only literal, throwing an exception if the read text doesn't match it. - /// It is assumed that the first letter of the literal has already been read. + /// Tokenizer which does all the *real* work of parsing JSON. /// </summary> - private void ConsumeLiteral(string text) + private sealed class JsonTextTokenizer : JsonTokenizer { - for (int i = 1; i < text.Length; i++) + // The set of states in which a value is valid next token. + private static readonly State ValueStates = State.ArrayStart | State.ArrayAfterComma | State.ObjectAfterColon | State.StartOfDocument; + + private readonly Stack<ContainerType> containerStack = new Stack<ContainerType>(); + private readonly PushBackReader reader; + private State state; + + internal JsonTextTokenizer(TextReader reader) { - char? next = reader.Read(); - if (next == null) + this.reader = new PushBackReader(reader); + state = State.StartOfDocument; + containerStack.Push(ContainerType.Document); + } + + /// <remarks> + /// This method essentially just loops through characters skipping whitespace, validating and + /// changing state (e.g. from ObjectBeforeColon to ObjectAfterColon) + /// until it reaches something which will be a genuine token (e.g. a start object, or a value) at which point + /// it returns the token. Although the method is large, it would be relatively hard to break down further... most + /// of it is the large switch statement, which sometimes returns and sometimes doesn't. + /// </remarks> + protected override JsonToken NextImpl() + { + if (state == State.ReaderExhausted) { - throw reader.CreateException("Unexpected end of text while reading literal token " + text); + throw new InvalidOperationException("Next() called after end of document"); } - if (next.Value != text[i]) + while (true) { - throw reader.CreateException("Unexpected character while reading literal token " + text); + var next = reader.Read(); + if (next == null) + { + ValidateState(State.ExpectedEndOfDocument, "Unexpected end of document in state: "); + state = State.ReaderExhausted; + return JsonToken.EndDocument; + } + switch (next.Value) + { + // Skip whitespace between tokens + case ' ': + case '\t': + case '\r': + case '\n': + break; + case ':': + ValidateState(State.ObjectBeforeColon, "Invalid state to read a colon: "); + state = State.ObjectAfterColon; + break; + case ',': + ValidateState(State.ObjectAfterProperty | State.ArrayAfterValue, "Invalid state to read a colon: "); + state = state == State.ObjectAfterProperty ? State.ObjectAfterComma : State.ArrayAfterComma; + break; + case '"': + string stringValue = ReadString(); + if ((state & (State.ObjectStart | State.ObjectAfterComma)) != 0) + { + state = State.ObjectBeforeColon; + return JsonToken.Name(stringValue); + } + else + { + ValidateAndModifyStateForValue("Invalid state to read a double quote: "); + return JsonToken.Value(stringValue); + } + case '{': + ValidateState(ValueStates, "Invalid state to read an open brace: "); + state = State.ObjectStart; + containerStack.Push(ContainerType.Object); + return JsonToken.StartObject; + case '}': + ValidateState(State.ObjectAfterProperty | State.ObjectStart, "Invalid state to read a close brace: "); + PopContainer(); + return JsonToken.EndObject; + case '[': + ValidateState(ValueStates, "Invalid state to read an open square bracket: "); + state = State.ArrayStart; + containerStack.Push(ContainerType.Array); + return JsonToken.StartArray; + case ']': + ValidateState(State.ArrayAfterValue | State.ArrayStart, "Invalid state to read a close square bracket: "); + PopContainer(); + return JsonToken.EndArray; + case 'n': // Start of null + ConsumeLiteral("null"); + ValidateAndModifyStateForValue("Invalid state to read a null literal: "); + return JsonToken.Null; + case 't': // Start of true + ConsumeLiteral("true"); + ValidateAndModifyStateForValue("Invalid state to read a true literal: "); + return JsonToken.True; + case 'f': // Start of false + ConsumeLiteral("false"); + ValidateAndModifyStateForValue("Invalid state to read a false literal: "); + return JsonToken.False; + case '-': // Start of a number + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + double number = ReadNumber(next.Value); + ValidateAndModifyStateForValue("Invalid state to read a number token: "); + return JsonToken.Value(number); + default: + throw new InvalidJsonException("Invalid first character of token: " + next.Value); + } } } - } - private double ReadNumber(char initialCharacter) - { - StringBuilder builder = new StringBuilder(); - if (initialCharacter == '-') - { - builder.Append("-"); - } - else - { - reader.PushBack(initialCharacter); - } - // Each method returns the character it read that doesn't belong in that part, - // so we know what to do next, including pushing the character back at the end. - // null is returned for "end of text". - char? next = ReadInt(builder); - if (next == '.') + private void ValidateState(State validStates, string errorPrefix) { - next = ReadFrac(builder); - } - if (next == 'e' || next == 'E') - { - next = ReadExp(builder); - } - // If we read a character which wasn't part of the number, push it back so we can read it again - // to parse the next token. - if (next != null) - { - reader.PushBack(next.Value); + if ((validStates & state) == 0) + { + throw reader.CreateException(errorPrefix + state); + } } - // TODO: What exception should we throw if the value can't be represented as a double? - try - { - return double.Parse(builder.ToString(), - NumberStyles.AllowLeadingSign | NumberStyles.AllowDecimalPoint | NumberStyles.AllowExponent, - CultureInfo.InvariantCulture); - } - catch (OverflowException) + /// <summary> + /// Reads a string token. It is assumed that the opening " has already been read. + /// </summary> + private string ReadString() { - throw reader.CreateException("Numeric value out of range: " + builder); + var value = new StringBuilder(); + bool haveHighSurrogate = false; + while (true) + { + char c = reader.ReadOrFail("Unexpected end of text while reading string"); + if (c < ' ') + { + throw reader.CreateException(string.Format(CultureInfo.InvariantCulture, "Invalid character in string literal: U+{0:x4}", (int) c)); + } + if (c == '"') + { + if (haveHighSurrogate) + { + throw reader.CreateException("Invalid use of surrogate pair code units"); + } + return value.ToString(); + } + if (c == '\\') + { + c = ReadEscapedCharacter(); + } + // TODO: Consider only allowing surrogate pairs that are either both escaped, + // or both not escaped. It would be a very odd text stream that contained a "lone" high surrogate + // followed by an escaped low surrogate or vice versa... and that couldn't even be represented in UTF-8. + if (haveHighSurrogate != char.IsLowSurrogate(c)) + { + throw reader.CreateException("Invalid use of surrogate pair code units"); + } + haveHighSurrogate = char.IsHighSurrogate(c); + value.Append(c); + } } - } - private char? ReadInt(StringBuilder builder) - { - char first = reader.ReadOrFail("Invalid numeric literal"); - if (first < '0' || first > '9') - { - throw reader.CreateException("Invalid numeric literal"); - } - builder.Append(first); - int digitCount; - char? next = ConsumeDigits(builder, out digitCount); - if (first == '0' && digitCount != 0) + /// <summary> + /// Reads an escaped character. It is assumed that the leading backslash has already been read. + /// </summary> + private char ReadEscapedCharacter() { - throw reader.CreateException("Invalid numeric literal: leading 0 for non-zero value."); + char c = reader.ReadOrFail("Unexpected end of text while reading character escape sequence"); + switch (c) + { + case 'n': + return '\n'; + case '\\': + return '\\'; + case 'b': + return '\b'; + case 'f': + return '\f'; + case 'r': + return '\r'; + case 't': + return '\t'; + case '"': + return '"'; + case '/': + return '/'; + case 'u': + return ReadUnicodeEscape(); + default: + throw reader.CreateException(string.Format(CultureInfo.InvariantCulture, "Invalid character in character escape sequence: U+{0:x4}", (int) c)); + } } - return next; - } - private char? ReadFrac(StringBuilder builder) - { - builder.Append('.'); // Already consumed this - int digitCount; - char? next = ConsumeDigits(builder, out digitCount); - if (digitCount == 0) + /// <summary> + /// Reads an escaped Unicode 4-nybble hex sequence. It is assumed that the leading \u has already been read. + /// </summary> + private char ReadUnicodeEscape() { - throw reader.CreateException("Invalid numeric literal: fraction with no trailing digits"); + int result = 0; + for (int i = 0; i < 4; i++) + { + char c = reader.ReadOrFail("Unexpected end of text while reading Unicode escape sequence"); + int nybble; + if (c >= '0' && c <= '9') + { + nybble = c - '0'; + } + else if (c >= 'a' && c <= 'f') + { + nybble = c - 'a' + 10; + } + else if (c >= 'A' && c <= 'F') + { + nybble = c - 'A' + 10; + } + else + { + throw reader.CreateException(string.Format(CultureInfo.InvariantCulture, "Invalid character in character escape sequence: U+{0:x4}", (int) c)); + } + result = (result << 4) + nybble; + } + return (char) result; } - return next; - } - private char? ReadExp(StringBuilder builder) - { - builder.Append('E'); // Already consumed this (or 'e') - char? next = reader.Read(); - if (next == null) + /// <summary> + /// Consumes a text-only literal, throwing an exception if the read text doesn't match it. + /// It is assumed that the first letter of the literal has already been read. + /// </summary> + private void ConsumeLiteral(string text) { - throw reader.CreateException("Invalid numeric literal: exponent with no trailing digits"); + for (int i = 1; i < text.Length; i++) + { + char? next = reader.Read(); + if (next == null) + { + throw reader.CreateException("Unexpected end of text while reading literal token " + text); + } + if (next.Value != text[i]) + { + throw reader.CreateException("Unexpected character while reading literal token " + text); + } + } } - if (next == '-' || next == '+') + + private double ReadNumber(char initialCharacter) { - builder.Append(next.Value); + StringBuilder builder = new StringBuilder(); + if (initialCharacter == '-') + { + builder.Append("-"); + } + else + { + reader.PushBack(initialCharacter); + } + // Each method returns the character it read that doesn't belong in that part, + // so we know what to do next, including pushing the character back at the end. + // null is returned for "end of text". + char? next = ReadInt(builder); + if (next == '.') + { + next = ReadFrac(builder); + } + if (next == 'e' || next == 'E') + { + next = ReadExp(builder); + } + // If we read a character which wasn't part of the number, push it back so we can read it again + // to parse the next token. + if (next != null) + { + reader.PushBack(next.Value); + } + + // TODO: What exception should we throw if the value can't be represented as a double? + try + { + return double.Parse(builder.ToString(), + NumberStyles.AllowLeadingSign | NumberStyles.AllowDecimalPoint | NumberStyles.AllowExponent, + CultureInfo.InvariantCulture); + } + catch (OverflowException) + { + throw reader.CreateException("Numeric value out of range: " + builder); + } } - else + + private char? ReadInt(StringBuilder builder) { - reader.PushBack(next.Value); + char first = reader.ReadOrFail("Invalid numeric literal"); + if (first < '0' || first > '9') + { + throw reader.CreateException("Invalid numeric literal"); + } + builder.Append(first); + int digitCount; + char? next = ConsumeDigits(builder, out digitCount); + if (first == '0' && digitCount != 0) + { + throw reader.CreateException("Invalid numeric literal: leading 0 for non-zero value."); + } + return next; } - int digitCount; - next = ConsumeDigits(builder, out digitCount); - if (digitCount == 0) + + private char? ReadFrac(StringBuilder builder) { - throw reader.CreateException("Invalid numeric literal: exponent without value"); + builder.Append('.'); // Already consumed this + int digitCount; + char? next = ConsumeDigits(builder, out digitCount); + if (digitCount == 0) + { + throw reader.CreateException("Invalid numeric literal: fraction with no trailing digits"); + } + return next; } - return next; - } - private char? ConsumeDigits(StringBuilder builder, out int count) - { - count = 0; - while (true) + private char? ReadExp(StringBuilder builder) { + builder.Append('E'); // Already consumed this (or 'e') char? next = reader.Read(); - if (next == null || next.Value < '0' || next.Value > '9') + if (next == null) + { + throw reader.CreateException("Invalid numeric literal: exponent with no trailing digits"); + } + if (next == '-' || next == '+') { - return next; + builder.Append(next.Value); } - count++; - builder.Append(next.Value); + else + { + reader.PushBack(next.Value); + } + int digitCount; + next = ConsumeDigits(builder, out digitCount); + if (digitCount == 0) + { + throw reader.CreateException("Invalid numeric literal: exponent without value"); + } + return next; } - } - /// <summary> - /// Validates that we're in a valid state to read a value (using the given error prefix if necessary) - /// and changes the state to the appropriate one, e.g. ObjectAfterColon to ObjectAfterProperty. - /// </summary> - private void ValidateAndModifyStateForValue(string errorPrefix) - { - ValidateState(ValueStates, errorPrefix); - switch (state) + private char? ConsumeDigits(StringBuilder builder, out int count) { - case State.StartOfDocument: - state = State.ExpectedEndOfDocument; - return; - case State.ObjectAfterColon: - state = State.ObjectAfterProperty; - return; - case State.ArrayStart: - case State.ArrayAfterComma: - state = State.ArrayAfterValue; - return; - default: - throw new InvalidOperationException("ValidateAndModifyStateForValue does not handle all value states (and should)"); + count = 0; + while (true) + { + char? next = reader.Read(); + if (next == null || next.Value < '0' || next.Value > '9') + { + return next; + } + count++; + builder.Append(next.Value); + } } - } - /// <summary> - /// Pops the top-most container, and sets the state to the appropriate one for the end of a value - /// in the parent container. - /// </summary> - private void PopContainer() - { - containerStack.Pop(); - var parent = containerStack.Peek(); - switch (parent) + /// <summary> + /// Validates that we're in a valid state to read a value (using the given error prefix if necessary) + /// and changes the state to the appropriate one, e.g. ObjectAfterColon to ObjectAfterProperty. + /// </summary> + private void ValidateAndModifyStateForValue(string errorPrefix) { - case ContainerType.Object: - state = State.ObjectAfterProperty; - break; - case ContainerType.Array: - state = State.ArrayAfterValue; - break; - case ContainerType.Document: - state = State.ExpectedEndOfDocument; - break; - default: - throw new InvalidOperationException("Unexpected container type: " + parent); + ValidateState(ValueStates, errorPrefix); + switch (state) + { + case State.StartOfDocument: + state = State.ExpectedEndOfDocument; + return; + case State.ObjectAfterColon: + state = State.ObjectAfterProperty; + return; + case State.ArrayStart: + case State.ArrayAfterComma: + state = State.ArrayAfterValue; + return; + default: + throw new InvalidOperationException("ValidateAndModifyStateForValue does not handle all value states (and should)"); + } } - } - private enum ContainerType - { - Document, Object, Array - } - - /// <summary> - /// Possible states of the tokenizer. - /// </summary> - /// <remarks> - /// <para>This is a flags enum purely so we can simply and efficiently represent a set of valid states - /// for checking.</para> - /// <para> - /// Each is documented with an example, - /// where ^ represents the current position within the text stream. The examples all use string values, - /// but could be any value, including nested objects/arrays. - /// The complete state of the tokenizer also includes a stack to indicate the contexts (arrays/objects). - /// Any additional notional state of "AfterValue" indicates that a value has been completed, at which - /// point there's an immediate transition to ExpectedEndOfDocument, ObjectAfterProperty or ArrayAfterValue. - /// </para> - /// <para> - /// These states were derived manually by reading RFC 7159 carefully. - /// </para> - /// </remarks> - [Flags] - private enum State - { - /// <summary> - /// ^ { "foo": "bar" } - /// Before the value in a document. Next states: ObjectStart, ArrayStart, "AfterValue" - /// </summary> - StartOfDocument = 1 << 0, - /// <summary> - /// { "foo": "bar" } ^ - /// After the value in a document. Next states: ReaderExhausted - /// </summary> - ExpectedEndOfDocument = 1 << 1, - /// <summary> - /// { "foo": "bar" } ^ (and already read to the end of the reader) - /// Terminal state. - /// </summary> - ReaderExhausted = 1 << 2, - /// <summary> - /// { ^ "foo": "bar" } - /// Before the *first* property in an object. - /// Next states: - /// "AfterValue" (empty object) - /// ObjectBeforeColon (read a name) - /// </summary> - ObjectStart = 1 << 3, - /// <summary> - /// { "foo" ^ : "bar", "x": "y" } - /// Next state: ObjectAfterColon - /// </summary> - ObjectBeforeColon = 1 << 4, - /// <summary> - /// { "foo" : ^ "bar", "x": "y" } - /// Before any property other than the first in an object. - /// (Equivalently: after any property in an object) - /// Next states: - /// "AfterValue" (value is simple) - /// ObjectStart (value is object) - /// ArrayStart (value is array) - /// </summary> - ObjectAfterColon = 1 << 5, - /// <summary> - /// { "foo" : "bar" ^ , "x" : "y" } - /// At the end of a property, so expecting either a comma or end-of-object - /// Next states: ObjectAfterComma or "AfterValue" - /// </summary> - ObjectAfterProperty = 1 << 6, - /// <summary> - /// { "foo":"bar", ^ "x":"y" } - /// Read the comma after the previous property, so expecting another property. - /// This is like ObjectStart, but closing brace isn't valid here - /// Next state: ObjectBeforeColon. - /// </summary> - ObjectAfterComma = 1 << 7, - /// <summary> - /// [ ^ "foo", "bar" ] - /// Before the *first* value in an array. - /// Next states: - /// "AfterValue" (read a value) - /// "AfterValue" (end of array; will pop stack) - /// </summary> - ArrayStart = 1 << 8, - /// <summary> - /// [ "foo" ^ , "bar" ] - /// After any value in an array, so expecting either a comma or end-of-array - /// Next states: ArrayAfterComma or "AfterValue" - /// </summary> - ArrayAfterValue = 1 << 9, /// <summary> - /// [ "foo", ^ "bar" ] - /// After a comma in an array, so there *must* be another value (simple or complex). - /// Next states: "AfterValue" (simple value), StartObject, StartArray + /// Pops the top-most container, and sets the state to the appropriate one for the end of a value + /// in the parent container. /// </summary> - ArrayAfterComma = 1 << 10 - } - - /// <summary> - /// Wrapper around a text reader allowing small amounts of buffering and location handling. - /// </summary> - private class PushBackReader - { - // TODO: Add locations for errors etc. - - private readonly TextReader reader; + private void PopContainer() + { + containerStack.Pop(); + var parent = containerStack.Peek(); + switch (parent) + { + case ContainerType.Object: + state = State.ObjectAfterProperty; + break; + case ContainerType.Array: + state = State.ArrayAfterValue; + break; + case ContainerType.Document: + state = State.ExpectedEndOfDocument; + break; + default: + throw new InvalidOperationException("Unexpected container type: " + parent); + } + } - internal PushBackReader(TextReader reader) + private enum ContainerType { - // TODO: Wrap the reader in a BufferedReader? - this.reader = reader; + Document, Object, Array } /// <summary> - /// The buffered next character, if we have one. + /// Possible states of the tokenizer. /// </summary> - private char? nextChar; + /// <remarks> + /// <para>This is a flags enum purely so we can simply and efficiently represent a set of valid states + /// for checking.</para> + /// <para> + /// Each is documented with an example, + /// where ^ represents the current position within the text stream. The examples all use string values, + /// but could be any value, including nested objects/arrays. + /// The complete state of the tokenizer also includes a stack to indicate the contexts (arrays/objects). + /// Any additional notional state of "AfterValue" indicates that a value has been completed, at which + /// point there's an immediate transition to ExpectedEndOfDocument, ObjectAfterProperty or ArrayAfterValue. + /// </para> + /// <para> + /// These states were derived manually by reading RFC 7159 carefully. + /// </para> + /// </remarks> + [Flags] + private enum State + { + /// <summary> + /// ^ { "foo": "bar" } + /// Before the value in a document. Next states: ObjectStart, ArrayStart, "AfterValue" + /// </summary> + StartOfDocument = 1 << 0, + /// <summary> + /// { "foo": "bar" } ^ + /// After the value in a document. Next states: ReaderExhausted + /// </summary> + ExpectedEndOfDocument = 1 << 1, + /// <summary> + /// { "foo": "bar" } ^ (and already read to the end of the reader) + /// Terminal state. + /// </summary> + ReaderExhausted = 1 << 2, + /// <summary> + /// { ^ "foo": "bar" } + /// Before the *first* property in an object. + /// Next states: + /// "AfterValue" (empty object) + /// ObjectBeforeColon (read a name) + /// </summary> + ObjectStart = 1 << 3, + /// <summary> + /// { "foo" ^ : "bar", "x": "y" } + /// Next state: ObjectAfterColon + /// </summary> + ObjectBeforeColon = 1 << 4, + /// <summary> + /// { "foo" : ^ "bar", "x": "y" } + /// Before any property other than the first in an object. + /// (Equivalently: after any property in an object) + /// Next states: + /// "AfterValue" (value is simple) + /// ObjectStart (value is object) + /// ArrayStart (value is array) + /// </summary> + ObjectAfterColon = 1 << 5, + /// <summary> + /// { "foo" : "bar" ^ , "x" : "y" } + /// At the end of a property, so expecting either a comma or end-of-object + /// Next states: ObjectAfterComma or "AfterValue" + /// </summary> + ObjectAfterProperty = 1 << 6, + /// <summary> + /// { "foo":"bar", ^ "x":"y" } + /// Read the comma after the previous property, so expecting another property. + /// This is like ObjectStart, but closing brace isn't valid here + /// Next state: ObjectBeforeColon. + /// </summary> + ObjectAfterComma = 1 << 7, + /// <summary> + /// [ ^ "foo", "bar" ] + /// Before the *first* value in an array. + /// Next states: + /// "AfterValue" (read a value) + /// "AfterValue" (end of array; will pop stack) + /// </summary> + ArrayStart = 1 << 8, + /// <summary> + /// [ "foo" ^ , "bar" ] + /// After any value in an array, so expecting either a comma or end-of-array + /// Next states: ArrayAfterComma or "AfterValue" + /// </summary> + ArrayAfterValue = 1 << 9, + /// <summary> + /// [ "foo", ^ "bar" ] + /// After a comma in an array, so there *must* be another value (simple or complex). + /// Next states: "AfterValue" (simple value), StartObject, StartArray + /// </summary> + ArrayAfterComma = 1 << 10 + } /// <summary> - /// Returns the next character in the stream, or null if we have reached the end. + /// Wrapper around a text reader allowing small amounts of buffering and location handling. /// </summary> - /// <returns></returns> - internal char? Read() + private class PushBackReader { - if (nextChar != null) + // TODO: Add locations for errors etc. + + private readonly TextReader reader; + + internal PushBackReader(TextReader reader) { - char? tmp = nextChar; - nextChar = null; - return tmp; + // TODO: Wrap the reader in a BufferedReader? + this.reader = reader; } - int next = reader.Read(); - return next == -1 ? null : (char?) next; - } - internal char ReadOrFail(string messageOnFailure) - { - char? next = Read(); - if (next == null) + /// <summary> + /// The buffered next character, if we have one. + /// </summary> + private char? nextChar; + + /// <summary> + /// Returns the next character in the stream, or null if we have reached the end. + /// </summary> + /// <returns></returns> + internal char? Read() { - throw CreateException(messageOnFailure); + if (nextChar != null) + { + char? tmp = nextChar; + nextChar = null; + return tmp; + } + int next = reader.Read(); + return next == -1 ? null : (char?) next; } - return next.Value; - } - internal void PushBack(char c) - { - if (nextChar != null) + internal char ReadOrFail(string messageOnFailure) { - throw new InvalidOperationException("Cannot push back when already buffering a character"); + char? next = Read(); + if (next == null) + { + throw CreateException(messageOnFailure); + } + return next.Value; } - nextChar = c; - } - /// <summary> - /// Creates a new exception appropriate for the current state of the reader. - /// </summary> - internal InvalidJsonException CreateException(string message) - { - // TODO: Keep track of and use the location. - return new InvalidJsonException(message); + internal void PushBack(char c) + { + if (nextChar != null) + { + throw new InvalidOperationException("Cannot push back when already buffering a character"); + } + nextChar = c; + } + + /// <summary> + /// Creates a new exception appropriate for the current state of the reader. + /// </summary> + internal InvalidJsonException CreateException(string message) + { + // TODO: Keep track of and use the location. + return new InvalidJsonException(message); + } } } } diff --git a/csharp/src/Google.Protobuf/MessageExtensions.cs b/csharp/src/Google.Protobuf/MessageExtensions.cs index d2d057c0..047156c3 100644 --- a/csharp/src/Google.Protobuf/MessageExtensions.cs +++ b/csharp/src/Google.Protobuf/MessageExtensions.cs @@ -46,8 +46,8 @@ namespace Google.Protobuf /// <param name="data">The data to merge, which must be protobuf-encoded binary data.</param> public static void MergeFrom(this IMessage message, byte[] data) { - Preconditions.CheckNotNull(message, "message"); - Preconditions.CheckNotNull(data, "data"); + ProtoPreconditions.CheckNotNull(message, "message"); + ProtoPreconditions.CheckNotNull(data, "data"); CodedInputStream input = new CodedInputStream(data); message.MergeFrom(input); input.CheckReadEndOfStreamTag(); @@ -60,8 +60,8 @@ namespace Google.Protobuf /// <param name="data">The data to merge, which must be protobuf-encoded binary data.</param> public static void MergeFrom(this IMessage message, ByteString data) { - Preconditions.CheckNotNull(message, "message"); - Preconditions.CheckNotNull(data, "data"); + ProtoPreconditions.CheckNotNull(message, "message"); + ProtoPreconditions.CheckNotNull(data, "data"); CodedInputStream input = data.CreateCodedInput(); message.MergeFrom(input); input.CheckReadEndOfStreamTag(); @@ -74,8 +74,8 @@ namespace Google.Protobuf /// <param name="input">Stream containing the data to merge, which must be protobuf-encoded binary data.</param> public static void MergeFrom(this IMessage message, Stream input) { - Preconditions.CheckNotNull(message, "message"); - Preconditions.CheckNotNull(input, "input"); + ProtoPreconditions.CheckNotNull(message, "message"); + ProtoPreconditions.CheckNotNull(input, "input"); CodedInputStream codedInput = new CodedInputStream(input); message.MergeFrom(codedInput); codedInput.CheckReadEndOfStreamTag(); @@ -92,8 +92,8 @@ namespace Google.Protobuf /// <param name="input">Stream containing the data to merge, which must be protobuf-encoded binary data.</param> public static void MergeDelimitedFrom(this IMessage message, Stream input) { - Preconditions.CheckNotNull(message, "message"); - Preconditions.CheckNotNull(input, "input"); + ProtoPreconditions.CheckNotNull(message, "message"); + ProtoPreconditions.CheckNotNull(input, "input"); int size = (int) CodedInputStream.ReadRawVarint32(input); Stream limitedStream = new LimitedInputStream(input, size); message.MergeFrom(limitedStream); @@ -106,7 +106,7 @@ namespace Google.Protobuf /// <returns>The message data as a byte array.</returns> public static byte[] ToByteArray(this IMessage message) { - Preconditions.CheckNotNull(message, "message"); + ProtoPreconditions.CheckNotNull(message, "message"); byte[] result = new byte[message.CalculateSize()]; CodedOutputStream output = new CodedOutputStream(result); message.WriteTo(output); @@ -121,8 +121,8 @@ namespace Google.Protobuf /// <param name="output">The stream to write to.</param> public static void WriteTo(this IMessage message, Stream output) { - Preconditions.CheckNotNull(message, "message"); - Preconditions.CheckNotNull(output, "output"); + ProtoPreconditions.CheckNotNull(message, "message"); + ProtoPreconditions.CheckNotNull(output, "output"); CodedOutputStream codedOutput = new CodedOutputStream(output); message.WriteTo(codedOutput); codedOutput.Flush(); @@ -135,8 +135,8 @@ namespace Google.Protobuf /// <param name="output">The output stream to write to.</param> public static void WriteDelimitedTo(this IMessage message, Stream output) { - Preconditions.CheckNotNull(message, "message"); - Preconditions.CheckNotNull(output, "output"); + ProtoPreconditions.CheckNotNull(message, "message"); + ProtoPreconditions.CheckNotNull(output, "output"); CodedOutputStream codedOutput = new CodedOutputStream(output); codedOutput.WriteRawVarint32((uint)message.CalculateSize()); message.WriteTo(codedOutput); @@ -150,7 +150,7 @@ namespace Google.Protobuf /// <returns>The message data as a byte string.</returns> public static ByteString ToByteString(this IMessage message) { - Preconditions.CheckNotNull(message, "message"); + ProtoPreconditions.CheckNotNull(message, "message"); return ByteString.AttachBytes(message.ToByteArray()); } } diff --git a/csharp/src/Google.Protobuf/MessageParser.cs b/csharp/src/Google.Protobuf/MessageParser.cs index 81be3c2a..8889638b 100644 --- a/csharp/src/Google.Protobuf/MessageParser.cs +++ b/csharp/src/Google.Protobuf/MessageParser.cs @@ -64,7 +64,7 @@ namespace Google.Protobuf /// <returns>The newly parsed message.</returns> public IMessage ParseFrom(byte[] data) { - Preconditions.CheckNotNull(data, "data"); + ProtoPreconditions.CheckNotNull(data, "data"); IMessage message = factory(); message.MergeFrom(data); return message; @@ -77,7 +77,7 @@ namespace Google.Protobuf /// <returns>The parsed message.</returns> public IMessage ParseFrom(ByteString data) { - Preconditions.CheckNotNull(data, "data"); + ProtoPreconditions.CheckNotNull(data, "data"); IMessage message = factory(); message.MergeFrom(data); return message; @@ -191,7 +191,7 @@ namespace Google.Protobuf /// <returns>The newly parsed message.</returns> public new T ParseFrom(byte[] data) { - Preconditions.CheckNotNull(data, "data"); + ProtoPreconditions.CheckNotNull(data, "data"); T message = factory(); message.MergeFrom(data); return message; @@ -204,7 +204,7 @@ namespace Google.Protobuf /// <returns>The parsed message.</returns> public new T ParseFrom(ByteString data) { - Preconditions.CheckNotNull(data, "data"); + ProtoPreconditions.CheckNotNull(data, "data"); T message = factory(); message.MergeFrom(data); return message; diff --git a/csharp/src/Google.Protobuf/Preconditions.cs b/csharp/src/Google.Protobuf/ProtoPreconditions.cs index 2db35ff6..abaeb9b4 100644 --- a/csharp/src/Google.Protobuf/Preconditions.cs +++ b/csharp/src/Google.Protobuf/ProtoPreconditions.cs @@ -35,9 +35,14 @@ using System; namespace Google.Protobuf { /// <summary> - /// Helper methods for throwing exceptions + /// Helper methods for throwing exceptions when preconditions are not met. /// </summary> - public static class Preconditions + /// <remarks> + /// This class is used internally and by generated code; it is not particularly + /// expected to be used from application code, although nothing prevents it + /// from being used that way. + /// </remarks> + public static class ProtoPreconditions { /// <summary> /// Throws an ArgumentNullException if the given value is null, otherwise diff --git a/csharp/src/Google.Protobuf/Reflection/Descriptor.cs b/csharp/src/Google.Protobuf/Reflection/Descriptor.cs index 34bc82ec..7de7b5fc 100644 --- a/csharp/src/Google.Protobuf/Reflection/Descriptor.cs +++ b/csharp/src/Google.Protobuf/Reflection/Descriptor.cs @@ -80,7 +80,7 @@ namespace Google.Protobuf.Reflection { "EhMKC291dHB1dF90eXBlGAMgASgJEi8KB29wdGlvbnMYBCABKAsyHi5nb29n", "bGUucHJvdG9idWYuTWV0aG9kT3B0aW9ucxIfChBjbGllbnRfc3RyZWFtaW5n", "GAUgASgIOgVmYWxzZRIfChBzZXJ2ZXJfc3RyZWFtaW5nGAYgASgIOgVmYWxz", - "ZSKqBQoLRmlsZU9wdGlvbnMSFAoMamF2YV9wYWNrYWdlGAEgASgJEhwKFGph", + "ZSKuBQoLRmlsZU9wdGlvbnMSFAoMamF2YV9wYWNrYWdlGAEgASgJEhwKFGph", "dmFfb3V0ZXJfY2xhc3NuYW1lGAggASgJEiIKE2phdmFfbXVsdGlwbGVfZmls", "ZXMYCiABKAg6BWZhbHNlEiwKHWphdmFfZ2VuZXJhdGVfZXF1YWxzX2FuZF9o", "YXNoGBQgASgIOgVmYWxzZRIlChZqYXZhX3N0cmluZ19jaGVja191dGY4GBsg", @@ -91,72 +91,77 @@ namespace Google.Protobuf.Reflection { "cHlfZ2VuZXJpY19zZXJ2aWNlcxgSIAEoCDoFZmFsc2USGQoKZGVwcmVjYXRl", "ZBgXIAEoCDoFZmFsc2USHwoQY2NfZW5hYmxlX2FyZW5hcxgfIAEoCDoFZmFs", "c2USGQoRb2JqY19jbGFzc19wcmVmaXgYJCABKAkSGAoQY3NoYXJwX25hbWVz", - "cGFjZRglIAEoCRInCh9qYXZhbmFub191c2VfZGVwcmVjYXRlZF9wYWNrYWdl", - "GCYgASgIEkMKFHVuaW50ZXJwcmV0ZWRfb3B0aW9uGOcHIAMoCzIkLmdvb2ds", - "ZS5wcm90b2J1Zi5VbmludGVycHJldGVkT3B0aW9uIjoKDE9wdGltaXplTW9k", - "ZRIJCgVTUEVFRBABEg0KCUNPREVfU0laRRACEhAKDExJVEVfUlVOVElNRRAD", - "KgkI6AcQgICAgAIi5gEKDk1lc3NhZ2VPcHRpb25zEiYKF21lc3NhZ2Vfc2V0", - "X3dpcmVfZm9ybWF0GAEgASgIOgVmYWxzZRIuCh9ub19zdGFuZGFyZF9kZXNj", - "cmlwdG9yX2FjY2Vzc29yGAIgASgIOgVmYWxzZRIZCgpkZXByZWNhdGVkGAMg", - "ASgIOgVmYWxzZRIRCgltYXBfZW50cnkYByABKAgSQwoUdW5pbnRlcnByZXRl", - "ZF9vcHRpb24Y5wcgAygLMiQuZ29vZ2xlLnByb3RvYnVmLlVuaW50ZXJwcmV0", - "ZWRPcHRpb24qCQjoBxCAgICAAiKYAwoMRmllbGRPcHRpb25zEjoKBWN0eXBl", - "GAEgASgOMiMuZ29vZ2xlLnByb3RvYnVmLkZpZWxkT3B0aW9ucy5DVHlwZToG", - "U1RSSU5HEg4KBnBhY2tlZBgCIAEoCBI/CgZqc3R5cGUYBiABKA4yJC5nb29n", - "bGUucHJvdG9idWYuRmllbGRPcHRpb25zLkpTVHlwZToJSlNfTk9STUFMEhMK", - "BGxhenkYBSABKAg6BWZhbHNlEhkKCmRlcHJlY2F0ZWQYAyABKAg6BWZhbHNl", - "EhMKBHdlYWsYCiABKAg6BWZhbHNlEkMKFHVuaW50ZXJwcmV0ZWRfb3B0aW9u", - "GOcHIAMoCzIkLmdvb2dsZS5wcm90b2J1Zi5VbmludGVycHJldGVkT3B0aW9u", - "Ii8KBUNUeXBlEgoKBlNUUklORxAAEggKBENPUkQQARIQCgxTVFJJTkdfUElF", - "Q0UQAiI1CgZKU1R5cGUSDQoJSlNfTk9STUFMEAASDQoJSlNfU1RSSU5HEAES", - "DQoJSlNfTlVNQkVSEAIqCQjoBxCAgICAAiKNAQoLRW51bU9wdGlvbnMSEwoL", - "YWxsb3dfYWxpYXMYAiABKAgSGQoKZGVwcmVjYXRlZBgDIAEoCDoFZmFsc2US", - "QwoUdW5pbnRlcnByZXRlZF9vcHRpb24Y5wcgAygLMiQuZ29vZ2xlLnByb3Rv", - "YnVmLlVuaW50ZXJwcmV0ZWRPcHRpb24qCQjoBxCAgICAAiJ9ChBFbnVtVmFs", - "dWVPcHRpb25zEhkKCmRlcHJlY2F0ZWQYASABKAg6BWZhbHNlEkMKFHVuaW50", - "ZXJwcmV0ZWRfb3B0aW9uGOcHIAMoCzIkLmdvb2dsZS5wcm90b2J1Zi5Vbmlu", - "dGVycHJldGVkT3B0aW9uKgkI6AcQgICAgAIiewoOU2VydmljZU9wdGlvbnMS", - "GQoKZGVwcmVjYXRlZBghIAEoCDoFZmFsc2USQwoUdW5pbnRlcnByZXRlZF9v", - "cHRpb24Y5wcgAygLMiQuZ29vZ2xlLnByb3RvYnVmLlVuaW50ZXJwcmV0ZWRP", - "cHRpb24qCQjoBxCAgICAAiJ6Cg1NZXRob2RPcHRpb25zEhkKCmRlcHJlY2F0", - "ZWQYISABKAg6BWZhbHNlEkMKFHVuaW50ZXJwcmV0ZWRfb3B0aW9uGOcHIAMo", - "CzIkLmdvb2dsZS5wcm90b2J1Zi5VbmludGVycHJldGVkT3B0aW9uKgkI6AcQ", - "gICAgAIingIKE1VuaW50ZXJwcmV0ZWRPcHRpb24SOwoEbmFtZRgCIAMoCzIt", - "Lmdvb2dsZS5wcm90b2J1Zi5VbmludGVycHJldGVkT3B0aW9uLk5hbWVQYXJ0", - "EhgKEGlkZW50aWZpZXJfdmFsdWUYAyABKAkSGgoScG9zaXRpdmVfaW50X3Zh", - "bHVlGAQgASgEEhoKEm5lZ2F0aXZlX2ludF92YWx1ZRgFIAEoAxIUCgxkb3Vi", - "bGVfdmFsdWUYBiABKAESFAoMc3RyaW5nX3ZhbHVlGAcgASgMEhcKD2FnZ3Jl", - "Z2F0ZV92YWx1ZRgIIAEoCRozCghOYW1lUGFydBIRCgluYW1lX3BhcnQYASAC", - "KAkSFAoMaXNfZXh0ZW5zaW9uGAIgAigIItUBCg5Tb3VyY2VDb2RlSW5mbxI6", - "Cghsb2NhdGlvbhgBIAMoCzIoLmdvb2dsZS5wcm90b2J1Zi5Tb3VyY2VDb2Rl", - "SW5mby5Mb2NhdGlvbhqGAQoITG9jYXRpb24SEAoEcGF0aBgBIAMoBUICEAES", - "EAoEc3BhbhgCIAMoBUICEAESGAoQbGVhZGluZ19jb21tZW50cxgDIAEoCRIZ", - "ChF0cmFpbGluZ19jb21tZW50cxgEIAEoCRIhChlsZWFkaW5nX2RldGFjaGVk", - "X2NvbW1lbnRzGAYgAygJQlgKE2NvbS5nb29nbGUucHJvdG9idWZCEERlc2Ny", - "aXB0b3JQcm90b3NIAVoKZGVzY3JpcHRvcqICA0dQQqoCGkdvb2dsZS5Qcm90", - "b2J1Zi5SZWZsZWN0aW9u")); - descriptor = pbr::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData, + "cGFjZRglIAEoCRIrCh9qYXZhbmFub191c2VfZGVwcmVjYXRlZF9wYWNrYWdl", + "GCYgASgIQgIYARJDChR1bmludGVycHJldGVkX29wdGlvbhjnByADKAsyJC5n", + "b29nbGUucHJvdG9idWYuVW5pbnRlcnByZXRlZE9wdGlvbiI6CgxPcHRpbWl6", + "ZU1vZGUSCQoFU1BFRUQQARINCglDT0RFX1NJWkUQAhIQCgxMSVRFX1JVTlRJ", + "TUUQAyoJCOgHEICAgIACIuYBCg5NZXNzYWdlT3B0aW9ucxImChdtZXNzYWdl", + "X3NldF93aXJlX2Zvcm1hdBgBIAEoCDoFZmFsc2USLgofbm9fc3RhbmRhcmRf", + "ZGVzY3JpcHRvcl9hY2Nlc3NvchgCIAEoCDoFZmFsc2USGQoKZGVwcmVjYXRl", + "ZBgDIAEoCDoFZmFsc2USEQoJbWFwX2VudHJ5GAcgASgIEkMKFHVuaW50ZXJw", + "cmV0ZWRfb3B0aW9uGOcHIAMoCzIkLmdvb2dsZS5wcm90b2J1Zi5VbmludGVy", + "cHJldGVkT3B0aW9uKgkI6AcQgICAgAIimAMKDEZpZWxkT3B0aW9ucxI6CgVj", + "dHlwZRgBIAEoDjIjLmdvb2dsZS5wcm90b2J1Zi5GaWVsZE9wdGlvbnMuQ1R5", + "cGU6BlNUUklORxIOCgZwYWNrZWQYAiABKAgSPwoGanN0eXBlGAYgASgOMiQu", + "Z29vZ2xlLnByb3RvYnVmLkZpZWxkT3B0aW9ucy5KU1R5cGU6CUpTX05PUk1B", + "TBITCgRsYXp5GAUgASgIOgVmYWxzZRIZCgpkZXByZWNhdGVkGAMgASgIOgVm", + "YWxzZRITCgR3ZWFrGAogASgIOgVmYWxzZRJDChR1bmludGVycHJldGVkX29w", + "dGlvbhjnByADKAsyJC5nb29nbGUucHJvdG9idWYuVW5pbnRlcnByZXRlZE9w", + "dGlvbiIvCgVDVHlwZRIKCgZTVFJJTkcQABIICgRDT1JEEAESEAoMU1RSSU5H", + "X1BJRUNFEAIiNQoGSlNUeXBlEg0KCUpTX05PUk1BTBAAEg0KCUpTX1NUUklO", + "RxABEg0KCUpTX05VTUJFUhACKgkI6AcQgICAgAIijQEKC0VudW1PcHRpb25z", + "EhMKC2FsbG93X2FsaWFzGAIgASgIEhkKCmRlcHJlY2F0ZWQYAyABKAg6BWZh", + "bHNlEkMKFHVuaW50ZXJwcmV0ZWRfb3B0aW9uGOcHIAMoCzIkLmdvb2dsZS5w", + "cm90b2J1Zi5VbmludGVycHJldGVkT3B0aW9uKgkI6AcQgICAgAIifQoQRW51", + "bVZhbHVlT3B0aW9ucxIZCgpkZXByZWNhdGVkGAEgASgIOgVmYWxzZRJDChR1", + "bmludGVycHJldGVkX29wdGlvbhjnByADKAsyJC5nb29nbGUucHJvdG9idWYu", + "VW5pbnRlcnByZXRlZE9wdGlvbioJCOgHEICAgIACInsKDlNlcnZpY2VPcHRp", + "b25zEhkKCmRlcHJlY2F0ZWQYISABKAg6BWZhbHNlEkMKFHVuaW50ZXJwcmV0", + "ZWRfb3B0aW9uGOcHIAMoCzIkLmdvb2dsZS5wcm90b2J1Zi5VbmludGVycHJl", + "dGVkT3B0aW9uKgkI6AcQgICAgAIiegoNTWV0aG9kT3B0aW9ucxIZCgpkZXBy", + "ZWNhdGVkGCEgASgIOgVmYWxzZRJDChR1bmludGVycHJldGVkX29wdGlvbhjn", + "ByADKAsyJC5nb29nbGUucHJvdG9idWYuVW5pbnRlcnByZXRlZE9wdGlvbioJ", + "COgHEICAgIACIp4CChNVbmludGVycHJldGVkT3B0aW9uEjsKBG5hbWUYAiAD", + "KAsyLS5nb29nbGUucHJvdG9idWYuVW5pbnRlcnByZXRlZE9wdGlvbi5OYW1l", + "UGFydBIYChBpZGVudGlmaWVyX3ZhbHVlGAMgASgJEhoKEnBvc2l0aXZlX2lu", + "dF92YWx1ZRgEIAEoBBIaChJuZWdhdGl2ZV9pbnRfdmFsdWUYBSABKAMSFAoM", + "ZG91YmxlX3ZhbHVlGAYgASgBEhQKDHN0cmluZ192YWx1ZRgHIAEoDBIXCg9h", + "Z2dyZWdhdGVfdmFsdWUYCCABKAkaMwoITmFtZVBhcnQSEQoJbmFtZV9wYXJ0", + "GAEgAigJEhQKDGlzX2V4dGVuc2lvbhgCIAIoCCLVAQoOU291cmNlQ29kZUlu", + "Zm8SOgoIbG9jYXRpb24YASADKAsyKC5nb29nbGUucHJvdG9idWYuU291cmNl", + "Q29kZUluZm8uTG9jYXRpb24ahgEKCExvY2F0aW9uEhAKBHBhdGgYASADKAVC", + "AhABEhAKBHNwYW4YAiADKAVCAhABEhgKEGxlYWRpbmdfY29tbWVudHMYAyAB", + "KAkSGQoRdHJhaWxpbmdfY29tbWVudHMYBCABKAkSIQoZbGVhZGluZ19kZXRh", + "Y2hlZF9jb21tZW50cxgGIAMoCSKnAQoRR2VuZXJhdGVkQ29kZUluZm8SQQoK", + "YW5ub3RhdGlvbhgBIAMoCzItLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRD", + "b2RlSW5mby5Bbm5vdGF0aW9uGk8KCkFubm90YXRpb24SEAoEcGF0aBgBIAMo", + "BUICEAESEwoLc291cmNlX2ZpbGUYAiABKAkSDQoFYmVnaW4YAyABKAUSCwoD", + "ZW5kGAQgASgFQlgKE2NvbS5nb29nbGUucHJvdG9idWZCEERlc2NyaXB0b3JQ", + "cm90b3NIAVoKZGVzY3JpcHRvcqICA0dQQqoCGkdvb2dsZS5Qcm90b2J1Zi5S", + "ZWZsZWN0aW9u")); + descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, new pbr::FileDescriptor[] { }, - new pbr::GeneratedCodeInfo(null, new pbr::GeneratedCodeInfo[] { - new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.Reflection.FileDescriptorSet), global::Google.Protobuf.Reflection.FileDescriptorSet.Parser, new[]{ "File" }, null, null, null), - new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.Reflection.FileDescriptorProto), global::Google.Protobuf.Reflection.FileDescriptorProto.Parser, new[]{ "Name", "Package", "Dependency", "PublicDependency", "WeakDependency", "MessageType", "EnumType", "Service", "Extension", "Options", "SourceCodeInfo", "Syntax" }, null, null, null), - new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.Reflection.DescriptorProto), global::Google.Protobuf.Reflection.DescriptorProto.Parser, new[]{ "Name", "Field", "Extension", "NestedType", "EnumType", "ExtensionRange", "OneofDecl", "Options", "ReservedRange", "ReservedName" }, null, null, new pbr::GeneratedCodeInfo[] { new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.Reflection.DescriptorProto.Types.ExtensionRange), global::Google.Protobuf.Reflection.DescriptorProto.Types.ExtensionRange.Parser, new[]{ "Start", "End" }, null, null, null), - new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.Reflection.DescriptorProto.Types.ReservedRange), global::Google.Protobuf.Reflection.DescriptorProto.Types.ReservedRange.Parser, new[]{ "Start", "End" }, null, null, null)}), - new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.Reflection.FieldDescriptorProto), global::Google.Protobuf.Reflection.FieldDescriptorProto.Parser, new[]{ "Name", "Number", "Label", "Type", "TypeName", "Extendee", "DefaultValue", "OneofIndex", "JsonName", "Options" }, null, new[]{ typeof(global::Google.Protobuf.Reflection.FieldDescriptorProto.Types.Type), typeof(global::Google.Protobuf.Reflection.FieldDescriptorProto.Types.Label) }, null), - new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.Reflection.OneofDescriptorProto), global::Google.Protobuf.Reflection.OneofDescriptorProto.Parser, new[]{ "Name" }, null, null, null), - new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.Reflection.EnumDescriptorProto), global::Google.Protobuf.Reflection.EnumDescriptorProto.Parser, new[]{ "Name", "Value", "Options" }, null, null, null), - new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.Reflection.EnumValueDescriptorProto), global::Google.Protobuf.Reflection.EnumValueDescriptorProto.Parser, new[]{ "Name", "Number", "Options" }, null, null, null), - new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.Reflection.ServiceDescriptorProto), global::Google.Protobuf.Reflection.ServiceDescriptorProto.Parser, new[]{ "Name", "Method", "Options" }, null, null, null), - new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.Reflection.MethodDescriptorProto), global::Google.Protobuf.Reflection.MethodDescriptorProto.Parser, new[]{ "Name", "InputType", "OutputType", "Options", "ClientStreaming", "ServerStreaming" }, null, null, null), - new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.Reflection.FileOptions), global::Google.Protobuf.Reflection.FileOptions.Parser, new[]{ "JavaPackage", "JavaOuterClassname", "JavaMultipleFiles", "JavaGenerateEqualsAndHash", "JavaStringCheckUtf8", "OptimizeFor", "GoPackage", "CcGenericServices", "JavaGenericServices", "PyGenericServices", "Deprecated", "CcEnableArenas", "ObjcClassPrefix", "CsharpNamespace", "JavananoUseDeprecatedPackage", "UninterpretedOption" }, null, new[]{ typeof(global::Google.Protobuf.Reflection.FileOptions.Types.OptimizeMode) }, null), - new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.Reflection.MessageOptions), global::Google.Protobuf.Reflection.MessageOptions.Parser, new[]{ "MessageSetWireFormat", "NoStandardDescriptorAccessor", "Deprecated", "MapEntry", "UninterpretedOption" }, null, null, null), - new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.Reflection.FieldOptions), global::Google.Protobuf.Reflection.FieldOptions.Parser, new[]{ "Ctype", "Packed", "Jstype", "Lazy", "Deprecated", "Weak", "UninterpretedOption" }, null, new[]{ typeof(global::Google.Protobuf.Reflection.FieldOptions.Types.CType), typeof(global::Google.Protobuf.Reflection.FieldOptions.Types.JSType) }, null), - new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.Reflection.EnumOptions), global::Google.Protobuf.Reflection.EnumOptions.Parser, new[]{ "AllowAlias", "Deprecated", "UninterpretedOption" }, null, null, null), - new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.Reflection.EnumValueOptions), global::Google.Protobuf.Reflection.EnumValueOptions.Parser, new[]{ "Deprecated", "UninterpretedOption" }, null, null, null), - new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.Reflection.ServiceOptions), global::Google.Protobuf.Reflection.ServiceOptions.Parser, new[]{ "Deprecated", "UninterpretedOption" }, null, null, null), - new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.Reflection.MethodOptions), global::Google.Protobuf.Reflection.MethodOptions.Parser, new[]{ "Deprecated", "UninterpretedOption" }, null, null, null), - new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.Reflection.UninterpretedOption), global::Google.Protobuf.Reflection.UninterpretedOption.Parser, new[]{ "Name", "IdentifierValue", "PositiveIntValue", "NegativeIntValue", "DoubleValue", "StringValue", "AggregateValue" }, null, null, new pbr::GeneratedCodeInfo[] { new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.Reflection.UninterpretedOption.Types.NamePart), global::Google.Protobuf.Reflection.UninterpretedOption.Types.NamePart.Parser, new[]{ "NamePart_", "IsExtension" }, null, null, null)}), - new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.Reflection.SourceCodeInfo), global::Google.Protobuf.Reflection.SourceCodeInfo.Parser, new[]{ "Location" }, null, null, new pbr::GeneratedCodeInfo[] { new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.Reflection.SourceCodeInfo.Types.Location), global::Google.Protobuf.Reflection.SourceCodeInfo.Types.Location.Parser, new[]{ "Path", "Span", "LeadingComments", "TrailingComments", "LeadingDetachedComments" }, null, null, null)}) + new pbr::GeneratedClrTypeInfo(null, new pbr::GeneratedClrTypeInfo[] { + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.FileDescriptorSet), global::Google.Protobuf.Reflection.FileDescriptorSet.Parser, new[]{ "File" }, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.FileDescriptorProto), global::Google.Protobuf.Reflection.FileDescriptorProto.Parser, new[]{ "Name", "Package", "Dependency", "PublicDependency", "WeakDependency", "MessageType", "EnumType", "Service", "Extension", "Options", "SourceCodeInfo", "Syntax" }, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.DescriptorProto), global::Google.Protobuf.Reflection.DescriptorProto.Parser, new[]{ "Name", "Field", "Extension", "NestedType", "EnumType", "ExtensionRange", "OneofDecl", "Options", "ReservedRange", "ReservedName" }, null, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.DescriptorProto.Types.ExtensionRange), global::Google.Protobuf.Reflection.DescriptorProto.Types.ExtensionRange.Parser, new[]{ "Start", "End" }, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.DescriptorProto.Types.ReservedRange), global::Google.Protobuf.Reflection.DescriptorProto.Types.ReservedRange.Parser, new[]{ "Start", "End" }, null, null, null)}), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.FieldDescriptorProto), global::Google.Protobuf.Reflection.FieldDescriptorProto.Parser, new[]{ "Name", "Number", "Label", "Type", "TypeName", "Extendee", "DefaultValue", "OneofIndex", "JsonName", "Options" }, null, new[]{ typeof(global::Google.Protobuf.Reflection.FieldDescriptorProto.Types.Type), typeof(global::Google.Protobuf.Reflection.FieldDescriptorProto.Types.Label) }, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.OneofDescriptorProto), global::Google.Protobuf.Reflection.OneofDescriptorProto.Parser, new[]{ "Name" }, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.EnumDescriptorProto), global::Google.Protobuf.Reflection.EnumDescriptorProto.Parser, new[]{ "Name", "Value", "Options" }, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.EnumValueDescriptorProto), global::Google.Protobuf.Reflection.EnumValueDescriptorProto.Parser, new[]{ "Name", "Number", "Options" }, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.ServiceDescriptorProto), global::Google.Protobuf.Reflection.ServiceDescriptorProto.Parser, new[]{ "Name", "Method", "Options" }, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.MethodDescriptorProto), global::Google.Protobuf.Reflection.MethodDescriptorProto.Parser, new[]{ "Name", "InputType", "OutputType", "Options", "ClientStreaming", "ServerStreaming" }, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.FileOptions), global::Google.Protobuf.Reflection.FileOptions.Parser, new[]{ "JavaPackage", "JavaOuterClassname", "JavaMultipleFiles", "JavaGenerateEqualsAndHash", "JavaStringCheckUtf8", "OptimizeFor", "GoPackage", "CcGenericServices", "JavaGenericServices", "PyGenericServices", "Deprecated", "CcEnableArenas", "ObjcClassPrefix", "CsharpNamespace", "JavananoUseDeprecatedPackage", "UninterpretedOption" }, null, new[]{ typeof(global::Google.Protobuf.Reflection.FileOptions.Types.OptimizeMode) }, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.MessageOptions), global::Google.Protobuf.Reflection.MessageOptions.Parser, new[]{ "MessageSetWireFormat", "NoStandardDescriptorAccessor", "Deprecated", "MapEntry", "UninterpretedOption" }, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.FieldOptions), global::Google.Protobuf.Reflection.FieldOptions.Parser, new[]{ "Ctype", "Packed", "Jstype", "Lazy", "Deprecated", "Weak", "UninterpretedOption" }, null, new[]{ typeof(global::Google.Protobuf.Reflection.FieldOptions.Types.CType), typeof(global::Google.Protobuf.Reflection.FieldOptions.Types.JSType) }, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.EnumOptions), global::Google.Protobuf.Reflection.EnumOptions.Parser, new[]{ "AllowAlias", "Deprecated", "UninterpretedOption" }, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.EnumValueOptions), global::Google.Protobuf.Reflection.EnumValueOptions.Parser, new[]{ "Deprecated", "UninterpretedOption" }, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.ServiceOptions), global::Google.Protobuf.Reflection.ServiceOptions.Parser, new[]{ "Deprecated", "UninterpretedOption" }, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.MethodOptions), global::Google.Protobuf.Reflection.MethodOptions.Parser, new[]{ "Deprecated", "UninterpretedOption" }, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.UninterpretedOption), global::Google.Protobuf.Reflection.UninterpretedOption.Parser, new[]{ "Name", "IdentifierValue", "PositiveIntValue", "NegativeIntValue", "DoubleValue", "StringValue", "AggregateValue" }, null, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.UninterpretedOption.Types.NamePart), global::Google.Protobuf.Reflection.UninterpretedOption.Types.NamePart.Parser, new[]{ "NamePart_", "IsExtension" }, null, null, null)}), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.SourceCodeInfo), global::Google.Protobuf.Reflection.SourceCodeInfo.Parser, new[]{ "Location" }, null, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.SourceCodeInfo.Types.Location), global::Google.Protobuf.Reflection.SourceCodeInfo.Types.Location.Parser, new[]{ "Path", "Span", "LeadingComments", "TrailingComments", "LeadingDetachedComments" }, null, null, null)}), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.GeneratedCodeInfo), global::Google.Protobuf.Reflection.GeneratedCodeInfo.Parser, new[]{ "Annotation" }, null, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.GeneratedCodeInfo.Types.Annotation), global::Google.Protobuf.Reflection.GeneratedCodeInfo.Types.Annotation.Parser, new[]{ "Path", "SourceFile", "Begin", "End" }, null, null, null)}) })); } #endregion @@ -225,7 +230,7 @@ namespace Google.Protobuf.Reflection { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -312,7 +317,7 @@ namespace Google.Protobuf.Reflection { public string Name { get { return name_; } set { - name_ = pb::Preconditions.CheckNotNull(value, "value"); + name_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } @@ -325,7 +330,7 @@ namespace Google.Protobuf.Reflection { public string Package { get { return package_; } set { - package_ = pb::Preconditions.CheckNotNull(value, "value"); + package_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } @@ -441,7 +446,7 @@ namespace Google.Protobuf.Reflection { public string Syntax { get { return syntax_; } set { - syntax_ = pb::Preconditions.CheckNotNull(value, "value"); + syntax_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } @@ -489,7 +494,7 @@ namespace Google.Protobuf.Reflection { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -697,7 +702,7 @@ namespace Google.Protobuf.Reflection { public string Name { get { return name_; } set { - name_ = pb::Preconditions.CheckNotNull(value, "value"); + name_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } @@ -827,7 +832,7 @@ namespace Google.Protobuf.Reflection { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -1021,7 +1026,7 @@ namespace Google.Protobuf.Reflection { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -1162,7 +1167,7 @@ namespace Google.Protobuf.Reflection { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -1270,7 +1275,7 @@ namespace Google.Protobuf.Reflection { public string Name { get { return name_; } set { - name_ = pb::Preconditions.CheckNotNull(value, "value"); + name_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } @@ -1321,7 +1326,7 @@ namespace Google.Protobuf.Reflection { public string TypeName { get { return typeName_; } set { - typeName_ = pb::Preconditions.CheckNotNull(value, "value"); + typeName_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } @@ -1335,7 +1340,7 @@ namespace Google.Protobuf.Reflection { public string Extendee { get { return extendee_; } set { - extendee_ = pb::Preconditions.CheckNotNull(value, "value"); + extendee_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } @@ -1352,7 +1357,7 @@ namespace Google.Protobuf.Reflection { public string DefaultValue { get { return defaultValue_; } set { - defaultValue_ = pb::Preconditions.CheckNotNull(value, "value"); + defaultValue_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } @@ -1382,7 +1387,7 @@ namespace Google.Protobuf.Reflection { public string JsonName { get { return jsonName_; } set { - jsonName_ = pb::Preconditions.CheckNotNull(value, "value"); + jsonName_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } @@ -1436,7 +1441,7 @@ namespace Google.Protobuf.Reflection { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -1715,7 +1720,7 @@ namespace Google.Protobuf.Reflection { public string Name { get { return name_; } set { - name_ = pb::Preconditions.CheckNotNull(value, "value"); + name_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } @@ -1741,7 +1746,7 @@ namespace Google.Protobuf.Reflection { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -1823,7 +1828,7 @@ namespace Google.Protobuf.Reflection { public string Name { get { return name_; } set { - name_ = pb::Preconditions.CheckNotNull(value, "value"); + name_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } @@ -1872,7 +1877,7 @@ namespace Google.Protobuf.Reflection { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -1981,7 +1986,7 @@ namespace Google.Protobuf.Reflection { public string Name { get { return name_; } set { - name_ = pb::Preconditions.CheckNotNull(value, "value"); + name_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } @@ -2031,7 +2036,7 @@ namespace Google.Protobuf.Reflection { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -2147,7 +2152,7 @@ namespace Google.Protobuf.Reflection { public string Name { get { return name_; } set { - name_ = pb::Preconditions.CheckNotNull(value, "value"); + name_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } @@ -2196,7 +2201,7 @@ namespace Google.Protobuf.Reflection { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -2308,7 +2313,7 @@ namespace Google.Protobuf.Reflection { public string Name { get { return name_; } set { - name_ = pb::Preconditions.CheckNotNull(value, "value"); + name_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } @@ -2322,7 +2327,7 @@ namespace Google.Protobuf.Reflection { public string InputType { get { return inputType_; } set { - inputType_ = pb::Preconditions.CheckNotNull(value, "value"); + inputType_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } @@ -2332,7 +2337,7 @@ namespace Google.Protobuf.Reflection { public string OutputType { get { return outputType_; } set { - outputType_ = pb::Preconditions.CheckNotNull(value, "value"); + outputType_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } @@ -2404,7 +2409,7 @@ namespace Google.Protobuf.Reflection { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -2578,7 +2583,7 @@ namespace Google.Protobuf.Reflection { public string JavaPackage { get { return javaPackage_; } set { - javaPackage_ = pb::Preconditions.CheckNotNull(value, "value"); + javaPackage_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } @@ -2595,7 +2600,7 @@ namespace Google.Protobuf.Reflection { public string JavaOuterClassname { get { return javaOuterClassname_; } set { - javaOuterClassname_ = pb::Preconditions.CheckNotNull(value, "value"); + javaOuterClassname_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } @@ -2682,7 +2687,7 @@ namespace Google.Protobuf.Reflection { public string GoPackage { get { return goPackage_; } set { - goPackage_ = pb::Preconditions.CheckNotNull(value, "value"); + goPackage_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } @@ -2768,7 +2773,7 @@ namespace Google.Protobuf.Reflection { public string ObjcClassPrefix { get { return objcClassPrefix_; } set { - objcClassPrefix_ = pb::Preconditions.CheckNotNull(value, "value"); + objcClassPrefix_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } @@ -2781,7 +2786,7 @@ namespace Google.Protobuf.Reflection { public string CsharpNamespace { get { return csharpNamespace_; } set { - csharpNamespace_ = pb::Preconditions.CheckNotNull(value, "value"); + csharpNamespace_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } @@ -2792,6 +2797,7 @@ namespace Google.Protobuf.Reflection { /// Whether the nano proto compiler should generate in the deprecated non-nano /// suffixed package. /// </summary> + [global::System.ObsoleteAttribute()] public bool JavananoUseDeprecatedPackage { get { return javananoUseDeprecatedPackage_; } set { @@ -2863,7 +2869,7 @@ namespace Google.Protobuf.Reflection { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -3302,7 +3308,7 @@ namespace Google.Protobuf.Reflection { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -3596,7 +3602,7 @@ namespace Google.Protobuf.Reflection { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -3845,7 +3851,7 @@ namespace Google.Protobuf.Reflection { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -3990,7 +3996,7 @@ namespace Google.Protobuf.Reflection { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -4121,7 +4127,7 @@ namespace Google.Protobuf.Reflection { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -4252,7 +4258,7 @@ namespace Google.Protobuf.Reflection { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -4363,7 +4369,7 @@ namespace Google.Protobuf.Reflection { public string IdentifierValue { get { return identifierValue_; } set { - identifierValue_ = pb::Preconditions.CheckNotNull(value, "value"); + identifierValue_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } @@ -4403,7 +4409,7 @@ namespace Google.Protobuf.Reflection { public pb::ByteString StringValue { get { return stringValue_; } set { - stringValue_ = pb::Preconditions.CheckNotNull(value, "value"); + stringValue_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } @@ -4413,7 +4419,7 @@ namespace Google.Protobuf.Reflection { public string AggregateValue { get { return aggregateValue_; } set { - aggregateValue_ = pb::Preconditions.CheckNotNull(value, "value"); + aggregateValue_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } @@ -4451,7 +4457,7 @@ namespace Google.Protobuf.Reflection { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -4615,7 +4621,7 @@ namespace Google.Protobuf.Reflection { public string NamePart_ { get { return namePart_; } set { - namePart_ = pb::Preconditions.CheckNotNull(value, "value"); + namePart_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } @@ -4653,7 +4659,7 @@ namespace Google.Protobuf.Reflection { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -4823,7 +4829,7 @@ namespace Google.Protobuf.Reflection { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -4998,7 +5004,7 @@ namespace Google.Protobuf.Reflection { public string LeadingComments { get { return leadingComments_; } set { - leadingComments_ = pb::Preconditions.CheckNotNull(value, "value"); + leadingComments_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } @@ -5008,7 +5014,7 @@ namespace Google.Protobuf.Reflection { public string TrailingComments { get { return trailingComments_; } set { - trailingComments_ = pb::Preconditions.CheckNotNull(value, "value"); + trailingComments_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } @@ -5051,7 +5057,7 @@ namespace Google.Protobuf.Reflection { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -5137,6 +5143,310 @@ namespace Google.Protobuf.Reflection { } + /// <summary> + /// Describes the relationship between generated code and its original source + /// file. A GeneratedCodeInfo message is associated with only one generated + /// source file, but may contain references to different source .proto files. + /// </summary> + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + internal sealed partial class GeneratedCodeInfo : pb::IMessage<GeneratedCodeInfo> { + private static readonly pb::MessageParser<GeneratedCodeInfo> _parser = new pb::MessageParser<GeneratedCodeInfo>(() => new GeneratedCodeInfo()); + public static pb::MessageParser<GeneratedCodeInfo> Parser { get { return _parser; } } + + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.Reflection.DescriptorReflection.Descriptor.MessageTypes[18]; } + } + + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + public GeneratedCodeInfo() { + OnConstruction(); + } + + partial void OnConstruction(); + + public GeneratedCodeInfo(GeneratedCodeInfo other) : this() { + annotation_ = other.annotation_.Clone(); + } + + public GeneratedCodeInfo Clone() { + return new GeneratedCodeInfo(this); + } + + /// <summary>Field number for the "annotation" field.</summary> + public const int AnnotationFieldNumber = 1; + private static readonly pb::FieldCodec<global::Google.Protobuf.Reflection.GeneratedCodeInfo.Types.Annotation> _repeated_annotation_codec + = pb::FieldCodec.ForMessage(10, global::Google.Protobuf.Reflection.GeneratedCodeInfo.Types.Annotation.Parser); + private readonly pbc::RepeatedField<global::Google.Protobuf.Reflection.GeneratedCodeInfo.Types.Annotation> annotation_ = new pbc::RepeatedField<global::Google.Protobuf.Reflection.GeneratedCodeInfo.Types.Annotation>(); + /// <summary> + /// An Annotation connects some span of text in generated code to an element + /// of its generating .proto file. + /// </summary> + public pbc::RepeatedField<global::Google.Protobuf.Reflection.GeneratedCodeInfo.Types.Annotation> Annotation { + get { return annotation_; } + } + + public override bool Equals(object other) { + return Equals(other as GeneratedCodeInfo); + } + + public bool Equals(GeneratedCodeInfo other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if(!annotation_.Equals(other.annotation_)) return false; + return true; + } + + public override int GetHashCode() { + int hash = 1; + hash ^= annotation_.GetHashCode(); + return hash; + } + + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + public void WriteTo(pb::CodedOutputStream output) { + annotation_.WriteTo(output, _repeated_annotation_codec); + } + + public int CalculateSize() { + int size = 0; + size += annotation_.CalculateSize(_repeated_annotation_codec); + return size; + } + + public void MergeFrom(GeneratedCodeInfo other) { + if (other == null) { + return; + } + annotation_.Add(other.annotation_); + } + + public void MergeFrom(pb::CodedInputStream input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + input.SkipLastField(); + break; + case 10: { + annotation_.AddEntriesFrom(input, _repeated_annotation_codec); + break; + } + } + } + } + + #region Nested types + /// <summary>Container for nested types declared in the GeneratedCodeInfo message type.</summary> + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + public static partial class Types { + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + internal sealed partial class Annotation : pb::IMessage<Annotation> { + private static readonly pb::MessageParser<Annotation> _parser = new pb::MessageParser<Annotation>(() => new Annotation()); + public static pb::MessageParser<Annotation> Parser { get { return _parser; } } + + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.Reflection.GeneratedCodeInfo.Descriptor.NestedTypes[0]; } + } + + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + public Annotation() { + OnConstruction(); + } + + partial void OnConstruction(); + + public Annotation(Annotation other) : this() { + path_ = other.path_.Clone(); + sourceFile_ = other.sourceFile_; + begin_ = other.begin_; + end_ = other.end_; + } + + public Annotation Clone() { + return new Annotation(this); + } + + /// <summary>Field number for the "path" field.</summary> + public const int PathFieldNumber = 1; + private static readonly pb::FieldCodec<int> _repeated_path_codec + = pb::FieldCodec.ForInt32(10); + private readonly pbc::RepeatedField<int> path_ = new pbc::RepeatedField<int>(); + /// <summary> + /// Identifies the element in the original source .proto file. This field + /// is formatted the same as SourceCodeInfo.Location.path. + /// </summary> + public pbc::RepeatedField<int> Path { + get { return path_; } + } + + /// <summary>Field number for the "source_file" field.</summary> + public const int SourceFileFieldNumber = 2; + private string sourceFile_ = ""; + /// <summary> + /// Identifies the filesystem path to the original source .proto. + /// </summary> + public string SourceFile { + get { return sourceFile_; } + set { + sourceFile_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + /// <summary>Field number for the "begin" field.</summary> + public const int BeginFieldNumber = 3; + private int begin_; + /// <summary> + /// Identifies the starting offset in bytes in the generated code + /// that relates to the identified object. + /// </summary> + public int Begin { + get { return begin_; } + set { + begin_ = value; + } + } + + /// <summary>Field number for the "end" field.</summary> + public const int EndFieldNumber = 4; + private int end_; + /// <summary> + /// Identifies the ending offset in bytes in the generated code that + /// relates to the identified offset. The end offset should be one past + /// the last relevant byte (so the length of the text = end - begin). + /// </summary> + public int End { + get { return end_; } + set { + end_ = value; + } + } + + public override bool Equals(object other) { + return Equals(other as Annotation); + } + + public bool Equals(Annotation other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if(!path_.Equals(other.path_)) return false; + if (SourceFile != other.SourceFile) return false; + if (Begin != other.Begin) return false; + if (End != other.End) return false; + return true; + } + + public override int GetHashCode() { + int hash = 1; + hash ^= path_.GetHashCode(); + if (SourceFile.Length != 0) hash ^= SourceFile.GetHashCode(); + if (Begin != 0) hash ^= Begin.GetHashCode(); + if (End != 0) hash ^= End.GetHashCode(); + return hash; + } + + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + public void WriteTo(pb::CodedOutputStream output) { + path_.WriteTo(output, _repeated_path_codec); + if (SourceFile.Length != 0) { + output.WriteRawTag(18); + output.WriteString(SourceFile); + } + if (Begin != 0) { + output.WriteRawTag(24); + output.WriteInt32(Begin); + } + if (End != 0) { + output.WriteRawTag(32); + output.WriteInt32(End); + } + } + + public int CalculateSize() { + int size = 0; + size += path_.CalculateSize(_repeated_path_codec); + if (SourceFile.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(SourceFile); + } + if (Begin != 0) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(Begin); + } + if (End != 0) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(End); + } + return size; + } + + public void MergeFrom(Annotation other) { + if (other == null) { + return; + } + path_.Add(other.path_); + if (other.SourceFile.Length != 0) { + SourceFile = other.SourceFile; + } + if (other.Begin != 0) { + Begin = other.Begin; + } + if (other.End != 0) { + End = other.End; + } + } + + public void MergeFrom(pb::CodedInputStream input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + input.SkipLastField(); + break; + case 10: + case 8: { + path_.AddEntriesFrom(input, _repeated_path_codec); + break; + } + case 18: { + SourceFile = input.ReadString(); + break; + } + case 24: { + Begin = input.ReadInt32(); + break; + } + case 32: { + End = input.ReadInt32(); + break; + } + } + } + } + + } + + } + #endregion + + } + #endregion } diff --git a/csharp/src/Google.Protobuf/Reflection/EnumDescriptor.cs b/csharp/src/Google.Protobuf/Reflection/EnumDescriptor.cs index 285f26f3..c732c93a 100644 --- a/csharp/src/Google.Protobuf/Reflection/EnumDescriptor.cs +++ b/csharp/src/Google.Protobuf/Reflection/EnumDescriptor.cs @@ -43,13 +43,13 @@ namespace Google.Protobuf.Reflection private readonly EnumDescriptorProto proto; private readonly MessageDescriptor containingType; private readonly IList<EnumValueDescriptor> values; - private readonly Type generatedType; + private readonly Type clrType; - internal EnumDescriptor(EnumDescriptorProto proto, FileDescriptor file, MessageDescriptor parent, int index, Type generatedType) + internal EnumDescriptor(EnumDescriptorProto proto, FileDescriptor file, MessageDescriptor parent, int index, Type clrType) : base(file, file.ComputeFullName(parent, proto.Name), index) { this.proto = proto; - this.generatedType = generatedType; + this.clrType = clrType; containingType = parent; if (proto.Value.Count == 0) @@ -73,9 +73,9 @@ namespace Google.Protobuf.Reflection public override string Name { get { return proto.Name; } } /// <summary> - /// The generated type for this enum, or <c>null</c> if the descriptor does not represent a generated type. + /// The CLR type for this enum. For generated code, this will be a CLR enum type. /// </summary> - public Type GeneratedType { get { return generatedType; } } + public Type ClrType { get { return clrType; } } /// <value> /// If this is a nested type, get the outer descriptor, otherwise null. diff --git a/csharp/src/Google.Protobuf/Reflection/FieldDescriptor.cs b/csharp/src/Google.Protobuf/Reflection/FieldDescriptor.cs index 3d6cc59f..c6caaec6 100644 --- a/csharp/src/Google.Protobuf/Reflection/FieldDescriptor.cs +++ b/csharp/src/Google.Protobuf/Reflection/FieldDescriptor.cs @@ -62,8 +62,7 @@ namespace Google.Protobuf.Reflection if (FieldNumber <= 0) { - throw new DescriptorValidationException(this, - "Field numbers must be positive integers."); + throw new DescriptorValidationException(this, "Field numbers must be positive integers."); } containingType = parent; // OneofIndex "defaults" to -1 due to a hack in FieldDescriptor.OnConstruction. @@ -72,7 +71,7 @@ namespace Google.Protobuf.Reflection if (proto.OneofIndex < 0 || proto.OneofIndex >= parent.Proto.OneofDecl.Count) { throw new DescriptorValidationException(this, - "FieldDescriptorProto.oneof_index is out of range for type " + parent.Name); + $"FieldDescriptorProto.oneof_index is out of range for type {parent.Name}"); } containingOneof = parent.Oneofs[proto.OneofIndex]; } @@ -94,13 +93,22 @@ namespace Google.Protobuf.Reflection internal FieldDescriptorProto Proto { get { return proto; } } /// <summary> - /// Returns the accessor for this field, or <c>null</c> if this descriptor does - /// not support reflective access. + /// Returns the accessor for this field. /// </summary> /// <remarks> + /// <para> /// While a <see cref="FieldDescriptor"/> describes the field, it does not provide /// any way of obtaining or changing the value of the field within a specific message; /// that is the responsibility of the accessor. + /// </para> + /// <para> + /// The value returned by this property will be non-null for all regular fields. However, + /// if a message containing a map field is introspected, the list of nested messages will include + /// an auto-generated nested key/value pair message for the field. This is not represented in any + /// generated type, and the value of the map field itself is represented by a dictionary in the + /// reflection API. There are never instances of those "hidden" messages, so no accessor is provided + /// and this property will return null. + /// </para> /// </remarks> public IFieldAccessor Accessor { get { return accessor; } } @@ -281,7 +289,7 @@ namespace Google.Protobuf.Reflection } else { - throw new DescriptorValidationException(this, "\"" + Proto.TypeName + "\" is not a type."); + throw new DescriptorValidationException(this, $"\"{Proto.TypeName}\" is not a type."); } } @@ -289,8 +297,7 @@ namespace Google.Protobuf.Reflection { if (!(typeDescriptor is MessageDescriptor)) { - throw new DescriptorValidationException(this, - "\"" + Proto.TypeName + "\" is not a message type."); + throw new DescriptorValidationException(this, $"\"{Proto.TypeName}\" is not a message type."); } messageType = (MessageDescriptor) typeDescriptor; @@ -303,7 +310,7 @@ namespace Google.Protobuf.Reflection { if (!(typeDescriptor is EnumDescriptor)) { - throw new DescriptorValidationException(this, "\"" + Proto.TypeName + "\" is not an enum type."); + throw new DescriptorValidationException(this, $"\"{Proto.TypeName}\" is not an enum type."); } enumType = (EnumDescriptor) typeDescriptor; } @@ -333,14 +340,16 @@ namespace Google.Protobuf.Reflection private IFieldAccessor CreateAccessor(string propertyName) { - if (containingType.GeneratedType == null || propertyName == null) + // If we're given no property name, that's because we really don't want an accessor. + // (At the moment, that means it's a map entry message...) + if (propertyName == null) { return null; } - var property = containingType.GeneratedType.GetProperty(propertyName); + var property = containingType.ClrType.GetProperty(propertyName); if (property == null) { - throw new DescriptorValidationException(this, "Property " + propertyName + " not found in " + containingType.GeneratedType); + throw new DescriptorValidationException(this, $"Property {propertyName} not found in {containingType.ClrType}"); } return IsMap ? new MapFieldAccessor(property, this) : IsRepeated ? new RepeatedFieldAccessor(property, this) diff --git a/csharp/src/Google.Protobuf/Reflection/FileDescriptor.cs b/csharp/src/Google.Protobuf/Reflection/FileDescriptor.cs index 549dfe28..ab7cd922 100644 --- a/csharp/src/Google.Protobuf/Reflection/FileDescriptor.cs +++ b/csharp/src/Google.Protobuf/Reflection/FileDescriptor.cs @@ -43,35 +43,26 @@ namespace Google.Protobuf.Reflection /// </summary> public sealed class FileDescriptor : IDescriptor { - private readonly ByteString descriptorData; - private readonly FileDescriptorProto proto; - private readonly IList<MessageDescriptor> messageTypes; - private readonly IList<EnumDescriptor> enumTypes; - private readonly IList<ServiceDescriptor> services; - private readonly IList<FileDescriptor> dependencies; - private readonly IList<FileDescriptor> publicDependencies; - private readonly DescriptorPool pool; - - private FileDescriptor(ByteString descriptorData, FileDescriptorProto proto, FileDescriptor[] dependencies, DescriptorPool pool, bool allowUnknownDependencies, GeneratedCodeInfo generatedCodeInfo) + private FileDescriptor(ByteString descriptorData, FileDescriptorProto proto, FileDescriptor[] dependencies, DescriptorPool pool, bool allowUnknownDependencies, GeneratedClrTypeInfo generatedCodeInfo) { - this.descriptorData = descriptorData; - this.pool = pool; - this.proto = proto; - this.dependencies = new ReadOnlyCollection<FileDescriptor>((FileDescriptor[]) dependencies.Clone()); + SerializedData = descriptorData; + DescriptorPool = pool; + Proto = proto; + Dependencies = new ReadOnlyCollection<FileDescriptor>((FileDescriptor[]) dependencies.Clone()); - publicDependencies = DeterminePublicDependencies(this, proto, dependencies, allowUnknownDependencies); + PublicDependencies = DeterminePublicDependencies(this, proto, dependencies, allowUnknownDependencies); pool.AddPackage(Package, this); - messageTypes = DescriptorUtil.ConvertAndMakeReadOnly(proto.MessageType, + MessageTypes = DescriptorUtil.ConvertAndMakeReadOnly(proto.MessageType, (message, index) => - new MessageDescriptor(message, this, null, index, generatedCodeInfo == null ? null : generatedCodeInfo.NestedTypes[index])); + new MessageDescriptor(message, this, null, index, generatedCodeInfo.NestedTypes[index])); - enumTypes = DescriptorUtil.ConvertAndMakeReadOnly(proto.EnumType, + EnumTypes = DescriptorUtil.ConvertAndMakeReadOnly(proto.EnumType, (enumType, index) => - new EnumDescriptor(enumType, this, null, index, generatedCodeInfo == null ? null : generatedCodeInfo.NestedEnums[index])); + new EnumDescriptor(enumType, this, null, index, generatedCodeInfo.NestedEnums[index])); - services = DescriptorUtil.ConvertAndMakeReadOnly(proto.Service, + Services = DescriptorUtil.ConvertAndMakeReadOnly(proto.Service, (service, index) => new ServiceDescriptor(service, this, index)); } @@ -132,99 +123,63 @@ namespace Google.Protobuf.Reflection /// <value> /// The descriptor in its protocol message representation. /// </value> - internal FileDescriptorProto Proto - { - get { return proto; } - } + internal FileDescriptorProto Proto { get; } /// <value> /// The file name. /// </value> - public string Name - { - get { return proto.Name; } - } + public string Name => Proto.Name; /// <summary> /// The package as declared in the .proto file. This may or may not /// be equivalent to the .NET namespace of the generated classes. /// </summary> - public string Package - { - get { return proto.Package; } - } + public string Package => Proto.Package; /// <value> /// Unmodifiable list of top-level message types declared in this file. /// </value> - public IList<MessageDescriptor> MessageTypes - { - get { return messageTypes; } - } + public IList<MessageDescriptor> MessageTypes { get; } /// <value> /// Unmodifiable list of top-level enum types declared in this file. /// </value> - public IList<EnumDescriptor> EnumTypes - { - get { return enumTypes; } - } + public IList<EnumDescriptor> EnumTypes { get; } /// <value> /// Unmodifiable list of top-level services declared in this file. /// </value> - public IList<ServiceDescriptor> Services - { - get { return services; } - } + public IList<ServiceDescriptor> Services { get; } /// <value> /// Unmodifiable list of this file's dependencies (imports). /// </value> - public IList<FileDescriptor> Dependencies - { - get { return dependencies; } - } + public IList<FileDescriptor> Dependencies { get; } /// <value> /// Unmodifiable list of this file's public dependencies (public imports). /// </value> - public IList<FileDescriptor> PublicDependencies - { - get { return publicDependencies; } - } + public IList<FileDescriptor> PublicDependencies { get; } /// <value> /// The original serialized binary form of this descriptor. /// </value> - public ByteString SerializedData - { - get { return descriptorData; } - } + public ByteString SerializedData { get; } /// <value> /// Implementation of IDescriptor.FullName - just returns the same as Name. /// </value> - string IDescriptor.FullName - { - get { return Name; } - } + string IDescriptor.FullName => Name; /// <value> /// Implementation of IDescriptor.File - just returns this descriptor. /// </value> - FileDescriptor IDescriptor.File - { - get { return this; } - } + FileDescriptor IDescriptor.File => this; /// <value> /// Pool containing symbol descriptors. /// </value> - internal DescriptorPool DescriptorPool - { - get { return pool; } - } + internal DescriptorPool DescriptorPool { get; } /// <summary> /// Finds a type (message, enum, service or extension) in the file by name. Does not find nested types. @@ -245,7 +200,7 @@ namespace Google.Protobuf.Reflection { name = Package + "." + name; } - T result = pool.FindSymbol<T>(name); + T result = DescriptorPool.FindSymbol<T>(name); if (result != null && result.File == this) { return result; @@ -264,11 +219,11 @@ namespace Google.Protobuf.Reflection /// file's dependencies, in the exact order listed in the .proto file. May be null, /// in which case it is treated as an empty array.</param> /// <param name="allowUnknownDependencies">Whether unknown dependencies are ignored (true) or cause an exception to be thrown (false).</param> - /// <param name="generatedCodeInfo">Reflection information, if any. May be null, specifically for non-generated code.</param> + /// <param name="generatedCodeInfo">Details about generated code, for the purposes of reflection.</param> /// <exception cref="DescriptorValidationException">If <paramref name="proto"/> is not /// a valid descriptor. This can occur for a number of reasons, such as a field /// having an undefined type or because two messages were defined with the same name.</exception> - private static FileDescriptor BuildFrom(ByteString descriptorData, FileDescriptorProto proto, FileDescriptor[] dependencies, bool allowUnknownDependencies, GeneratedCodeInfo generatedCodeInfo) + private static FileDescriptor BuildFrom(ByteString descriptorData, FileDescriptorProto proto, FileDescriptor[] dependencies, bool allowUnknownDependencies, GeneratedClrTypeInfo generatedCodeInfo) { // Building descriptors involves two steps: translating and linking. // In the translation step (implemented by FileDescriptor's @@ -291,15 +246,17 @@ namespace Google.Protobuf.Reflection // need. if (dependencies.Length != proto.Dependency.Count) { - throw new DescriptorValidationException(result, - "Dependencies passed to FileDescriptor.BuildFrom() don't match " + - "those listed in the FileDescriptorProto."); + throw new DescriptorValidationException( + result, + "Dependencies passed to FileDescriptor.BuildFrom() don't match " + + "those listed in the FileDescriptorProto."); } for (int i = 0; i < proto.Dependency.Count; i++) { if (dependencies[i].Name != proto.Dependency[i]) { - throw new DescriptorValidationException(result, + throw new DescriptorValidationException( + result, "Dependencies passed to FileDescriptor.BuildFrom() don't match " + "those listed in the FileDescriptorProto. Expected: " + proto.Dependency[i] + " but was: " + dependencies[i].Name); @@ -312,28 +269,29 @@ namespace Google.Protobuf.Reflection private void CrossLink() { - foreach (MessageDescriptor message in messageTypes) + foreach (MessageDescriptor message in MessageTypes) { message.CrossLink(); } - foreach (ServiceDescriptor service in services) + foreach (ServiceDescriptor service in Services) { service.CrossLink(); } } /// <summary> - /// Creates an instance for generated code. + /// Creates a descriptor for generated code. /// </summary> /// <remarks> - /// The <paramref name="generatedCodeInfo"/> parameter should be null for descriptors which don't correspond to - /// generated types. Otherwise, it should be a <see cref="GeneratedCodeInfo"/> with nested types and nested - /// enums corresponding to the types and enums contained within the file descriptor. + /// This method is only designed to be used by the results of generating code with protoc, + /// which creates the appropriate dependencies etc. It has to be public because the generated + /// code is "external", but should not be called directly by end users. /// </remarks> - public static FileDescriptor InternalBuildGeneratedFileFrom(byte[] descriptorData, - FileDescriptor[] dependencies, - GeneratedCodeInfo generatedCodeInfo) + public static FileDescriptor FromGeneratedCode( + byte[] descriptorData, + FileDescriptor[] dependencies, + GeneratedClrTypeInfo generatedCodeInfo) { FileDescriptorProto proto; try @@ -345,8 +303,6 @@ namespace Google.Protobuf.Reflection throw new ArgumentException("Failed to parse protocol buffer descriptor for generated code.", e); } - - try { // When building descriptors for generated code, we allow unknown @@ -355,7 +311,7 @@ namespace Google.Protobuf.Reflection } catch (DescriptorValidationException e) { - throw new ArgumentException("Invalid embedded descriptor for \"" + proto.Name + "\".", e); + throw new ArgumentException($"Invalid embedded descriptor for \"{proto.Name}\".", e); } } @@ -367,7 +323,7 @@ namespace Google.Protobuf.Reflection /// </returns> public override string ToString() { - return "FileDescriptor for " + proto.Name; + return $"FileDescriptor for {Name}"; } /// <summary> diff --git a/csharp/src/Google.Protobuf/Reflection/GeneratedClrTypeInfo.cs b/csharp/src/Google.Protobuf/Reflection/GeneratedClrTypeInfo.cs new file mode 100644 index 00000000..fe5db656 --- /dev/null +++ b/csharp/src/Google.Protobuf/Reflection/GeneratedClrTypeInfo.cs @@ -0,0 +1,103 @@ +#region Copyright notice and license +// Protocol Buffers - Google's data interchange format +// Copyright 2015 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#endregion +using System; + +namespace Google.Protobuf.Reflection +{ + /// <summary> + /// Extra information provided by generated code when initializing a message or file descriptor. + /// These are constructed as required, and are not long-lived. Hand-written code should + /// never need to use this type. + /// </summary> + public sealed class GeneratedClrTypeInfo + { + private static readonly string[] EmptyNames = new string[0]; + private static readonly GeneratedClrTypeInfo[] EmptyCodeInfo = new GeneratedClrTypeInfo[0]; + + /// <summary> + /// Irrelevant for file descriptors; the CLR type for the message for message descriptors. + /// </summary> + public Type ClrType { get; private set; } + + /// <summary> + /// Irrelevant for file descriptors; the parser for message descriptors. + /// </summary> + public MessageParser Parser { get; } + + /// <summary> + /// Irrelevant for file descriptors; the CLR property names (in message descriptor field order) + /// for fields in the message for message descriptors. + /// </summary> + public string[] PropertyNames { get; } + + /// <summary> + /// Irrelevant for file descriptors; the CLR property "base" names (in message descriptor oneof order) + /// for oneofs in the message for message descriptors. It is expected that for a oneof name of "Foo", + /// there will be a "FooCase" property and a "ClearFoo" method. + /// </summary> + public string[] OneofNames { get; } + + /// <summary> + /// The reflection information for types within this file/message descriptor. Elements may be null + /// if there is no corresponding generated type, e.g. for map entry types. + /// </summary> + public GeneratedClrTypeInfo[] NestedTypes { get; } + + /// <summary> + /// The CLR types for enums within this file/message descriptor. + /// </summary> + public Type[] NestedEnums { get; } + + /// <summary> + /// Creates a GeneratedClrTypeInfo for a message descriptor, with nested types, nested enums, the CLR type, property names and oneof names. + /// Each array parameter may be null, to indicate a lack of values. + /// The parameter order is designed to make it feasible to format the generated code readably. + /// </summary> + public GeneratedClrTypeInfo(Type clrType, MessageParser parser, string[] propertyNames, string[] oneofNames, Type[] nestedEnums, GeneratedClrTypeInfo[] nestedTypes) + { + NestedTypes = nestedTypes ?? EmptyCodeInfo; + NestedEnums = nestedEnums ?? ReflectionUtil.EmptyTypes; + ClrType = clrType; + Parser = parser; + PropertyNames = propertyNames ?? EmptyNames; + OneofNames = oneofNames ?? EmptyNames; + } + + /// <summary> + /// Creates a GeneratedClrTypeInfo for a file descriptor, with only types and enums. + /// </summary> + public GeneratedClrTypeInfo(Type[] nestedEnums, GeneratedClrTypeInfo[] nestedTypes) + : this(null, null, null, null, nestedEnums, nestedTypes) + { + } + } +}
\ No newline at end of file diff --git a/csharp/src/Google.Protobuf/Reflection/GeneratedCodeInfo.cs b/csharp/src/Google.Protobuf/Reflection/GeneratedCodeInfo.cs deleted file mode 100644 index ff4ad0aa..00000000 --- a/csharp/src/Google.Protobuf/Reflection/GeneratedCodeInfo.cs +++ /dev/null @@ -1,72 +0,0 @@ -using System; - -namespace Google.Protobuf.Reflection -{ - /// <summary> - /// Extra information provided by generated code when initializing a message or file descriptor. - /// These are constructed as required, and are not long-lived. Hand-written code should - /// never need to use this type. - /// </summary> - public sealed class GeneratedCodeInfo - { - private static readonly string[] EmptyNames = new string[0]; - private static readonly GeneratedCodeInfo[] EmptyCodeInfo = new GeneratedCodeInfo[0]; - - /// <summary> - /// Irrelevant for file descriptors; the CLR type for the message for message descriptors. - /// </summary> - public Type ClrType { get; private set; } - - /// <summary> - /// Irrelevant for file descriptors; the parser for message descriptors. - /// </summary> - public MessageParser Parser { get; private set; } - - /// <summary> - /// Irrelevant for file descriptors; the CLR property names (in message descriptor field order) - /// for fields in the message for message descriptors. - /// </summary> - public string[] PropertyNames { get; private set; } - - /// <summary> - /// Irrelevant for file descriptors; the CLR property "base" names (in message descriptor oneof order) - /// for oneofs in the message for message descriptors. It is expected that for a oneof name of "Foo", - /// there will be a "FooCase" property and a "ClearFoo" method. - /// </summary> - public string[] OneofNames { get; private set; } - - /// <summary> - /// The reflection information for types within this file/message descriptor. Elements may be null - /// if there is no corresponding generated type, e.g. for map entry types. - /// </summary> - public GeneratedCodeInfo[] NestedTypes { get; private set; } - - /// <summary> - /// The CLR types for enums within this file/message descriptor. - /// </summary> - public Type[] NestedEnums { get; private set; } - - /// <summary> - /// Creates a GeneratedCodeInfo for a message descriptor, with nested types, nested enums, the CLR type, property names and oneof names. - /// Each array parameter may be null, to indicate a lack of values. - /// The parameter order is designed to make it feasible to format the generated code readably. - /// </summary> - public GeneratedCodeInfo(Type clrType, MessageParser parser, string[] propertyNames, string[] oneofNames, Type[] nestedEnums, GeneratedCodeInfo[] nestedTypes) - { - NestedTypes = nestedTypes ?? EmptyCodeInfo; - NestedEnums = nestedEnums ?? ReflectionUtil.EmptyTypes; - ClrType = clrType; - Parser = parser; - PropertyNames = propertyNames ?? EmptyNames; - OneofNames = oneofNames ?? EmptyNames; - } - - /// <summary> - /// Creates a GeneratedCodeInfo for a file descriptor, with only types and enums. - /// </summary> - public GeneratedCodeInfo(Type[] nestedEnums, GeneratedCodeInfo[] nestedTypes) - : this(null, null, null, null, nestedEnums, nestedTypes) - { - } - } -}
\ No newline at end of file diff --git a/csharp/src/Google.Protobuf/Reflection/MessageDescriptor.cs b/csharp/src/Google.Protobuf/Reflection/MessageDescriptor.cs index 65040e42..f5798d1e 100644 --- a/csharp/src/Google.Protobuf/Reflection/MessageDescriptor.cs +++ b/csharp/src/Google.Protobuf/Reflection/MessageDescriptor.cs @@ -56,153 +56,156 @@ namespace Google.Protobuf.Reflection "google/protobuf/type.proto", }; - private readonly DescriptorProto proto; - private readonly MessageDescriptor containingType; - private readonly IList<MessageDescriptor> nestedTypes; - private readonly IList<EnumDescriptor> enumTypes; private readonly IList<FieldDescriptor> fieldsInDeclarationOrder; private readonly IList<FieldDescriptor> fieldsInNumberOrder; private readonly IDictionary<string, FieldDescriptor> jsonFieldMap; - private readonly FieldCollection fields; - private readonly IList<OneofDescriptor> oneofs; - // CLR representation of the type described by this descriptor, if any. - private readonly Type generatedType; - private readonly MessageParser parser; - internal MessageDescriptor(DescriptorProto proto, FileDescriptor file, MessageDescriptor parent, int typeIndex, GeneratedCodeInfo generatedCodeInfo) + internal MessageDescriptor(DescriptorProto proto, FileDescriptor file, MessageDescriptor parent, int typeIndex, GeneratedClrTypeInfo generatedCodeInfo) : base(file, file.ComputeFullName(parent, proto.Name), typeIndex) { - this.proto = proto; - parser = generatedCodeInfo == null ? null : generatedCodeInfo.Parser; - generatedType = generatedCodeInfo == null ? null : generatedCodeInfo.ClrType; - - containingType = parent; - - oneofs = DescriptorUtil.ConvertAndMakeReadOnly( + Proto = proto; + Parser = generatedCodeInfo?.Parser; + ClrType = generatedCodeInfo?.ClrType; + ContainingType = parent; + + // Note use of generatedCodeInfo. rather than generatedCodeInfo?. here... we don't expect + // to see any nested oneofs, types or enums in "not actually generated" code... we do + // expect fields though (for map entry messages). + Oneofs = DescriptorUtil.ConvertAndMakeReadOnly( proto.OneofDecl, (oneof, index) => - new OneofDescriptor(oneof, file, this, index, generatedCodeInfo == null ? null : generatedCodeInfo.OneofNames[index])); + new OneofDescriptor(oneof, file, this, index, generatedCodeInfo.OneofNames[index])); - nestedTypes = DescriptorUtil.ConvertAndMakeReadOnly( + NestedTypes = DescriptorUtil.ConvertAndMakeReadOnly( proto.NestedType, (type, index) => - new MessageDescriptor(type, file, this, index, generatedCodeInfo == null ? null : generatedCodeInfo.NestedTypes[index])); + new MessageDescriptor(type, file, this, index, generatedCodeInfo.NestedTypes[index])); - enumTypes = DescriptorUtil.ConvertAndMakeReadOnly( + EnumTypes = DescriptorUtil.ConvertAndMakeReadOnly( proto.EnumType, (type, index) => - new EnumDescriptor(type, file, this, index, generatedCodeInfo == null ? null : generatedCodeInfo.NestedEnums[index])); + new EnumDescriptor(type, file, this, index, generatedCodeInfo.NestedEnums[index])); fieldsInDeclarationOrder = DescriptorUtil.ConvertAndMakeReadOnly( proto.Field, (field, index) => - new FieldDescriptor(field, file, this, index, generatedCodeInfo == null ? null : generatedCodeInfo.PropertyNames[index])); + new FieldDescriptor(field, file, this, index, generatedCodeInfo?.PropertyNames[index])); fieldsInNumberOrder = new ReadOnlyCollection<FieldDescriptor>(fieldsInDeclarationOrder.OrderBy(field => field.FieldNumber).ToArray()); // TODO: Use field => field.Proto.JsonName when we're confident it's appropriate. (And then use it in the formatter, too.) - jsonFieldMap = new ReadOnlyDictionary<string, FieldDescriptor>(fieldsInNumberOrder.ToDictionary(field => JsonFormatter.ToCamelCase(field.Name))); + jsonFieldMap = CreateJsonFieldMap(fieldsInNumberOrder); file.DescriptorPool.AddSymbol(this); - fields = new FieldCollection(this); + Fields = new FieldCollection(this); } - - /// <summary> - /// Returns the total number of nested types and enums, recursively. - /// </summary> - private int CountTotalGeneratedTypes() + + private static ReadOnlyDictionary<string, FieldDescriptor> CreateJsonFieldMap(IList<FieldDescriptor> fields) { - return nestedTypes.Sum(nested => nested.CountTotalGeneratedTypes()) + enumTypes.Count; + var map = new Dictionary<string, FieldDescriptor>(); + foreach (var field in fields) + { + map[JsonFormatter.ToCamelCase(field.Name)] = field; + map[field.Name] = field; + } + return new ReadOnlyDictionary<string, FieldDescriptor>(map); } /// <summary> /// The brief name of the descriptor's target. /// </summary> - public override string Name { get { return proto.Name; } } + public override string Name => Proto.Name; - internal DescriptorProto Proto { get { return proto; } } + internal DescriptorProto Proto { get; } /// <summary> - /// The generated type for this message, or <c>null</c> if the descriptor does not represent a generated type. + /// The CLR type used to represent message instances from this descriptor. /// </summary> - public Type GeneratedType { get { return generatedType; } } + /// <remarks> + /// <para> + /// The value returned by this property will be non-null for all regular fields. However, + /// if a message containing a map field is introspected, the list of nested messages will include + /// an auto-generated nested key/value pair message for the field. This is not represented in any + /// generated type, so this property will return null in such cases. + /// </para> + /// <para> + /// For wrapper types (<see cref="Google.Protobuf.WellKnownTypes.StringValue"/> and the like), the type returned here + /// will be the generated message type, not the native type used by reflection for fields of those types. Code + /// using reflection should call <see cref="IsWrapperType"/> to determine whether a message descriptor represents + /// a wrapper type, and handle the result appropriately. + /// </para> + /// </remarks> + public Type ClrType { get; } /// <summary> /// A parser for this message type. /// </summary> /// <remarks> + /// <para> /// As <see cref="MessageDescriptor"/> is not generic, this cannot be statically - /// typed to the relevant type, but if <see cref="GeneratedType"/> returns a non-null value, the parser returned + /// typed to the relevant type, but it should produce objects of a type compatible with <see cref="ClrType"/>. + /// </para> + /// <para> + /// The value returned by this property will be non-null for all regular fields. However, + /// if a message containing a map field is introspected, the list of nested messages will include + /// an auto-generated nested key/value pair message for the field. No message parser object is created for + /// such messages, so this property will return null in such cases. + /// </para> + /// <para> + /// For wrapper types (<see cref="Google.Protobuf.WellKnownTypes.StringValue"/> and the like), the parser returned here + /// will be the generated message type, not the native type used by reflection for fields of those types. Code + /// using reflection should call <see cref="IsWrapperType"/> to determine whether a message descriptor represents + /// a wrapper type, and handle the result appropriately. + /// </para> /// </remarks> - public MessageParser Parser { get { return parser; } } + public MessageParser Parser { get; } /// <summary> /// Returns whether this message is one of the "well known types" which may have runtime/protoc support. /// </summary> - internal bool IsWellKnownType - { - get - { - return File.Package == "google.protobuf" && WellKnownTypeNames.Contains(File.Name); - } - } + internal bool IsWellKnownType => File.Package == "google.protobuf" && WellKnownTypeNames.Contains(File.Name); + + /// <summary> + /// Returns whether this message is one of the "wrapper types" used for fields which represent primitive values + /// with the addition of presence. + /// </summary> + internal bool IsWrapperType => File.Package == "google.protobuf" && File.Name == "google/protobuf/wrappers.proto"; /// <value> /// If this is a nested type, get the outer descriptor, otherwise null. /// </value> - public MessageDescriptor ContainingType - { - get { return containingType; } - } + public MessageDescriptor ContainingType { get; } /// <value> /// A collection of fields, which can be retrieved by name or field number. /// </value> - public FieldCollection Fields - { - get { return fields; } - } + public FieldCollection Fields { get; } /// <value> /// An unmodifiable list of this message type's nested types. /// </value> - public IList<MessageDescriptor> NestedTypes - { - get { return nestedTypes; } - } + public IList<MessageDescriptor> NestedTypes { get; } /// <value> /// An unmodifiable list of this message type's enum types. /// </value> - public IList<EnumDescriptor> EnumTypes - { - get { return enumTypes; } - } + public IList<EnumDescriptor> EnumTypes { get; } /// <value> /// An unmodifiable list of the "oneof" field collections in this message type. /// </value> - public IList<OneofDescriptor> Oneofs - { - get { return oneofs; } - } + public IList<OneofDescriptor> Oneofs { get; } /// <summary> /// Finds a field by field name. /// </summary> /// <param name="name">The unqualified name of the field (e.g. "foo").</param> /// <returns>The field's descriptor, or null if not found.</returns> - public FieldDescriptor FindFieldByName(String name) - { - return File.DescriptorPool.FindSymbol<FieldDescriptor>(FullName + "." + name); - } + public FieldDescriptor FindFieldByName(String name) => File.DescriptorPool.FindSymbol<FieldDescriptor>(FullName + "." + name); /// <summary> /// Finds a field by field number. /// </summary> /// <param name="number">The field number within this message type.</param> /// <returns>The field's descriptor, or null if not found.</returns> - public FieldDescriptor FindFieldByNumber(int number) - { - return File.DescriptorPool.FindFieldByNumber(this, number); - } + public FieldDescriptor FindFieldByNumber(int number) => File.DescriptorPool.FindFieldByNumber(this, number); /// <summary> /// Finds a nested descriptor by name. The is valid for fields, nested @@ -210,18 +213,15 @@ namespace Google.Protobuf.Reflection /// </summary> /// <param name="name">The unqualified name of the descriptor, e.g. "Foo"</param> /// <returns>The descriptor, or null if not found.</returns> - public T FindDescriptor<T>(string name) - where T : class, IDescriptor - { - return File.DescriptorPool.FindSymbol<T>(FullName + "." + name); - } + public T FindDescriptor<T>(string name) where T : class, IDescriptor => + File.DescriptorPool.FindSymbol<T>(FullName + "." + name); /// <summary> /// Looks up and cross-links all fields and nested types. /// </summary> internal void CrossLink() { - foreach (MessageDescriptor message in nestedTypes) + foreach (MessageDescriptor message in NestedTypes) { message.CrossLink(); } @@ -231,7 +231,7 @@ namespace Google.Protobuf.Reflection field.CrossLink(); } - foreach (OneofDescriptor oneof in oneofs) + foreach (OneofDescriptor oneof in Oneofs) { oneof.CrossLink(); } @@ -253,10 +253,7 @@ namespace Google.Protobuf.Reflection /// Returns the fields in the message as an immutable list, in the order in which they /// are declared in the source .proto file. /// </value> - public IList<FieldDescriptor> InDeclarationOrder() - { - return messageDescriptor.fieldsInDeclarationOrder; - } + public IList<FieldDescriptor> InDeclarationOrder() => messageDescriptor.fieldsInDeclarationOrder; /// <value> /// Returns the fields in the message as an immutable list, in ascending field number @@ -264,22 +261,17 @@ namespace Google.Protobuf.Reflection /// index in the list to the field number; to retrieve a field by field number, it is better /// to use the <see cref="FieldCollection"/> indexer. /// </value> - public IList<FieldDescriptor> InFieldNumberOrder() - { - return messageDescriptor.fieldsInNumberOrder; - } + public IList<FieldDescriptor> InFieldNumberOrder() => messageDescriptor.fieldsInNumberOrder; // TODO: consider making this public in the future. (Being conservative for now...) /// <value> - /// Returns a read-only dictionary mapping the field names in this message as they're used + /// Returns a read-only dictionary mapping the field names in this message as they're available /// in the JSON representation to the field descriptors. For example, a field <c>foo_bar</c> - /// in the message would result in an entry with a key <c>fooBar</c>. + /// in the message would result two entries, one with a key <c>fooBar</c> and one with a key + /// <c>foo_bar</c>, both referring to the same field. /// </value> - internal IDictionary<string, FieldDescriptor> ByJsonName() - { - return messageDescriptor.jsonFieldMap; - } + internal IDictionary<string, FieldDescriptor> ByJsonName() => messageDescriptor.jsonFieldMap; /// <summary> /// Retrieves the descriptor for the field with the given number. diff --git a/csharp/src/Google.Protobuf/Reflection/OneofDescriptor.cs b/csharp/src/Google.Protobuf/Reflection/OneofDescriptor.cs index d51ee526..22020acf 100644 --- a/csharp/src/Google.Protobuf/Reflection/OneofDescriptor.cs +++ b/csharp/src/Google.Protobuf/Reflection/OneofDescriptor.cs @@ -86,8 +86,7 @@ namespace Google.Protobuf.Reflection /// in a particular message. /// </summary> /// <value> - /// The accessor used for reflective access, or <c>null</c> if reflection is not - /// supported by this descriptor. + /// The accessor used for reflective access. /// </value> public OneofAccessor Accessor { get { return accessor; } } @@ -106,19 +105,15 @@ namespace Google.Protobuf.Reflection private OneofAccessor CreateAccessor(string clrName) { - if (containingType.GeneratedType == null || clrName == null) - { - return null; - } - var caseProperty = containingType.GeneratedType.GetProperty(clrName + "Case"); + var caseProperty = containingType.ClrType.GetProperty(clrName + "Case"); if (caseProperty == null) { - throw new DescriptorValidationException(this, "Property " + clrName + "Case not found in " + containingType.GeneratedType); + throw new DescriptorValidationException(this, $"Property {clrName}Case not found in {containingType.ClrType}"); } - var clearMethod = containingType.GeneratedType.GetMethod("Clear" + clrName); + var clearMethod = containingType.ClrType.GetMethod("Clear" + clrName); if (clearMethod == null) { - throw new DescriptorValidationException(this, "Method Clear" + clrName + " not found in " + containingType.GeneratedType); + throw new DescriptorValidationException(this, $"Method Clear{clrName} not found in {containingType.ClrType}"); } return new OneofAccessor(caseProperty, clearMethod, this); diff --git a/csharp/src/Google.Protobuf/Reflection/TypeRegistry.cs b/csharp/src/Google.Protobuf/Reflection/TypeRegistry.cs new file mode 100644 index 00000000..e94e3e6c --- /dev/null +++ b/csharp/src/Google.Protobuf/Reflection/TypeRegistry.cs @@ -0,0 +1,183 @@ +#region Copyright notice and license +// Protocol Buffers - Google's data interchange format +// Copyright 2015 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#endregion +using System.Collections.Generic; +using System.Linq; + +namespace Google.Protobuf.Reflection +{ + /// <summary> + /// An immutable registry of types which can be looked up by their full name. + /// </summary> + public sealed class TypeRegistry + { + /// <summary> + /// An empty type registry, containing no types. + /// </summary> + public static TypeRegistry Empty { get; } = new TypeRegistry(new Dictionary<string, MessageDescriptor>()); + + private readonly Dictionary<string, MessageDescriptor> fullNameToMessageMap; + + private TypeRegistry(Dictionary<string, MessageDescriptor> fullNameToMessageMap) + { + this.fullNameToMessageMap = fullNameToMessageMap; + } + + /// <summary> + /// Attempts to find a message descriptor by its full name. + /// </summary> + /// <param name="fullName">The full name of the message, which is the dot-separated + /// combination of package, containing messages and message name</param> + /// <returns>The message descriptor corresponding to <paramref name="fullName"/> or null + /// if there is no such message descriptor.</returns> + public MessageDescriptor Find(string fullName) + { + MessageDescriptor ret; + // Ignore the return value as ret will end up with the right value either way. + fullNameToMessageMap.TryGetValue(fullName, out ret); + return ret; + } + + /// <summary> + /// Creates a type registry from the specified set of file descriptors. + /// </summary> + /// <remarks> + /// This is a convenience overload for <see cref="FromFiles(IEnumerable{FileDescriptor})"/> + /// to allow calls such as <c>TypeRegistry.FromFiles(descriptor1, descriptor2)</c>. + /// </remarks> + /// <param name="fileDescriptors">The set of files to include in the registry. Must not contain null values.</param> + /// <returns>A type registry for the given files.</returns> + public static TypeRegistry FromFiles(params FileDescriptor[] fileDescriptors) + { + return FromFiles((IEnumerable<FileDescriptor>) fileDescriptors); + } + + /// <summary> + /// Creates a type registry from the specified set of file descriptors. + /// </summary> + /// <remarks> + /// All message types within all the specified files are added to the registry, and + /// the dependencies of the specified files are also added, recursively. + /// </remarks> + /// <param name="fileDescriptors">The set of files to include in the registry. Must not contain null values.</param> + /// <returns>A type registry for the given files.</returns> + public static TypeRegistry FromFiles(IEnumerable<FileDescriptor> fileDescriptors) + { + ProtoPreconditions.CheckNotNull(fileDescriptors, nameof(fileDescriptors)); + var builder = new Builder(); + foreach (var file in fileDescriptors) + { + builder.AddFile(file); + } + return builder.Build(); + } + + /// <summary> + /// Creates a type registry from the file descriptor parents of the specified set of message descriptors. + /// </summary> + /// <remarks> + /// This is a convenience overload for <see cref="FromMessages(IEnumerable{MessageDescriptor})"/> + /// to allow calls such as <c>TypeRegistry.FromFiles(descriptor1, descriptor2)</c>. + /// </remarks> + /// <param name="messageDescriptors">The set of message descriptors to use to identify file descriptors to include in the registry. + /// Must not contain null values.</param> + /// <returns>A type registry for the given files.</returns> + public static TypeRegistry FromMessages(params MessageDescriptor[] messageDescriptors) + { + return FromMessages((IEnumerable<MessageDescriptor>) messageDescriptors); + } + + /// <summary> + /// Creates a type registry from the file descriptor parents of the specified set of message descriptors. + /// </summary> + /// <remarks> + /// The specified message descriptors are only used to identify their file descriptors; the returned registry + /// contains all the types within the file descriptors which contain the specified message descriptors (and + /// the dependencies of those files), not just the specified messages. + /// </remarks> + /// <param name="messageDescriptors">The set of message descriptors to use to identify file descriptors to include in the registry. + /// Must not contain null values.</param> + /// <returns>A type registry for the given files.</returns> + public static TypeRegistry FromMessages(IEnumerable<MessageDescriptor> messageDescriptors) + { + ProtoPreconditions.CheckNotNull(messageDescriptors, nameof(messageDescriptors)); + return FromFiles(messageDescriptors.Select(md => md.File)); + } + + /// <summary> + /// Builder class which isn't exposed, but acts as a convenient alternative to passing round two dictionaries in recursive calls. + /// </summary> + private class Builder + { + private readonly Dictionary<string, MessageDescriptor> types; + private readonly HashSet<string> fileDescriptorNames; + + internal Builder() + { + types = new Dictionary<string, MessageDescriptor>(); + fileDescriptorNames = new HashSet<string>(); + } + + internal void AddFile(FileDescriptor fileDescriptor) + { + if (!fileDescriptorNames.Add(fileDescriptor.Name)) + { + return; + } + foreach (var dependency in fileDescriptor.Dependencies) + { + AddFile(dependency); + } + foreach (var message in fileDescriptor.MessageTypes) + { + AddMessage(message); + } + } + + private void AddMessage(MessageDescriptor messageDescriptor) + { + foreach (var nestedType in messageDescriptor.NestedTypes) + { + AddMessage(nestedType); + } + // This will overwrite any previous entry. Given that each file should + // only be added once, this could be a problem such as package A.B with type C, + // and package A with type B.C... it's unclear what we should do in that case. + types[messageDescriptor.FullName] = messageDescriptor; + } + + internal TypeRegistry Build() + { + return new TypeRegistry(types); + } + } + } +} diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/Any.cs b/csharp/src/Google.Protobuf/WellKnownTypes/Any.cs index c69bec04..48cd99a1 100644 --- a/csharp/src/Google.Protobuf/WellKnownTypes/Any.cs +++ b/csharp/src/Google.Protobuf/WellKnownTypes/Any.cs @@ -27,10 +27,10 @@ namespace Google.Protobuf.WellKnownTypes { "JgoDQW55EhAKCHR5cGVfdXJsGAEgASgJEg0KBXZhbHVlGAIgASgMQksKE2Nv", "bS5nb29nbGUucHJvdG9idWZCCEFueVByb3RvUAGgAQGiAgNHUEKqAh5Hb29n", "bGUuUHJvdG9idWYuV2VsbEtub3duVHlwZXNiBnByb3RvMw==")); - descriptor = pbr::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData, + descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, new pbr::FileDescriptor[] { }, - new pbr::GeneratedCodeInfo(null, new pbr::GeneratedCodeInfo[] { - new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.WellKnownTypes.Any), global::Google.Protobuf.WellKnownTypes.Any.Parser, new[]{ "TypeUrl", "Value" }, null, null, null) + new pbr::GeneratedClrTypeInfo(null, new pbr::GeneratedClrTypeInfo[] { + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.WellKnownTypes.Any), global::Google.Protobuf.WellKnownTypes.Any.Parser, new[]{ "TypeUrl", "Value" }, null, null, null) })); } #endregion @@ -61,8 +61,8 @@ namespace Google.Protobuf.WellKnownTypes { /// /// If the embedded message type is well-known and has a custom JSON /// representation, that representation will be embedded adding a field - /// `value` which holds the custom JSON in addition to the the `@type` - /// field. Example (for message [google.protobuf.Duration][google.protobuf.Duration]): + /// `value` which holds the custom JSON in addition to the `@type` + /// field. Example (for message [google.protobuf.Duration][]): /// /// { /// "@type": "type.googleapis.com/google.protobuf.Duration", @@ -110,7 +110,7 @@ namespace Google.Protobuf.WellKnownTypes { /// * If no schema is provided, `https` is assumed. /// * The last segment of the URL's path must represent the fully /// qualified name of the type (as in `path/google.protobuf.Duration`). - /// * An HTTP GET on the URL must yield a [google.protobuf.Type][google.protobuf.Type] + /// * An HTTP GET on the URL must yield a [google.protobuf.Type][] /// value in binary format, or produce an error. /// * Applications are allowed to cache lookup results based on the /// URL, or have them precompiled into a binary to avoid any @@ -124,7 +124,7 @@ namespace Google.Protobuf.WellKnownTypes { public string TypeUrl { get { return typeUrl_; } set { - typeUrl_ = pb::Preconditions.CheckNotNull(value, "value"); + typeUrl_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } @@ -137,7 +137,7 @@ namespace Google.Protobuf.WellKnownTypes { public pb::ByteString Value { get { return value_; } set { - value_ = pb::Preconditions.CheckNotNull(value, "value"); + value_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } @@ -165,7 +165,7 @@ namespace Google.Protobuf.WellKnownTypes { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/AnyPartial.cs b/csharp/src/Google.Protobuf/WellKnownTypes/AnyPartial.cs index 082f7432..9d43856e 100644 --- a/csharp/src/Google.Protobuf/WellKnownTypes/AnyPartial.cs +++ b/csharp/src/Google.Protobuf/WellKnownTypes/AnyPartial.cs @@ -72,7 +72,7 @@ namespace Google.Protobuf.WellKnownTypes /// <returns>An Any message with the content and type URL of <paramref name="message"/>.</returns> public static Any Pack(IMessage message) { - Preconditions.CheckNotNull(message, "message"); + ProtoPreconditions.CheckNotNull(message, "message"); return new Any { TypeUrl = GetTypeUrl(message.Descriptor), Value = message.ToByteString() }; } } diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/Api.cs b/csharp/src/Google.Protobuf/WellKnownTypes/Api.cs index 23528994..de7aea3a 100644 --- a/csharp/src/Google.Protobuf/WellKnownTypes/Api.cs +++ b/csharp/src/Google.Protobuf/WellKnownTypes/Api.cs @@ -39,12 +39,12 @@ namespace Google.Protobuf.WellKnownTypes { "eCIjCgVNaXhpbhIMCgRuYW1lGAEgASgJEgwKBHJvb3QYAiABKAlCSwoTY29t", "Lmdvb2dsZS5wcm90b2J1ZkIIQXBpUHJvdG9QAaABAaICA0dQQqoCHkdvb2ds", "ZS5Qcm90b2J1Zi5XZWxsS25vd25UeXBlc2IGcHJvdG8z")); - descriptor = pbr::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData, + descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, new pbr::FileDescriptor[] { global::Google.Protobuf.WellKnownTypes.SourceContextReflection.Descriptor, global::Google.Protobuf.WellKnownTypes.TypeReflection.Descriptor, }, - new pbr::GeneratedCodeInfo(null, new pbr::GeneratedCodeInfo[] { - new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.WellKnownTypes.Api), global::Google.Protobuf.WellKnownTypes.Api.Parser, new[]{ "Name", "Methods", "Options", "Version", "SourceContext", "Mixins", "Syntax" }, null, null, null), - new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.WellKnownTypes.Method), global::Google.Protobuf.WellKnownTypes.Method.Parser, new[]{ "Name", "RequestTypeUrl", "RequestStreaming", "ResponseTypeUrl", "ResponseStreaming", "Options", "Syntax" }, null, null, null), - new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.WellKnownTypes.Mixin), global::Google.Protobuf.WellKnownTypes.Mixin.Parser, new[]{ "Name", "Root" }, null, null, null) + new pbr::GeneratedClrTypeInfo(null, new pbr::GeneratedClrTypeInfo[] { + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.WellKnownTypes.Api), global::Google.Protobuf.WellKnownTypes.Api.Parser, new[]{ "Name", "Methods", "Options", "Version", "SourceContext", "Mixins", "Syntax" }, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.WellKnownTypes.Method), global::Google.Protobuf.WellKnownTypes.Method.Parser, new[]{ "Name", "RequestTypeUrl", "RequestStreaming", "ResponseTypeUrl", "ResponseStreaming", "Options", "Syntax" }, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.WellKnownTypes.Mixin), global::Google.Protobuf.WellKnownTypes.Mixin.Parser, new[]{ "Name", "Root" }, null, null, null) })); } #endregion @@ -97,7 +97,7 @@ namespace Google.Protobuf.WellKnownTypes { public string Name { get { return name_; } set { - name_ = pb::Preconditions.CheckNotNull(value, "value"); + name_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } @@ -153,7 +153,7 @@ namespace Google.Protobuf.WellKnownTypes { public string Version { get { return version_; } set { - version_ = pb::Preconditions.CheckNotNull(value, "value"); + version_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } @@ -230,7 +230,7 @@ namespace Google.Protobuf.WellKnownTypes { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -388,7 +388,7 @@ namespace Google.Protobuf.WellKnownTypes { public string Name { get { return name_; } set { - name_ = pb::Preconditions.CheckNotNull(value, "value"); + name_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } @@ -401,7 +401,7 @@ namespace Google.Protobuf.WellKnownTypes { public string RequestTypeUrl { get { return requestTypeUrl_; } set { - requestTypeUrl_ = pb::Preconditions.CheckNotNull(value, "value"); + requestTypeUrl_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } @@ -427,7 +427,7 @@ namespace Google.Protobuf.WellKnownTypes { public string ResponseTypeUrl { get { return responseTypeUrl_; } set { - responseTypeUrl_ = pb::Preconditions.CheckNotNull(value, "value"); + responseTypeUrl_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } @@ -503,7 +503,7 @@ namespace Google.Protobuf.WellKnownTypes { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -653,7 +653,6 @@ namespace Google.Protobuf.WellKnownTypes { /// /// package google.storage.v2; /// service Storage { - /// // (-- see AccessControl.GetAcl --) /// rpc GetAcl(GetAclRequest) returns (Acl); /// /// // Get a data record. @@ -741,7 +740,7 @@ namespace Google.Protobuf.WellKnownTypes { public string Name { get { return name_; } set { - name_ = pb::Preconditions.CheckNotNull(value, "value"); + name_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } @@ -755,7 +754,7 @@ namespace Google.Protobuf.WellKnownTypes { public string Root { get { return root_; } set { - root_ = pb::Preconditions.CheckNotNull(value, "value"); + root_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } @@ -783,7 +782,7 @@ namespace Google.Protobuf.WellKnownTypes { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/Duration.cs b/csharp/src/Google.Protobuf/WellKnownTypes/Duration.cs index 7b3767a2..73e221d4 100644 --- a/csharp/src/Google.Protobuf/WellKnownTypes/Duration.cs +++ b/csharp/src/Google.Protobuf/WellKnownTypes/Duration.cs @@ -28,10 +28,10 @@ namespace Google.Protobuf.WellKnownTypes { "ASgFQlAKE2NvbS5nb29nbGUucHJvdG9idWZCDUR1cmF0aW9uUHJvdG9QAaAB", "AaICA0dQQqoCHkdvb2dsZS5Qcm90b2J1Zi5XZWxsS25vd25UeXBlc2IGcHJv", "dG8z")); - descriptor = pbr::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData, + descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, new pbr::FileDescriptor[] { }, - new pbr::GeneratedCodeInfo(null, new pbr::GeneratedCodeInfo[] { - new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.WellKnownTypes.Duration), global::Google.Protobuf.WellKnownTypes.Duration.Parser, new[]{ "Seconds", "Nanos" }, null, null, null) + new pbr::GeneratedClrTypeInfo(null, new pbr::GeneratedClrTypeInfo[] { + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.WellKnownTypes.Duration), global::Google.Protobuf.WellKnownTypes.Duration.Parser, new[]{ "Seconds", "Nanos" }, null, null, null) })); } #endregion @@ -164,7 +164,7 @@ namespace Google.Protobuf.WellKnownTypes { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/DurationPartial.cs b/csharp/src/Google.Protobuf/WellKnownTypes/DurationPartial.cs index 324f48fc..f164bfd1 100644 --- a/csharp/src/Google.Protobuf/WellKnownTypes/DurationPartial.cs +++ b/csharp/src/Google.Protobuf/WellKnownTypes/DurationPartial.cs @@ -31,12 +31,14 @@ #endregion using System; +using System.Globalization; +using System.Text; namespace Google.Protobuf.WellKnownTypes { // Manually-written partial class for the Duration well-known type, // providing a conversion to TimeSpan and convenience operators. - public partial class Duration + public partial class Duration : ICustomDiagnosticMessage { /// <summary> /// The number of nanoseconds in a second. @@ -57,15 +59,37 @@ namespace Google.Protobuf.WellKnownTypes /// </summary> public const long MinSeconds = -315576000000L; + internal const int MaxNanoseconds = NanosecondsPerSecond - 1; + internal const int MinNanoseconds = -NanosecondsPerSecond + 1; + + internal static bool IsNormalized(long seconds, int nanoseconds) + { + // Simple boundaries + if (seconds < MinSeconds || seconds > MaxSeconds || + nanoseconds < MinNanoseconds || nanoseconds > MaxNanoseconds) + { + return false; + } + // We only have a problem is one is strictly negative and the other is + // strictly positive. + return Math.Sign(seconds) * Math.Sign(nanoseconds) != -1; + } + /// <summary> /// Converts this <see cref="Duration"/> to a <see cref="TimeSpan"/>. /// </summary> /// <remarks>If the duration is not a precise number of ticks, it is truncated towards 0.</remarks> /// <returns>The value of this duration, as a <c>TimeSpan</c>.</returns> + /// <exception cref="InvalidOperationException">This value isn't a valid normalized duration, as + /// described in the documentation.</exception> public TimeSpan ToTimeSpan() { checked { + if (!IsNormalized(Seconds, Nanos)) + { + throw new InvalidOperationException("Duration was not a valid normalized duration"); + } long ticks = Seconds * TimeSpan.TicksPerSecond + Nanos / NanosecondsPerTick; return TimeSpan.FromTicks(ticks); } @@ -94,7 +118,7 @@ namespace Google.Protobuf.WellKnownTypes /// <returns>The negated value of this duration.</returns> public static Duration operator -(Duration value) { - Preconditions.CheckNotNull(value, "value"); + ProtoPreconditions.CheckNotNull(value, "value"); checked { return Normalize(-value.Seconds, -value.Nanos); @@ -109,8 +133,8 @@ namespace Google.Protobuf.WellKnownTypes /// <returns></returns> public static Duration operator +(Duration lhs, Duration rhs) { - Preconditions.CheckNotNull(lhs, "lhs"); - Preconditions.CheckNotNull(rhs, "rhs"); + ProtoPreconditions.CheckNotNull(lhs, "lhs"); + ProtoPreconditions.CheckNotNull(rhs, "rhs"); checked { return Normalize(lhs.Seconds + rhs.Seconds, lhs.Nanos + rhs.Nanos); @@ -125,8 +149,8 @@ namespace Google.Protobuf.WellKnownTypes /// <returns>The difference between the two specified durations.</returns> public static Duration operator -(Duration lhs, Duration rhs) { - Preconditions.CheckNotNull(lhs, "lhs"); - Preconditions.CheckNotNull(rhs, "rhs"); + ProtoPreconditions.CheckNotNull(lhs, "lhs"); + ProtoPreconditions.CheckNotNull(rhs, "rhs"); checked { return Normalize(lhs.Seconds - rhs.Seconds, lhs.Nanos - rhs.Nanos); @@ -157,5 +181,90 @@ namespace Google.Protobuf.WellKnownTypes } return new Duration { Seconds = seconds, Nanos = nanoseconds }; } + + /// <summary> + /// Converts a duration specified in seconds/nanoseconds to a string. + /// </summary> + /// <remarks> + /// If the value is a normalized duration in the range described in <c>duration.proto</c>, + /// <paramref name="diagnosticOnly"/> is ignored. Otherwise, if the parameter is <c>true</c>, + /// a JSON object with a warning is returned; if it is <c>false</c>, an <see cref="InvalidOperationException"/> is thrown. + /// </remarks> + /// <param name="seconds">Seconds portion of the duration.</param> + /// <param name="nanoseconds">Nanoseconds portion of the duration.</param> + /// <param name="diagnosticOnly">Determines the handling of non-normalized values</param> + /// <exception cref="InvalidOperationException">The represented duration is invalid, and <paramref name="diagnosticOnly"/> is <c>false</c>.</exception> + internal static string ToJson(long seconds, int nanoseconds, bool diagnosticOnly) + { + if (IsNormalized(seconds, nanoseconds)) + { + var builder = new StringBuilder(); + builder.Append('"'); + // The seconds part will normally provide the minus sign if we need it, but not if it's 0... + if (seconds == 0 && nanoseconds < 0) + { + builder.Append('-'); + } + + builder.Append(seconds.ToString("d", CultureInfo.InvariantCulture)); + AppendNanoseconds(builder, Math.Abs(nanoseconds)); + builder.Append("s\""); + return builder.ToString(); + } + if (diagnosticOnly) + { + // Note: the double braces here are escaping for braces in format strings. + return string.Format(CultureInfo.InvariantCulture, + "{{ \"@warning\": \"Invalid Duration\", \"seconds\": \"{0}\", \"nanos\": {1} }}", + seconds, + nanoseconds); + } + else + { + throw new InvalidOperationException("Non-normalized duration value"); + } + } + + /// <summary> + /// Returns a string representation of this <see cref="Duration"/> for diagnostic purposes. + /// </summary> + /// <remarks> + /// Normally the returned value will be a JSON string value (including leading and trailing quotes) but + /// when the value is non-normalized or out of range, a JSON object representation will be returned + /// instead, including a warning. This is to avoid exceptions being thrown when trying to + /// diagnose problems - the regular JSON formatter will still throw an exception for non-normalized + /// values. + /// </remarks> + /// <returns>A string representation of this value.</returns> + public string ToDiagnosticString() + { + return ToJson(Seconds, Nanos, true); + } + + /// <summary> + /// Appends a number of nanoseconds to a StringBuilder. Either 0 digits are added (in which + /// case no "." is appended), or 3 6 or 9 digits. This is internal for use in Timestamp as well + /// as Duration. + /// </summary> + internal static void AppendNanoseconds(StringBuilder builder, int nanos) + { + if (nanos != 0) + { + builder.Append('.'); + // Output to 3, 6 or 9 digits. + if (nanos % 1000000 == 0) + { + builder.Append((nanos / 1000000).ToString("d3", CultureInfo.InvariantCulture)); + } + else if (nanos % 1000 == 0) + { + builder.Append((nanos / 1000).ToString("d6", CultureInfo.InvariantCulture)); + } + else + { + builder.Append(nanos.ToString("d9", CultureInfo.InvariantCulture)); + } + } + } } } diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/Empty.cs b/csharp/src/Google.Protobuf/WellKnownTypes/Empty.cs index 3b09f1e8..6cad4124 100644 --- a/csharp/src/Google.Protobuf/WellKnownTypes/Empty.cs +++ b/csharp/src/Google.Protobuf/WellKnownTypes/Empty.cs @@ -24,13 +24,13 @@ namespace Google.Protobuf.WellKnownTypes { byte[] descriptorData = global::System.Convert.FromBase64String( string.Concat( "Chtnb29nbGUvcHJvdG9idWYvZW1wdHkucHJvdG8SD2dvb2dsZS5wcm90b2J1", - "ZiIHCgVFbXB0eUJNChNjb20uZ29vZ2xlLnByb3RvYnVmQgpFbXB0eVByb3Rv", - "UAGgAQGiAgNHUEKqAh5Hb29nbGUuUHJvdG9idWYuV2VsbEtub3duVHlwZXNi", - "BnByb3RvMw==")); - descriptor = pbr::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData, + "ZiIHCgVFbXB0eUJQChNjb20uZ29vZ2xlLnByb3RvYnVmQgpFbXB0eVByb3Rv", + "UAGgAQH4AQGiAgNHUEKqAh5Hb29nbGUuUHJvdG9idWYuV2VsbEtub3duVHlw", + "ZXNiBnByb3RvMw==")); + descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, new pbr::FileDescriptor[] { }, - new pbr::GeneratedCodeInfo(null, new pbr::GeneratedCodeInfo[] { - new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.WellKnownTypes.Empty), global::Google.Protobuf.WellKnownTypes.Empty.Parser, null, null, null, null) + new pbr::GeneratedClrTypeInfo(null, new pbr::GeneratedClrTypeInfo[] { + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.WellKnownTypes.Empty), global::Google.Protobuf.WellKnownTypes.Empty.Parser, null, null, null, null) })); } #endregion @@ -94,7 +94,7 @@ namespace Google.Protobuf.WellKnownTypes { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/FieldMask.cs b/csharp/src/Google.Protobuf/WellKnownTypes/FieldMask.cs index 3ec74cbe..2ba2b96f 100644 --- a/csharp/src/Google.Protobuf/WellKnownTypes/FieldMask.cs +++ b/csharp/src/Google.Protobuf/WellKnownTypes/FieldMask.cs @@ -27,10 +27,10 @@ namespace Google.Protobuf.WellKnownTypes { "b3RvYnVmIhoKCUZpZWxkTWFzaxINCgVwYXRocxgBIAMoCUJRChNjb20uZ29v", "Z2xlLnByb3RvYnVmQg5GaWVsZE1hc2tQcm90b1ABoAEBogIDR1BCqgIeR29v", "Z2xlLlByb3RvYnVmLldlbGxLbm93blR5cGVzYgZwcm90bzM=")); - descriptor = pbr::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData, + descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, new pbr::FileDescriptor[] { }, - new pbr::GeneratedCodeInfo(null, new pbr::GeneratedCodeInfo[] { - new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.WellKnownTypes.FieldMask), global::Google.Protobuf.WellKnownTypes.FieldMask.Parser, new[]{ "Paths" }, null, null, null) + new pbr::GeneratedClrTypeInfo(null, new pbr::GeneratedClrTypeInfo[] { + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.WellKnownTypes.FieldMask), global::Google.Protobuf.WellKnownTypes.FieldMask.Parser, new[]{ "Paths" }, null, null, null) })); } #endregion @@ -69,7 +69,7 @@ namespace Google.Protobuf.WellKnownTypes { /// z: 8 /// /// The result will not contain specific values for fields x,y and z - /// (there value will be set to the default, and omitted in proto text + /// (their value will be set to the default, and omitted in proto text /// output): /// /// f { @@ -221,7 +221,7 @@ namespace Google.Protobuf.WellKnownTypes { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/FieldMaskPartial.cs b/csharp/src/Google.Protobuf/WellKnownTypes/FieldMaskPartial.cs new file mode 100644 index 00000000..df1292dc --- /dev/null +++ b/csharp/src/Google.Protobuf/WellKnownTypes/FieldMaskPartial.cs @@ -0,0 +1,122 @@ +#region Copyright notice and license +// Protocol Buffers - Google's data interchange format +// Copyright 2016 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#endregion + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Google.Protobuf.WellKnownTypes +{ + // Manually-written partial class for the FieldMask well-known type. + public partial class FieldMask : ICustomDiagnosticMessage + { + /// <summary> + /// Converts a timestamp specified in seconds/nanoseconds to a string. + /// </summary> + /// <remarks> + /// If the value is a normalized duration in the range described in <c>field_mask.proto</c>, + /// <paramref name="diagnosticOnly"/> is ignored. Otherwise, if the parameter is <c>true</c>, + /// a JSON object with a warning is returned; if it is <c>false</c>, an <see cref="InvalidOperationException"/> is thrown. + /// </remarks> + /// <param name="paths">Paths in the field mask</param> + /// <param name="diagnosticOnly">Determines the handling of non-normalized values</param> + /// <exception cref="InvalidOperationException">The represented duration is invalid, and <paramref name="diagnosticOnly"/> is <c>false</c>.</exception> + internal static string ToJson(IList<string> paths, bool diagnosticOnly) + { + var firstInvalid = paths.FirstOrDefault(p => !ValidatePath(p)); + if (firstInvalid == null) + { + var builder = new StringBuilder(); + JsonFormatter.WriteString(builder, string.Join(",", paths.Select(JsonFormatter.ToCamelCase))); + return builder.ToString(); + } + else + { + if (diagnosticOnly) + { + var builder = new StringBuilder(); + builder.Append("{ \"@warning\": \"Invalid FieldMask\", \"paths\": "); + JsonFormatter.Default.WriteList(builder, (IList) paths); + builder.Append(" }"); + return builder.ToString(); + } + else + { + throw new InvalidOperationException($"Invalid field mask to be converted to JSON: {firstInvalid}"); + } + } + } + + /// <summary> + /// Camel-case converter with added strictness for field mask formatting. + /// </summary> + /// <exception cref="InvalidOperationException">The field mask is invalid for JSON representation</exception> + private static bool ValidatePath(string input) + { + for (int i = 0; i < input.Length; i++) + { + char c = input[i]; + if (c >= 'A' && c <= 'Z') + { + return false; + } + if (c == '_' && i < input.Length - 1) + { + char next = input[i + 1]; + if (next < 'a' || next > 'z') + { + return false; + } + } + } + return true; + } + + /// <summary> + /// Returns a string representation of this <see cref="FieldMask"/> for diagnostic purposes. + /// </summary> + /// <remarks> + /// Normally the returned value will be a JSON string value (including leading and trailing quotes) but + /// when the value is non-normalized or out of range, a JSON object representation will be returned + /// instead, including a warning. This is to avoid exceptions being thrown when trying to + /// diagnose problems - the regular JSON formatter will still throw an exception for non-normalized + /// values. + /// </remarks> + /// <returns>A string representation of this value.</returns> + public string ToDiagnosticString() + { + return ToJson(Paths, true); + } + } +} diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/SourceContext.cs b/csharp/src/Google.Protobuf/WellKnownTypes/SourceContext.cs index cf12e6c6..a235ecef 100644 --- a/csharp/src/Google.Protobuf/WellKnownTypes/SourceContext.cs +++ b/csharp/src/Google.Protobuf/WellKnownTypes/SourceContext.cs @@ -28,10 +28,10 @@ namespace Google.Protobuf.WellKnownTypes { "CUJVChNjb20uZ29vZ2xlLnByb3RvYnVmQhJTb3VyY2VDb250ZXh0UHJvdG9Q", "AaABAaICA0dQQqoCHkdvb2dsZS5Qcm90b2J1Zi5XZWxsS25vd25UeXBlc2IG", "cHJvdG8z")); - descriptor = pbr::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData, + descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, new pbr::FileDescriptor[] { }, - new pbr::GeneratedCodeInfo(null, new pbr::GeneratedCodeInfo[] { - new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.WellKnownTypes.SourceContext), global::Google.Protobuf.WellKnownTypes.SourceContext.Parser, new[]{ "FileName" }, null, null, null) + new pbr::GeneratedClrTypeInfo(null, new pbr::GeneratedClrTypeInfo[] { + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.WellKnownTypes.SourceContext), global::Google.Protobuf.WellKnownTypes.SourceContext.Parser, new[]{ "FileName" }, null, null, null) })); } #endregion @@ -79,7 +79,7 @@ namespace Google.Protobuf.WellKnownTypes { public string FileName { get { return fileName_; } set { - fileName_ = pb::Preconditions.CheckNotNull(value, "value"); + fileName_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } @@ -105,7 +105,7 @@ namespace Google.Protobuf.WellKnownTypes { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/Struct.cs b/csharp/src/Google.Protobuf/WellKnownTypes/Struct.cs index 54d5a806..8e2ce8cf 100644 --- a/csharp/src/Google.Protobuf/WellKnownTypes/Struct.cs +++ b/csharp/src/Google.Protobuf/WellKnownTypes/Struct.cs @@ -37,12 +37,12 @@ namespace Google.Protobuf.WellKnownTypes { "QUxVRRAAQk4KE2NvbS5nb29nbGUucHJvdG9idWZCC1N0cnVjdFByb3RvUAGg", "AQGiAgNHUEKqAh5Hb29nbGUuUHJvdG9idWYuV2VsbEtub3duVHlwZXNiBnBy", "b3RvMw==")); - descriptor = pbr::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData, + descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, new pbr::FileDescriptor[] { }, - new pbr::GeneratedCodeInfo(new[] {typeof(global::Google.Protobuf.WellKnownTypes.NullValue), }, new pbr::GeneratedCodeInfo[] { - new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.WellKnownTypes.Struct), global::Google.Protobuf.WellKnownTypes.Struct.Parser, new[]{ "Fields" }, null, null, new pbr::GeneratedCodeInfo[] { null, }), - new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.WellKnownTypes.Value), global::Google.Protobuf.WellKnownTypes.Value.Parser, new[]{ "NullValue", "NumberValue", "StringValue", "BoolValue", "StructValue", "ListValue" }, new[]{ "Kind" }, null, null), - new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.WellKnownTypes.ListValue), global::Google.Protobuf.WellKnownTypes.ListValue.Parser, new[]{ "Values" }, null, null, null) + new pbr::GeneratedClrTypeInfo(new[] {typeof(global::Google.Protobuf.WellKnownTypes.NullValue), }, new pbr::GeneratedClrTypeInfo[] { + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.WellKnownTypes.Struct), global::Google.Protobuf.WellKnownTypes.Struct.Parser, new[]{ "Fields" }, null, null, new pbr::GeneratedClrTypeInfo[] { null, }), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.WellKnownTypes.Value), global::Google.Protobuf.WellKnownTypes.Value.Parser, new[]{ "NullValue", "NumberValue", "StringValue", "BoolValue", "StructValue", "ListValue" }, new[]{ "Kind" }, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.WellKnownTypes.ListValue), global::Google.Protobuf.WellKnownTypes.ListValue.Parser, new[]{ "Values" }, null, null, null) })); } #endregion @@ -136,7 +136,7 @@ namespace Google.Protobuf.WellKnownTypes { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -262,7 +262,7 @@ namespace Google.Protobuf.WellKnownTypes { public string StringValue { get { return kindCase_ == KindOneofCase.StringValue ? (string) kind_ : ""; } set { - kind_ = pb::Preconditions.CheckNotNull(value, "value"); + kind_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); kindCase_ = KindOneofCase.StringValue; } } @@ -361,7 +361,7 @@ namespace Google.Protobuf.WellKnownTypes { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -555,7 +555,7 @@ namespace Google.Protobuf.WellKnownTypes { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/Timestamp.cs b/csharp/src/Google.Protobuf/WellKnownTypes/Timestamp.cs index a26b2bf8..318b0f61 100644 --- a/csharp/src/Google.Protobuf/WellKnownTypes/Timestamp.cs +++ b/csharp/src/Google.Protobuf/WellKnownTypes/Timestamp.cs @@ -25,13 +25,13 @@ namespace Google.Protobuf.WellKnownTypes { string.Concat( "Ch9nb29nbGUvcHJvdG9idWYvdGltZXN0YW1wLnByb3RvEg9nb29nbGUucHJv", "dG9idWYiKwoJVGltZXN0YW1wEg8KB3NlY29uZHMYASABKAMSDQoFbmFub3MY", - "AiABKAVCUQoTY29tLmdvb2dsZS5wcm90b2J1ZkIOVGltZXN0YW1wUHJvdG9Q", - "AaABAaICA0dQQqoCHkdvb2dsZS5Qcm90b2J1Zi5XZWxsS25vd25UeXBlc2IG", - "cHJvdG8z")); - descriptor = pbr::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData, + "AiABKAVCVAoTY29tLmdvb2dsZS5wcm90b2J1ZkIOVGltZXN0YW1wUHJvdG9Q", + "AaABAfgBAaICA0dQQqoCHkdvb2dsZS5Qcm90b2J1Zi5XZWxsS25vd25UeXBl", + "c2IGcHJvdG8z")); + descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, new pbr::FileDescriptor[] { }, - new pbr::GeneratedCodeInfo(null, new pbr::GeneratedCodeInfo[] { - new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.WellKnownTypes.Timestamp), global::Google.Protobuf.WellKnownTypes.Timestamp.Parser, new[]{ "Seconds", "Nanos" }, null, null, null) + new pbr::GeneratedClrTypeInfo(null, new pbr::GeneratedClrTypeInfo[] { + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.WellKnownTypes.Timestamp), global::Google.Protobuf.WellKnownTypes.Timestamp.Parser, new[]{ "Seconds", "Nanos" }, null, null, null) })); } #endregion @@ -175,7 +175,7 @@ namespace Google.Protobuf.WellKnownTypes { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/TimestampPartial.cs b/csharp/src/Google.Protobuf/WellKnownTypes/TimestampPartial.cs index d284acd6..aa403473 100644 --- a/csharp/src/Google.Protobuf/WellKnownTypes/TimestampPartial.cs +++ b/csharp/src/Google.Protobuf/WellKnownTypes/TimestampPartial.cs @@ -31,15 +31,25 @@ #endregion using System; +using System.Globalization; +using System.Text; namespace Google.Protobuf.WellKnownTypes { - public partial class Timestamp + public partial class Timestamp : ICustomDiagnosticMessage { private static readonly DateTime UnixEpoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); - private static readonly long BclSecondsAtUnixEpoch = UnixEpoch.Ticks / TimeSpan.TicksPerSecond; - internal static readonly long UnixSecondsAtBclMinValue = -BclSecondsAtUnixEpoch; - internal static readonly long UnixSecondsAtBclMaxValue = (DateTime.MaxValue.Ticks / TimeSpan.TicksPerSecond) - BclSecondsAtUnixEpoch; + // Constants determined programmatically, but then hard-coded so they can be constant expressions. + private const long BclSecondsAtUnixEpoch = 62135596800; + internal const long UnixSecondsAtBclMaxValue = 253402300799; + internal const long UnixSecondsAtBclMinValue = -BclSecondsAtUnixEpoch; + internal const int MaxNanos = Duration.NanosecondsPerSecond - 1; + + private static bool IsNormalized(long seconds, int nanoseconds) => + nanoseconds >= 0 && + nanoseconds <= MaxNanos && + seconds >= UnixSecondsAtBclMinValue && + seconds <= UnixSecondsAtBclMaxValue; /// <summary> /// Returns the difference between one <see cref="Timestamp"/> and another, as a <see cref="Duration"/>. @@ -49,8 +59,8 @@ namespace Google.Protobuf.WellKnownTypes /// <returns>The difference between the two specified timestamps.</returns> public static Duration operator -(Timestamp lhs, Timestamp rhs) { - Preconditions.CheckNotNull(lhs, "lhs"); - Preconditions.CheckNotNull(rhs, "rhs"); + ProtoPreconditions.CheckNotNull(lhs, "lhs"); + ProtoPreconditions.CheckNotNull(rhs, "rhs"); checked { return Duration.Normalize(lhs.Seconds - rhs.Seconds, lhs.Nanos - rhs.Nanos); @@ -65,8 +75,8 @@ namespace Google.Protobuf.WellKnownTypes /// <returns>The result of adding the duration to the timestamp.</returns> public static Timestamp operator +(Timestamp lhs, Duration rhs) { - Preconditions.CheckNotNull(lhs, "lhs"); - Preconditions.CheckNotNull(rhs, "rhs"); + ProtoPreconditions.CheckNotNull(lhs, "lhs"); + ProtoPreconditions.CheckNotNull(rhs, "rhs"); checked { return Normalize(lhs.Seconds + rhs.Seconds, lhs.Nanos + rhs.Nanos); @@ -81,8 +91,8 @@ namespace Google.Protobuf.WellKnownTypes /// <returns>The result of subtracting the duration from the timestamp.</returns> public static Timestamp operator -(Timestamp lhs, Duration rhs) { - Preconditions.CheckNotNull(lhs, "lhs"); - Preconditions.CheckNotNull(rhs, "rhs"); + ProtoPreconditions.CheckNotNull(lhs, "lhs"); + ProtoPreconditions.CheckNotNull(rhs, "rhs"); checked { return Normalize(lhs.Seconds - rhs.Seconds, lhs.Nanos - rhs.Nanos); @@ -99,8 +109,14 @@ namespace Google.Protobuf.WellKnownTypes /// <see cref="DateTime"/> value precisely on a second. /// </remarks> /// <returns>This timestamp as a <c>DateTime</c>.</returns> + /// <exception cref="InvalidOperationException">The timestamp contains invalid values; either it is + /// incorrectly normalized or is outside the valid range.</exception> public DateTime ToDateTime() { + if (!IsNormalized(Seconds, Nanos)) + { + throw new InvalidOperationException(@"Timestamp contains invalid values: Seconds={Seconds}; Nanos={Nanos}"); + } return UnixEpoch.AddSeconds(Seconds).AddTicks(Nanos / Duration.NanosecondsPerTick); } @@ -114,6 +130,8 @@ namespace Google.Protobuf.WellKnownTypes /// <see cref="DateTimeOffset"/> value precisely on a second. /// </remarks> /// <returns>This timestamp as a <c>DateTimeOffset</c>.</returns> + /// <exception cref="InvalidOperationException">The timestamp contains invalid values; either it is + /// incorrectly normalized or is outside the valid range.</exception> public DateTimeOffset ToDateTimeOffset() { return new DateTimeOffset(ToDateTime(), TimeSpan.Zero); @@ -165,5 +183,59 @@ namespace Google.Protobuf.WellKnownTypes } return new Timestamp { Seconds = seconds, Nanos = nanoseconds }; } + + /// <summary> + /// Converts a timestamp specified in seconds/nanoseconds to a string. + /// </summary> + /// <remarks> + /// If the value is a normalized duration in the range described in <c>timestamp.proto</c>, + /// <paramref name="diagnosticOnly"/> is ignored. Otherwise, if the parameter is <c>true</c>, + /// a JSON object with a warning is returned; if it is <c>false</c>, an <see cref="InvalidOperationException"/> is thrown. + /// </remarks> + /// <param name="seconds">Seconds portion of the duration.</param> + /// <param name="nanoseconds">Nanoseconds portion of the duration.</param> + /// <param name="diagnosticOnly">Determines the handling of non-normalized values</param> + /// <exception cref="InvalidOperationException">The represented duration is invalid, and <paramref name="diagnosticOnly"/> is <c>false</c>.</exception> + internal static string ToJson(long seconds, int nanoseconds, bool diagnosticOnly) + { + if (IsNormalized(seconds, nanoseconds)) + { + // Use .NET's formatting for the value down to the second, including an opening double quote (as it's a string value) + DateTime dateTime = UnixEpoch.AddSeconds(seconds); + var builder = new StringBuilder(); + builder.Append('"'); + builder.Append(dateTime.ToString("yyyy'-'MM'-'dd'T'HH:mm:ss", CultureInfo.InvariantCulture)); + Duration.AppendNanoseconds(builder, nanoseconds); + builder.Append("Z\""); + return builder.ToString(); + } + if (diagnosticOnly) + { + return string.Format(CultureInfo.InvariantCulture, + "{{ \"@warning\": \"Invalid Timestamp\", \"seconds\": \"{0}\", \"nanos\": {1} }}", + seconds, + nanoseconds); + } + else + { + throw new InvalidOperationException("Non-normalized timestamp value"); + } + } + + /// <summary> + /// Returns a string representation of this <see cref="Timestamp"/> for diagnostic purposes. + /// </summary> + /// <remarks> + /// Normally the returned value will be a JSON string value (including leading and trailing quotes) but + /// when the value is non-normalized or out of range, a JSON object representation will be returned + /// instead, including a warning. This is to avoid exceptions being thrown when trying to + /// diagnose problems - the regular JSON formatter will still throw an exception for non-normalized + /// values. + /// </remarks> + /// <returns>A string representation of this value.</returns> + public string ToDiagnosticString() + { + return ToJson(Seconds, Nanos, true); + } } } diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/Type.cs b/csharp/src/Google.Protobuf/WellKnownTypes/Type.cs index edd302e7..8faa1d1c 100644 --- a/csharp/src/Google.Protobuf/WellKnownTypes/Type.cs +++ b/csharp/src/Google.Protobuf/WellKnownTypes/Type.cs @@ -30,41 +30,42 @@ namespace Google.Protobuf.WellKnownTypes { "b2ZzGAMgAygJEigKB29wdGlvbnMYBCADKAsyFy5nb29nbGUucHJvdG9idWYu", "T3B0aW9uEjYKDnNvdXJjZV9jb250ZXh0GAUgASgLMh4uZ29vZ2xlLnByb3Rv", "YnVmLlNvdXJjZUNvbnRleHQSJwoGc3ludGF4GAYgASgOMhcuZ29vZ2xlLnBy", - "b3RvYnVmLlN5bnRheCK+BQoFRmllbGQSKQoEa2luZBgBIAEoDjIbLmdvb2ds", + "b3RvYnVmLlN5bnRheCLVBQoFRmllbGQSKQoEa2luZBgBIAEoDjIbLmdvb2ds", "ZS5wcm90b2J1Zi5GaWVsZC5LaW5kEjcKC2NhcmRpbmFsaXR5GAIgASgOMiIu", "Z29vZ2xlLnByb3RvYnVmLkZpZWxkLkNhcmRpbmFsaXR5Eg4KBm51bWJlchgD", "IAEoBRIMCgRuYW1lGAQgASgJEhAKCHR5cGVfdXJsGAYgASgJEhMKC29uZW9m", "X2luZGV4GAcgASgFEg4KBnBhY2tlZBgIIAEoCBIoCgdvcHRpb25zGAkgAygL", - "MhcuZ29vZ2xlLnByb3RvYnVmLk9wdGlvbhIRCglqc29uX25hbWUYCiABKAki", - "yAIKBEtpbmQSEAoMVFlQRV9VTktOT1dOEAASDwoLVFlQRV9ET1VCTEUQARIO", - "CgpUWVBFX0ZMT0FUEAISDgoKVFlQRV9JTlQ2NBADEg8KC1RZUEVfVUlOVDY0", - "EAQSDgoKVFlQRV9JTlQzMhAFEhAKDFRZUEVfRklYRUQ2NBAGEhAKDFRZUEVf", - "RklYRUQzMhAHEg0KCVRZUEVfQk9PTBAIEg8KC1RZUEVfU1RSSU5HEAkSDgoK", - "VFlQRV9HUk9VUBAKEhAKDFRZUEVfTUVTU0FHRRALEg4KClRZUEVfQllURVMQ", - "DBIPCgtUWVBFX1VJTlQzMhANEg0KCVRZUEVfRU5VTRAOEhEKDVRZUEVfU0ZJ", - "WEVEMzIQDxIRCg1UWVBFX1NGSVhFRDY0EBASDwoLVFlQRV9TSU5UMzIQERIP", - "CgtUWVBFX1NJTlQ2NBASInQKC0NhcmRpbmFsaXR5EhcKE0NBUkRJTkFMSVRZ", - "X1VOS05PV04QABIYChRDQVJESU5BTElUWV9PUFRJT05BTBABEhgKFENBUkRJ", - "TkFMSVRZX1JFUVVJUkVEEAISGAoUQ0FSRElOQUxJVFlfUkVQRUFURUQQAyLO", - "AQoERW51bRIMCgRuYW1lGAEgASgJEi0KCWVudW12YWx1ZRgCIAMoCzIaLmdv", - "b2dsZS5wcm90b2J1Zi5FbnVtVmFsdWUSKAoHb3B0aW9ucxgDIAMoCzIXLmdv", - "b2dsZS5wcm90b2J1Zi5PcHRpb24SNgoOc291cmNlX2NvbnRleHQYBCABKAsy", - "Hi5nb29nbGUucHJvdG9idWYuU291cmNlQ29udGV4dBInCgZzeW50YXgYBSAB", - "KA4yFy5nb29nbGUucHJvdG9idWYuU3ludGF4IlMKCUVudW1WYWx1ZRIMCgRu", - "YW1lGAEgASgJEg4KBm51bWJlchgCIAEoBRIoCgdvcHRpb25zGAMgAygLMhcu", - "Z29vZ2xlLnByb3RvYnVmLk9wdGlvbiI7CgZPcHRpb24SDAoEbmFtZRgBIAEo", - "CRIjCgV2YWx1ZRgCIAEoCzIULmdvb2dsZS5wcm90b2J1Zi5BbnkqLgoGU3lu", - "dGF4EhEKDVNZTlRBWF9QUk9UTzIQABIRCg1TWU5UQVhfUFJPVE8zEAFCTAoT", - "Y29tLmdvb2dsZS5wcm90b2J1ZkIJVHlwZVByb3RvUAGgAQGiAgNHUEKqAh5H", - "b29nbGUuUHJvdG9idWYuV2VsbEtub3duVHlwZXNiBnByb3RvMw==")); - descriptor = pbr::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData, + "MhcuZ29vZ2xlLnByb3RvYnVmLk9wdGlvbhIRCglqc29uX25hbWUYCiABKAkS", + "FQoNZGVmYXVsdF92YWx1ZRgLIAEoCSLIAgoES2luZBIQCgxUWVBFX1VOS05P", + "V04QABIPCgtUWVBFX0RPVUJMRRABEg4KClRZUEVfRkxPQVQQAhIOCgpUWVBF", + "X0lOVDY0EAMSDwoLVFlQRV9VSU5UNjQQBBIOCgpUWVBFX0lOVDMyEAUSEAoM", + "VFlQRV9GSVhFRDY0EAYSEAoMVFlQRV9GSVhFRDMyEAcSDQoJVFlQRV9CT09M", + "EAgSDwoLVFlQRV9TVFJJTkcQCRIOCgpUWVBFX0dST1VQEAoSEAoMVFlQRV9N", + "RVNTQUdFEAsSDgoKVFlQRV9CWVRFUxAMEg8KC1RZUEVfVUlOVDMyEA0SDQoJ", + "VFlQRV9FTlVNEA4SEQoNVFlQRV9TRklYRUQzMhAPEhEKDVRZUEVfU0ZJWEVE", + "NjQQEBIPCgtUWVBFX1NJTlQzMhAREg8KC1RZUEVfU0lOVDY0EBIidAoLQ2Fy", + "ZGluYWxpdHkSFwoTQ0FSRElOQUxJVFlfVU5LTk9XThAAEhgKFENBUkRJTkFM", + "SVRZX09QVElPTkFMEAESGAoUQ0FSRElOQUxJVFlfUkVRVUlSRUQQAhIYChRD", + "QVJESU5BTElUWV9SRVBFQVRFRBADIs4BCgRFbnVtEgwKBG5hbWUYASABKAkS", + "LQoJZW51bXZhbHVlGAIgAygLMhouZ29vZ2xlLnByb3RvYnVmLkVudW1WYWx1", + "ZRIoCgdvcHRpb25zGAMgAygLMhcuZ29vZ2xlLnByb3RvYnVmLk9wdGlvbhI2", + "Cg5zb3VyY2VfY29udGV4dBgEIAEoCzIeLmdvb2dsZS5wcm90b2J1Zi5Tb3Vy", + "Y2VDb250ZXh0EicKBnN5bnRheBgFIAEoDjIXLmdvb2dsZS5wcm90b2J1Zi5T", + "eW50YXgiUwoJRW51bVZhbHVlEgwKBG5hbWUYASABKAkSDgoGbnVtYmVyGAIg", + "ASgFEigKB29wdGlvbnMYAyADKAsyFy5nb29nbGUucHJvdG9idWYuT3B0aW9u", + "IjsKBk9wdGlvbhIMCgRuYW1lGAEgASgJEiMKBXZhbHVlGAIgASgLMhQuZ29v", + "Z2xlLnByb3RvYnVmLkFueSouCgZTeW50YXgSEQoNU1lOVEFYX1BST1RPMhAA", + "EhEKDVNZTlRBWF9QUk9UTzMQAUJMChNjb20uZ29vZ2xlLnByb3RvYnVmQglU", + "eXBlUHJvdG9QAaABAaICA0dQQqoCHkdvb2dsZS5Qcm90b2J1Zi5XZWxsS25v", + "d25UeXBlc2IGcHJvdG8z")); + descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, new pbr::FileDescriptor[] { global::Google.Protobuf.WellKnownTypes.AnyReflection.Descriptor, global::Google.Protobuf.WellKnownTypes.SourceContextReflection.Descriptor, }, - new pbr::GeneratedCodeInfo(new[] {typeof(global::Google.Protobuf.WellKnownTypes.Syntax), }, new pbr::GeneratedCodeInfo[] { - new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.WellKnownTypes.Type), global::Google.Protobuf.WellKnownTypes.Type.Parser, new[]{ "Name", "Fields", "Oneofs", "Options", "SourceContext", "Syntax" }, null, null, null), - new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.WellKnownTypes.Field), global::Google.Protobuf.WellKnownTypes.Field.Parser, new[]{ "Kind", "Cardinality", "Number", "Name", "TypeUrl", "OneofIndex", "Packed", "Options", "JsonName" }, null, new[]{ typeof(global::Google.Protobuf.WellKnownTypes.Field.Types.Kind), typeof(global::Google.Protobuf.WellKnownTypes.Field.Types.Cardinality) }, null), - new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.WellKnownTypes.Enum), global::Google.Protobuf.WellKnownTypes.Enum.Parser, new[]{ "Name", "Enumvalue", "Options", "SourceContext", "Syntax" }, null, null, null), - new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.WellKnownTypes.EnumValue), global::Google.Protobuf.WellKnownTypes.EnumValue.Parser, new[]{ "Name", "Number", "Options" }, null, null, null), - new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.WellKnownTypes.Option), global::Google.Protobuf.WellKnownTypes.Option.Parser, new[]{ "Name", "Value" }, null, null, null) + new pbr::GeneratedClrTypeInfo(new[] {typeof(global::Google.Protobuf.WellKnownTypes.Syntax), }, new pbr::GeneratedClrTypeInfo[] { + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.WellKnownTypes.Type), global::Google.Protobuf.WellKnownTypes.Type.Parser, new[]{ "Name", "Fields", "Oneofs", "Options", "SourceContext", "Syntax" }, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.WellKnownTypes.Field), global::Google.Protobuf.WellKnownTypes.Field.Parser, new[]{ "Kind", "Cardinality", "Number", "Name", "TypeUrl", "OneofIndex", "Packed", "Options", "JsonName", "DefaultValue" }, null, new[]{ typeof(global::Google.Protobuf.WellKnownTypes.Field.Types.Kind), typeof(global::Google.Protobuf.WellKnownTypes.Field.Types.Cardinality) }, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.WellKnownTypes.Enum), global::Google.Protobuf.WellKnownTypes.Enum.Parser, new[]{ "Name", "Enumvalue", "Options", "SourceContext", "Syntax" }, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.WellKnownTypes.EnumValue), global::Google.Protobuf.WellKnownTypes.EnumValue.Parser, new[]{ "Name", "Number", "Options" }, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.WellKnownTypes.Option), global::Google.Protobuf.WellKnownTypes.Option.Parser, new[]{ "Name", "Value" }, null, null, null) })); } #endregion @@ -72,15 +73,15 @@ namespace Google.Protobuf.WellKnownTypes { } #region Enums /// <summary> - /// Syntax specifies the syntax in which a service element was defined. + /// The syntax in which a protocol buffer element is defined. /// </summary> public enum Syntax { /// <summary> - /// Syntax "proto2" + /// Syntax `proto2`. /// </summary> SYNTAX_PROTO2 = 0, /// <summary> - /// Syntax "proto3" + /// Syntax `proto3`. /// </summary> SYNTAX_PROTO3 = 1, } @@ -89,7 +90,7 @@ namespace Google.Protobuf.WellKnownTypes { #region Messages /// <summary> - /// A light-weight descriptor for a proto message type. + /// A protocol buffer message type. /// </summary> [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] public sealed partial class Type : pb::IMessage<Type> { @@ -132,7 +133,7 @@ namespace Google.Protobuf.WellKnownTypes { public string Name { get { return name_; } set { - name_ = pb::Preconditions.CheckNotNull(value, "value"); + name_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } @@ -154,7 +155,7 @@ namespace Google.Protobuf.WellKnownTypes { = pb::FieldCodec.ForString(26); private readonly pbc::RepeatedField<string> oneofs_ = new pbc::RepeatedField<string>(); /// <summary> - /// The list of oneof definitions. + /// The list of types appearing in `oneof` definitions in this type. /// </summary> public pbc::RepeatedField<string> Oneofs { get { return oneofs_; } @@ -166,7 +167,7 @@ namespace Google.Protobuf.WellKnownTypes { = pb::FieldCodec.ForMessage(34, global::Google.Protobuf.WellKnownTypes.Option.Parser); private readonly pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Option> options_ = new pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Option>(); /// <summary> - /// The proto options. + /// The protocol buffer options. /// </summary> public pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Option> Options { get { return options_; } @@ -230,7 +231,7 @@ namespace Google.Protobuf.WellKnownTypes { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -330,7 +331,7 @@ namespace Google.Protobuf.WellKnownTypes { } /// <summary> - /// Field represents a single field of a message type. + /// A single field of a message type. /// </summary> [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] public sealed partial class Field : pb::IMessage<Field> { @@ -361,6 +362,7 @@ namespace Google.Protobuf.WellKnownTypes { packed_ = other.packed_; options_ = other.options_.Clone(); jsonName_ = other.jsonName_; + defaultValue_ = other.defaultValue_; } public Field Clone() { @@ -371,7 +373,7 @@ namespace Google.Protobuf.WellKnownTypes { public const int KindFieldNumber = 1; private global::Google.Protobuf.WellKnownTypes.Field.Types.Kind kind_ = global::Google.Protobuf.WellKnownTypes.Field.Types.Kind.TYPE_UNKNOWN; /// <summary> - /// The field kind. + /// The field type. /// </summary> public global::Google.Protobuf.WellKnownTypes.Field.Types.Kind Kind { get { return kind_; } @@ -384,7 +386,7 @@ namespace Google.Protobuf.WellKnownTypes { public const int CardinalityFieldNumber = 2; private global::Google.Protobuf.WellKnownTypes.Field.Types.Cardinality cardinality_ = global::Google.Protobuf.WellKnownTypes.Field.Types.Cardinality.CARDINALITY_UNKNOWN; /// <summary> - /// The field cardinality, i.e. optional/required/repeated. + /// The field cardinality. /// </summary> public global::Google.Protobuf.WellKnownTypes.Field.Types.Cardinality Cardinality { get { return cardinality_; } @@ -397,7 +399,7 @@ namespace Google.Protobuf.WellKnownTypes { public const int NumberFieldNumber = 3; private int number_; /// <summary> - /// The proto field number. + /// The field number. /// </summary> public int Number { get { return number_; } @@ -415,7 +417,7 @@ namespace Google.Protobuf.WellKnownTypes { public string Name { get { return name_; } set { - name_ = pb::Preconditions.CheckNotNull(value, "value"); + name_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } @@ -423,13 +425,13 @@ namespace Google.Protobuf.WellKnownTypes { public const int TypeUrlFieldNumber = 6; private string typeUrl_ = ""; /// <summary> - /// The type URL (without the scheme) when the type is MESSAGE or ENUM, - /// such as `type.googleapis.com/google.protobuf.Empty`. + /// The field type URL, without the scheme, for message or enumeration + /// types. Example: `"type.googleapis.com/google.protobuf.Timestamp"`. /// </summary> public string TypeUrl { get { return typeUrl_; } set { - typeUrl_ = pb::Preconditions.CheckNotNull(value, "value"); + typeUrl_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } @@ -437,7 +439,8 @@ namespace Google.Protobuf.WellKnownTypes { public const int OneofIndexFieldNumber = 7; private int oneofIndex_; /// <summary> - /// Index in Type.oneofs. Starts at 1. Zero means no oneof mapping. + /// The index of the field type in `Type.oneofs`, for message or enumeration + /// types. The first type has index 1; zero means the type is not in the list. /// </summary> public int OneofIndex { get { return oneofIndex_; } @@ -465,7 +468,7 @@ namespace Google.Protobuf.WellKnownTypes { = pb::FieldCodec.ForMessage(74, global::Google.Protobuf.WellKnownTypes.Option.Parser); private readonly pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Option> options_ = new pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Option>(); /// <summary> - /// The proto options. + /// The protocol buffer options. /// </summary> public pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Option> Options { get { return options_; } @@ -475,12 +478,25 @@ namespace Google.Protobuf.WellKnownTypes { public const int JsonNameFieldNumber = 10; private string jsonName_ = ""; /// <summary> - /// The JSON name for this field. + /// The field JSON name. /// </summary> public string JsonName { get { return jsonName_; } set { - jsonName_ = pb::Preconditions.CheckNotNull(value, "value"); + jsonName_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + /// <summary>Field number for the "default_value" field.</summary> + public const int DefaultValueFieldNumber = 11; + private string defaultValue_ = ""; + /// <summary> + /// The string value of the default value of this field. Proto2 syntax only. + /// </summary> + public string DefaultValue { + get { return defaultValue_; } + set { + defaultValue_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } @@ -504,6 +520,7 @@ namespace Google.Protobuf.WellKnownTypes { if (Packed != other.Packed) return false; if(!options_.Equals(other.options_)) return false; if (JsonName != other.JsonName) return false; + if (DefaultValue != other.DefaultValue) return false; return true; } @@ -518,11 +535,12 @@ namespace Google.Protobuf.WellKnownTypes { if (Packed != false) hash ^= Packed.GetHashCode(); hash ^= options_.GetHashCode(); if (JsonName.Length != 0) hash ^= JsonName.GetHashCode(); + if (DefaultValue.Length != 0) hash ^= DefaultValue.GetHashCode(); return hash; } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -559,6 +577,10 @@ namespace Google.Protobuf.WellKnownTypes { output.WriteRawTag(82); output.WriteString(JsonName); } + if (DefaultValue.Length != 0) { + output.WriteRawTag(90); + output.WriteString(DefaultValue); + } } public int CalculateSize() { @@ -588,6 +610,9 @@ namespace Google.Protobuf.WellKnownTypes { if (JsonName.Length != 0) { size += 1 + pb::CodedOutputStream.ComputeStringSize(JsonName); } + if (DefaultValue.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(DefaultValue); + } return size; } @@ -620,6 +645,9 @@ namespace Google.Protobuf.WellKnownTypes { if (other.JsonName.Length != 0) { JsonName = other.JsonName; } + if (other.DefaultValue.Length != 0) { + DefaultValue = other.DefaultValue; + } } public void MergeFrom(pb::CodedInputStream input) { @@ -665,6 +693,10 @@ namespace Google.Protobuf.WellKnownTypes { JsonName = input.ReadString(); break; } + case 90: { + DefaultValue = input.ReadString(); + break; + } } } } @@ -674,7 +706,7 @@ namespace Google.Protobuf.WellKnownTypes { [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] public static partial class Types { /// <summary> - /// Kind represents a basic field type. + /// Basic field types. /// </summary> public enum Kind { /// <summary> @@ -718,7 +750,7 @@ namespace Google.Protobuf.WellKnownTypes { /// </summary> TYPE_STRING = 9, /// <summary> - /// Field type group (deprecated proto2 type) + /// Field type group. Proto2 syntax only, and deprecated. /// </summary> TYPE_GROUP = 10, /// <summary> @@ -756,12 +788,11 @@ namespace Google.Protobuf.WellKnownTypes { } /// <summary> - /// Cardinality represents whether a field is optional, required, or - /// repeated. + /// Whether a field is optional, required, or repeated. /// </summary> public enum Cardinality { /// <summary> - /// The field cardinality is unknown. Typically an error condition. + /// For fields with unknown cardinality. /// </summary> CARDINALITY_UNKNOWN = 0, /// <summary> @@ -769,7 +800,7 @@ namespace Google.Protobuf.WellKnownTypes { /// </summary> CARDINALITY_OPTIONAL = 1, /// <summary> - /// For required fields. Not used for proto3. + /// For required fields. Proto2 syntax only. /// </summary> CARDINALITY_REQUIRED = 2, /// <summary> @@ -826,7 +857,7 @@ namespace Google.Protobuf.WellKnownTypes { public string Name { get { return name_; } set { - name_ = pb::Preconditions.CheckNotNull(value, "value"); + name_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } @@ -848,7 +879,7 @@ namespace Google.Protobuf.WellKnownTypes { = pb::FieldCodec.ForMessage(26, global::Google.Protobuf.WellKnownTypes.Option.Parser); private readonly pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Option> options_ = new pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Option>(); /// <summary> - /// Proto options for the enum type. + /// Protocol buffer options. /// </summary> public pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Option> Options { get { return options_; } @@ -910,7 +941,7 @@ namespace Google.Protobuf.WellKnownTypes { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -1043,7 +1074,7 @@ namespace Google.Protobuf.WellKnownTypes { public string Name { get { return name_; } set { - name_ = pb::Preconditions.CheckNotNull(value, "value"); + name_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } @@ -1066,7 +1097,7 @@ namespace Google.Protobuf.WellKnownTypes { = pb::FieldCodec.ForMessage(26, global::Google.Protobuf.WellKnownTypes.Option.Parser); private readonly pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Option> options_ = new pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Option>(); /// <summary> - /// Proto options for the enum value. + /// Protocol buffer options. /// </summary> public pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Option> Options { get { return options_; } @@ -1098,7 +1129,7 @@ namespace Google.Protobuf.WellKnownTypes { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -1164,7 +1195,8 @@ namespace Google.Protobuf.WellKnownTypes { } /// <summary> - /// Proto option attached to messages/fields/enums etc. + /// A protocol buffer option, which can be attached to a message, field, + /// enumeration, etc. /// </summary> [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] public sealed partial class Option : pb::IMessage<Option> { @@ -1198,12 +1230,12 @@ namespace Google.Protobuf.WellKnownTypes { public const int NameFieldNumber = 1; private string name_ = ""; /// <summary> - /// Proto option name. + /// The option's name. For example, `"java_package"`. /// </summary> public string Name { get { return name_; } set { - name_ = pb::Preconditions.CheckNotNull(value, "value"); + name_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } @@ -1211,7 +1243,7 @@ namespace Google.Protobuf.WellKnownTypes { public const int ValueFieldNumber = 2; private global::Google.Protobuf.WellKnownTypes.Any value_; /// <summary> - /// Proto option value. + /// The option's value. For example, `"com.google.protobuf"`. /// </summary> public global::Google.Protobuf.WellKnownTypes.Any Value { get { return value_; } @@ -1244,7 +1276,7 @@ namespace Google.Protobuf.WellKnownTypes { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/ValuePartial.cs b/csharp/src/Google.Protobuf/WellKnownTypes/ValuePartial.cs index b4b6c05e..d34b560d 100644 --- a/csharp/src/Google.Protobuf/WellKnownTypes/ValuePartial.cs +++ b/csharp/src/Google.Protobuf/WellKnownTypes/ValuePartial.cs @@ -41,7 +41,7 @@ namespace Google.Protobuf.WellKnownTypes /// <returns>A newly-created Value message with the given value.</returns> public static Value ForString(string value) { - Preconditions.CheckNotNull(value, "value"); + ProtoPreconditions.CheckNotNull(value, "value"); return new Value { StringValue = value }; } @@ -81,7 +81,7 @@ namespace Google.Protobuf.WellKnownTypes /// <returns>A newly-created Value message an initial list value.</returns> public static Value ForList(params Value[] values) { - Preconditions.CheckNotNull(values, "values"); + ProtoPreconditions.CheckNotNull(values, "values"); return new Value { ListValue = new ListValue { Values = { values } } }; } @@ -92,7 +92,7 @@ namespace Google.Protobuf.WellKnownTypes /// <returns>A newly-created Value message an initial struct value.</returns> public static Value ForStruct(Struct value) { - Preconditions.CheckNotNull(value, "value"); + ProtoPreconditions.CheckNotNull(value, "value"); return new Value { StructValue = value }; } } diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/Wrappers.cs b/csharp/src/Google.Protobuf/WellKnownTypes/Wrappers.cs index 9fa6c2ec..d6796d1a 100644 --- a/csharp/src/Google.Protobuf/WellKnownTypes/Wrappers.cs +++ b/csharp/src/Google.Protobuf/WellKnownTypes/Wrappers.cs @@ -29,21 +29,22 @@ namespace Google.Protobuf.WellKnownTypes { "KAMiHAoLVUludDY0VmFsdWUSDQoFdmFsdWUYASABKAQiGwoKSW50MzJWYWx1", "ZRINCgV2YWx1ZRgBIAEoBSIcCgtVSW50MzJWYWx1ZRINCgV2YWx1ZRgBIAEo", "DSIaCglCb29sVmFsdWUSDQoFdmFsdWUYASABKAgiHAoLU3RyaW5nVmFsdWUS", - "DQoFdmFsdWUYASABKAkiGwoKQnl0ZXNWYWx1ZRINCgV2YWx1ZRgBIAEoDEJQ", - "ChNjb20uZ29vZ2xlLnByb3RvYnVmQg1XcmFwcGVyc1Byb3RvUAGgAQGiAgNH", - "UEKqAh5Hb29nbGUuUHJvdG9idWYuV2VsbEtub3duVHlwZXNiBnByb3RvMw==")); - descriptor = pbr::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData, + "DQoFdmFsdWUYASABKAkiGwoKQnl0ZXNWYWx1ZRINCgV2YWx1ZRgBIAEoDEJT", + "ChNjb20uZ29vZ2xlLnByb3RvYnVmQg1XcmFwcGVyc1Byb3RvUAGgAQH4AQGi", + "AgNHUEKqAh5Hb29nbGUuUHJvdG9idWYuV2VsbEtub3duVHlwZXNiBnByb3Rv", + "Mw==")); + descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, new pbr::FileDescriptor[] { }, - new pbr::GeneratedCodeInfo(null, new pbr::GeneratedCodeInfo[] { - new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.WellKnownTypes.DoubleValue), global::Google.Protobuf.WellKnownTypes.DoubleValue.Parser, new[]{ "Value" }, null, null, null), - new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.WellKnownTypes.FloatValue), global::Google.Protobuf.WellKnownTypes.FloatValue.Parser, new[]{ "Value" }, null, null, null), - new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.WellKnownTypes.Int64Value), global::Google.Protobuf.WellKnownTypes.Int64Value.Parser, new[]{ "Value" }, null, null, null), - new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.WellKnownTypes.UInt64Value), global::Google.Protobuf.WellKnownTypes.UInt64Value.Parser, new[]{ "Value" }, null, null, null), - new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.WellKnownTypes.Int32Value), global::Google.Protobuf.WellKnownTypes.Int32Value.Parser, new[]{ "Value" }, null, null, null), - new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.WellKnownTypes.UInt32Value), global::Google.Protobuf.WellKnownTypes.UInt32Value.Parser, new[]{ "Value" }, null, null, null), - new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.WellKnownTypes.BoolValue), global::Google.Protobuf.WellKnownTypes.BoolValue.Parser, new[]{ "Value" }, null, null, null), - new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.WellKnownTypes.StringValue), global::Google.Protobuf.WellKnownTypes.StringValue.Parser, new[]{ "Value" }, null, null, null), - new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.WellKnownTypes.BytesValue), global::Google.Protobuf.WellKnownTypes.BytesValue.Parser, new[]{ "Value" }, null, null, null) + new pbr::GeneratedClrTypeInfo(null, new pbr::GeneratedClrTypeInfo[] { + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.WellKnownTypes.DoubleValue), global::Google.Protobuf.WellKnownTypes.DoubleValue.Parser, new[]{ "Value" }, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.WellKnownTypes.FloatValue), global::Google.Protobuf.WellKnownTypes.FloatValue.Parser, new[]{ "Value" }, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.WellKnownTypes.Int64Value), global::Google.Protobuf.WellKnownTypes.Int64Value.Parser, new[]{ "Value" }, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.WellKnownTypes.UInt64Value), global::Google.Protobuf.WellKnownTypes.UInt64Value.Parser, new[]{ "Value" }, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.WellKnownTypes.Int32Value), global::Google.Protobuf.WellKnownTypes.Int32Value.Parser, new[]{ "Value" }, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.WellKnownTypes.UInt32Value), global::Google.Protobuf.WellKnownTypes.UInt32Value.Parser, new[]{ "Value" }, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.WellKnownTypes.BoolValue), global::Google.Protobuf.WellKnownTypes.BoolValue.Parser, new[]{ "Value" }, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.WellKnownTypes.StringValue), global::Google.Protobuf.WellKnownTypes.StringValue.Parser, new[]{ "Value" }, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.WellKnownTypes.BytesValue), global::Google.Protobuf.WellKnownTypes.BytesValue.Parser, new[]{ "Value" }, null, null, null) })); } #endregion @@ -117,7 +118,7 @@ namespace Google.Protobuf.WellKnownTypes { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -228,7 +229,7 @@ namespace Google.Protobuf.WellKnownTypes { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -339,7 +340,7 @@ namespace Google.Protobuf.WellKnownTypes { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -450,7 +451,7 @@ namespace Google.Protobuf.WellKnownTypes { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -561,7 +562,7 @@ namespace Google.Protobuf.WellKnownTypes { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -672,7 +673,7 @@ namespace Google.Protobuf.WellKnownTypes { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -783,7 +784,7 @@ namespace Google.Protobuf.WellKnownTypes { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -868,7 +869,7 @@ namespace Google.Protobuf.WellKnownTypes { public string Value { get { return value_; } set { - value_ = pb::Preconditions.CheckNotNull(value, "value"); + value_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } @@ -894,7 +895,7 @@ namespace Google.Protobuf.WellKnownTypes { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { @@ -979,7 +980,7 @@ namespace Google.Protobuf.WellKnownTypes { public pb::ByteString Value { get { return value_; } set { - value_ = pb::Preconditions.CheckNotNull(value, "value"); + value_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); } } @@ -1005,7 +1006,7 @@ namespace Google.Protobuf.WellKnownTypes { } public override string ToString() { - return pb::JsonFormatter.Default.Format(this); + return pb::JsonFormatter.ToDiagnosticString(this); } public void WriteTo(pb::CodedOutputStream output) { diff --git a/csharp/src/Google.Protobuf/packages.config b/csharp/src/Google.Protobuf/packages.config new file mode 100644 index 00000000..40b8fd92 --- /dev/null +++ b/csharp/src/Google.Protobuf/packages.config @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8"?> +<packages> + <package id="NuSpec.ReferenceGenerator" version="1.4.1" targetFramework="portable45-net45+win8+wp8+wpa81" developmentDependency="true" /> +</packages>
\ No newline at end of file |