diff options
Diffstat (limited to 'csharp')
87 files changed, 5370 insertions, 1467 deletions
diff --git a/csharp/.gitignore b/csharp/.gitignore index dbb3dd39..07ea90ac 100644 --- a/csharp/.gitignore +++ b/csharp/.gitignore @@ -5,6 +5,8 @@ src/AddressBook/bin src/AddressBook/obj src/Google.Protobuf/bin/ src/Google.Protobuf/obj/ +src/Google.Protobuf.Conformance/bin/ +src/Google.Protobuf.Conformance/obj/ src/Google.Protobuf.Test/bin/ src/Google.Protobuf.Test/obj/ src/Google.Protobuf.JsonDump/bin/ diff --git a/csharp/buildall.sh b/csharp/buildall.sh index d903c1ca..45af705f 100755 --- a/csharp/buildall.sh +++ b/csharp/buildall.sh @@ -6,7 +6,6 @@ NUNIT_CONSOLE=nunit-console # The rest you can leave intact CONFIG=Release -KEYFILE=../keys/Google.Protobuf.snk # TODO(jtattermusch): signing! SRC=$(dirname $0)/src set -ex diff --git a/csharp/generate_protos.sh b/csharp/generate_protos.sh index b4343a6e..962f2a9c 100755 --- a/csharp/generate_protos.sh +++ b/csharp/generate_protos.sh @@ -62,9 +62,12 @@ $PROTOC -Isrc --csharp_out=csharp/src/Google.Protobuf.Test/TestProtos \ src/google/protobuf/unittest_well_known_types.proto -$PROTOC -Icsharp/protos/extest --csharp_out=csharp/src/Google.Protobuf.Test/TestProtos \ - csharp/protos/extest/unittest_issues.proto +$PROTOC -Icsharp/protos --csharp_out=csharp/src/Google.Protobuf.Test/TestProtos \ + csharp/protos/unittest_issues.proto # AddressBook sample protos $PROTOC -Iexamples --csharp_out=csharp/src/AddressBook \ examples/addressbook.proto + +$PROTOC -Iconformance --csharp_out=csharp/src/Google.Protobuf.Conformance \ + conformance/conformance.proto diff --git a/csharp/keys/Google.Protobuf.public.snk b/csharp/keys/Google.Protobuf.public.snk Binary files differnew file mode 100644 index 00000000..59cd3698 --- /dev/null +++ b/csharp/keys/Google.Protobuf.public.snk diff --git a/csharp/keys/Google.Protobuf.snk b/csharp/keys/Google.Protobuf.snk Binary files differdeleted file mode 100644 index 6bbfc90f..00000000 --- a/csharp/keys/Google.Protobuf.snk +++ /dev/null diff --git a/csharp/keys/README.md b/csharp/keys/README.md new file mode 100644 index 00000000..1a014198 --- /dev/null +++ b/csharp/keys/README.md @@ -0,0 +1,5 @@ +Contents +-------- + +- Google.Protobuf.public.snk: + Public key to verify strong name of Google.Protobuf assemblies.
\ No newline at end of file diff --git a/csharp/keys/generate_new_key.bat b/csharp/keys/generate_new_key.bat deleted file mode 100644 index 6af599a1..00000000 --- a/csharp/keys/generate_new_key.bat +++ /dev/null @@ -1,13 +0,0 @@ -@ECHO OFF
-IF EXIST "C:\Program Files\Microsoft SDKs\Windows\v7.0\Bin\sn.exe" GOTO FOUND
-goto USEPATH
-
-:FOUND
-"C:\Program Files\Microsoft SDKs\Windows\v7.0\Bin\sn.exe" -k %~dp0\Google.Protobuf.snk
-GOTO EXIT
-
-:USEPATH
-sn.exe -k %~dp0\Google.Protobuf.snk
-GOTO EXIT
-
-:EXIT
\ No newline at end of file diff --git a/csharp/protos/extest/unittest_issues.proto b/csharp/protos/unittest_issues.proto index b0c92fa2..989b3dc4 100644 --- a/csharp/protos/extest/unittest_issues.proto +++ b/csharp/protos/unittest_issues.proto @@ -1,91 +1,119 @@ -syntax = "proto3";
-
-// These proto descriptors have at one time been reported as an issue or defect.
-// They are kept here to replicate the issue, and continue to verify the fix.
-
-// Issue: Non-"Google.Protobuffers" namespace will ensure that protobuffer library types are qualified
-option csharp_namespace = "UnitTest.Issues.TestProtos";
-
-package unittest_issues;
-option optimize_for = SPEED;
-
-// Issue 307: when generating doubly-nested types, any references
-// should be of the form A.Types.B.Types.C.
-message Issue307 {
- message NestedOnce {
- message NestedTwice {
- }
- }
-}
-
-// Old issue 13: http://code.google.com/p/protobuf-csharp-port/issues/detail?id=13
-// New issue 309: https://github.com/google/protobuf/issues/309
-
-// message A {
-// optional int32 _A = 1;
-// }
-
-// message B {
-// optional int32 B_ = 1;
-// }
-
-//message AB {
-// optional int32 a_b = 1;
-//}
-
-// Similar issue with numeric names
-// Java code failed too, so probably best for this to be a restriction.
-// See https://github.com/google/protobuf/issues/308
-// message NumberField {
-// optional int32 _01 = 1;
-// }
-
-// issue 19 - negative enum values
-
-enum NegativeEnum {
- NEGATIVE_ENUM_ZERO = 0;
- FiveBelow = -5;
- MinusOne = -1;
-}
-
-message NegativeEnumMessage {
- NegativeEnum value = 1;
- repeated NegativeEnum values = 2 [packed = false];
- repeated NegativeEnum packed_values = 3 [packed=true];
-}
-
-// Issue 21: http://code.google.com/p/protobuf-csharp-port/issues/detail?id=21
-// Decorate fields with [deprecated=true] as [System.Obsolete]
-
-message DeprecatedChild {
-}
-
-enum DeprecatedEnum {
- DEPRECATED_ZERO = 0;
- one = 1;
-}
-
-message DeprecatedFieldsMessage {
- int32 PrimitiveValue = 1 [deprecated = true];
- repeated int32 PrimitiveArray = 2 [deprecated = true];
-
- DeprecatedChild MessageValue = 3 [deprecated = true];
- repeated DeprecatedChild MessageArray = 4 [deprecated = true];
-
- DeprecatedEnum EnumValue = 5 [deprecated = true];
- repeated DeprecatedEnum EnumArray = 6 [deprecated = true];
-}
-
-// Issue 45: http://code.google.com/p/protobuf-csharp-port/issues/detail?id=45
-message ItemField {
- int32 item = 1;
-}
-
-message ReservedNames {
- // Force a nested type called Types
- message SomeNestedType {
- }
-
- int32 types = 1;
- int32 descriptor = 2;
+syntax = "proto3"; + +// These proto descriptors have at one time been reported as an issue or defect. +// They are kept here to replicate the issue, and continue to verify the fix. + +// Issue: Non-"Google.Protobuffers" namespace will ensure that protobuffer library types are qualified +option csharp_namespace = "UnitTest.Issues.TestProtos"; + +package unittest_issues; +option optimize_for = SPEED; + +// Issue 307: when generating doubly-nested types, any references +// should be of the form A.Types.B.Types.C. +message Issue307 { + message NestedOnce { + message NestedTwice { + } + } +} + +// Old issue 13: http://code.google.com/p/protobuf-csharp-port/issues/detail?id=13 +// New issue 309: https://github.com/google/protobuf/issues/309 + +// message A { +// optional int32 _A = 1; +// } + +// message B { +// optional int32 B_ = 1; +// } + +//message AB { +// optional int32 a_b = 1; +//} + +// Similar issue with numeric names +// Java code failed too, so probably best for this to be a restriction. +// See https://github.com/google/protobuf/issues/308 +// message NumberField { +// optional int32 _01 = 1; +// } + +// issue 19 - negative enum values + +enum NegativeEnum { + NEGATIVE_ENUM_ZERO = 0; + FiveBelow = -5; + MinusOne = -1; +} + +message NegativeEnumMessage { + NegativeEnum value = 1; + repeated NegativeEnum values = 2 [packed = false]; + repeated NegativeEnum packed_values = 3 [packed=true]; +} + +// Issue 21: http://code.google.com/p/protobuf-csharp-port/issues/detail?id=21 +// Decorate fields with [deprecated=true] as [System.Obsolete] + +message DeprecatedChild { +} + +enum DeprecatedEnum { + DEPRECATED_ZERO = 0; + one = 1; +} + +message DeprecatedFieldsMessage { + int32 PrimitiveValue = 1 [deprecated = true]; + repeated int32 PrimitiveArray = 2 [deprecated = true]; + + DeprecatedChild MessageValue = 3 [deprecated = true]; + repeated DeprecatedChild MessageArray = 4 [deprecated = true]; + + DeprecatedEnum EnumValue = 5 [deprecated = true]; + repeated DeprecatedEnum EnumArray = 6 [deprecated = true]; +} + +// Issue 45: http://code.google.com/p/protobuf-csharp-port/issues/detail?id=45 +message ItemField { + int32 item = 1; +} + +message ReservedNames { + // Force a nested type called Types + message SomeNestedType { + } + + int32 types = 1; + int32 descriptor = 2; +} + +message TestJsonFieldOrdering { + // These fields are deliberately not declared in numeric + // order, and the oneof fields aren't contiguous either. + // This allows for reasonably robust tests of JSON output + // ordering. + // TestFieldOrderings in unittest_proto3.proto is similar, + // but doesn't include oneofs. + // TODO: Consider adding oneofs to TestFieldOrderings, although + // that will require fixing other tests in multiple platforms. + // Alternatively, consider just adding this to + // unittest_proto3.proto if multiple platforms want it. + + int32 plain_int32 = 4; + + oneof o1 { + string o1_string = 2; + int32 o1_int32 = 5; + } + + string plain_string = 1; + + oneof o2 { + int32 o2_int32 = 6; + string o2_string = 3; + } + }
\ No newline at end of file diff --git a/csharp/src/AddressBook/Addressbook.cs b/csharp/src/AddressBook/Addressbook.cs index 25752e20..f2be5bae 100644 --- a/csharp/src/AddressBook/Addressbook.cs +++ b/csharp/src/AddressBook/Addressbook.cs @@ -186,14 +186,10 @@ namespace Google.Protobuf.Examples.AddressBook { public void MergeFrom(pb::CodedInputStream input) { uint tag; - while (input.ReadTag(out tag)) { + while ((tag = input.ReadTag()) != 0) { switch(tag) { - case 0: - throw pb::InvalidProtocolBufferException.InvalidTag(); default: - if (pb::WireFormat.IsEndGroupTag(tag)) { - return; - } + input.SkipLastField(); break; case 10: { Name = input.ReadString(); @@ -333,14 +329,10 @@ namespace Google.Protobuf.Examples.AddressBook { public void MergeFrom(pb::CodedInputStream input) { uint tag; - while (input.ReadTag(out tag)) { + while ((tag = input.ReadTag()) != 0) { switch(tag) { - case 0: - throw pb::InvalidProtocolBufferException.InvalidTag(); default: - if (pb::WireFormat.IsEndGroupTag(tag)) { - return; - } + input.SkipLastField(); break; case 10: { Number = input.ReadString(); @@ -440,14 +432,10 @@ namespace Google.Protobuf.Examples.AddressBook { public void MergeFrom(pb::CodedInputStream input) { uint tag; - while (input.ReadTag(out tag)) { + while ((tag = input.ReadTag()) != 0) { switch(tag) { - case 0: - throw pb::InvalidProtocolBufferException.InvalidTag(); default: - if (pb::WireFormat.IsEndGroupTag(tag)) { - return; - } + input.SkipLastField(); break; case 10: { people_.AddEntriesFrom(input, _repeated_people_codec); diff --git a/csharp/src/AddressBook/Properties/AssemblyInfo.cs b/csharp/src/AddressBook/Properties/AssemblyInfo.cs index e9c40dce..9cb014c0 100644 --- a/csharp/src/AddressBook/Properties/AssemblyInfo.cs +++ b/csharp/src/AddressBook/Properties/AssemblyInfo.cs @@ -10,20 +10,9 @@ using System.Runtime.InteropServices; [assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("AddressBook")]
-[assembly: AssemblyCopyright("Copyright © 2008")]
+[assembly: AssemblyCopyright("Copyright © 2015")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
-// Version information for an assembly consists of the following four values:
-//
-// Major Version
-// Minor Version
-// Build Number
-// Revision
-//
-// You can specify all the values or you can default the Build and Revision Numbers
-// by using the '*' as shown below:
-// [assembly: AssemblyVersion("2.4.1.555")]
-
-[assembly: AssemblyVersion("2.4.1.555")]
-[assembly: AssemblyFileVersion("2.4.1.555")]
\ No newline at end of file +[assembly: AssemblyVersion("3.0.0.0")]
+[assembly: AssemblyFileVersion("3.0.0.0")]
diff --git a/csharp/src/Google.Protobuf.Conformance/App.config b/csharp/src/Google.Protobuf.Conformance/App.config new file mode 100644 index 00000000..8e156463 --- /dev/null +++ b/csharp/src/Google.Protobuf.Conformance/App.config @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="utf-8" ?> +<configuration> + <startup> + <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" /> + </startup> +</configuration>
\ No newline at end of file diff --git a/csharp/src/Google.Protobuf.Conformance/Conformance.cs b/csharp/src/Google.Protobuf.Conformance/Conformance.cs new file mode 100644 index 00000000..e905d4e4 --- /dev/null +++ b/csharp/src/Google.Protobuf.Conformance/Conformance.cs @@ -0,0 +1,2380 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: conformance.proto +#pragma warning disable 1591, 0612, 3021 +#region Designer generated code + +using pb = global::Google.Protobuf; +using pbc = global::Google.Protobuf.Collections; +using pbr = global::Google.Protobuf.Reflection; +using scg = global::System.Collections.Generic; +namespace Conformance { + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + public static partial class Conformance { + + #region Descriptor + public static pbr::FileDescriptor Descriptor { + get { return descriptor; } + } + private static pbr::FileDescriptor descriptor; + + static Conformance() { + 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), new[]{ "ProtobufPayload", "JsonPayload", "RequestedOutputFormat" }, new[]{ "Payload" }, null, null), + new pbr::GeneratedCodeInfo(typeof(global::Conformance.ConformanceResponse), new[]{ "ParseError", "RuntimeError", "ProtobufPayload", "JsonPayload", "Skipped" }, new[]{ "Result" }, null, null), + new pbr::GeneratedCodeInfo(typeof(global::Conformance.TestAllTypes), 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), 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), new[]{ "C" }, null, null, null) + })); + } + #endregion + + } + #region Enums + public enum WireFormat { + UNSPECIFIED = 0, + PROTOBUF = 1, + JSON = 2, + } + + public enum ForeignEnum { + FOREIGN_FOO = 0, + FOREIGN_BAR = 1, + FOREIGN_BAZ = 2, + } + + #endregion + + #region Messages + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + public sealed partial class ConformanceRequest : pb::IMessage<ConformanceRequest> { + private static readonly pb::MessageParser<ConformanceRequest> _parser = new pb::MessageParser<ConformanceRequest>(() => new ConformanceRequest()); + public static pb::MessageParser<ConformanceRequest> Parser { get { return _parser; } } + + public static pbr::MessageDescriptor Descriptor { + get { return global::Conformance.Conformance.Descriptor.MessageTypes[0]; } + } + + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + public ConformanceRequest() { + OnConstruction(); + } + + partial void OnConstruction(); + + public ConformanceRequest(ConformanceRequest other) : this() { + requestedOutputFormat_ = other.requestedOutputFormat_; + switch (other.PayloadCase) { + case PayloadOneofCase.ProtobufPayload: + ProtobufPayload = other.ProtobufPayload; + break; + case PayloadOneofCase.JsonPayload: + JsonPayload = other.JsonPayload; + break; + } + + } + + public ConformanceRequest Clone() { + return new ConformanceRequest(this); + } + + public const int ProtobufPayloadFieldNumber = 1; + public pb::ByteString ProtobufPayload { + get { return payloadCase_ == PayloadOneofCase.ProtobufPayload ? (pb::ByteString) payload_ : pb::ByteString.Empty; } + set { + payload_ = pb::Preconditions.CheckNotNull(value, "value"); + payloadCase_ = PayloadOneofCase.ProtobufPayload; + } + } + + public const int JsonPayloadFieldNumber = 2; + public string JsonPayload { + get { return payloadCase_ == PayloadOneofCase.JsonPayload ? (string) payload_ : ""; } + set { + payload_ = pb::Preconditions.CheckNotNull(value, "value"); + payloadCase_ = PayloadOneofCase.JsonPayload; + } + } + + public const int RequestedOutputFormatFieldNumber = 3; + private global::Conformance.WireFormat requestedOutputFormat_ = global::Conformance.WireFormat.UNSPECIFIED; + public global::Conformance.WireFormat RequestedOutputFormat { + get { return requestedOutputFormat_; } + set { + requestedOutputFormat_ = value; + } + } + + private object payload_; + public enum PayloadOneofCase { + None = 0, + ProtobufPayload = 1, + JsonPayload = 2, + } + private PayloadOneofCase payloadCase_ = PayloadOneofCase.None; + public PayloadOneofCase PayloadCase { + get { return payloadCase_; } + } + + public void ClearPayload() { + payloadCase_ = PayloadOneofCase.None; + payload_ = null; + } + + public override bool Equals(object other) { + return Equals(other as ConformanceRequest); + } + + public bool Equals(ConformanceRequest other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (ProtobufPayload != other.ProtobufPayload) return false; + if (JsonPayload != other.JsonPayload) return false; + if (RequestedOutputFormat != other.RequestedOutputFormat) return false; + return true; + } + + public override int GetHashCode() { + int hash = 1; + if (payloadCase_ == PayloadOneofCase.ProtobufPayload) hash ^= ProtobufPayload.GetHashCode(); + if (payloadCase_ == PayloadOneofCase.JsonPayload) hash ^= JsonPayload.GetHashCode(); + if (RequestedOutputFormat != global::Conformance.WireFormat.UNSPECIFIED) hash ^= RequestedOutputFormat.GetHashCode(); + return hash; + } + + public override string ToString() { + return pb::JsonFormatter.Default.Format(this); + } + + public void WriteTo(pb::CodedOutputStream output) { + if (payloadCase_ == PayloadOneofCase.ProtobufPayload) { + output.WriteRawTag(10); + output.WriteBytes(ProtobufPayload); + } + if (payloadCase_ == PayloadOneofCase.JsonPayload) { + output.WriteRawTag(18); + output.WriteString(JsonPayload); + } + if (RequestedOutputFormat != global::Conformance.WireFormat.UNSPECIFIED) { + output.WriteRawTag(24); + output.WriteEnum((int) RequestedOutputFormat); + } + } + + public int CalculateSize() { + int size = 0; + if (payloadCase_ == PayloadOneofCase.ProtobufPayload) { + size += 1 + pb::CodedOutputStream.ComputeBytesSize(ProtobufPayload); + } + if (payloadCase_ == PayloadOneofCase.JsonPayload) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(JsonPayload); + } + if (RequestedOutputFormat != global::Conformance.WireFormat.UNSPECIFIED) { + size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) RequestedOutputFormat); + } + return size; + } + + public void MergeFrom(ConformanceRequest other) { + if (other == null) { + return; + } + if (other.RequestedOutputFormat != global::Conformance.WireFormat.UNSPECIFIED) { + RequestedOutputFormat = other.RequestedOutputFormat; + } + switch (other.PayloadCase) { + case PayloadOneofCase.ProtobufPayload: + ProtobufPayload = other.ProtobufPayload; + break; + case PayloadOneofCase.JsonPayload: + JsonPayload = other.JsonPayload; + break; + } + + } + + public void MergeFrom(pb::CodedInputStream input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + input.SkipLastField(); + break; + case 10: { + ProtobufPayload = input.ReadBytes(); + break; + } + case 18: { + JsonPayload = input.ReadString(); + break; + } + case 24: { + requestedOutputFormat_ = (global::Conformance.WireFormat) input.ReadEnum(); + break; + } + } + } + } + + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + public sealed partial class ConformanceResponse : pb::IMessage<ConformanceResponse> { + private static readonly pb::MessageParser<ConformanceResponse> _parser = new pb::MessageParser<ConformanceResponse>(() => new ConformanceResponse()); + public static pb::MessageParser<ConformanceResponse> Parser { get { return _parser; } } + + public static pbr::MessageDescriptor Descriptor { + get { return global::Conformance.Conformance.Descriptor.MessageTypes[1]; } + } + + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + public ConformanceResponse() { + OnConstruction(); + } + + partial void OnConstruction(); + + public ConformanceResponse(ConformanceResponse other) : this() { + switch (other.ResultCase) { + case ResultOneofCase.ParseError: + ParseError = other.ParseError; + break; + case ResultOneofCase.RuntimeError: + RuntimeError = other.RuntimeError; + break; + case ResultOneofCase.ProtobufPayload: + ProtobufPayload = other.ProtobufPayload; + break; + case ResultOneofCase.JsonPayload: + JsonPayload = other.JsonPayload; + break; + case ResultOneofCase.Skipped: + Skipped = other.Skipped; + break; + } + + } + + public ConformanceResponse Clone() { + return new ConformanceResponse(this); + } + + public const int ParseErrorFieldNumber = 1; + public string ParseError { + get { return resultCase_ == ResultOneofCase.ParseError ? (string) result_ : ""; } + set { + result_ = pb::Preconditions.CheckNotNull(value, "value"); + resultCase_ = ResultOneofCase.ParseError; + } + } + + public const int RuntimeErrorFieldNumber = 2; + public string RuntimeError { + get { return resultCase_ == ResultOneofCase.RuntimeError ? (string) result_ : ""; } + set { + result_ = pb::Preconditions.CheckNotNull(value, "value"); + resultCase_ = ResultOneofCase.RuntimeError; + } + } + + public const int ProtobufPayloadFieldNumber = 3; + public pb::ByteString ProtobufPayload { + get { return resultCase_ == ResultOneofCase.ProtobufPayload ? (pb::ByteString) result_ : pb::ByteString.Empty; } + set { + result_ = pb::Preconditions.CheckNotNull(value, "value"); + resultCase_ = ResultOneofCase.ProtobufPayload; + } + } + + public const int JsonPayloadFieldNumber = 4; + public string JsonPayload { + get { return resultCase_ == ResultOneofCase.JsonPayload ? (string) result_ : ""; } + set { + result_ = pb::Preconditions.CheckNotNull(value, "value"); + resultCase_ = ResultOneofCase.JsonPayload; + } + } + + public const int SkippedFieldNumber = 5; + public string Skipped { + get { return resultCase_ == ResultOneofCase.Skipped ? (string) result_ : ""; } + set { + result_ = pb::Preconditions.CheckNotNull(value, "value"); + resultCase_ = ResultOneofCase.Skipped; + } + } + + private object result_; + public enum ResultOneofCase { + None = 0, + ParseError = 1, + RuntimeError = 2, + ProtobufPayload = 3, + JsonPayload = 4, + Skipped = 5, + } + private ResultOneofCase resultCase_ = ResultOneofCase.None; + public ResultOneofCase ResultCase { + get { return resultCase_; } + } + + public void ClearResult() { + resultCase_ = ResultOneofCase.None; + result_ = null; + } + + public override bool Equals(object other) { + return Equals(other as ConformanceResponse); + } + + public bool Equals(ConformanceResponse other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (ParseError != other.ParseError) return false; + if (RuntimeError != other.RuntimeError) return false; + if (ProtobufPayload != other.ProtobufPayload) return false; + if (JsonPayload != other.JsonPayload) return false; + if (Skipped != other.Skipped) return false; + return true; + } + + public override int GetHashCode() { + int hash = 1; + if (resultCase_ == ResultOneofCase.ParseError) hash ^= ParseError.GetHashCode(); + if (resultCase_ == ResultOneofCase.RuntimeError) hash ^= RuntimeError.GetHashCode(); + if (resultCase_ == ResultOneofCase.ProtobufPayload) hash ^= ProtobufPayload.GetHashCode(); + if (resultCase_ == ResultOneofCase.JsonPayload) hash ^= JsonPayload.GetHashCode(); + if (resultCase_ == ResultOneofCase.Skipped) hash ^= Skipped.GetHashCode(); + return hash; + } + + public override string ToString() { + return pb::JsonFormatter.Default.Format(this); + } + + public void WriteTo(pb::CodedOutputStream output) { + if (resultCase_ == ResultOneofCase.ParseError) { + output.WriteRawTag(10); + output.WriteString(ParseError); + } + if (resultCase_ == ResultOneofCase.RuntimeError) { + output.WriteRawTag(18); + output.WriteString(RuntimeError); + } + if (resultCase_ == ResultOneofCase.ProtobufPayload) { + output.WriteRawTag(26); + output.WriteBytes(ProtobufPayload); + } + if (resultCase_ == ResultOneofCase.JsonPayload) { + output.WriteRawTag(34); + output.WriteString(JsonPayload); + } + if (resultCase_ == ResultOneofCase.Skipped) { + output.WriteRawTag(42); + output.WriteString(Skipped); + } + } + + public int CalculateSize() { + int size = 0; + if (resultCase_ == ResultOneofCase.ParseError) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(ParseError); + } + if (resultCase_ == ResultOneofCase.RuntimeError) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(RuntimeError); + } + if (resultCase_ == ResultOneofCase.ProtobufPayload) { + size += 1 + pb::CodedOutputStream.ComputeBytesSize(ProtobufPayload); + } + if (resultCase_ == ResultOneofCase.JsonPayload) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(JsonPayload); + } + if (resultCase_ == ResultOneofCase.Skipped) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Skipped); + } + return size; + } + + public void MergeFrom(ConformanceResponse other) { + if (other == null) { + return; + } + switch (other.ResultCase) { + case ResultOneofCase.ParseError: + ParseError = other.ParseError; + break; + case ResultOneofCase.RuntimeError: + RuntimeError = other.RuntimeError; + break; + case ResultOneofCase.ProtobufPayload: + ProtobufPayload = other.ProtobufPayload; + break; + case ResultOneofCase.JsonPayload: + JsonPayload = other.JsonPayload; + break; + case ResultOneofCase.Skipped: + Skipped = other.Skipped; + break; + } + + } + + public void MergeFrom(pb::CodedInputStream input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + input.SkipLastField(); + break; + case 10: { + ParseError = input.ReadString(); + break; + } + case 18: { + RuntimeError = input.ReadString(); + break; + } + case 26: { + ProtobufPayload = input.ReadBytes(); + break; + } + case 34: { + JsonPayload = input.ReadString(); + break; + } + case 42: { + Skipped = input.ReadString(); + break; + } + } + } + } + + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + public sealed partial class TestAllTypes : pb::IMessage<TestAllTypes> { + private static readonly pb::MessageParser<TestAllTypes> _parser = new pb::MessageParser<TestAllTypes>(() => new TestAllTypes()); + public static pb::MessageParser<TestAllTypes> Parser { get { return _parser; } } + + public static pbr::MessageDescriptor Descriptor { + get { return global::Conformance.Conformance.Descriptor.MessageTypes[2]; } + } + + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + public TestAllTypes() { + OnConstruction(); + } + + partial void OnConstruction(); + + public TestAllTypes(TestAllTypes other) : this() { + optionalInt32_ = other.optionalInt32_; + optionalInt64_ = other.optionalInt64_; + optionalUint32_ = other.optionalUint32_; + optionalUint64_ = other.optionalUint64_; + optionalSint32_ = other.optionalSint32_; + optionalSint64_ = other.optionalSint64_; + optionalFixed32_ = other.optionalFixed32_; + optionalFixed64_ = other.optionalFixed64_; + optionalSfixed32_ = other.optionalSfixed32_; + optionalSfixed64_ = other.optionalSfixed64_; + optionalFloat_ = other.optionalFloat_; + optionalDouble_ = other.optionalDouble_; + optionalBool_ = other.optionalBool_; + optionalString_ = other.optionalString_; + optionalBytes_ = other.optionalBytes_; + OptionalNestedMessage = other.optionalNestedMessage_ != null ? other.OptionalNestedMessage.Clone() : null; + OptionalForeignMessage = other.optionalForeignMessage_ != null ? other.OptionalForeignMessage.Clone() : null; + optionalNestedEnum_ = other.optionalNestedEnum_; + optionalForeignEnum_ = other.optionalForeignEnum_; + optionalStringPiece_ = other.optionalStringPiece_; + optionalCord_ = other.optionalCord_; + RecursiveMessage = other.recursiveMessage_ != null ? other.RecursiveMessage.Clone() : null; + repeatedInt32_ = other.repeatedInt32_.Clone(); + repeatedInt64_ = other.repeatedInt64_.Clone(); + repeatedUint32_ = other.repeatedUint32_.Clone(); + repeatedUint64_ = other.repeatedUint64_.Clone(); + repeatedSint32_ = other.repeatedSint32_.Clone(); + repeatedSint64_ = other.repeatedSint64_.Clone(); + repeatedFixed32_ = other.repeatedFixed32_.Clone(); + repeatedFixed64_ = other.repeatedFixed64_.Clone(); + repeatedSfixed32_ = other.repeatedSfixed32_.Clone(); + repeatedSfixed64_ = other.repeatedSfixed64_.Clone(); + repeatedFloat_ = other.repeatedFloat_.Clone(); + repeatedDouble_ = other.repeatedDouble_.Clone(); + repeatedBool_ = other.repeatedBool_.Clone(); + repeatedString_ = other.repeatedString_.Clone(); + repeatedBytes_ = other.repeatedBytes_.Clone(); + repeatedNestedMessage_ = other.repeatedNestedMessage_.Clone(); + repeatedForeignMessage_ = other.repeatedForeignMessage_.Clone(); + repeatedNestedEnum_ = other.repeatedNestedEnum_.Clone(); + repeatedForeignEnum_ = other.repeatedForeignEnum_.Clone(); + repeatedStringPiece_ = other.repeatedStringPiece_.Clone(); + repeatedCord_ = other.repeatedCord_.Clone(); + mapInt32Int32_ = other.mapInt32Int32_.Clone(); + mapInt64Int64_ = other.mapInt64Int64_.Clone(); + mapUint32Uint32_ = other.mapUint32Uint32_.Clone(); + mapUint64Uint64_ = other.mapUint64Uint64_.Clone(); + mapSint32Sint32_ = other.mapSint32Sint32_.Clone(); + mapSint64Sint64_ = other.mapSint64Sint64_.Clone(); + mapFixed32Fixed32_ = other.mapFixed32Fixed32_.Clone(); + mapFixed64Fixed64_ = other.mapFixed64Fixed64_.Clone(); + mapSfixed32Sfixed32_ = other.mapSfixed32Sfixed32_.Clone(); + mapSfixed64Sfixed64_ = other.mapSfixed64Sfixed64_.Clone(); + mapInt32Float_ = other.mapInt32Float_.Clone(); + mapInt32Double_ = other.mapInt32Double_.Clone(); + mapBoolBool_ = other.mapBoolBool_.Clone(); + mapStringString_ = other.mapStringString_.Clone(); + mapStringBytes_ = other.mapStringBytes_.Clone(); + mapStringNestedMessage_ = other.mapStringNestedMessage_.Clone(); + mapStringForeignMessage_ = other.mapStringForeignMessage_.Clone(); + mapStringNestedEnum_ = other.mapStringNestedEnum_.Clone(); + mapStringForeignEnum_ = other.mapStringForeignEnum_.Clone(); + switch (other.OneofFieldCase) { + case OneofFieldOneofCase.OneofUint32: + OneofUint32 = other.OneofUint32; + break; + case OneofFieldOneofCase.OneofNestedMessage: + OneofNestedMessage = other.OneofNestedMessage.Clone(); + break; + case OneofFieldOneofCase.OneofString: + OneofString = other.OneofString; + break; + case OneofFieldOneofCase.OneofBytes: + OneofBytes = other.OneofBytes; + break; + } + + } + + public TestAllTypes Clone() { + return new TestAllTypes(this); + } + + public const int OptionalInt32FieldNumber = 1; + private int optionalInt32_; + public int OptionalInt32 { + get { return optionalInt32_; } + set { + optionalInt32_ = value; + } + } + + public const int OptionalInt64FieldNumber = 2; + private long optionalInt64_; + public long OptionalInt64 { + get { return optionalInt64_; } + set { + optionalInt64_ = value; + } + } + + public const int OptionalUint32FieldNumber = 3; + private uint optionalUint32_; + public uint OptionalUint32 { + get { return optionalUint32_; } + set { + optionalUint32_ = value; + } + } + + public const int OptionalUint64FieldNumber = 4; + private ulong optionalUint64_; + public ulong OptionalUint64 { + get { return optionalUint64_; } + set { + optionalUint64_ = value; + } + } + + public const int OptionalSint32FieldNumber = 5; + private int optionalSint32_; + public int OptionalSint32 { + get { return optionalSint32_; } + set { + optionalSint32_ = value; + } + } + + public const int OptionalSint64FieldNumber = 6; + private long optionalSint64_; + public long OptionalSint64 { + get { return optionalSint64_; } + set { + optionalSint64_ = value; + } + } + + public const int OptionalFixed32FieldNumber = 7; + private uint optionalFixed32_; + public uint OptionalFixed32 { + get { return optionalFixed32_; } + set { + optionalFixed32_ = value; + } + } + + public const int OptionalFixed64FieldNumber = 8; + private ulong optionalFixed64_; + public ulong OptionalFixed64 { + get { return optionalFixed64_; } + set { + optionalFixed64_ = value; + } + } + + public const int OptionalSfixed32FieldNumber = 9; + private int optionalSfixed32_; + public int OptionalSfixed32 { + get { return optionalSfixed32_; } + set { + optionalSfixed32_ = value; + } + } + + public const int OptionalSfixed64FieldNumber = 10; + private long optionalSfixed64_; + public long OptionalSfixed64 { + get { return optionalSfixed64_; } + set { + optionalSfixed64_ = value; + } + } + + public const int OptionalFloatFieldNumber = 11; + private float optionalFloat_; + public float OptionalFloat { + get { return optionalFloat_; } + set { + optionalFloat_ = value; + } + } + + public const int OptionalDoubleFieldNumber = 12; + private double optionalDouble_; + public double OptionalDouble { + get { return optionalDouble_; } + set { + optionalDouble_ = value; + } + } + + public const int OptionalBoolFieldNumber = 13; + private bool optionalBool_; + public bool OptionalBool { + get { return optionalBool_; } + set { + optionalBool_ = value; + } + } + + public const int OptionalStringFieldNumber = 14; + private string optionalString_ = ""; + public string OptionalString { + get { return optionalString_; } + set { + optionalString_ = pb::Preconditions.CheckNotNull(value, "value"); + } + } + + public const int OptionalBytesFieldNumber = 15; + private pb::ByteString optionalBytes_ = pb::ByteString.Empty; + public pb::ByteString OptionalBytes { + get { return optionalBytes_; } + set { + optionalBytes_ = pb::Preconditions.CheckNotNull(value, "value"); + } + } + + public const int OptionalNestedMessageFieldNumber = 18; + private global::Conformance.TestAllTypes.Types.NestedMessage optionalNestedMessage_; + public global::Conformance.TestAllTypes.Types.NestedMessage OptionalNestedMessage { + get { return optionalNestedMessage_; } + set { + optionalNestedMessage_ = value; + } + } + + public const int OptionalForeignMessageFieldNumber = 19; + private global::Conformance.ForeignMessage optionalForeignMessage_; + public global::Conformance.ForeignMessage OptionalForeignMessage { + get { return optionalForeignMessage_; } + set { + optionalForeignMessage_ = value; + } + } + + public const int OptionalNestedEnumFieldNumber = 21; + private global::Conformance.TestAllTypes.Types.NestedEnum optionalNestedEnum_ = global::Conformance.TestAllTypes.Types.NestedEnum.FOO; + public global::Conformance.TestAllTypes.Types.NestedEnum OptionalNestedEnum { + get { return optionalNestedEnum_; } + set { + optionalNestedEnum_ = value; + } + } + + public const int OptionalForeignEnumFieldNumber = 22; + private global::Conformance.ForeignEnum optionalForeignEnum_ = global::Conformance.ForeignEnum.FOREIGN_FOO; + public global::Conformance.ForeignEnum OptionalForeignEnum { + get { return optionalForeignEnum_; } + set { + optionalForeignEnum_ = value; + } + } + + public const int OptionalStringPieceFieldNumber = 24; + private string optionalStringPiece_ = ""; + public string OptionalStringPiece { + get { return optionalStringPiece_; } + set { + optionalStringPiece_ = pb::Preconditions.CheckNotNull(value, "value"); + } + } + + public const int OptionalCordFieldNumber = 25; + private string optionalCord_ = ""; + public string OptionalCord { + get { return optionalCord_; } + set { + optionalCord_ = pb::Preconditions.CheckNotNull(value, "value"); + } + } + + public const int RecursiveMessageFieldNumber = 27; + private global::Conformance.TestAllTypes recursiveMessage_; + public global::Conformance.TestAllTypes RecursiveMessage { + get { return recursiveMessage_; } + set { + recursiveMessage_ = value; + } + } + + public const int RepeatedInt32FieldNumber = 31; + private static readonly pb::FieldCodec<int> _repeated_repeatedInt32_codec + = pb::FieldCodec.ForInt32(250); + private readonly pbc::RepeatedField<int> repeatedInt32_ = new pbc::RepeatedField<int>(); + public pbc::RepeatedField<int> RepeatedInt32 { + get { return repeatedInt32_; } + } + + public const int RepeatedInt64FieldNumber = 32; + private static readonly pb::FieldCodec<long> _repeated_repeatedInt64_codec + = pb::FieldCodec.ForInt64(258); + private readonly pbc::RepeatedField<long> repeatedInt64_ = new pbc::RepeatedField<long>(); + public pbc::RepeatedField<long> RepeatedInt64 { + get { return repeatedInt64_; } + } + + public const int RepeatedUint32FieldNumber = 33; + private static readonly pb::FieldCodec<uint> _repeated_repeatedUint32_codec + = pb::FieldCodec.ForUInt32(266); + private readonly pbc::RepeatedField<uint> repeatedUint32_ = new pbc::RepeatedField<uint>(); + public pbc::RepeatedField<uint> RepeatedUint32 { + get { return repeatedUint32_; } + } + + public const int RepeatedUint64FieldNumber = 34; + private static readonly pb::FieldCodec<ulong> _repeated_repeatedUint64_codec + = pb::FieldCodec.ForUInt64(274); + private readonly pbc::RepeatedField<ulong> repeatedUint64_ = new pbc::RepeatedField<ulong>(); + public pbc::RepeatedField<ulong> RepeatedUint64 { + get { return repeatedUint64_; } + } + + public const int RepeatedSint32FieldNumber = 35; + private static readonly pb::FieldCodec<int> _repeated_repeatedSint32_codec + = pb::FieldCodec.ForSInt32(282); + private readonly pbc::RepeatedField<int> repeatedSint32_ = new pbc::RepeatedField<int>(); + public pbc::RepeatedField<int> RepeatedSint32 { + get { return repeatedSint32_; } + } + + public const int RepeatedSint64FieldNumber = 36; + private static readonly pb::FieldCodec<long> _repeated_repeatedSint64_codec + = pb::FieldCodec.ForSInt64(290); + private readonly pbc::RepeatedField<long> repeatedSint64_ = new pbc::RepeatedField<long>(); + public pbc::RepeatedField<long> RepeatedSint64 { + get { return repeatedSint64_; } + } + + public const int RepeatedFixed32FieldNumber = 37; + private static readonly pb::FieldCodec<uint> _repeated_repeatedFixed32_codec + = pb::FieldCodec.ForFixed32(298); + private readonly pbc::RepeatedField<uint> repeatedFixed32_ = new pbc::RepeatedField<uint>(); + public pbc::RepeatedField<uint> RepeatedFixed32 { + get { return repeatedFixed32_; } + } + + public const int RepeatedFixed64FieldNumber = 38; + private static readonly pb::FieldCodec<ulong> _repeated_repeatedFixed64_codec + = pb::FieldCodec.ForFixed64(306); + private readonly pbc::RepeatedField<ulong> repeatedFixed64_ = new pbc::RepeatedField<ulong>(); + public pbc::RepeatedField<ulong> RepeatedFixed64 { + get { return repeatedFixed64_; } + } + + public const int RepeatedSfixed32FieldNumber = 39; + private static readonly pb::FieldCodec<int> _repeated_repeatedSfixed32_codec + = pb::FieldCodec.ForSFixed32(314); + private readonly pbc::RepeatedField<int> repeatedSfixed32_ = new pbc::RepeatedField<int>(); + public pbc::RepeatedField<int> RepeatedSfixed32 { + get { return repeatedSfixed32_; } + } + + public const int RepeatedSfixed64FieldNumber = 40; + private static readonly pb::FieldCodec<long> _repeated_repeatedSfixed64_codec + = pb::FieldCodec.ForSFixed64(322); + private readonly pbc::RepeatedField<long> repeatedSfixed64_ = new pbc::RepeatedField<long>(); + public pbc::RepeatedField<long> RepeatedSfixed64 { + get { return repeatedSfixed64_; } + } + + public const int RepeatedFloatFieldNumber = 41; + private static readonly pb::FieldCodec<float> _repeated_repeatedFloat_codec + = pb::FieldCodec.ForFloat(330); + private readonly pbc::RepeatedField<float> repeatedFloat_ = new pbc::RepeatedField<float>(); + public pbc::RepeatedField<float> RepeatedFloat { + get { return repeatedFloat_; } + } + + public const int RepeatedDoubleFieldNumber = 42; + private static readonly pb::FieldCodec<double> _repeated_repeatedDouble_codec + = pb::FieldCodec.ForDouble(338); + private readonly pbc::RepeatedField<double> repeatedDouble_ = new pbc::RepeatedField<double>(); + public pbc::RepeatedField<double> RepeatedDouble { + get { return repeatedDouble_; } + } + + public const int RepeatedBoolFieldNumber = 43; + private static readonly pb::FieldCodec<bool> _repeated_repeatedBool_codec + = pb::FieldCodec.ForBool(346); + private readonly pbc::RepeatedField<bool> repeatedBool_ = new pbc::RepeatedField<bool>(); + public pbc::RepeatedField<bool> RepeatedBool { + get { return repeatedBool_; } + } + + public const int RepeatedStringFieldNumber = 44; + private static readonly pb::FieldCodec<string> _repeated_repeatedString_codec + = pb::FieldCodec.ForString(354); + private readonly pbc::RepeatedField<string> repeatedString_ = new pbc::RepeatedField<string>(); + public pbc::RepeatedField<string> RepeatedString { + get { return repeatedString_; } + } + + public const int RepeatedBytesFieldNumber = 45; + private static readonly pb::FieldCodec<pb::ByteString> _repeated_repeatedBytes_codec + = pb::FieldCodec.ForBytes(362); + private readonly pbc::RepeatedField<pb::ByteString> repeatedBytes_ = new pbc::RepeatedField<pb::ByteString>(); + public pbc::RepeatedField<pb::ByteString> RepeatedBytes { + get { return repeatedBytes_; } + } + + public const int RepeatedNestedMessageFieldNumber = 48; + private static readonly pb::FieldCodec<global::Conformance.TestAllTypes.Types.NestedMessage> _repeated_repeatedNestedMessage_codec + = pb::FieldCodec.ForMessage(386, global::Conformance.TestAllTypes.Types.NestedMessage.Parser); + private readonly pbc::RepeatedField<global::Conformance.TestAllTypes.Types.NestedMessage> repeatedNestedMessage_ = new pbc::RepeatedField<global::Conformance.TestAllTypes.Types.NestedMessage>(); + public pbc::RepeatedField<global::Conformance.TestAllTypes.Types.NestedMessage> RepeatedNestedMessage { + get { return repeatedNestedMessage_; } + } + + public const int RepeatedForeignMessageFieldNumber = 49; + private static readonly pb::FieldCodec<global::Conformance.ForeignMessage> _repeated_repeatedForeignMessage_codec + = pb::FieldCodec.ForMessage(394, global::Conformance.ForeignMessage.Parser); + private readonly pbc::RepeatedField<global::Conformance.ForeignMessage> repeatedForeignMessage_ = new pbc::RepeatedField<global::Conformance.ForeignMessage>(); + public pbc::RepeatedField<global::Conformance.ForeignMessage> RepeatedForeignMessage { + get { return repeatedForeignMessage_; } + } + + public const int RepeatedNestedEnumFieldNumber = 51; + private static readonly pb::FieldCodec<global::Conformance.TestAllTypes.Types.NestedEnum> _repeated_repeatedNestedEnum_codec + = pb::FieldCodec.ForEnum(410, x => (int) x, x => (global::Conformance.TestAllTypes.Types.NestedEnum) x); + private readonly pbc::RepeatedField<global::Conformance.TestAllTypes.Types.NestedEnum> repeatedNestedEnum_ = new pbc::RepeatedField<global::Conformance.TestAllTypes.Types.NestedEnum>(); + public pbc::RepeatedField<global::Conformance.TestAllTypes.Types.NestedEnum> RepeatedNestedEnum { + get { return repeatedNestedEnum_; } + } + + public const int RepeatedForeignEnumFieldNumber = 52; + private static readonly pb::FieldCodec<global::Conformance.ForeignEnum> _repeated_repeatedForeignEnum_codec + = pb::FieldCodec.ForEnum(418, x => (int) x, x => (global::Conformance.ForeignEnum) x); + private readonly pbc::RepeatedField<global::Conformance.ForeignEnum> repeatedForeignEnum_ = new pbc::RepeatedField<global::Conformance.ForeignEnum>(); + public pbc::RepeatedField<global::Conformance.ForeignEnum> RepeatedForeignEnum { + get { return repeatedForeignEnum_; } + } + + public const int RepeatedStringPieceFieldNumber = 54; + private static readonly pb::FieldCodec<string> _repeated_repeatedStringPiece_codec + = pb::FieldCodec.ForString(434); + private readonly pbc::RepeatedField<string> repeatedStringPiece_ = new pbc::RepeatedField<string>(); + public pbc::RepeatedField<string> RepeatedStringPiece { + get { return repeatedStringPiece_; } + } + + public const int RepeatedCordFieldNumber = 55; + private static readonly pb::FieldCodec<string> _repeated_repeatedCord_codec + = pb::FieldCodec.ForString(442); + private readonly pbc::RepeatedField<string> repeatedCord_ = new pbc::RepeatedField<string>(); + public pbc::RepeatedField<string> RepeatedCord { + get { return repeatedCord_; } + } + + public const int MapInt32Int32FieldNumber = 56; + private static readonly pbc::MapField<int, int>.Codec _map_mapInt32Int32_codec + = new pbc::MapField<int, int>.Codec(pb::FieldCodec.ForInt32(8), pb::FieldCodec.ForInt32(16), 450); + private readonly pbc::MapField<int, int> mapInt32Int32_ = new pbc::MapField<int, int>(); + public pbc::MapField<int, int> MapInt32Int32 { + get { return mapInt32Int32_; } + } + + public const int MapInt64Int64FieldNumber = 57; + private static readonly pbc::MapField<long, long>.Codec _map_mapInt64Int64_codec + = new pbc::MapField<long, long>.Codec(pb::FieldCodec.ForInt64(8), pb::FieldCodec.ForInt64(16), 458); + private readonly pbc::MapField<long, long> mapInt64Int64_ = new pbc::MapField<long, long>(); + public pbc::MapField<long, long> MapInt64Int64 { + get { return mapInt64Int64_; } + } + + public const int MapUint32Uint32FieldNumber = 58; + private static readonly pbc::MapField<uint, uint>.Codec _map_mapUint32Uint32_codec + = new pbc::MapField<uint, uint>.Codec(pb::FieldCodec.ForUInt32(8), pb::FieldCodec.ForUInt32(16), 466); + private readonly pbc::MapField<uint, uint> mapUint32Uint32_ = new pbc::MapField<uint, uint>(); + public pbc::MapField<uint, uint> MapUint32Uint32 { + get { return mapUint32Uint32_; } + } + + public const int MapUint64Uint64FieldNumber = 59; + private static readonly pbc::MapField<ulong, ulong>.Codec _map_mapUint64Uint64_codec + = new pbc::MapField<ulong, ulong>.Codec(pb::FieldCodec.ForUInt64(8), pb::FieldCodec.ForUInt64(16), 474); + private readonly pbc::MapField<ulong, ulong> mapUint64Uint64_ = new pbc::MapField<ulong, ulong>(); + public pbc::MapField<ulong, ulong> MapUint64Uint64 { + get { return mapUint64Uint64_; } + } + + public const int MapSint32Sint32FieldNumber = 60; + private static readonly pbc::MapField<int, int>.Codec _map_mapSint32Sint32_codec + = new pbc::MapField<int, int>.Codec(pb::FieldCodec.ForSInt32(8), pb::FieldCodec.ForSInt32(16), 482); + private readonly pbc::MapField<int, int> mapSint32Sint32_ = new pbc::MapField<int, int>(); + public pbc::MapField<int, int> MapSint32Sint32 { + get { return mapSint32Sint32_; } + } + + public const int MapSint64Sint64FieldNumber = 61; + private static readonly pbc::MapField<long, long>.Codec _map_mapSint64Sint64_codec + = new pbc::MapField<long, long>.Codec(pb::FieldCodec.ForSInt64(8), pb::FieldCodec.ForSInt64(16), 490); + private readonly pbc::MapField<long, long> mapSint64Sint64_ = new pbc::MapField<long, long>(); + public pbc::MapField<long, long> MapSint64Sint64 { + get { return mapSint64Sint64_; } + } + + public const int MapFixed32Fixed32FieldNumber = 62; + private static readonly pbc::MapField<uint, uint>.Codec _map_mapFixed32Fixed32_codec + = new pbc::MapField<uint, uint>.Codec(pb::FieldCodec.ForFixed32(13), pb::FieldCodec.ForFixed32(21), 498); + private readonly pbc::MapField<uint, uint> mapFixed32Fixed32_ = new pbc::MapField<uint, uint>(); + public pbc::MapField<uint, uint> MapFixed32Fixed32 { + get { return mapFixed32Fixed32_; } + } + + public const int MapFixed64Fixed64FieldNumber = 63; + private static readonly pbc::MapField<ulong, ulong>.Codec _map_mapFixed64Fixed64_codec + = new pbc::MapField<ulong, ulong>.Codec(pb::FieldCodec.ForFixed64(9), pb::FieldCodec.ForFixed64(17), 506); + private readonly pbc::MapField<ulong, ulong> mapFixed64Fixed64_ = new pbc::MapField<ulong, ulong>(); + public pbc::MapField<ulong, ulong> MapFixed64Fixed64 { + get { return mapFixed64Fixed64_; } + } + + public const int MapSfixed32Sfixed32FieldNumber = 64; + private static readonly pbc::MapField<int, int>.Codec _map_mapSfixed32Sfixed32_codec + = new pbc::MapField<int, int>.Codec(pb::FieldCodec.ForSFixed32(13), pb::FieldCodec.ForSFixed32(21), 514); + private readonly pbc::MapField<int, int> mapSfixed32Sfixed32_ = new pbc::MapField<int, int>(); + public pbc::MapField<int, int> MapSfixed32Sfixed32 { + get { return mapSfixed32Sfixed32_; } + } + + public const int MapSfixed64Sfixed64FieldNumber = 65; + private static readonly pbc::MapField<long, long>.Codec _map_mapSfixed64Sfixed64_codec + = new pbc::MapField<long, long>.Codec(pb::FieldCodec.ForSFixed64(9), pb::FieldCodec.ForSFixed64(17), 522); + private readonly pbc::MapField<long, long> mapSfixed64Sfixed64_ = new pbc::MapField<long, long>(); + public pbc::MapField<long, long> MapSfixed64Sfixed64 { + get { return mapSfixed64Sfixed64_; } + } + + public const int MapInt32FloatFieldNumber = 66; + private static readonly pbc::MapField<int, float>.Codec _map_mapInt32Float_codec + = new pbc::MapField<int, float>.Codec(pb::FieldCodec.ForInt32(8), pb::FieldCodec.ForFloat(21), 530); + private readonly pbc::MapField<int, float> mapInt32Float_ = new pbc::MapField<int, float>(); + public pbc::MapField<int, float> MapInt32Float { + get { return mapInt32Float_; } + } + + public const int MapInt32DoubleFieldNumber = 67; + private static readonly pbc::MapField<int, double>.Codec _map_mapInt32Double_codec + = new pbc::MapField<int, double>.Codec(pb::FieldCodec.ForInt32(8), pb::FieldCodec.ForDouble(17), 538); + private readonly pbc::MapField<int, double> mapInt32Double_ = new pbc::MapField<int, double>(); + public pbc::MapField<int, double> MapInt32Double { + get { return mapInt32Double_; } + } + + public const int MapBoolBoolFieldNumber = 68; + private static readonly pbc::MapField<bool, bool>.Codec _map_mapBoolBool_codec + = new pbc::MapField<bool, bool>.Codec(pb::FieldCodec.ForBool(8), pb::FieldCodec.ForBool(16), 546); + private readonly pbc::MapField<bool, bool> mapBoolBool_ = new pbc::MapField<bool, bool>(); + public pbc::MapField<bool, bool> MapBoolBool { + get { return mapBoolBool_; } + } + + public const int MapStringStringFieldNumber = 69; + private static readonly pbc::MapField<string, string>.Codec _map_mapStringString_codec + = new pbc::MapField<string, string>.Codec(pb::FieldCodec.ForString(10), pb::FieldCodec.ForString(18), 554); + private readonly pbc::MapField<string, string> mapStringString_ = new pbc::MapField<string, string>(); + public pbc::MapField<string, string> MapStringString { + get { return mapStringString_; } + } + + public const int MapStringBytesFieldNumber = 70; + private static readonly pbc::MapField<string, pb::ByteString>.Codec _map_mapStringBytes_codec + = new pbc::MapField<string, pb::ByteString>.Codec(pb::FieldCodec.ForString(10), pb::FieldCodec.ForBytes(18), 562); + private readonly pbc::MapField<string, pb::ByteString> mapStringBytes_ = new pbc::MapField<string, pb::ByteString>(); + public pbc::MapField<string, pb::ByteString> MapStringBytes { + get { return mapStringBytes_; } + } + + public const int MapStringNestedMessageFieldNumber = 71; + private static readonly pbc::MapField<string, global::Conformance.TestAllTypes.Types.NestedMessage>.Codec _map_mapStringNestedMessage_codec + = new pbc::MapField<string, global::Conformance.TestAllTypes.Types.NestedMessage>.Codec(pb::FieldCodec.ForString(10), pb::FieldCodec.ForMessage(18, global::Conformance.TestAllTypes.Types.NestedMessage.Parser), 570); + private readonly pbc::MapField<string, global::Conformance.TestAllTypes.Types.NestedMessage> mapStringNestedMessage_ = new pbc::MapField<string, global::Conformance.TestAllTypes.Types.NestedMessage>(); + public pbc::MapField<string, global::Conformance.TestAllTypes.Types.NestedMessage> MapStringNestedMessage { + get { return mapStringNestedMessage_; } + } + + public const int MapStringForeignMessageFieldNumber = 72; + private static readonly pbc::MapField<string, global::Conformance.ForeignMessage>.Codec _map_mapStringForeignMessage_codec + = new pbc::MapField<string, global::Conformance.ForeignMessage>.Codec(pb::FieldCodec.ForString(10), pb::FieldCodec.ForMessage(18, global::Conformance.ForeignMessage.Parser), 578); + private readonly pbc::MapField<string, global::Conformance.ForeignMessage> mapStringForeignMessage_ = new pbc::MapField<string, global::Conformance.ForeignMessage>(); + public pbc::MapField<string, global::Conformance.ForeignMessage> MapStringForeignMessage { + get { return mapStringForeignMessage_; } + } + + public const int MapStringNestedEnumFieldNumber = 73; + private static readonly pbc::MapField<string, global::Conformance.TestAllTypes.Types.NestedEnum>.Codec _map_mapStringNestedEnum_codec + = new pbc::MapField<string, global::Conformance.TestAllTypes.Types.NestedEnum>.Codec(pb::FieldCodec.ForString(10), pb::FieldCodec.ForEnum(16, x => (int) x, x => (global::Conformance.TestAllTypes.Types.NestedEnum) x), 586); + private readonly pbc::MapField<string, global::Conformance.TestAllTypes.Types.NestedEnum> mapStringNestedEnum_ = new pbc::MapField<string, global::Conformance.TestAllTypes.Types.NestedEnum>(); + public pbc::MapField<string, global::Conformance.TestAllTypes.Types.NestedEnum> MapStringNestedEnum { + get { return mapStringNestedEnum_; } + } + + public const int MapStringForeignEnumFieldNumber = 74; + private static readonly pbc::MapField<string, global::Conformance.ForeignEnum>.Codec _map_mapStringForeignEnum_codec + = new pbc::MapField<string, global::Conformance.ForeignEnum>.Codec(pb::FieldCodec.ForString(10), pb::FieldCodec.ForEnum(16, x => (int) x, x => (global::Conformance.ForeignEnum) x), 594); + private readonly pbc::MapField<string, global::Conformance.ForeignEnum> mapStringForeignEnum_ = new pbc::MapField<string, global::Conformance.ForeignEnum>(); + public pbc::MapField<string, global::Conformance.ForeignEnum> MapStringForeignEnum { + get { return mapStringForeignEnum_; } + } + + public const int OneofUint32FieldNumber = 111; + public uint OneofUint32 { + get { return oneofFieldCase_ == OneofFieldOneofCase.OneofUint32 ? (uint) oneofField_ : 0; } + set { + oneofField_ = value; + oneofFieldCase_ = OneofFieldOneofCase.OneofUint32; + } + } + + public const int OneofNestedMessageFieldNumber = 112; + public global::Conformance.TestAllTypes.Types.NestedMessage OneofNestedMessage { + get { return oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage ? (global::Conformance.TestAllTypes.Types.NestedMessage) oneofField_ : null; } + set { + oneofField_ = value; + oneofFieldCase_ = value == null ? OneofFieldOneofCase.None : OneofFieldOneofCase.OneofNestedMessage; + } + } + + public const int OneofStringFieldNumber = 113; + public string OneofString { + get { return oneofFieldCase_ == OneofFieldOneofCase.OneofString ? (string) oneofField_ : ""; } + set { + oneofField_ = pb::Preconditions.CheckNotNull(value, "value"); + oneofFieldCase_ = OneofFieldOneofCase.OneofString; + } + } + + public const int OneofBytesFieldNumber = 114; + public pb::ByteString OneofBytes { + get { return oneofFieldCase_ == OneofFieldOneofCase.OneofBytes ? (pb::ByteString) oneofField_ : pb::ByteString.Empty; } + set { + oneofField_ = pb::Preconditions.CheckNotNull(value, "value"); + oneofFieldCase_ = OneofFieldOneofCase.OneofBytes; + } + } + + private object oneofField_; + public enum OneofFieldOneofCase { + None = 0, + OneofUint32 = 111, + OneofNestedMessage = 112, + OneofString = 113, + OneofBytes = 114, + } + private OneofFieldOneofCase oneofFieldCase_ = OneofFieldOneofCase.None; + public OneofFieldOneofCase OneofFieldCase { + get { return oneofFieldCase_; } + } + + public void ClearOneofField() { + oneofFieldCase_ = OneofFieldOneofCase.None; + oneofField_ = null; + } + + public override bool Equals(object other) { + return Equals(other as TestAllTypes); + } + + public bool Equals(TestAllTypes other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (OptionalInt32 != other.OptionalInt32) return false; + if (OptionalInt64 != other.OptionalInt64) return false; + if (OptionalUint32 != other.OptionalUint32) return false; + if (OptionalUint64 != other.OptionalUint64) return false; + if (OptionalSint32 != other.OptionalSint32) return false; + if (OptionalSint64 != other.OptionalSint64) return false; + if (OptionalFixed32 != other.OptionalFixed32) return false; + if (OptionalFixed64 != other.OptionalFixed64) return false; + if (OptionalSfixed32 != other.OptionalSfixed32) return false; + if (OptionalSfixed64 != other.OptionalSfixed64) return false; + if (OptionalFloat != other.OptionalFloat) return false; + if (OptionalDouble != other.OptionalDouble) return false; + if (OptionalBool != other.OptionalBool) return false; + if (OptionalString != other.OptionalString) return false; + if (OptionalBytes != other.OptionalBytes) return false; + if (!object.Equals(OptionalNestedMessage, other.OptionalNestedMessage)) return false; + if (!object.Equals(OptionalForeignMessage, other.OptionalForeignMessage)) return false; + if (OptionalNestedEnum != other.OptionalNestedEnum) return false; + if (OptionalForeignEnum != other.OptionalForeignEnum) return false; + if (OptionalStringPiece != other.OptionalStringPiece) return false; + if (OptionalCord != other.OptionalCord) return false; + if (!object.Equals(RecursiveMessage, other.RecursiveMessage)) return false; + if(!repeatedInt32_.Equals(other.repeatedInt32_)) return false; + if(!repeatedInt64_.Equals(other.repeatedInt64_)) return false; + if(!repeatedUint32_.Equals(other.repeatedUint32_)) return false; + if(!repeatedUint64_.Equals(other.repeatedUint64_)) return false; + if(!repeatedSint32_.Equals(other.repeatedSint32_)) return false; + if(!repeatedSint64_.Equals(other.repeatedSint64_)) return false; + if(!repeatedFixed32_.Equals(other.repeatedFixed32_)) return false; + if(!repeatedFixed64_.Equals(other.repeatedFixed64_)) return false; + if(!repeatedSfixed32_.Equals(other.repeatedSfixed32_)) return false; + if(!repeatedSfixed64_.Equals(other.repeatedSfixed64_)) return false; + if(!repeatedFloat_.Equals(other.repeatedFloat_)) return false; + if(!repeatedDouble_.Equals(other.repeatedDouble_)) return false; + if(!repeatedBool_.Equals(other.repeatedBool_)) return false; + if(!repeatedString_.Equals(other.repeatedString_)) return false; + if(!repeatedBytes_.Equals(other.repeatedBytes_)) return false; + if(!repeatedNestedMessage_.Equals(other.repeatedNestedMessage_)) return false; + if(!repeatedForeignMessage_.Equals(other.repeatedForeignMessage_)) return false; + if(!repeatedNestedEnum_.Equals(other.repeatedNestedEnum_)) return false; + if(!repeatedForeignEnum_.Equals(other.repeatedForeignEnum_)) return false; + if(!repeatedStringPiece_.Equals(other.repeatedStringPiece_)) return false; + if(!repeatedCord_.Equals(other.repeatedCord_)) return false; + if (!MapInt32Int32.Equals(other.MapInt32Int32)) return false; + if (!MapInt64Int64.Equals(other.MapInt64Int64)) return false; + if (!MapUint32Uint32.Equals(other.MapUint32Uint32)) return false; + if (!MapUint64Uint64.Equals(other.MapUint64Uint64)) return false; + if (!MapSint32Sint32.Equals(other.MapSint32Sint32)) return false; + if (!MapSint64Sint64.Equals(other.MapSint64Sint64)) return false; + if (!MapFixed32Fixed32.Equals(other.MapFixed32Fixed32)) return false; + if (!MapFixed64Fixed64.Equals(other.MapFixed64Fixed64)) return false; + if (!MapSfixed32Sfixed32.Equals(other.MapSfixed32Sfixed32)) return false; + if (!MapSfixed64Sfixed64.Equals(other.MapSfixed64Sfixed64)) return false; + if (!MapInt32Float.Equals(other.MapInt32Float)) return false; + if (!MapInt32Double.Equals(other.MapInt32Double)) return false; + if (!MapBoolBool.Equals(other.MapBoolBool)) return false; + if (!MapStringString.Equals(other.MapStringString)) return false; + if (!MapStringBytes.Equals(other.MapStringBytes)) return false; + if (!MapStringNestedMessage.Equals(other.MapStringNestedMessage)) return false; + if (!MapStringForeignMessage.Equals(other.MapStringForeignMessage)) return false; + if (!MapStringNestedEnum.Equals(other.MapStringNestedEnum)) return false; + if (!MapStringForeignEnum.Equals(other.MapStringForeignEnum)) return false; + if (OneofUint32 != other.OneofUint32) return false; + if (!object.Equals(OneofNestedMessage, other.OneofNestedMessage)) return false; + if (OneofString != other.OneofString) return false; + if (OneofBytes != other.OneofBytes) return false; + return true; + } + + public override int GetHashCode() { + int hash = 1; + if (OptionalInt32 != 0) hash ^= OptionalInt32.GetHashCode(); + if (OptionalInt64 != 0L) hash ^= OptionalInt64.GetHashCode(); + if (OptionalUint32 != 0) hash ^= OptionalUint32.GetHashCode(); + if (OptionalUint64 != 0UL) hash ^= OptionalUint64.GetHashCode(); + if (OptionalSint32 != 0) hash ^= OptionalSint32.GetHashCode(); + if (OptionalSint64 != 0L) hash ^= OptionalSint64.GetHashCode(); + if (OptionalFixed32 != 0) hash ^= OptionalFixed32.GetHashCode(); + if (OptionalFixed64 != 0UL) hash ^= OptionalFixed64.GetHashCode(); + if (OptionalSfixed32 != 0) hash ^= OptionalSfixed32.GetHashCode(); + if (OptionalSfixed64 != 0L) hash ^= OptionalSfixed64.GetHashCode(); + if (OptionalFloat != 0F) hash ^= OptionalFloat.GetHashCode(); + if (OptionalDouble != 0D) hash ^= OptionalDouble.GetHashCode(); + if (OptionalBool != false) hash ^= OptionalBool.GetHashCode(); + if (OptionalString.Length != 0) hash ^= OptionalString.GetHashCode(); + if (OptionalBytes.Length != 0) hash ^= OptionalBytes.GetHashCode(); + if (optionalNestedMessage_ != null) hash ^= OptionalNestedMessage.GetHashCode(); + if (optionalForeignMessage_ != null) hash ^= OptionalForeignMessage.GetHashCode(); + if (OptionalNestedEnum != global::Conformance.TestAllTypes.Types.NestedEnum.FOO) hash ^= OptionalNestedEnum.GetHashCode(); + if (OptionalForeignEnum != global::Conformance.ForeignEnum.FOREIGN_FOO) hash ^= OptionalForeignEnum.GetHashCode(); + if (OptionalStringPiece.Length != 0) hash ^= OptionalStringPiece.GetHashCode(); + if (OptionalCord.Length != 0) hash ^= OptionalCord.GetHashCode(); + if (recursiveMessage_ != null) hash ^= RecursiveMessage.GetHashCode(); + hash ^= repeatedInt32_.GetHashCode(); + hash ^= repeatedInt64_.GetHashCode(); + hash ^= repeatedUint32_.GetHashCode(); + hash ^= repeatedUint64_.GetHashCode(); + hash ^= repeatedSint32_.GetHashCode(); + hash ^= repeatedSint64_.GetHashCode(); + hash ^= repeatedFixed32_.GetHashCode(); + hash ^= repeatedFixed64_.GetHashCode(); + hash ^= repeatedSfixed32_.GetHashCode(); + hash ^= repeatedSfixed64_.GetHashCode(); + hash ^= repeatedFloat_.GetHashCode(); + hash ^= repeatedDouble_.GetHashCode(); + hash ^= repeatedBool_.GetHashCode(); + hash ^= repeatedString_.GetHashCode(); + hash ^= repeatedBytes_.GetHashCode(); + hash ^= repeatedNestedMessage_.GetHashCode(); + hash ^= repeatedForeignMessage_.GetHashCode(); + hash ^= repeatedNestedEnum_.GetHashCode(); + hash ^= repeatedForeignEnum_.GetHashCode(); + hash ^= repeatedStringPiece_.GetHashCode(); + hash ^= repeatedCord_.GetHashCode(); + hash ^= MapInt32Int32.GetHashCode(); + hash ^= MapInt64Int64.GetHashCode(); + hash ^= MapUint32Uint32.GetHashCode(); + hash ^= MapUint64Uint64.GetHashCode(); + hash ^= MapSint32Sint32.GetHashCode(); + hash ^= MapSint64Sint64.GetHashCode(); + hash ^= MapFixed32Fixed32.GetHashCode(); + hash ^= MapFixed64Fixed64.GetHashCode(); + hash ^= MapSfixed32Sfixed32.GetHashCode(); + hash ^= MapSfixed64Sfixed64.GetHashCode(); + hash ^= MapInt32Float.GetHashCode(); + hash ^= MapInt32Double.GetHashCode(); + hash ^= MapBoolBool.GetHashCode(); + hash ^= MapStringString.GetHashCode(); + hash ^= MapStringBytes.GetHashCode(); + hash ^= MapStringNestedMessage.GetHashCode(); + hash ^= MapStringForeignMessage.GetHashCode(); + hash ^= MapStringNestedEnum.GetHashCode(); + hash ^= MapStringForeignEnum.GetHashCode(); + if (oneofFieldCase_ == OneofFieldOneofCase.OneofUint32) hash ^= OneofUint32.GetHashCode(); + if (oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage) hash ^= OneofNestedMessage.GetHashCode(); + if (oneofFieldCase_ == OneofFieldOneofCase.OneofString) hash ^= OneofString.GetHashCode(); + if (oneofFieldCase_ == OneofFieldOneofCase.OneofBytes) hash ^= OneofBytes.GetHashCode(); + return hash; + } + + public override string ToString() { + return pb::JsonFormatter.Default.Format(this); + } + + public void WriteTo(pb::CodedOutputStream output) { + if (OptionalInt32 != 0) { + output.WriteRawTag(8); + output.WriteInt32(OptionalInt32); + } + if (OptionalInt64 != 0L) { + output.WriteRawTag(16); + output.WriteInt64(OptionalInt64); + } + if (OptionalUint32 != 0) { + output.WriteRawTag(24); + output.WriteUInt32(OptionalUint32); + } + if (OptionalUint64 != 0UL) { + output.WriteRawTag(32); + output.WriteUInt64(OptionalUint64); + } + if (OptionalSint32 != 0) { + output.WriteRawTag(40); + output.WriteSInt32(OptionalSint32); + } + if (OptionalSint64 != 0L) { + output.WriteRawTag(48); + output.WriteSInt64(OptionalSint64); + } + if (OptionalFixed32 != 0) { + output.WriteRawTag(61); + output.WriteFixed32(OptionalFixed32); + } + if (OptionalFixed64 != 0UL) { + output.WriteRawTag(65); + output.WriteFixed64(OptionalFixed64); + } + if (OptionalSfixed32 != 0) { + output.WriteRawTag(77); + output.WriteSFixed32(OptionalSfixed32); + } + if (OptionalSfixed64 != 0L) { + output.WriteRawTag(81); + output.WriteSFixed64(OptionalSfixed64); + } + if (OptionalFloat != 0F) { + output.WriteRawTag(93); + output.WriteFloat(OptionalFloat); + } + if (OptionalDouble != 0D) { + output.WriteRawTag(97); + output.WriteDouble(OptionalDouble); + } + if (OptionalBool != false) { + output.WriteRawTag(104); + output.WriteBool(OptionalBool); + } + if (OptionalString.Length != 0) { + output.WriteRawTag(114); + output.WriteString(OptionalString); + } + if (OptionalBytes.Length != 0) { + output.WriteRawTag(122); + output.WriteBytes(OptionalBytes); + } + if (optionalNestedMessage_ != null) { + output.WriteRawTag(146, 1); + output.WriteMessage(OptionalNestedMessage); + } + if (optionalForeignMessage_ != null) { + output.WriteRawTag(154, 1); + output.WriteMessage(OptionalForeignMessage); + } + if (OptionalNestedEnum != global::Conformance.TestAllTypes.Types.NestedEnum.FOO) { + output.WriteRawTag(168, 1); + output.WriteEnum((int) OptionalNestedEnum); + } + if (OptionalForeignEnum != global::Conformance.ForeignEnum.FOREIGN_FOO) { + output.WriteRawTag(176, 1); + output.WriteEnum((int) OptionalForeignEnum); + } + if (OptionalStringPiece.Length != 0) { + output.WriteRawTag(194, 1); + output.WriteString(OptionalStringPiece); + } + if (OptionalCord.Length != 0) { + output.WriteRawTag(202, 1); + output.WriteString(OptionalCord); + } + if (recursiveMessage_ != null) { + output.WriteRawTag(218, 1); + output.WriteMessage(RecursiveMessage); + } + repeatedInt32_.WriteTo(output, _repeated_repeatedInt32_codec); + repeatedInt64_.WriteTo(output, _repeated_repeatedInt64_codec); + repeatedUint32_.WriteTo(output, _repeated_repeatedUint32_codec); + repeatedUint64_.WriteTo(output, _repeated_repeatedUint64_codec); + repeatedSint32_.WriteTo(output, _repeated_repeatedSint32_codec); + repeatedSint64_.WriteTo(output, _repeated_repeatedSint64_codec); + repeatedFixed32_.WriteTo(output, _repeated_repeatedFixed32_codec); + repeatedFixed64_.WriteTo(output, _repeated_repeatedFixed64_codec); + repeatedSfixed32_.WriteTo(output, _repeated_repeatedSfixed32_codec); + repeatedSfixed64_.WriteTo(output, _repeated_repeatedSfixed64_codec); + repeatedFloat_.WriteTo(output, _repeated_repeatedFloat_codec); + repeatedDouble_.WriteTo(output, _repeated_repeatedDouble_codec); + repeatedBool_.WriteTo(output, _repeated_repeatedBool_codec); + repeatedString_.WriteTo(output, _repeated_repeatedString_codec); + repeatedBytes_.WriteTo(output, _repeated_repeatedBytes_codec); + repeatedNestedMessage_.WriteTo(output, _repeated_repeatedNestedMessage_codec); + repeatedForeignMessage_.WriteTo(output, _repeated_repeatedForeignMessage_codec); + repeatedNestedEnum_.WriteTo(output, _repeated_repeatedNestedEnum_codec); + repeatedForeignEnum_.WriteTo(output, _repeated_repeatedForeignEnum_codec); + repeatedStringPiece_.WriteTo(output, _repeated_repeatedStringPiece_codec); + repeatedCord_.WriteTo(output, _repeated_repeatedCord_codec); + mapInt32Int32_.WriteTo(output, _map_mapInt32Int32_codec); + mapInt64Int64_.WriteTo(output, _map_mapInt64Int64_codec); + mapUint32Uint32_.WriteTo(output, _map_mapUint32Uint32_codec); + mapUint64Uint64_.WriteTo(output, _map_mapUint64Uint64_codec); + mapSint32Sint32_.WriteTo(output, _map_mapSint32Sint32_codec); + mapSint64Sint64_.WriteTo(output, _map_mapSint64Sint64_codec); + mapFixed32Fixed32_.WriteTo(output, _map_mapFixed32Fixed32_codec); + mapFixed64Fixed64_.WriteTo(output, _map_mapFixed64Fixed64_codec); + mapSfixed32Sfixed32_.WriteTo(output, _map_mapSfixed32Sfixed32_codec); + mapSfixed64Sfixed64_.WriteTo(output, _map_mapSfixed64Sfixed64_codec); + mapInt32Float_.WriteTo(output, _map_mapInt32Float_codec); + mapInt32Double_.WriteTo(output, _map_mapInt32Double_codec); + mapBoolBool_.WriteTo(output, _map_mapBoolBool_codec); + mapStringString_.WriteTo(output, _map_mapStringString_codec); + mapStringBytes_.WriteTo(output, _map_mapStringBytes_codec); + mapStringNestedMessage_.WriteTo(output, _map_mapStringNestedMessage_codec); + mapStringForeignMessage_.WriteTo(output, _map_mapStringForeignMessage_codec); + mapStringNestedEnum_.WriteTo(output, _map_mapStringNestedEnum_codec); + mapStringForeignEnum_.WriteTo(output, _map_mapStringForeignEnum_codec); + if (oneofFieldCase_ == OneofFieldOneofCase.OneofUint32) { + output.WriteRawTag(248, 6); + output.WriteUInt32(OneofUint32); + } + if (oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage) { + output.WriteRawTag(130, 7); + output.WriteMessage(OneofNestedMessage); + } + if (oneofFieldCase_ == OneofFieldOneofCase.OneofString) { + output.WriteRawTag(138, 7); + output.WriteString(OneofString); + } + if (oneofFieldCase_ == OneofFieldOneofCase.OneofBytes) { + output.WriteRawTag(146, 7); + output.WriteBytes(OneofBytes); + } + } + + public int CalculateSize() { + int size = 0; + if (OptionalInt32 != 0) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(OptionalInt32); + } + if (OptionalInt64 != 0L) { + size += 1 + pb::CodedOutputStream.ComputeInt64Size(OptionalInt64); + } + if (OptionalUint32 != 0) { + size += 1 + pb::CodedOutputStream.ComputeUInt32Size(OptionalUint32); + } + if (OptionalUint64 != 0UL) { + size += 1 + pb::CodedOutputStream.ComputeUInt64Size(OptionalUint64); + } + if (OptionalSint32 != 0) { + size += 1 + pb::CodedOutputStream.ComputeSInt32Size(OptionalSint32); + } + if (OptionalSint64 != 0L) { + size += 1 + pb::CodedOutputStream.ComputeSInt64Size(OptionalSint64); + } + if (OptionalFixed32 != 0) { + size += 1 + 4; + } + if (OptionalFixed64 != 0UL) { + size += 1 + 8; + } + if (OptionalSfixed32 != 0) { + size += 1 + 4; + } + if (OptionalSfixed64 != 0L) { + size += 1 + 8; + } + if (OptionalFloat != 0F) { + size += 1 + 4; + } + if (OptionalDouble != 0D) { + size += 1 + 8; + } + if (OptionalBool != false) { + size += 1 + 1; + } + if (OptionalString.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(OptionalString); + } + if (OptionalBytes.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeBytesSize(OptionalBytes); + } + if (optionalNestedMessage_ != null) { + size += 2 + pb::CodedOutputStream.ComputeMessageSize(OptionalNestedMessage); + } + if (optionalForeignMessage_ != null) { + size += 2 + pb::CodedOutputStream.ComputeMessageSize(OptionalForeignMessage); + } + if (OptionalNestedEnum != global::Conformance.TestAllTypes.Types.NestedEnum.FOO) { + size += 2 + pb::CodedOutputStream.ComputeEnumSize((int) OptionalNestedEnum); + } + if (OptionalForeignEnum != global::Conformance.ForeignEnum.FOREIGN_FOO) { + size += 2 + pb::CodedOutputStream.ComputeEnumSize((int) OptionalForeignEnum); + } + if (OptionalStringPiece.Length != 0) { + size += 2 + pb::CodedOutputStream.ComputeStringSize(OptionalStringPiece); + } + if (OptionalCord.Length != 0) { + size += 2 + pb::CodedOutputStream.ComputeStringSize(OptionalCord); + } + if (recursiveMessage_ != null) { + size += 2 + pb::CodedOutputStream.ComputeMessageSize(RecursiveMessage); + } + size += repeatedInt32_.CalculateSize(_repeated_repeatedInt32_codec); + size += repeatedInt64_.CalculateSize(_repeated_repeatedInt64_codec); + size += repeatedUint32_.CalculateSize(_repeated_repeatedUint32_codec); + size += repeatedUint64_.CalculateSize(_repeated_repeatedUint64_codec); + size += repeatedSint32_.CalculateSize(_repeated_repeatedSint32_codec); + size += repeatedSint64_.CalculateSize(_repeated_repeatedSint64_codec); + size += repeatedFixed32_.CalculateSize(_repeated_repeatedFixed32_codec); + size += repeatedFixed64_.CalculateSize(_repeated_repeatedFixed64_codec); + size += repeatedSfixed32_.CalculateSize(_repeated_repeatedSfixed32_codec); + size += repeatedSfixed64_.CalculateSize(_repeated_repeatedSfixed64_codec); + size += repeatedFloat_.CalculateSize(_repeated_repeatedFloat_codec); + size += repeatedDouble_.CalculateSize(_repeated_repeatedDouble_codec); + size += repeatedBool_.CalculateSize(_repeated_repeatedBool_codec); + size += repeatedString_.CalculateSize(_repeated_repeatedString_codec); + size += repeatedBytes_.CalculateSize(_repeated_repeatedBytes_codec); + size += repeatedNestedMessage_.CalculateSize(_repeated_repeatedNestedMessage_codec); + size += repeatedForeignMessage_.CalculateSize(_repeated_repeatedForeignMessage_codec); + size += repeatedNestedEnum_.CalculateSize(_repeated_repeatedNestedEnum_codec); + size += repeatedForeignEnum_.CalculateSize(_repeated_repeatedForeignEnum_codec); + size += repeatedStringPiece_.CalculateSize(_repeated_repeatedStringPiece_codec); + size += repeatedCord_.CalculateSize(_repeated_repeatedCord_codec); + size += mapInt32Int32_.CalculateSize(_map_mapInt32Int32_codec); + size += mapInt64Int64_.CalculateSize(_map_mapInt64Int64_codec); + size += mapUint32Uint32_.CalculateSize(_map_mapUint32Uint32_codec); + size += mapUint64Uint64_.CalculateSize(_map_mapUint64Uint64_codec); + size += mapSint32Sint32_.CalculateSize(_map_mapSint32Sint32_codec); + size += mapSint64Sint64_.CalculateSize(_map_mapSint64Sint64_codec); + size += mapFixed32Fixed32_.CalculateSize(_map_mapFixed32Fixed32_codec); + size += mapFixed64Fixed64_.CalculateSize(_map_mapFixed64Fixed64_codec); + size += mapSfixed32Sfixed32_.CalculateSize(_map_mapSfixed32Sfixed32_codec); + size += mapSfixed64Sfixed64_.CalculateSize(_map_mapSfixed64Sfixed64_codec); + size += mapInt32Float_.CalculateSize(_map_mapInt32Float_codec); + size += mapInt32Double_.CalculateSize(_map_mapInt32Double_codec); + size += mapBoolBool_.CalculateSize(_map_mapBoolBool_codec); + size += mapStringString_.CalculateSize(_map_mapStringString_codec); + size += mapStringBytes_.CalculateSize(_map_mapStringBytes_codec); + size += mapStringNestedMessage_.CalculateSize(_map_mapStringNestedMessage_codec); + size += mapStringForeignMessage_.CalculateSize(_map_mapStringForeignMessage_codec); + size += mapStringNestedEnum_.CalculateSize(_map_mapStringNestedEnum_codec); + size += mapStringForeignEnum_.CalculateSize(_map_mapStringForeignEnum_codec); + if (oneofFieldCase_ == OneofFieldOneofCase.OneofUint32) { + size += 2 + pb::CodedOutputStream.ComputeUInt32Size(OneofUint32); + } + if (oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage) { + size += 2 + pb::CodedOutputStream.ComputeMessageSize(OneofNestedMessage); + } + if (oneofFieldCase_ == OneofFieldOneofCase.OneofString) { + size += 2 + pb::CodedOutputStream.ComputeStringSize(OneofString); + } + if (oneofFieldCase_ == OneofFieldOneofCase.OneofBytes) { + size += 2 + pb::CodedOutputStream.ComputeBytesSize(OneofBytes); + } + return size; + } + + public void MergeFrom(TestAllTypes other) { + if (other == null) { + return; + } + if (other.OptionalInt32 != 0) { + OptionalInt32 = other.OptionalInt32; + } + if (other.OptionalInt64 != 0L) { + OptionalInt64 = other.OptionalInt64; + } + if (other.OptionalUint32 != 0) { + OptionalUint32 = other.OptionalUint32; + } + if (other.OptionalUint64 != 0UL) { + OptionalUint64 = other.OptionalUint64; + } + if (other.OptionalSint32 != 0) { + OptionalSint32 = other.OptionalSint32; + } + if (other.OptionalSint64 != 0L) { + OptionalSint64 = other.OptionalSint64; + } + if (other.OptionalFixed32 != 0) { + OptionalFixed32 = other.OptionalFixed32; + } + if (other.OptionalFixed64 != 0UL) { + OptionalFixed64 = other.OptionalFixed64; + } + if (other.OptionalSfixed32 != 0) { + OptionalSfixed32 = other.OptionalSfixed32; + } + if (other.OptionalSfixed64 != 0L) { + OptionalSfixed64 = other.OptionalSfixed64; + } + if (other.OptionalFloat != 0F) { + OptionalFloat = other.OptionalFloat; + } + if (other.OptionalDouble != 0D) { + OptionalDouble = other.OptionalDouble; + } + if (other.OptionalBool != false) { + OptionalBool = other.OptionalBool; + } + if (other.OptionalString.Length != 0) { + OptionalString = other.OptionalString; + } + if (other.OptionalBytes.Length != 0) { + OptionalBytes = other.OptionalBytes; + } + if (other.optionalNestedMessage_ != null) { + if (optionalNestedMessage_ == null) { + optionalNestedMessage_ = new global::Conformance.TestAllTypes.Types.NestedMessage(); + } + OptionalNestedMessage.MergeFrom(other.OptionalNestedMessage); + } + if (other.optionalForeignMessage_ != null) { + if (optionalForeignMessage_ == null) { + optionalForeignMessage_ = new global::Conformance.ForeignMessage(); + } + OptionalForeignMessage.MergeFrom(other.OptionalForeignMessage); + } + if (other.OptionalNestedEnum != global::Conformance.TestAllTypes.Types.NestedEnum.FOO) { + OptionalNestedEnum = other.OptionalNestedEnum; + } + if (other.OptionalForeignEnum != global::Conformance.ForeignEnum.FOREIGN_FOO) { + OptionalForeignEnum = other.OptionalForeignEnum; + } + if (other.OptionalStringPiece.Length != 0) { + OptionalStringPiece = other.OptionalStringPiece; + } + if (other.OptionalCord.Length != 0) { + OptionalCord = other.OptionalCord; + } + if (other.recursiveMessage_ != null) { + if (recursiveMessage_ == null) { + recursiveMessage_ = new global::Conformance.TestAllTypes(); + } + RecursiveMessage.MergeFrom(other.RecursiveMessage); + } + repeatedInt32_.Add(other.repeatedInt32_); + repeatedInt64_.Add(other.repeatedInt64_); + repeatedUint32_.Add(other.repeatedUint32_); + repeatedUint64_.Add(other.repeatedUint64_); + repeatedSint32_.Add(other.repeatedSint32_); + repeatedSint64_.Add(other.repeatedSint64_); + repeatedFixed32_.Add(other.repeatedFixed32_); + repeatedFixed64_.Add(other.repeatedFixed64_); + repeatedSfixed32_.Add(other.repeatedSfixed32_); + repeatedSfixed64_.Add(other.repeatedSfixed64_); + repeatedFloat_.Add(other.repeatedFloat_); + repeatedDouble_.Add(other.repeatedDouble_); + repeatedBool_.Add(other.repeatedBool_); + repeatedString_.Add(other.repeatedString_); + repeatedBytes_.Add(other.repeatedBytes_); + repeatedNestedMessage_.Add(other.repeatedNestedMessage_); + repeatedForeignMessage_.Add(other.repeatedForeignMessage_); + repeatedNestedEnum_.Add(other.repeatedNestedEnum_); + repeatedForeignEnum_.Add(other.repeatedForeignEnum_); + repeatedStringPiece_.Add(other.repeatedStringPiece_); + repeatedCord_.Add(other.repeatedCord_); + mapInt32Int32_.Add(other.mapInt32Int32_); + mapInt64Int64_.Add(other.mapInt64Int64_); + mapUint32Uint32_.Add(other.mapUint32Uint32_); + mapUint64Uint64_.Add(other.mapUint64Uint64_); + mapSint32Sint32_.Add(other.mapSint32Sint32_); + mapSint64Sint64_.Add(other.mapSint64Sint64_); + mapFixed32Fixed32_.Add(other.mapFixed32Fixed32_); + mapFixed64Fixed64_.Add(other.mapFixed64Fixed64_); + mapSfixed32Sfixed32_.Add(other.mapSfixed32Sfixed32_); + mapSfixed64Sfixed64_.Add(other.mapSfixed64Sfixed64_); + mapInt32Float_.Add(other.mapInt32Float_); + mapInt32Double_.Add(other.mapInt32Double_); + mapBoolBool_.Add(other.mapBoolBool_); + mapStringString_.Add(other.mapStringString_); + mapStringBytes_.Add(other.mapStringBytes_); + mapStringNestedMessage_.Add(other.mapStringNestedMessage_); + mapStringForeignMessage_.Add(other.mapStringForeignMessage_); + mapStringNestedEnum_.Add(other.mapStringNestedEnum_); + mapStringForeignEnum_.Add(other.mapStringForeignEnum_); + switch (other.OneofFieldCase) { + case OneofFieldOneofCase.OneofUint32: + OneofUint32 = other.OneofUint32; + break; + case OneofFieldOneofCase.OneofNestedMessage: + OneofNestedMessage = other.OneofNestedMessage; + break; + case OneofFieldOneofCase.OneofString: + OneofString = other.OneofString; + break; + case OneofFieldOneofCase.OneofBytes: + OneofBytes = other.OneofBytes; + break; + } + + } + + public void MergeFrom(pb::CodedInputStream input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + input.SkipLastField(); + break; + case 8: { + OptionalInt32 = input.ReadInt32(); + break; + } + case 16: { + OptionalInt64 = input.ReadInt64(); + break; + } + case 24: { + OptionalUint32 = input.ReadUInt32(); + break; + } + case 32: { + OptionalUint64 = input.ReadUInt64(); + break; + } + case 40: { + OptionalSint32 = input.ReadSInt32(); + break; + } + case 48: { + OptionalSint64 = input.ReadSInt64(); + break; + } + case 61: { + OptionalFixed32 = input.ReadFixed32(); + break; + } + case 65: { + OptionalFixed64 = input.ReadFixed64(); + break; + } + case 77: { + OptionalSfixed32 = input.ReadSFixed32(); + break; + } + case 81: { + OptionalSfixed64 = input.ReadSFixed64(); + break; + } + case 93: { + OptionalFloat = input.ReadFloat(); + break; + } + case 97: { + OptionalDouble = input.ReadDouble(); + break; + } + case 104: { + OptionalBool = input.ReadBool(); + break; + } + case 114: { + OptionalString = input.ReadString(); + break; + } + case 122: { + OptionalBytes = input.ReadBytes(); + break; + } + case 146: { + if (optionalNestedMessage_ == null) { + optionalNestedMessage_ = new global::Conformance.TestAllTypes.Types.NestedMessage(); + } + input.ReadMessage(optionalNestedMessage_); + break; + } + case 154: { + if (optionalForeignMessage_ == null) { + optionalForeignMessage_ = new global::Conformance.ForeignMessage(); + } + input.ReadMessage(optionalForeignMessage_); + break; + } + case 168: { + optionalNestedEnum_ = (global::Conformance.TestAllTypes.Types.NestedEnum) input.ReadEnum(); + break; + } + case 176: { + optionalForeignEnum_ = (global::Conformance.ForeignEnum) input.ReadEnum(); + break; + } + case 194: { + OptionalStringPiece = input.ReadString(); + break; + } + case 202: { + OptionalCord = input.ReadString(); + break; + } + case 218: { + if (recursiveMessage_ == null) { + recursiveMessage_ = new global::Conformance.TestAllTypes(); + } + input.ReadMessage(recursiveMessage_); + break; + } + case 250: + case 248: { + repeatedInt32_.AddEntriesFrom(input, _repeated_repeatedInt32_codec); + break; + } + case 258: + case 256: { + repeatedInt64_.AddEntriesFrom(input, _repeated_repeatedInt64_codec); + break; + } + case 266: + case 264: { + repeatedUint32_.AddEntriesFrom(input, _repeated_repeatedUint32_codec); + break; + } + case 274: + case 272: { + repeatedUint64_.AddEntriesFrom(input, _repeated_repeatedUint64_codec); + break; + } + case 282: + case 280: { + repeatedSint32_.AddEntriesFrom(input, _repeated_repeatedSint32_codec); + break; + } + case 290: + case 288: { + repeatedSint64_.AddEntriesFrom(input, _repeated_repeatedSint64_codec); + break; + } + case 298: + case 301: { + repeatedFixed32_.AddEntriesFrom(input, _repeated_repeatedFixed32_codec); + break; + } + case 306: + case 305: { + repeatedFixed64_.AddEntriesFrom(input, _repeated_repeatedFixed64_codec); + break; + } + case 314: + case 317: { + repeatedSfixed32_.AddEntriesFrom(input, _repeated_repeatedSfixed32_codec); + break; + } + case 322: + case 321: { + repeatedSfixed64_.AddEntriesFrom(input, _repeated_repeatedSfixed64_codec); + break; + } + case 330: + case 333: { + repeatedFloat_.AddEntriesFrom(input, _repeated_repeatedFloat_codec); + break; + } + case 338: + case 337: { + repeatedDouble_.AddEntriesFrom(input, _repeated_repeatedDouble_codec); + break; + } + case 346: + case 344: { + repeatedBool_.AddEntriesFrom(input, _repeated_repeatedBool_codec); + break; + } + case 354: { + repeatedString_.AddEntriesFrom(input, _repeated_repeatedString_codec); + break; + } + case 362: { + repeatedBytes_.AddEntriesFrom(input, _repeated_repeatedBytes_codec); + break; + } + case 386: { + repeatedNestedMessage_.AddEntriesFrom(input, _repeated_repeatedNestedMessage_codec); + break; + } + case 394: { + repeatedForeignMessage_.AddEntriesFrom(input, _repeated_repeatedForeignMessage_codec); + break; + } + case 410: + case 408: { + repeatedNestedEnum_.AddEntriesFrom(input, _repeated_repeatedNestedEnum_codec); + break; + } + case 418: + case 416: { + repeatedForeignEnum_.AddEntriesFrom(input, _repeated_repeatedForeignEnum_codec); + break; + } + case 434: { + repeatedStringPiece_.AddEntriesFrom(input, _repeated_repeatedStringPiece_codec); + break; + } + case 442: { + repeatedCord_.AddEntriesFrom(input, _repeated_repeatedCord_codec); + break; + } + case 450: { + mapInt32Int32_.AddEntriesFrom(input, _map_mapInt32Int32_codec); + break; + } + case 458: { + mapInt64Int64_.AddEntriesFrom(input, _map_mapInt64Int64_codec); + break; + } + case 466: { + mapUint32Uint32_.AddEntriesFrom(input, _map_mapUint32Uint32_codec); + break; + } + case 474: { + mapUint64Uint64_.AddEntriesFrom(input, _map_mapUint64Uint64_codec); + break; + } + case 482: { + mapSint32Sint32_.AddEntriesFrom(input, _map_mapSint32Sint32_codec); + break; + } + case 490: { + mapSint64Sint64_.AddEntriesFrom(input, _map_mapSint64Sint64_codec); + break; + } + case 498: { + mapFixed32Fixed32_.AddEntriesFrom(input, _map_mapFixed32Fixed32_codec); + break; + } + case 506: { + mapFixed64Fixed64_.AddEntriesFrom(input, _map_mapFixed64Fixed64_codec); + break; + } + case 514: { + mapSfixed32Sfixed32_.AddEntriesFrom(input, _map_mapSfixed32Sfixed32_codec); + break; + } + case 522: { + mapSfixed64Sfixed64_.AddEntriesFrom(input, _map_mapSfixed64Sfixed64_codec); + break; + } + case 530: { + mapInt32Float_.AddEntriesFrom(input, _map_mapInt32Float_codec); + break; + } + case 538: { + mapInt32Double_.AddEntriesFrom(input, _map_mapInt32Double_codec); + break; + } + case 546: { + mapBoolBool_.AddEntriesFrom(input, _map_mapBoolBool_codec); + break; + } + case 554: { + mapStringString_.AddEntriesFrom(input, _map_mapStringString_codec); + break; + } + case 562: { + mapStringBytes_.AddEntriesFrom(input, _map_mapStringBytes_codec); + break; + } + case 570: { + mapStringNestedMessage_.AddEntriesFrom(input, _map_mapStringNestedMessage_codec); + break; + } + case 578: { + mapStringForeignMessage_.AddEntriesFrom(input, _map_mapStringForeignMessage_codec); + break; + } + case 586: { + mapStringNestedEnum_.AddEntriesFrom(input, _map_mapStringNestedEnum_codec); + break; + } + case 594: { + mapStringForeignEnum_.AddEntriesFrom(input, _map_mapStringForeignEnum_codec); + break; + } + case 888: { + OneofUint32 = input.ReadUInt32(); + break; + } + case 898: { + global::Conformance.TestAllTypes.Types.NestedMessage subBuilder = new global::Conformance.TestAllTypes.Types.NestedMessage(); + if (oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage) { + subBuilder.MergeFrom(OneofNestedMessage); + } + input.ReadMessage(subBuilder); + OneofNestedMessage = subBuilder; + break; + } + case 906: { + OneofString = input.ReadString(); + break; + } + case 914: { + OneofBytes = input.ReadBytes(); + break; + } + } + } + } + + #region Nested types + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + public static partial class Types { + public enum NestedEnum { + FOO = 0, + BAR = 1, + BAZ = 2, + NEG = -1, + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + public sealed partial class NestedMessage : pb::IMessage<NestedMessage> { + private static readonly pb::MessageParser<NestedMessage> _parser = new pb::MessageParser<NestedMessage>(() => new NestedMessage()); + public static pb::MessageParser<NestedMessage> Parser { get { return _parser; } } + + public static pbr::MessageDescriptor Descriptor { + get { return global::Conformance.TestAllTypes.Descriptor.NestedTypes[0]; } + } + + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + public NestedMessage() { + OnConstruction(); + } + + partial void OnConstruction(); + + public NestedMessage(NestedMessage other) : this() { + a_ = other.a_; + Corecursive = other.corecursive_ != null ? other.Corecursive.Clone() : null; + } + + public NestedMessage Clone() { + return new NestedMessage(this); + } + + public const int AFieldNumber = 1; + private int a_; + public int A { + get { return a_; } + set { + a_ = value; + } + } + + public const int CorecursiveFieldNumber = 2; + private global::Conformance.TestAllTypes corecursive_; + public global::Conformance.TestAllTypes Corecursive { + get { return corecursive_; } + set { + corecursive_ = value; + } + } + + public override bool Equals(object other) { + return Equals(other as NestedMessage); + } + + public bool Equals(NestedMessage other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (A != other.A) return false; + if (!object.Equals(Corecursive, other.Corecursive)) return false; + return true; + } + + public override int GetHashCode() { + int hash = 1; + if (A != 0) hash ^= A.GetHashCode(); + if (corecursive_ != null) hash ^= Corecursive.GetHashCode(); + return hash; + } + + public override string ToString() { + return pb::JsonFormatter.Default.Format(this); + } + + public void WriteTo(pb::CodedOutputStream output) { + if (A != 0) { + output.WriteRawTag(8); + output.WriteInt32(A); + } + if (corecursive_ != null) { + output.WriteRawTag(18); + output.WriteMessage(Corecursive); + } + } + + public int CalculateSize() { + int size = 0; + if (A != 0) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(A); + } + if (corecursive_ != null) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(Corecursive); + } + return size; + } + + public void MergeFrom(NestedMessage other) { + if (other == null) { + return; + } + if (other.A != 0) { + A = other.A; + } + if (other.corecursive_ != null) { + if (corecursive_ == null) { + corecursive_ = new global::Conformance.TestAllTypes(); + } + Corecursive.MergeFrom(other.Corecursive); + } + } + + public void MergeFrom(pb::CodedInputStream input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + input.SkipLastField(); + break; + case 8: { + A = input.ReadInt32(); + break; + } + case 18: { + if (corecursive_ == null) { + corecursive_ = new global::Conformance.TestAllTypes(); + } + input.ReadMessage(corecursive_); + break; + } + } + } + } + + } + + } + #endregion + + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + public sealed partial class ForeignMessage : pb::IMessage<ForeignMessage> { + private static readonly pb::MessageParser<ForeignMessage> _parser = new pb::MessageParser<ForeignMessage>(() => new ForeignMessage()); + public static pb::MessageParser<ForeignMessage> Parser { get { return _parser; } } + + public static pbr::MessageDescriptor Descriptor { + get { return global::Conformance.Conformance.Descriptor.MessageTypes[3]; } + } + + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + public ForeignMessage() { + OnConstruction(); + } + + partial void OnConstruction(); + + public ForeignMessage(ForeignMessage other) : this() { + c_ = other.c_; + } + + public ForeignMessage Clone() { + return new ForeignMessage(this); + } + + public const int CFieldNumber = 1; + private int c_; + public int C { + get { return c_; } + set { + c_ = value; + } + } + + public override bool Equals(object other) { + return Equals(other as ForeignMessage); + } + + public bool Equals(ForeignMessage other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (C != other.C) return false; + return true; + } + + public override int GetHashCode() { + int hash = 1; + if (C != 0) hash ^= C.GetHashCode(); + return hash; + } + + public override string ToString() { + return pb::JsonFormatter.Default.Format(this); + } + + public void WriteTo(pb::CodedOutputStream output) { + if (C != 0) { + output.WriteRawTag(8); + output.WriteInt32(C); + } + } + + public int CalculateSize() { + int size = 0; + if (C != 0) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(C); + } + return size; + } + + public void MergeFrom(ForeignMessage other) { + if (other == null) { + return; + } + if (other.C != 0) { + C = other.C; + } + } + + public void MergeFrom(pb::CodedInputStream input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + input.SkipLastField(); + break; + case 8: { + C = input.ReadInt32(); + break; + } + } + } + } + + } + + #endregion + +} + +#endregion Designer generated code diff --git a/csharp/src/Google.Protobuf.Conformance/Google.Protobuf.Conformance.csproj b/csharp/src/Google.Protobuf.Conformance/Google.Protobuf.Conformance.csproj new file mode 100644 index 00000000..82f728d1 --- /dev/null +++ b/csharp/src/Google.Protobuf.Conformance/Google.Protobuf.Conformance.csproj @@ -0,0 +1,61 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" /> + <PropertyGroup> + <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> + <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> + <ProjectGuid>{0607D1B8-80D6-4B35-9857-1263C1B32B94}</ProjectGuid> + <OutputType>Exe</OutputType> + <AppDesignerFolder>Properties</AppDesignerFolder> + <RootNamespace>Google.Protobuf.Conformance</RootNamespace> + <AssemblyName>Google.Protobuf.Conformance</AssemblyName> + <TargetFrameworkVersion>v4.5</TargetFrameworkVersion> + <FileAlignment>512</FileAlignment> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> + <PlatformTarget>AnyCPU</PlatformTarget> + <DebugSymbols>true</DebugSymbols> + <DebugType>full</DebugType> + <Optimize>false</Optimize> + <OutputPath>bin\Debug\</OutputPath> + <DefineConstants>DEBUG;TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> + <PlatformTarget>AnyCPU</PlatformTarget> + <DebugType>pdbonly</DebugType> + <Optimize>true</Optimize> + <OutputPath>bin\Release\</OutputPath> + <DefineConstants>TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <ItemGroup> + <Reference Include="System" /> + <Reference Include="System.Core" /> + <Reference Include="Microsoft.CSharp" /> + </ItemGroup> + <ItemGroup> + <Compile Include="Conformance.cs" /> + <Compile Include="Program.cs" /> + <Compile Include="Properties\AssemblyInfo.cs" /> + </ItemGroup> + <ItemGroup> + <None Include="App.config" /> + </ItemGroup> + <ItemGroup> + <ProjectReference Include="..\Google.Protobuf\Google.Protobuf.csproj"> + <Project>{6908bdce-d925-43f3-94ac-a531e6df2591}</Project> + <Name>Google.Protobuf</Name> + </ProjectReference> + </ItemGroup> + <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> + <!-- 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"> + </Target> + <Target Name="AfterBuild"> + </Target> + --> +</Project>
\ No newline at end of file diff --git a/csharp/src/Google.Protobuf.Conformance/Program.cs b/csharp/src/Google.Protobuf.Conformance/Program.cs new file mode 100644 index 00000000..af92da9f --- /dev/null +++ b/csharp/src/Google.Protobuf.Conformance/Program.cs @@ -0,0 +1,126 @@ +#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 Conformance; +using System; +using System.IO; + +namespace Google.Protobuf.Conformance +{ + /// <summary> + /// Conformance tests. The test runner will provide JSON or proto data on stdin, + /// and this program will produce its output on stdout. + /// </summary> + class Program + { + private static void Main(string[] args) + { + // This way we get the binary streams instead of readers/writers. + var input = new BinaryReader(Console.OpenStandardInput()); + var output = new BinaryWriter(Console.OpenStandardOutput()); + + int count = 0; + while (RunTest(input, output)) + { + count++; + } + Console.Error.WriteLine("Received EOF after {0} tests", count); + } + + private static bool RunTest(BinaryReader input, BinaryWriter output) + { + int? size = ReadInt32(input); + if (size == null) + { + return false; + } + byte[] inputData = input.ReadBytes(size.Value); + if (inputData.Length != size.Value) + { + throw new EndOfStreamException("Read " + inputData.Length + " bytes of data when expecting " + size); + } + ConformanceRequest request = ConformanceRequest.Parser.ParseFrom(inputData); + ConformanceResponse response = PerformRequest(request); + byte[] outputData = response.ToByteArray(); + output.Write(outputData.Length); + output.Write(outputData); + // Ready for another test... + return true; + } + + private static ConformanceResponse PerformRequest(ConformanceRequest request) + { + TestAllTypes message; + switch (request.PayloadCase) + { + case ConformanceRequest.PayloadOneofCase.JsonPayload: + return new ConformanceResponse { Skipped = "JSON parsing not implemented in C# yet" }; + case ConformanceRequest.PayloadOneofCase.ProtobufPayload: + try + { + 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); + } + switch (request.RequestedOutputFormat) + { + 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); + } + } + + private static int? ReadInt32(BinaryReader input) + { + byte[] bytes = input.ReadBytes(4); + if (bytes.Length == 0) + { + // Cleanly reached the end of the stream + return null; + } + if (bytes.Length != 4) + { + throw new EndOfStreamException("Read " + bytes.Length + " bytes of size when expecting 4"); + } + return bytes[0] | (bytes[1] << 8) | (bytes[2] << 16) | (bytes[3] << 24); + } + } +} diff --git a/csharp/src/Google.Protobuf.Conformance/Properties/AssemblyInfo.cs b/csharp/src/Google.Protobuf.Conformance/Properties/AssemblyInfo.cs new file mode 100644 index 00000000..d22e90fd --- /dev/null +++ b/csharp/src/Google.Protobuf.Conformance/Properties/AssemblyInfo.cs @@ -0,0 +1,48 @@ +#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.Reflection; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("Google.Protobuf.Conformance")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("Google.Protobuf.Conformance")] +[assembly: AssemblyCopyright("Copyright © 2015")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +[assembly: AssemblyVersion("3.0.0.0")] +[assembly: AssemblyFileVersion("3.0.0.0")] diff --git a/csharp/src/Google.Protobuf.JsonDump/Properties/AssemblyInfo.cs b/csharp/src/Google.Protobuf.JsonDump/Properties/AssemblyInfo.cs index a8ce8eae..d980b013 100644 --- a/csharp/src/Google.Protobuf.JsonDump/Properties/AssemblyInfo.cs +++ b/csharp/src/Google.Protobuf.JsonDump/Properties/AssemblyInfo.cs @@ -11,20 +11,9 @@ using System.Runtime.InteropServices; [assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("ProtoDump")]
-[assembly: AssemblyCopyright("Copyright © 2009")]
+[assembly: AssemblyCopyright("Copyright © 2015")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
-// Version information for an assembly consists of the following four values:
-//
-// Major Version
-// Minor Version
-// Build Number
-// Revision
-//
-// You can specify all the values or you can default the Build and Revision Numbers
-// by using the '*' as shown below:
-// [assembly: AssemblyVersion("2.4.1.555")]
-
-[assembly: AssemblyVersion("2.4.1.555")]
-[assembly: AssemblyFileVersion("2.4.1.555")]
\ No newline at end of file +[assembly: AssemblyVersion("3.0.0.0")]
+[assembly: AssemblyFileVersion("3.0.0.0")]
diff --git a/csharp/src/Google.Protobuf.Test/CodedInputStreamExtensions.cs b/csharp/src/Google.Protobuf.Test/CodedInputStreamExtensions.cs index 408c7cb9..23af2887 100644 --- a/csharp/src/Google.Protobuf.Test/CodedInputStreamExtensions.cs +++ b/csharp/src/Google.Protobuf.Test/CodedInputStreamExtensions.cs @@ -38,8 +38,7 @@ namespace Google.Protobuf { public static void AssertNextTag(this CodedInputStream input, uint expectedTag) { - uint tag; - Assert.IsTrue(input.ReadTag(out tag)); + uint tag = input.ReadTag(); Assert.AreEqual(expectedTag, tag); } diff --git a/csharp/src/Google.Protobuf.Test/CodedInputStreamTest.cs b/csharp/src/Google.Protobuf.Test/CodedInputStreamTest.cs index fa88d407..54c44e47 100644 --- a/csharp/src/Google.Protobuf.Test/CodedInputStreamTest.cs +++ b/csharp/src/Google.Protobuf.Test/CodedInputStreamTest.cs @@ -59,20 +59,20 @@ namespace Google.Protobuf /// </summary>
private static void AssertReadVarint(byte[] data, ulong value)
{
- CodedInputStream input = CodedInputStream.CreateInstance(data);
+ CodedInputStream input = new CodedInputStream(data);
Assert.AreEqual((uint) value, input.ReadRawVarint32());
- input = CodedInputStream.CreateInstance(data);
+ input = new CodedInputStream(data);
Assert.AreEqual(value, input.ReadRawVarint64());
Assert.IsTrue(input.IsAtEnd);
// Try different block sizes.
for (int bufferSize = 1; bufferSize <= 16; bufferSize *= 2)
{
- input = CodedInputStream.CreateInstance(new SmallBlockInputStream(data, bufferSize));
+ input = new CodedInputStream(new SmallBlockInputStream(data, bufferSize));
Assert.AreEqual((uint) value, input.ReadRawVarint32());
- input = CodedInputStream.CreateInstance(new SmallBlockInputStream(data, bufferSize));
+ input = new CodedInputStream(new SmallBlockInputStream(data, bufferSize));
Assert.AreEqual(value, input.ReadRawVarint64());
Assert.IsTrue(input.IsAtEnd);
}
@@ -95,11 +95,11 @@ namespace Google.Protobuf /// </summary>
private static void AssertReadVarintFailure(InvalidProtocolBufferException expected, byte[] data)
{
- CodedInputStream input = CodedInputStream.CreateInstance(data);
+ CodedInputStream input = new CodedInputStream(data);
var exception = Assert.Throws<InvalidProtocolBufferException>(() => input.ReadRawVarint32());
Assert.AreEqual(expected.Message, exception.Message);
- input = CodedInputStream.CreateInstance(data);
+ input = new CodedInputStream(data);
exception = Assert.Throws<InvalidProtocolBufferException>(() => input.ReadRawVarint64());
Assert.AreEqual(expected.Message, exception.Message);
@@ -152,14 +152,14 @@ namespace Google.Protobuf /// </summary>
private static void AssertReadLittleEndian32(byte[] data, uint value)
{
- CodedInputStream input = CodedInputStream.CreateInstance(data);
+ CodedInputStream input = new CodedInputStream(data);
Assert.AreEqual(value, input.ReadRawLittleEndian32());
Assert.IsTrue(input.IsAtEnd);
// Try different block sizes.
for (int blockSize = 1; blockSize <= 16; blockSize *= 2)
{
- input = CodedInputStream.CreateInstance(
+ input = new CodedInputStream(
new SmallBlockInputStream(data, blockSize));
Assert.AreEqual(value, input.ReadRawLittleEndian32());
Assert.IsTrue(input.IsAtEnd);
@@ -172,14 +172,14 @@ namespace Google.Protobuf /// </summary>
private static void AssertReadLittleEndian64(byte[] data, ulong value)
{
- CodedInputStream input = CodedInputStream.CreateInstance(data);
+ CodedInputStream input = new CodedInputStream(data);
Assert.AreEqual(value, input.ReadRawLittleEndian64());
Assert.IsTrue(input.IsAtEnd);
// Try different block sizes.
for (int blockSize = 1; blockSize <= 16; blockSize *= 2)
{
- input = CodedInputStream.CreateInstance(
+ input = new CodedInputStream(
new SmallBlockInputStream(data, blockSize));
Assert.AreEqual(value, input.ReadRawLittleEndian64());
Assert.IsTrue(input.IsAtEnd);
@@ -269,7 +269,7 @@ namespace Google.Protobuf public void ReadMaliciouslyLargeBlob()
{
MemoryStream ms = new MemoryStream();
- CodedOutputStream output = CodedOutputStream.CreateInstance(ms);
+ CodedOutputStream output = new CodedOutputStream(ms);
uint tag = WireFormat.MakeTag(1, WireFormat.WireType.LengthDelimited);
output.WriteRawVarint32(tag);
@@ -278,12 +278,9 @@ namespace Google.Protobuf output.Flush();
ms.Position = 0;
- CodedInputStream input = CodedInputStream.CreateInstance(ms);
- uint testtag;
- Assert.IsTrue(input.ReadTag(out testtag));
- Assert.AreEqual(tag, testtag);
+ CodedInputStream input = new CodedInputStream(ms);
+ Assert.AreEqual(tag, input.ReadTag());
- // TODO(jonskeet): Should this be ArgumentNullException instead?
Assert.Throws<InvalidProtocolBufferException>(() => input.ReadBytes());
}
@@ -323,38 +320,18 @@ namespace Google.Protobuf Assert.Throws<InvalidProtocolBufferException>(() => TestRecursiveMessage.Parser.ParseFrom(data65));
- CodedInputStream input = data64.CreateCodedInput();
- input.SetRecursionLimit(8);
+ CodedInputStream input = CodedInputStream.CreateWithLimits(new MemoryStream(data64.ToByteArray()), 1000000, 63);
Assert.Throws<InvalidProtocolBufferException>(() => TestRecursiveMessage.Parser.ParseFrom(input));
}
- /*
[Test]
public void SizeLimit()
{
// Have to use a Stream rather than ByteString.CreateCodedInput as SizeLimit doesn't
// apply to the latter case.
- MemoryStream ms = new MemoryStream(TestUtil.GetAllSet().ToByteString().ToByteArray());
- CodedInputStream input = CodedInputStream.CreateInstance(ms);
- input.SetSizeLimit(16);
-
- Assert.Throws<InvalidProtocolBufferException>(() => TestAllTypes.ParseFrom(input));
- }*/
-
- [Test]
- public void ResetSizeCounter()
- {
- CodedInputStream input = CodedInputStream.CreateInstance(
- new SmallBlockInputStream(new byte[256], 8));
- input.SetSizeLimit(16);
- input.ReadRawBytes(16);
-
- Assert.Throws<InvalidProtocolBufferException>(() => input.ReadRawByte());
-
- input.ResetSizeCounter();
- input.ReadRawByte(); // No exception thrown.
-
- Assert.Throws<InvalidProtocolBufferException>(() => input.ReadRawBytes(16));
+ MemoryStream ms = new MemoryStream(SampleMessages.CreateFullTestAllTypes().ToByteArray());
+ CodedInputStream input = CodedInputStream.CreateWithLimits(ms, 16, 100);
+ Assert.Throws<InvalidProtocolBufferException>(() => TestAllTypes.Parser.ParseFrom(input));
}
/// <summary>
@@ -366,7 +343,7 @@ namespace Google.Protobuf public void ReadInvalidUtf8()
{
MemoryStream ms = new MemoryStream();
- CodedOutputStream output = CodedOutputStream.CreateInstance(ms);
+ CodedOutputStream output = new CodedOutputStream(ms);
uint tag = WireFormat.MakeTag(1, WireFormat.WireType.LengthDelimited);
output.WriteRawVarint32(tag);
@@ -375,11 +352,9 @@ namespace Google.Protobuf output.Flush();
ms.Position = 0;
- CodedInputStream input = CodedInputStream.CreateInstance(ms);
+ CodedInputStream input = new CodedInputStream(ms);
- uint actualTag;
- Assert.IsTrue(input.ReadTag(out actualTag));
- Assert.AreEqual(tag, actualTag);
+ Assert.AreEqual(tag, input.ReadTag());
string text = input.ReadString();
Assert.AreEqual('\ufffd', text[0]);
}
@@ -409,7 +384,7 @@ namespace Google.Protobuf public void TestNegativeEnum()
{
byte[] bytes = { 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01 };
- CodedInputStream input = CodedInputStream.CreateInstance(bytes);
+ CodedInputStream input = new CodedInputStream(bytes);
Assert.AreEqual((int)SampleEnum.NegativeValue, input.ReadEnum());
Assert.IsTrue(input.IsAtEnd);
}
@@ -420,7 +395,7 @@ namespace Google.Protobuf {
using (var ms = new MemoryStream())
{
- CodedOutputStream output = CodedOutputStream.CreateInstance(ms);
+ CodedOutputStream output = new CodedOutputStream(ms);
output.WriteTag(1, WireFormat.WireType.LengthDelimited);
output.WriteBytes(ByteString.CopyFrom(new byte[100]));
output.WriteTag(2, WireFormat.WireType.LengthDelimited);
@@ -428,17 +403,128 @@ namespace Google.Protobuf output.Flush();
ms.Position = 0;
- CodedInputStream input = CodedInputStream.CreateInstance(ms, new byte[ms.Length / 2]);
+ CodedInputStream input = new CodedInputStream(ms, new byte[ms.Length / 2], 0, 0);
- uint tag;
- Assert.IsTrue(input.ReadTag(out tag));
+ uint tag = input.ReadTag();
Assert.AreEqual(1, WireFormat.GetTagFieldNumber(tag));
Assert.AreEqual(100, input.ReadBytes().Length);
- Assert.IsTrue(input.ReadTag(out tag));
+ tag = input.ReadTag();
Assert.AreEqual(2, WireFormat.GetTagFieldNumber(tag));
Assert.AreEqual(100, input.ReadBytes().Length);
}
}
+
+ [Test]
+ public void Tag0Throws()
+ {
+ var input = new CodedInputStream(new byte[] { 0 });
+ Assert.Throws<InvalidProtocolBufferException>(() => input.ReadTag());
+ }
+
+ [Test]
+ public void SkipGroup()
+ {
+ // Create an output stream with a group in:
+ // Field 1: string "field 1"
+ // Field 2: group containing:
+ // Field 1: fixed int32 value 100
+ // Field 2: string "ignore me"
+ // Field 3: nested group containing
+ // Field 1: fixed int64 value 1000
+ // Field 3: string "field 3"
+ var stream = new MemoryStream();
+ var output = new CodedOutputStream(stream);
+ output.WriteTag(1, WireFormat.WireType.LengthDelimited);
+ output.WriteString("field 1");
+
+ // The outer group...
+ output.WriteTag(2, WireFormat.WireType.StartGroup);
+ output.WriteTag(1, WireFormat.WireType.Fixed32);
+ output.WriteFixed32(100);
+ output.WriteTag(2, WireFormat.WireType.LengthDelimited);
+ output.WriteString("ignore me");
+ // The nested group...
+ output.WriteTag(3, WireFormat.WireType.StartGroup);
+ output.WriteTag(1, WireFormat.WireType.Fixed64);
+ output.WriteFixed64(1000);
+ // Note: Not sure the field number is relevant for end group...
+ output.WriteTag(3, WireFormat.WireType.EndGroup);
+
+ // End the outer group
+ output.WriteTag(2, WireFormat.WireType.EndGroup);
+
+ output.WriteTag(3, WireFormat.WireType.LengthDelimited);
+ output.WriteString("field 3");
+ output.Flush();
+ stream.Position = 0;
+
+ // Now act like a generated client
+ var input = new CodedInputStream(stream);
+ Assert.AreEqual(WireFormat.MakeTag(1, WireFormat.WireType.LengthDelimited), input.ReadTag());
+ Assert.AreEqual("field 1", input.ReadString());
+ Assert.AreEqual(WireFormat.MakeTag(2, WireFormat.WireType.StartGroup), input.ReadTag());
+ input.SkipLastField(); // Should consume the whole group, including the nested one.
+ Assert.AreEqual(WireFormat.MakeTag(3, WireFormat.WireType.LengthDelimited), input.ReadTag());
+ Assert.AreEqual("field 3", input.ReadString());
+ }
+
+ [Test]
+ public void EndOfStreamReachedWhileSkippingGroup()
+ {
+ var stream = new MemoryStream();
+ var output = new CodedOutputStream(stream);
+ output.WriteTag(1, WireFormat.WireType.StartGroup);
+ output.WriteTag(2, WireFormat.WireType.StartGroup);
+ output.WriteTag(2, WireFormat.WireType.EndGroup);
+
+ output.Flush();
+ stream.Position = 0;
+
+ // Now act like a generated client
+ var input = new CodedInputStream(stream);
+ input.ReadTag();
+ Assert.Throws<InvalidProtocolBufferException>(() => input.SkipLastField());
+ }
+
+ [Test]
+ public void RecursionLimitAppliedWhileSkippingGroup()
+ {
+ var stream = new MemoryStream();
+ var output = new CodedOutputStream(stream);
+ for (int i = 0; i < CodedInputStream.DefaultRecursionLimit + 1; i++)
+ {
+ output.WriteTag(1, WireFormat.WireType.StartGroup);
+ }
+ for (int i = 0; i < CodedInputStream.DefaultRecursionLimit + 1; i++)
+ {
+ output.WriteTag(1, WireFormat.WireType.EndGroup);
+ }
+ output.Flush();
+ stream.Position = 0;
+
+ // Now act like a generated client
+ var input = new CodedInputStream(stream);
+ Assert.AreEqual(WireFormat.MakeTag(1, WireFormat.WireType.StartGroup), input.ReadTag());
+ Assert.Throws<InvalidProtocolBufferException>(() => input.SkipLastField());
+ }
+
+ [Test]
+ public void Construction_Invalid()
+ {
+ Assert.Throws<ArgumentNullException>(() => new CodedInputStream((byte[]) null));
+ Assert.Throws<ArgumentNullException>(() => new CodedInputStream(null, 0, 0));
+ Assert.Throws<ArgumentNullException>(() => new CodedInputStream((Stream) null));
+ Assert.Throws<ArgumentOutOfRangeException>(() => new CodedInputStream(new byte[10], 100, 0));
+ Assert.Throws<ArgumentOutOfRangeException>(() => new CodedInputStream(new byte[10], 5, 10));
+ }
+
+ [Test]
+ public void CreateWithLimits_InvalidLimits()
+ {
+ var stream = new MemoryStream();
+ Assert.Throws<ArgumentOutOfRangeException>(() => CodedInputStream.CreateWithLimits(stream, 0, 1));
+ Assert.Throws<ArgumentOutOfRangeException>(() => CodedInputStream.CreateWithLimits(stream, 1, 0));
+ }
}
}
\ No newline at end of file diff --git a/csharp/src/Google.Protobuf.Test/CodedOutputStreamTest.cs b/csharp/src/Google.Protobuf.Test/CodedOutputStreamTest.cs index c3d92a66..3297fe87 100644 --- a/csharp/src/Google.Protobuf.Test/CodedOutputStreamTest.cs +++ b/csharp/src/Google.Protobuf.Test/CodedOutputStreamTest.cs @@ -49,7 +49,7 @@ namespace Google.Protobuf if ((value >> 32) == 0)
{
MemoryStream rawOutput = new MemoryStream();
- CodedOutputStream output = CodedOutputStream.CreateInstance(rawOutput);
+ CodedOutputStream output = new CodedOutputStream(rawOutput);
output.WriteRawVarint32((uint) value);
output.Flush();
Assert.AreEqual(data, rawOutput.ToArray());
@@ -59,7 +59,7 @@ namespace Google.Protobuf {
MemoryStream rawOutput = new MemoryStream();
- CodedOutputStream output = CodedOutputStream.CreateInstance(rawOutput);
+ CodedOutputStream output = new CodedOutputStream(rawOutput);
output.WriteRawVarint64(value);
output.Flush();
Assert.AreEqual(data, rawOutput.ToArray());
@@ -76,7 +76,7 @@ namespace Google.Protobuf {
MemoryStream rawOutput = new MemoryStream();
CodedOutputStream output =
- CodedOutputStream.CreateInstance(rawOutput, bufferSize);
+ new CodedOutputStream(rawOutput, bufferSize);
output.WriteRawVarint32((uint) value);
output.Flush();
Assert.AreEqual(data, rawOutput.ToArray());
@@ -84,7 +84,7 @@ namespace Google.Protobuf {
MemoryStream rawOutput = new MemoryStream();
- CodedOutputStream output = CodedOutputStream.CreateInstance(rawOutput, bufferSize);
+ CodedOutputStream output = new CodedOutputStream(rawOutput, bufferSize);
output.WriteRawVarint64(value);
output.Flush();
Assert.AreEqual(data, rawOutput.ToArray());
@@ -134,7 +134,7 @@ namespace Google.Protobuf private static void AssertWriteLittleEndian32(byte[] data, uint value)
{
MemoryStream rawOutput = new MemoryStream();
- CodedOutputStream output = CodedOutputStream.CreateInstance(rawOutput);
+ CodedOutputStream output = new CodedOutputStream(rawOutput);
output.WriteRawLittleEndian32(value);
output.Flush();
Assert.AreEqual(data, rawOutput.ToArray());
@@ -143,7 +143,7 @@ namespace Google.Protobuf for (int bufferSize = 1; bufferSize <= 16; bufferSize *= 2)
{
rawOutput = new MemoryStream();
- output = CodedOutputStream.CreateInstance(rawOutput, bufferSize);
+ output = new CodedOutputStream(rawOutput, bufferSize);
output.WriteRawLittleEndian32(value);
output.Flush();
Assert.AreEqual(data, rawOutput.ToArray());
@@ -157,7 +157,7 @@ namespace Google.Protobuf private static void AssertWriteLittleEndian64(byte[] data, ulong value)
{
MemoryStream rawOutput = new MemoryStream();
- CodedOutputStream output = CodedOutputStream.CreateInstance(rawOutput);
+ CodedOutputStream output = new CodedOutputStream(rawOutput);
output.WriteRawLittleEndian64(value);
output.Flush();
Assert.AreEqual(data, rawOutput.ToArray());
@@ -166,7 +166,7 @@ namespace Google.Protobuf for (int blockSize = 1; blockSize <= 16; blockSize *= 2)
{
rawOutput = new MemoryStream();
- output = CodedOutputStream.CreateInstance(rawOutput, blockSize);
+ output = new CodedOutputStream(rawOutput, blockSize);
output.WriteRawLittleEndian64(value);
output.Flush();
Assert.AreEqual(data, rawOutput.ToArray());
@@ -201,7 +201,7 @@ namespace Google.Protobuf for (int blockSize = 1; blockSize < 256; blockSize *= 2)
{
MemoryStream rawOutput = new MemoryStream();
- CodedOutputStream output = CodedOutputStream.CreateInstance(rawOutput, blockSize);
+ CodedOutputStream output = new CodedOutputStream(rawOutput, blockSize);
message.WriteTo(output);
output.Flush();
Assert.AreEqual(rawBytes, rawOutput.ToArray());
@@ -276,7 +276,7 @@ namespace Google.Protobuf Assert.AreEqual(10, CodedOutputStream.ComputeEnumSize((int) SampleEnum.NegativeValue));
byte[] bytes = new byte[10];
- CodedOutputStream output = CodedOutputStream.CreateInstance(bytes);
+ CodedOutputStream output = new CodedOutputStream(bytes);
output.WriteEnum((int) SampleEnum.NegativeValue);
Assert.AreEqual(0, output.SpaceLeft);
@@ -293,7 +293,7 @@ namespace Google.Protobuf byte[] child = new byte[120];
{
MemoryStream ms = new MemoryStream(child);
- CodedOutputStream cout = CodedOutputStream.CreateInstance(ms, 20);
+ CodedOutputStream cout = new CodedOutputStream(ms, 20);
// Field 11: numeric value: 500
cout.WriteTag(11, WireFormat.WireType.Varint);
Assert.AreEqual(1, cout.Position);
@@ -314,7 +314,7 @@ namespace Google.Protobuf byte[] bytes = new byte[130];
{
- CodedOutputStream cout = CodedOutputStream.CreateInstance(bytes);
+ CodedOutputStream cout = new CodedOutputStream(bytes);
// Field 1: numeric value: 500
cout.WriteTag(1, WireFormat.WireType.Varint);
Assert.AreEqual(1, cout.Position);
@@ -334,16 +334,17 @@ namespace Google.Protobuf }
// Now test Input stream:
{
- CodedInputStream cin = CodedInputStream.CreateInstance(new MemoryStream(bytes), new byte[50]);
- uint tag;
+ CodedInputStream cin = new CodedInputStream(new MemoryStream(bytes), new byte[50], 0, 0);
Assert.AreEqual(0, cin.Position);
// Field 1:
- Assert.IsTrue(cin.ReadTag(out tag) && tag >> 3 == 1);
+ uint tag = cin.ReadTag();
+ Assert.AreEqual(1, tag >> 3);
Assert.AreEqual(1, cin.Position);
Assert.AreEqual(500, cin.ReadInt32());
Assert.AreEqual(3, cin.Position);
//Field 2:
- Assert.IsTrue(cin.ReadTag(out tag) && tag >> 3 == 2);
+ tag = cin.ReadTag();
+ Assert.AreEqual(2, tag >> 3);
Assert.AreEqual(4, cin.Position);
int childlen = cin.ReadLength();
Assert.AreEqual(120, childlen);
@@ -353,19 +354,22 @@ namespace Google.Protobuf // Now we are reading child message
{
// Field 11: numeric value: 500
- Assert.IsTrue(cin.ReadTag(out tag) && tag >> 3 == 11);
+ tag = cin.ReadTag();
+ Assert.AreEqual(11, tag >> 3);
Assert.AreEqual(6, cin.Position);
Assert.AreEqual(500, cin.ReadInt32());
Assert.AreEqual(8, cin.Position);
//Field 12: length delimited 120 bytes
- Assert.IsTrue(cin.ReadTag(out tag) && tag >> 3 == 12);
+ tag = cin.ReadTag();
+ Assert.AreEqual(12, tag >> 3);
Assert.AreEqual(9, cin.Position);
ByteString bstr = cin.ReadBytes();
Assert.AreEqual(110, bstr.Length);
Assert.AreEqual((byte) 109, bstr[109]);
Assert.AreEqual(120, cin.Position);
// Field 13: fixed numeric value: 501
- Assert.IsTrue(cin.ReadTag(out tag) && tag >> 3 == 13);
+ tag = cin.ReadTag();
+ Assert.AreEqual(13, tag >> 3);
// ROK - Previously broken here, this returned 126 failing to account for bufferSizeAfterLimit
Assert.AreEqual(121, cin.Position);
Assert.AreEqual(501, cin.ReadSFixed32());
@@ -375,7 +379,8 @@ namespace Google.Protobuf cin.PopLimit(oldlimit);
Assert.AreEqual(125, cin.Position);
// Field 3: fixed numeric value: 501
- Assert.IsTrue(cin.ReadTag(out tag) && tag >> 3 == 3);
+ tag = cin.ReadTag();
+ Assert.AreEqual(3, tag >> 3);
Assert.AreEqual(126, cin.Position);
Assert.AreEqual(501, cin.ReadSFixed32());
Assert.AreEqual(130, cin.Position);
diff --git a/csharp/src/Google.Protobuf.Test/Collections/MapFieldTest.cs b/csharp/src/Google.Protobuf.Test/Collections/MapFieldTest.cs index c62ac046..29c4c2a9 100644 --- a/csharp/src/Google.Protobuf.Test/Collections/MapFieldTest.cs +++ b/csharp/src/Google.Protobuf.Test/Collections/MapFieldTest.cs @@ -477,6 +477,91 @@ namespace Google.Protobuf.Collections Assert.IsTrue(new MapField<int, int?>(true).AllowsNullValues); } + [Test] + public void KeysReturnsLiveView() + { + var map = new MapField<string, string>(); + var keys = map.Keys; + CollectionAssert.AreEqual(new string[0], keys); + map["foo"] = "bar"; + map["x"] = "y"; + CollectionAssert.AreEqual(new[] { "foo", "x" }, keys); + } + + [Test] + public void ValuesReturnsLiveView() + { + var map = new MapField<string, string>(); + var values = map.Values; + CollectionAssert.AreEqual(new string[0], values); + map["foo"] = "bar"; + map["x"] = "y"; + CollectionAssert.AreEqual(new[] { "bar", "y" }, values); + } + + // Just test keys - we know the implementation is the same for values + [Test] + public void ViewsAreReadOnly() + { + var map = new MapField<string, string>(); + var keys = map.Keys; + Assert.IsTrue(keys.IsReadOnly); + Assert.Throws<NotSupportedException>(() => keys.Clear()); + Assert.Throws<NotSupportedException>(() => keys.Remove("a")); + Assert.Throws<NotSupportedException>(() => keys.Add("a")); + } + + // Just test keys - we know the implementation is the same for values + [Test] + public void ViewCopyTo() + { + var map = new MapField<string, string> { { "foo", "bar" }, { "x", "y" } }; + var keys = map.Keys; + var array = new string[4]; + Assert.Throws<ArgumentException>(() => keys.CopyTo(array, 3)); + Assert.Throws<ArgumentOutOfRangeException>(() => keys.CopyTo(array, -1)); + keys.CopyTo(array, 1); + CollectionAssert.AreEqual(new[] { null, "foo", "x", null }, array); + } + + // Just test keys - we know the implementation is the same for values + [Test] + public void NonGenericViewCopyTo() + { + IDictionary map = new MapField<string, string> { { "foo", "bar" }, { "x", "y" } }; + ICollection keys = map.Keys; + // Note the use of the Array type here rather than string[] + Array array = new string[4]; + Assert.Throws<ArgumentException>(() => keys.CopyTo(array, 3)); + Assert.Throws<ArgumentOutOfRangeException>(() => keys.CopyTo(array, -1)); + keys.CopyTo(array, 1); + CollectionAssert.AreEqual(new[] { null, "foo", "x", null }, array); + } + + [Test] + public void KeysContains() + { + var map = new MapField<string, string> { { "foo", "bar" }, { "x", "y" } }; + var keys = map.Keys; + Assert.IsTrue(keys.Contains("foo")); + Assert.IsFalse(keys.Contains("bar")); // It's a value! + Assert.IsFalse(keys.Contains("1")); + // Keys can't be null, so we should prevent contains check + Assert.Throws<ArgumentNullException>(() => keys.Contains(null)); + } + + [Test] + public void ValuesContains() + { + var map = new MapField<string, string> { { "foo", "bar" }, { "x", "y" } }; + var values = map.Values; + Assert.IsTrue(values.Contains("bar")); + Assert.IsFalse(values.Contains("foo")); // It's a key! + Assert.IsFalse(values.Contains("1")); + // Values can be null, so this makes sense + Assert.IsFalse(values.Contains(null)); + } + private static KeyValuePair<TKey, TValue> NewKeyValuePair<TKey, TValue>(TKey key, TValue value) { return new KeyValuePair<TKey, TValue>(key, value); diff --git a/csharp/src/Google.Protobuf.Test/Collections/RepeatedFieldTest.cs b/csharp/src/Google.Protobuf.Test/Collections/RepeatedFieldTest.cs index 33c4e10c..8c804fdd 100644 --- a/csharp/src/Google.Protobuf.Test/Collections/RepeatedFieldTest.cs +++ b/csharp/src/Google.Protobuf.Test/Collections/RepeatedFieldTest.cs @@ -221,7 +221,7 @@ namespace Google.Protobuf.Collections { uint packedTag = WireFormat.MakeTag(10, WireFormat.WireType.LengthDelimited); var stream = new MemoryStream(); - var output = CodedOutputStream.CreateInstance(stream); + var output = new CodedOutputStream(stream); var length = CodedOutputStream.ComputeInt32Size(10) + CodedOutputStream.ComputeInt32Size(999) + CodedOutputStream.ComputeInt32Size(-1000); @@ -237,7 +237,7 @@ namespace Google.Protobuf.Collections // actually packed. uint nonPackedTag = WireFormat.MakeTag(10, WireFormat.WireType.LengthDelimited); var field = new RepeatedField<int>(); - var input = CodedInputStream.CreateInstance(stream); + var input = new CodedInputStream(stream); input.AssertNextTag(packedTag); field.AddEntriesFrom(input, FieldCodec.ForInt32(nonPackedTag)); CollectionAssert.AreEqual(new[] { 10, 999, -1000 }, field); @@ -249,7 +249,7 @@ namespace Google.Protobuf.Collections { uint nonPackedTag = WireFormat.MakeTag(10, WireFormat.WireType.Varint); var stream = new MemoryStream(); - var output = CodedOutputStream.CreateInstance(stream); + var output = new CodedOutputStream(stream); output.WriteTag(nonPackedTag); output.WriteInt32(10); output.WriteTag(nonPackedTag); @@ -263,7 +263,7 @@ namespace Google.Protobuf.Collections // actually not packed. uint packedTag = WireFormat.MakeTag(10, WireFormat.WireType.LengthDelimited); var field = new RepeatedField<int>(); - var input = CodedInputStream.CreateInstance(stream); + var input = new CodedInputStream(stream); input.AssertNextTag(nonPackedTag); field.AddEntriesFrom(input, FieldCodec.ForInt32(packedTag)); CollectionAssert.AreEqual(new[] { 10, 999, -1000 }, field); @@ -275,7 +275,7 @@ namespace Google.Protobuf.Collections { uint tag = WireFormat.MakeTag(10, WireFormat.WireType.LengthDelimited); var stream = new MemoryStream(); - var output = CodedOutputStream.CreateInstance(stream); + var output = new CodedOutputStream(stream); output.WriteTag(tag); output.WriteString("Foo"); output.WriteTag(tag); @@ -286,7 +286,7 @@ namespace Google.Protobuf.Collections stream.Position = 0; var field = new RepeatedField<string>(); - var input = CodedInputStream.CreateInstance(stream); + var input = new CodedInputStream(stream); input.AssertNextTag(tag); field.AddEntriesFrom(input, FieldCodec.ForString(tag)); CollectionAssert.AreEqual(new[] { "Foo", "", "Bar" }, field); @@ -301,7 +301,7 @@ namespace Google.Protobuf.Collections uint tag = WireFormat.MakeTag(10, WireFormat.WireType.LengthDelimited); var stream = new MemoryStream(); - var output = CodedOutputStream.CreateInstance(stream); + var output = new CodedOutputStream(stream); output.WriteTag(tag); output.WriteMessage(message1); output.WriteTag(tag); @@ -310,7 +310,7 @@ namespace Google.Protobuf.Collections stream.Position = 0; var field = new RepeatedField<ForeignMessage>(); - var input = CodedInputStream.CreateInstance(stream); + var input = new CodedInputStream(stream); input.AssertNextTag(tag); field.AddEntriesFrom(input, FieldCodec.ForMessage(tag, ForeignMessage.Parser)); CollectionAssert.AreEqual(new[] { message1, message2}, field); @@ -323,12 +323,12 @@ namespace Google.Protobuf.Collections uint tag = WireFormat.MakeTag(10, WireFormat.WireType.LengthDelimited); var field = new RepeatedField<int> { 10, 1000, 1000000 }; var stream = new MemoryStream(); - var output = CodedOutputStream.CreateInstance(stream); + var output = new CodedOutputStream(stream); field.WriteTo(output, FieldCodec.ForInt32(tag)); output.Flush(); stream.Position = 0; - var input = CodedInputStream.CreateInstance(stream); + var input = new CodedInputStream(stream); input.AssertNextTag(tag); var length = input.ReadLength(); Assert.AreEqual(10, input.ReadInt32()); @@ -344,12 +344,12 @@ namespace Google.Protobuf.Collections uint tag = WireFormat.MakeTag(10, WireFormat.WireType.Varint); var field = new RepeatedField<int> { 10, 1000, 1000000}; var stream = new MemoryStream(); - var output = CodedOutputStream.CreateInstance(stream); + var output = new CodedOutputStream(stream); field.WriteTo(output, FieldCodec.ForInt32(tag)); output.Flush(); stream.Position = 0; - var input = CodedInputStream.CreateInstance(stream); + var input = new CodedInputStream(stream); input.AssertNextTag(tag); Assert.AreEqual(10, input.ReadInt32()); input.AssertNextTag(tag); @@ -365,12 +365,12 @@ namespace Google.Protobuf.Collections uint tag = WireFormat.MakeTag(10, WireFormat.WireType.LengthDelimited); var field = new RepeatedField<string> { "Foo", "", "Bar" }; var stream = new MemoryStream(); - var output = CodedOutputStream.CreateInstance(stream); + var output = new CodedOutputStream(stream); field.WriteTo(output, FieldCodec.ForString(tag)); output.Flush(); stream.Position = 0; - var input = CodedInputStream.CreateInstance(stream); + var input = new CodedInputStream(stream); input.AssertNextTag(tag); Assert.AreEqual("Foo", input.ReadString()); input.AssertNextTag(tag); @@ -388,12 +388,12 @@ namespace Google.Protobuf.Collections uint tag = WireFormat.MakeTag(10, WireFormat.WireType.LengthDelimited); var field = new RepeatedField<ForeignMessage> { message1, message2 }; var stream = new MemoryStream(); - var output = CodedOutputStream.CreateInstance(stream); + var output = new CodedOutputStream(stream); field.WriteTo(output, FieldCodec.ForMessage(tag, ForeignMessage.Parser)); output.Flush(); stream.Position = 0; - var input = CodedInputStream.CreateInstance(stream); + var input = new CodedInputStream(stream); input.AssertNextTag(tag); Assert.AreEqual(message1, input.ReadMessage(ForeignMessage.Parser)); input.AssertNextTag(tag); @@ -444,7 +444,7 @@ namespace Google.Protobuf.Collections int arraySize = 1 + 1 + (11 * 5); int msgSize = arraySize; byte[] bytes = new byte[msgSize]; - CodedOutputStream output = CodedOutputStream.CreateInstance(bytes); + CodedOutputStream output = new CodedOutputStream(bytes); uint tag = WireFormat.MakeTag(8, WireFormat.WireType.Varint); for (int i = 0; i >= -5; i--) { @@ -454,8 +454,8 @@ namespace Google.Protobuf.Collections Assert.AreEqual(0, output.SpaceLeft); - CodedInputStream input = CodedInputStream.CreateInstance(bytes); - Assert.IsTrue(input.ReadTag(out tag)); + CodedInputStream input = new CodedInputStream(bytes); + tag = input.ReadTag(); RepeatedField<SampleEnum> values = new RepeatedField<SampleEnum>(); values.AddEntriesFrom(input, FieldCodec.ForEnum(tag, x => (int)x, x => (SampleEnum)x)); @@ -476,7 +476,7 @@ namespace Google.Protobuf.Collections int arraySize = 1 + (10 * 5); int msgSize = 1 + 1 + arraySize; byte[] bytes = new byte[msgSize]; - CodedOutputStream output = CodedOutputStream.CreateInstance(bytes); + CodedOutputStream output = new CodedOutputStream(bytes); // Length-delimited to show we want the packed representation uint tag = WireFormat.MakeTag(8, WireFormat.WireType.LengthDelimited); output.WriteTag(tag); @@ -492,8 +492,8 @@ namespace Google.Protobuf.Collections } Assert.AreEqual(0, output.SpaceLeft); - CodedInputStream input = CodedInputStream.CreateInstance(bytes); - Assert.IsTrue(input.ReadTag(out tag)); + CodedInputStream input = new CodedInputStream(bytes); + tag = input.ReadTag(); RepeatedField<SampleEnum> values = new RepeatedField<SampleEnum>(); values.AddEntriesFrom(input, FieldCodec.ForEnum(tag, x => (int)x, x => (SampleEnum)x)); diff --git a/csharp/src/Google.Protobuf.Test/FieldCodecTest.cs b/csharp/src/Google.Protobuf.Test/FieldCodecTest.cs index c6ed2a21..38ba227f 100644 --- a/csharp/src/Google.Protobuf.Test/FieldCodecTest.cs +++ b/csharp/src/Google.Protobuf.Test/FieldCodecTest.cs @@ -39,6 +39,7 @@ namespace Google.Protobuf { public class FieldCodecTest { +#pragma warning disable 0414 // Used by tests via reflection - do not remove! private static readonly List<ICodecTestData> Codecs = new List<ICodecTestData> { new FieldCodecTestData<bool>(FieldCodec.ForBool(100), true, "Bool"), @@ -61,6 +62,7 @@ namespace Google.Protobuf new FieldCodecTestData<ForeignMessage>( FieldCodec.ForMessage(100, ForeignMessage.Parser), new ForeignMessage { C = 10 }, "Message"), }; +#pragma warning restore 0414 [Test, TestCaseSource("Codecs")] public void RoundTripWithTag(ICodecTestData codec) @@ -120,11 +122,11 @@ namespace Google.Protobuf public void TestRoundTripRaw() { var stream = new MemoryStream(); - var codedOutput = CodedOutputStream.CreateInstance(stream); + var codedOutput = new CodedOutputStream(stream); codec.ValueWriter(codedOutput, sampleValue); codedOutput.Flush(); stream.Position = 0; - var codedInput = CodedInputStream.CreateInstance(stream); + var codedInput = new CodedInputStream(stream); Assert.AreEqual(sampleValue, codec.ValueReader(codedInput)); Assert.IsTrue(codedInput.IsAtEnd); } @@ -132,11 +134,11 @@ namespace Google.Protobuf public void TestRoundTripWithTag() { var stream = new MemoryStream(); - var codedOutput = CodedOutputStream.CreateInstance(stream); + var codedOutput = new CodedOutputStream(stream); codec.WriteTagAndValue(codedOutput, sampleValue); codedOutput.Flush(); stream.Position = 0; - var codedInput = CodedInputStream.CreateInstance(stream); + var codedInput = new CodedInputStream(stream); codedInput.AssertNextTag(codec.Tag); Assert.AreEqual(sampleValue, codec.Read(codedInput)); Assert.IsTrue(codedInput.IsAtEnd); @@ -145,7 +147,7 @@ namespace Google.Protobuf public void TestCalculateSizeWithTag() { var stream = new MemoryStream(); - var codedOutput = CodedOutputStream.CreateInstance(stream); + var codedOutput = new CodedOutputStream(stream); codec.WriteTagAndValue(codedOutput, sampleValue); codedOutput.Flush(); Assert.AreEqual(stream.Position, codec.CalculateSizeWithTag(sampleValue)); @@ -155,7 +157,7 @@ namespace Google.Protobuf { // WriteTagAndValue ignores default values var stream = new MemoryStream(); - var codedOutput = CodedOutputStream.CreateInstance(stream); + var codedOutput = new CodedOutputStream(stream); codec.WriteTagAndValue(codedOutput, codec.DefaultValue); codedOutput.Flush(); Assert.AreEqual(0, stream.Position); @@ -168,13 +170,13 @@ namespace Google.Protobuf // The plain ValueWriter/ValueReader delegates don't. if (codec.DefaultValue != null) // This part isn't appropriate for message types. { - codedOutput = CodedOutputStream.CreateInstance(stream); + codedOutput = new CodedOutputStream(stream); codec.ValueWriter(codedOutput, codec.DefaultValue); codedOutput.Flush(); Assert.AreNotEqual(0, stream.Position); Assert.AreEqual(stream.Position, codec.ValueSizeCalculator(codec.DefaultValue)); stream.Position = 0; - var codedInput = CodedInputStream.CreateInstance(stream); + var codedInput = new CodedInputStream(stream); Assert.AreEqual(codec.DefaultValue, codec.ValueReader(codedInput)); } } diff --git a/csharp/src/Google.Protobuf.Test/GeneratedMessageTest.cs b/csharp/src/Google.Protobuf.Test/GeneratedMessageTest.cs index 140b878c..575d4586 100644 --- a/csharp/src/Google.Protobuf.Test/GeneratedMessageTest.cs +++ b/csharp/src/Google.Protobuf.Test/GeneratedMessageTest.cs @@ -36,6 +36,8 @@ using Google.Protobuf.TestProtos; using NUnit.Framework;
using System.Collections;
using System.Collections.Generic;
+using System.Linq;
+using Google.Protobuf.WellKnownTypes;
namespace Google.Protobuf
{
@@ -253,11 +255,11 @@ namespace Google.Protobuf {
// Hand-craft the stream to contain a single entry with just a value.
var memoryStream = new MemoryStream();
- var output = CodedOutputStream.CreateInstance(memoryStream);
+ var output = new CodedOutputStream(memoryStream);
output.WriteTag(TestMap.MapInt32ForeignMessageFieldNumber, WireFormat.WireType.LengthDelimited);
var nestedMessage = new ForeignMessage { C = 20 };
// Size of the entry (tag, size written by WriteMessage, data written by WriteMessage)
- output.WriteRawVarint32((uint)(nestedMessage.CalculateSize() + 3));
+ output.WriteLength(2 + nestedMessage.CalculateSize());
output.WriteTag(2, WireFormat.WireType.LengthDelimited);
output.WriteMessage(nestedMessage);
output.Flush();
@@ -271,7 +273,7 @@ namespace Google.Protobuf {
// Hand-craft the stream to contain a single entry with three fields
var memoryStream = new MemoryStream();
- var output = CodedOutputStream.CreateInstance(memoryStream);
+ var output = new CodedOutputStream(memoryStream);
output.WriteTag(TestMap.MapInt32Int32FieldNumber, WireFormat.WireType.LengthDelimited);
@@ -281,7 +283,7 @@ namespace Google.Protobuf // Each field can be represented in a single byte, with a single byte tag.
// Total message size: 6 bytes.
- output.WriteRawVarint32(6);
+ output.WriteLength(6);
output.WriteTag(1, WireFormat.WireType.Varint);
output.WriteInt32(key);
output.WriteTag(2, WireFormat.WireType.Varint);
@@ -298,7 +300,7 @@ namespace Google.Protobuf public void MapFieldOrderIsIrrelevant()
{
var memoryStream = new MemoryStream();
- var output = CodedOutputStream.CreateInstance(memoryStream);
+ var output = new CodedOutputStream(memoryStream);
output.WriteTag(TestMap.MapInt32Int32FieldNumber, WireFormat.WireType.LengthDelimited);
@@ -307,7 +309,7 @@ namespace Google.Protobuf // Each field can be represented in a single byte, with a single byte tag.
// Total message size: 4 bytes.
- output.WriteRawVarint32(4);
+ output.WriteLength(4);
output.WriteTag(2, WireFormat.WireType.Varint);
output.WriteInt32(value);
output.WriteTag(1, WireFormat.WireType.Varint);
@@ -322,7 +324,7 @@ namespace Google.Protobuf public void MapNonContiguousEntries()
{
var memoryStream = new MemoryStream();
- var output = CodedOutputStream.CreateInstance(memoryStream);
+ var output = new CodedOutputStream(memoryStream);
// Message structure:
// Entry for MapInt32Int32
@@ -333,7 +335,7 @@ namespace Google.Protobuf var key1 = 10;
var value1 = 20;
output.WriteTag(TestMap.MapInt32Int32FieldNumber, WireFormat.WireType.LengthDelimited);
- output.WriteRawVarint32(4);
+ output.WriteLength(4);
output.WriteTag(1, WireFormat.WireType.Varint);
output.WriteInt32(key1);
output.WriteTag(2, WireFormat.WireType.Varint);
@@ -343,7 +345,7 @@ namespace Google.Protobuf var key2 = "a";
var value2 = "b";
output.WriteTag(TestMap.MapStringStringFieldNumber, WireFormat.WireType.LengthDelimited);
- output.WriteRawVarint32(6); // 3 bytes per entry: tag, size, character
+ output.WriteLength(6); // 3 bytes per entry: tag, size, character
output.WriteTag(1, WireFormat.WireType.LengthDelimited);
output.WriteString(key2);
output.WriteTag(2, WireFormat.WireType.LengthDelimited);
@@ -353,7 +355,7 @@ namespace Google.Protobuf var key3 = 15;
var value3 = 25;
output.WriteTag(TestMap.MapInt32Int32FieldNumber, WireFormat.WireType.LengthDelimited);
- output.WriteRawVarint32(4);
+ output.WriteLength(4);
output.WriteTag(1, WireFormat.WireType.Varint);
output.WriteInt32(key3);
output.WriteTag(2, WireFormat.WireType.Varint);
@@ -373,7 +375,7 @@ namespace Google.Protobuf public void DuplicateKeys_LastEntryWins()
{
var memoryStream = new MemoryStream();
- var output = CodedOutputStream.CreateInstance(memoryStream);
+ var output = new CodedOutputStream(memoryStream);
var key = 10;
var value1 = 20;
@@ -381,7 +383,7 @@ namespace Google.Protobuf // First entry
output.WriteTag(TestMap.MapInt32Int32FieldNumber, WireFormat.WireType.LengthDelimited);
- output.WriteRawVarint32(4);
+ output.WriteLength(4);
output.WriteTag(1, WireFormat.WireType.Varint);
output.WriteInt32(key);
output.WriteTag(2, WireFormat.WireType.Varint);
@@ -389,7 +391,7 @@ namespace Google.Protobuf // Second entry - same key, different value
output.WriteTag(TestMap.MapInt32Int32FieldNumber, WireFormat.WireType.LengthDelimited);
- output.WriteRawVarint32(4);
+ output.WriteLength(4);
output.WriteTag(1, WireFormat.WireType.Varint);
output.WriteInt32(key);
output.WriteTag(2, WireFormat.WireType.Varint);
@@ -590,5 +592,64 @@ namespace Google.Protobuf Assert.AreEqual(message, message2);
Assert.AreEqual(TestAllTypes.OneofFieldOneofCase.OneofUint32, message2.OneofFieldCase);
}
+
+ [Test]
+ public void IgnoreUnknownFields_RealDataStillRead()
+ {
+ var message = SampleMessages.CreateFullTestAllTypes();
+ var stream = new MemoryStream();
+ var output = new CodedOutputStream(stream);
+ var unusedFieldNumber = 23456;
+ Assert.IsFalse(TestAllTypes.Descriptor.Fields.InDeclarationOrder().Select(x => x.FieldNumber).Contains(unusedFieldNumber));
+ output.WriteTag(unusedFieldNumber, WireFormat.WireType.LengthDelimited);
+ output.WriteString("ignore me");
+ message.WriteTo(output);
+ output.Flush();
+
+ stream.Position = 0;
+ var parsed = TestAllTypes.Parser.ParseFrom(stream);
+ Assert.AreEqual(message, parsed);
+ }
+
+ [Test]
+ public void IgnoreUnknownFields_AllTypes()
+ {
+ // Simple way of ensuring we can skip all kinds of fields.
+ var data = SampleMessages.CreateFullTestAllTypes().ToByteArray();
+ var empty = Empty.Parser.ParseFrom(data);
+ Assert.AreEqual(new Empty(), empty);
+ }
+
+ // This was originally seen as a conformance test failure.
+ [Test]
+ public void TruncatedMessageFieldThrows()
+ {
+ // 130, 3 is the message tag
+ // 1 is the data length - but there's no data.
+ var data = new byte[] { 130, 3, 1 };
+ Assert.Throws<InvalidProtocolBufferException>(() => TestAllTypes.Parser.ParseFrom(data));
+ }
+
+ /// <summary>
+ /// Demonstrates current behaviour with an extraneous end group tag - see issue 688
+ /// for details; we may want to change this.
+ /// </summary>
+ [Test]
+ public void ExtraEndGroupSkipped()
+ {
+ var message = SampleMessages.CreateFullTestAllTypes();
+ var stream = new MemoryStream();
+ var output = new CodedOutputStream(stream);
+
+ output.WriteTag(100, WireFormat.WireType.EndGroup);
+ output.WriteTag(TestAllTypes.SingleFixed32FieldNumber, WireFormat.WireType.Fixed32);
+ output.WriteFixed32(123);
+
+ output.Flush();
+
+ stream.Position = 0;
+ var parsed = TestAllTypes.Parser.ParseFrom(stream);
+ Assert.AreEqual(new TestAllTypes { SingleFixed32 = 123 }, parsed);
+ }
}
}
diff --git a/csharp/src/Google.Protobuf.Test/Google.Protobuf.Test.csproj b/csharp/src/Google.Protobuf.Test/Google.Protobuf.Test.csproj index eb6d3960..d9593828 100644 --- a/csharp/src/Google.Protobuf.Test/Google.Protobuf.Test.csproj +++ b/csharp/src/Google.Protobuf.Test/Google.Protobuf.Test.csproj @@ -12,8 +12,6 @@ <AssemblyName>Google.Protobuf.Test</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
- <SignAssembly>true</SignAssembly>
- <AssemblyOriginatorKeyFile>..\..\keys\Google.Protobuf.snk</AssemblyOriginatorKeyFile>
<OldToolsVersion>3.5</OldToolsVersion>
<TargetFrameworkProfile>
</TargetFrameworkProfile>
@@ -45,6 +43,20 @@ <GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'ReleaseSigned|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\ReleaseSigned</OutputPath>
+ <IntermediateOutputPath>obj\ReleaseSigned\</IntermediateOutputPath>
+ <DefineConstants>TRACE;$(EnvironmentFlavor);$(EnvironmentTemplate)</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <NoStdLib>true</NoStdLib>
+ <GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
+ <Prefer32Bit>false</Prefer32Bit>
+ <SignAssembly>True</SignAssembly>
+ <AssemblyOriginatorKeyFile>C:\keys\Google.Protobuf.snk</AssemblyOriginatorKeyFile>
+ </PropertyGroup>
<ItemGroup>
<Reference Include="mscorlib" />
<Reference Include="nunit.core, Version=2.6.4.14350, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77, processorArchitecture=MSIL">
diff --git a/csharp/src/Google.Protobuf.Test/IssuesTest.cs b/csharp/src/Google.Protobuf.Test/IssuesTest.cs index 47a10c50..a0350035 100644 --- a/csharp/src/Google.Protobuf.Test/IssuesTest.cs +++ b/csharp/src/Google.Protobuf.Test/IssuesTest.cs @@ -49,8 +49,7 @@ namespace Google.Protobuf ItemField message = new ItemField { Item = 3 };
FieldDescriptor field = ItemField.Descriptor.FindFieldByName("item");
Assert.NotNull(field);
- // TODO(jonskeet): Reflection...
- // Assert.AreEqual(3, (int)message[field]);
+ Assert.AreEqual(3, (int)field.Accessor.GetValue(message));
}
[Test]
diff --git a/csharp/src/Google.Protobuf.Test/JsonFormatterTest.cs b/csharp/src/Google.Protobuf.Test/JsonFormatterTest.cs index a6715698..ecd7f46b 100644 --- a/csharp/src/Google.Protobuf.Test/JsonFormatterTest.cs +++ b/csharp/src/Google.Protobuf.Test/JsonFormatterTest.cs @@ -31,15 +31,17 @@ #endregion using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; using Google.Protobuf.TestProtos; using NUnit.Framework; +using UnitTest.Issues.TestProtos; +using Google.Protobuf.WellKnownTypes; namespace Google.Protobuf { + /// <summary> + /// Tests for the JSON formatter. Note that in these tests, double quotes are replaced with apostrophes + /// for the sake of readability (embedding \" everywhere is painful). See the AssertJson method for details. + /// </summary> public class JsonFormatterTest { [Test] @@ -47,16 +49,16 @@ namespace Google.Protobuf { var formatter = new JsonFormatter(new JsonFormatter.Settings(formatDefaultValues: false)); - Assert.AreEqual("{ }", formatter.Format(new ForeignMessage())); - Assert.AreEqual("{ }", formatter.Format(new TestAllTypes())); - Assert.AreEqual("{ }", formatter.Format(new TestMap())); + AssertJson("{ }", formatter.Format(new ForeignMessage())); + AssertJson("{ }", formatter.Format(new TestAllTypes())); + AssertJson("{ }", formatter.Format(new TestMap())); } [Test] public void DefaultValues_WhenIncluded() { var formatter = new JsonFormatter(new JsonFormatter.Settings(formatDefaultValues: true)); - Assert.AreEqual("{ \"c\": 0 }", formatter.Format(new ForeignMessage())); + AssertJson("{ 'c': 0 }", formatter.Format(new ForeignMessage())); } [Test] @@ -89,45 +91,45 @@ namespace Google.Protobuf }; var actualText = JsonFormatter.Default.Format(message); - // Fields in declaration order, which matches numeric order. + // Fields in numeric order var expectedText = "{ " + - "\"singleInt32\": 100, " + - "\"singleInt64\": \"3210987654321\", " + - "\"singleUint32\": 4294967295, " + - "\"singleUint64\": \"18446744073709551615\", " + - "\"singleSint32\": -456, " + - "\"singleSint64\": \"-12345678901235\", " + - "\"singleFixed32\": 23, " + - "\"singleFixed64\": \"1234567890123\", " + - "\"singleSfixed32\": -123, " + - "\"singleSfixed64\": \"-12345678901234\", " + - "\"singleFloat\": 12.25, " + - "\"singleDouble\": 23.5, " + - "\"singleBool\": true, " + - "\"singleString\": \"test\\twith\\ttabs\", " + - "\"singleBytes\": \"AQIDBA==\", " + - "\"singleNestedMessage\": { \"bb\": 35 }, " + - "\"singleForeignMessage\": { \"c\": 10 }, " + - "\"singleImportMessage\": { \"d\": 20 }, " + - "\"singleNestedEnum\": \"FOO\", " + - "\"singleForeignEnum\": \"FOREIGN_BAR\", " + - "\"singleImportEnum\": \"IMPORT_BAZ\", " + - "\"singlePublicImportMessage\": { \"e\": 54 }" + + "'singleInt32': 100, " + + "'singleInt64': '3210987654321', " + + "'singleUint32': 4294967295, " + + "'singleUint64': '18446744073709551615', " + + "'singleSint32': -456, " + + "'singleSint64': '-12345678901235', " + + "'singleFixed32': 23, " + + "'singleFixed64': '1234567890123', " + + "'singleSfixed32': -123, " + + "'singleSfixed64': '-12345678901234', " + + "'singleFloat': 12.25, " + + "'singleDouble': 23.5, " + + "'singleBool': true, " + + "'singleString': 'test\\twith\\ttabs', " + + "'singleBytes': 'AQIDBA==', " + + "'singleNestedMessage': { 'bb': 35 }, " + + "'singleForeignMessage': { 'c': 10 }, " + + "'singleImportMessage': { 'd': 20 }, " + + "'singleNestedEnum': 'FOO', " + + "'singleForeignEnum': 'FOREIGN_BAR', " + + "'singleImportEnum': 'IMPORT_BAZ', " + + "'singlePublicImportMessage': { 'e': 54 }" + " }"; - Assert.AreEqual(expectedText, actualText); + AssertJson(expectedText, actualText); } [Test] public void RepeatedField() { - Assert.AreEqual("{ \"repeatedInt32\": [ 1, 2, 3, 4, 5 ] }", + AssertJson("{ 'repeatedInt32': [ 1, 2, 3, 4, 5 ] }", JsonFormatter.Default.Format(new TestAllTypes { RepeatedInt32 = { 1, 2, 3, 4, 5 } })); } [Test] public void MapField_StringString() { - Assert.AreEqual("{ \"mapStringString\": { \"with spaces\": \"bar\", \"a\": \"b\" } }", + AssertJson("{ 'mapStringString': { 'with spaces': 'bar', 'a': 'b' } }", JsonFormatter.Default.Format(new TestMap { MapStringString = { { "with spaces", "bar" }, { "a", "b" } } })); } @@ -135,7 +137,7 @@ namespace Google.Protobuf public void MapField_Int32Int32() { // The keys are quoted, but the values aren't. - Assert.AreEqual("{ \"mapInt32Int32\": { \"0\": 1, \"2\": 3 } }", + AssertJson("{ 'mapInt32Int32': { '0': 1, '2': 3 } }", JsonFormatter.Default.Format(new TestMap { MapInt32Int32 = { { 0, 1 }, { 2, 3 } } })); } @@ -143,34 +145,34 @@ namespace Google.Protobuf public void MapField_BoolBool() { // The keys are quoted, but the values aren't. - Assert.AreEqual("{ \"mapBoolBool\": { \"false\": true, \"true\": false } }", + AssertJson("{ 'mapBoolBool': { 'false': true, 'true': false } }", JsonFormatter.Default.Format(new TestMap { MapBoolBool = { { false, true }, { true, false } } })); } [TestCase(1.0, "1")] - [TestCase(double.NaN, "\"NaN\"")] - [TestCase(double.PositiveInfinity, "\"Infinity\"")] - [TestCase(double.NegativeInfinity, "\"-Infinity\"")] + [TestCase(double.NaN, "'NaN'")] + [TestCase(double.PositiveInfinity, "'Infinity'")] + [TestCase(double.NegativeInfinity, "'-Infinity'")] public void DoubleRepresentations(double value, string expectedValueText) { var message = new TestAllTypes { SingleDouble = value }; string actualText = JsonFormatter.Default.Format(message); - string expectedText = "{ \"singleDouble\": " + expectedValueText + " }"; - Assert.AreEqual(expectedText, actualText); + string expectedText = "{ 'singleDouble': " + expectedValueText + " }"; + AssertJson(expectedText, actualText); } [Test] public void UnknownEnumValueOmitted_SingleField() { var message = new TestAllTypes { SingleForeignEnum = (ForeignEnum) 100 }; - Assert.AreEqual("{ }", JsonFormatter.Default.Format(message)); + AssertJson("{ }", JsonFormatter.Default.Format(message)); } [Test] public void UnknownEnumValueOmitted_RepeatedField() { var message = new TestAllTypes { RepeatedForeignEnum = { ForeignEnum.FOREIGN_BAZ, (ForeignEnum) 100, ForeignEnum.FOREIGN_FOO } }; - Assert.AreEqual("{ \"repeatedForeignEnum\": [ \"FOREIGN_BAZ\", \"FOREIGN_FOO\" ] }", JsonFormatter.Default.Format(message)); + AssertJson("{ 'repeatedForeignEnum': [ 'FOREIGN_BAZ', 'FOREIGN_FOO' ] }", JsonFormatter.Default.Format(message)); } [Test] @@ -178,7 +180,7 @@ namespace Google.Protobuf { // This matches the C++ behaviour. var message = new TestMap { MapInt32Enum = { { 1, MapEnum.MAP_ENUM_FOO }, { 2, (MapEnum) 100 }, { 3, MapEnum.MAP_ENUM_BAR } } }; - Assert.AreEqual("{ \"mapInt32Enum\": { \"1\": \"MAP_ENUM_FOO\", \"3\": \"MAP_ENUM_BAR\" } }", JsonFormatter.Default.Format(message)); + AssertJson("{ 'mapInt32Enum': { '1': 'MAP_ENUM_FOO', '3': 'MAP_ENUM_BAR' } }", JsonFormatter.Default.Format(message)); } [Test] @@ -187,14 +189,14 @@ namespace Google.Protobuf // *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 } }; - Assert.AreEqual("{ \"repeatedForeignEnum\": [ ] }", JsonFormatter.Default.Format(message)); + AssertJson("{ 'repeatedForeignEnum': [ ] }", JsonFormatter.Default.Format(message)); } [Test] public void NullValueForMessage() { var message = new TestMap { MapInt32ForeignMessage = { { 10, null } } }; - Assert.AreEqual("{ \"mapInt32ForeignMessage\": { \"10\": null } }", JsonFormatter.Default.Format(message)); + AssertJson("{ 'mapInt32ForeignMessage': { '10': null } }", JsonFormatter.Default.Format(message)); } [Test] @@ -204,14 +206,14 @@ namespace Google.Protobuf public void SimpleNonAscii(string text, string encoded) { var message = new TestAllTypes { SingleString = text }; - Assert.AreEqual("{ \"singleString\": \"" + encoded + "\" }", JsonFormatter.Default.Format(message)); + AssertJson("{ 'singleString': '" + encoded + "' }", JsonFormatter.Default.Format(message)); } [Test] public void SurrogatePairEscaping() { var message = new TestAllTypes { SingleString = "a\uD801\uDC01b" }; - Assert.AreEqual("{ \"singleString\": \"a\\ud801\\udc01b\" }", JsonFormatter.Default.Format(message)); + AssertJson("{ 'singleString': 'a\\ud801\\udc01b' }", JsonFormatter.Default.Format(message)); } [Test] @@ -240,8 +242,8 @@ namespace Google.Protobuf [Test] [TestCase(null, "{ }")] - [TestCase("x", "{ \"fooString\": \"x\" }")] - [TestCase("", "{ \"fooString\": \"\" }")] + [TestCase("x", "{ 'fooString': 'x' }")] + [TestCase("", "{ 'fooString': '' }")] [TestCase(null, "{ }")] public void Oneof(string fooStringValue, string expectedJson) { @@ -253,9 +255,9 @@ namespace Google.Protobuf // We should get the same result both with and without "format default values". var formatter = new JsonFormatter(new JsonFormatter.Settings(false)); - Assert.AreEqual(expectedJson, formatter.Format(message)); + AssertJson(expectedJson, formatter.Format(message)); formatter = new JsonFormatter(new JsonFormatter.Settings(true)); - Assert.AreEqual(expectedJson, formatter.Format(message)); + AssertJson(expectedJson, formatter.Format(message)); } [Test] @@ -270,8 +272,8 @@ namespace Google.Protobuf BytesField = ByteString.FromBase64("ABCD"), StringField = "" }; - var expectedJson = "{ \"int64Field\": \"10\", \"int32Field\": 0, \"stringField\": \"\", \"bytesField\": \"ABCD\" }"; - Assert.AreEqual(expectedJson, JsonFormatter.Default.Format(message)); + var expectedJson = "{ 'int64Field': '10', 'int32Field': 0, 'stringField': '', 'bytesField': 'ABCD' }"; + AssertJson(expectedJson, JsonFormatter.Default.Format(message)); } [Test] @@ -284,5 +286,135 @@ namespace Google.Protobuf Assert.IsTrue(actualJson.Contains("\"int64Field\": null")); Assert.IsFalse(actualJson.Contains("\"int32Field\": null")); } + + [Test] + public void OutputIsInNumericFieldOrder_NoDefaults() + { + var formatter = new JsonFormatter(new JsonFormatter.Settings(false)); + var message = new TestJsonFieldOrdering { PlainString = "p1", PlainInt32 = 2 }; + AssertJson("{ 'plainString': 'p1', 'plainInt32': 2 }", formatter.Format(message)); + message = new TestJsonFieldOrdering { O1Int32 = 5, O2String = "o2", PlainInt32 = 10, PlainString = "plain" }; + AssertJson("{ 'plainString': 'plain', 'o2String': 'o2', 'plainInt32': 10, 'o1Int32': 5 }", formatter.Format(message)); + message = new TestJsonFieldOrdering { O1String = "", O2Int32 = 0, PlainInt32 = 10, PlainString = "plain" }; + AssertJson("{ 'plainString': 'plain', 'o1String': '', 'plainInt32': 10, 'o2Int32': 0 }", formatter.Format(message)); + } + + [Test] + public void OutputIsInNumericFieldOrder_WithDefaults() + { + var formatter = new JsonFormatter(new JsonFormatter.Settings(true)); + var message = new TestJsonFieldOrdering(); + AssertJson("{ 'plainString': '', 'plainInt32': 0 }", formatter.Format(message)); + message = new TestJsonFieldOrdering { O1Int32 = 5, O2String = "o2", PlainInt32 = 10, PlainString = "plain" }; + AssertJson("{ 'plainString': 'plain', 'o2String': 'o2', 'plainInt32': 10, 'o1Int32': 5 }", formatter.Format(message)); + message = new TestJsonFieldOrdering { O1String = "", O2Int32 = 0, PlainInt32 = 10, PlainString = "plain" }; + AssertJson("{ 'plainString': 'plain', 'o1String': '', 'plainInt32': 10, 'o2Int32': 0 }", formatter.Format(message)); + } + + [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()); + + // One before and one after the Unix epoch + 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", + new DateTime(2015, 7, 31, 10, 29, 34, DateTimeKind.Utc).ToTimestamp().ToString()); + } + + [Test] + public void TimestampField() + { + var message = new TestWellKnownTypes { TimestampField = new Timestamp() }; + AssertJson("{ 'timestampField': '1970-01-01T00:00:00Z' }", JsonFormatter.Default.Format(message)); + } + + [Test] + [TestCase(0, 0, "0s")] + [TestCase(1, 0, "1s")] + [TestCase(-1, 0, "-1s")] + [TestCase(0, 100000000, "0.100s")] + [TestCase(0, 120000000, "0.120s")] + [TestCase(0, 123000000, "0.123s")] + [TestCase(0, 123400000, "0.123400s")] + [TestCase(0, 123450000, "0.123450s")] + [TestCase(0, 123456000, "0.123456s")] + [TestCase(0, 123456700, "0.123456700s")] + [TestCase(0, 123456780, "0.123456780s")] + [TestCase(0, 123456789, "0.123456789s")] + [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()); + } + + [Test] + public void DurationField() + { + var message = new TestWellKnownTypes { DurationField = new Duration() }; + AssertJson("{ 'durationField': '0s' }", JsonFormatter.Default.Format(message)); + } + + [Test] + public void StructSample() + { + var message = new Struct + { + Fields = + { + { "a", new Value { NullValue = new NullValue() } }, + { "b", new Value { BoolValue = false } }, + { "c", new Value { NumberValue = 10.5 } }, + { "d", new Value { StringValue = "text" } }, + { "e", new Value { ListValue = new ListValue { Values = { new Value { StringValue = "t1" }, new Value { NumberValue = 5 } } } } }, + { "f", new Value { StructValue = new Struct { Fields = { { "nested", new Value { StringValue = "value" } } } } } } + } + }; + AssertJson("{ 'a': null, 'b': false, 'c': 10.5, 'd': 'text', 'e': [ 't1', 5 ], 'f': { 'nested': 'value' } }", message.ToString()); + } + + [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()); + + // Invalid, but we shouldn't create broken JSON... + fieldMask = new FieldMask { Paths = { "x\\y" } }; + Assert.AreEqual(@"x\\y", fieldMask.ToString()); + } + + [Test] + public void FieldMaskField() + { + var message = new TestWellKnownTypes { FieldMaskField = new FieldMask { Paths = { "user.display_name", "photo" } } }; + AssertJson("{ 'fieldMaskField': 'user.displayName,photo' }", JsonFormatter.Default.Format(message)); + } + + /// <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 + /// to read. + /// </summary> + private static void AssertJson(string expectedJsonWithApostrophes, string actualJson) + { + var expectedJson = expectedJsonWithApostrophes.Replace("'", "\""); + Assert.AreEqual(expectedJson, actualJson); + } } } diff --git a/csharp/src/Google.Protobuf.Test/Properties/AssemblyInfo.cs b/csharp/src/Google.Protobuf.Test/Properties/AssemblyInfo.cs index b551388c..d00acf85 100644 --- a/csharp/src/Google.Protobuf.Test/Properties/AssemblyInfo.cs +++ b/csharp/src/Google.Protobuf.Test/Properties/AssemblyInfo.cs @@ -12,19 +12,9 @@ using System.Runtime.InteropServices; [assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Google.Protobuf.Test")]
-[assembly: AssemblyCopyright("Copyright � 2008")]
+[assembly: AssemblyCopyright("Copyright © 2015")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
-// Version information for an assembly consists of the following four values:
-//
-// Major Version
-// Minor Version
-// Build Number
-// Revision
-//
-// You can specify all the values or you can default the Build and Revision Numbers
-// by using the '*' as shown below:
-// [assembly: AssemblyVersion("2.4.1.555")]
-
-[assembly: AssemblyVersion("2.4.1.555")]
+[assembly: AssemblyVersion("3.0.0.0")]
+[assembly: AssemblyFileVersion("3.0.0.0")]
diff --git a/csharp/src/Google.Protobuf.Test/Reflection/DescriptorsTest.cs b/csharp/src/Google.Protobuf.Test/Reflection/DescriptorsTest.cs index e84a0727..643816e6 100644 --- a/csharp/src/Google.Protobuf.Test/Reflection/DescriptorsTest.cs +++ b/csharp/src/Google.Protobuf.Test/Reflection/DescriptorsTest.cs @@ -238,5 +238,18 @@ namespace Google.Protobuf.Reflection Assert.IsNull(fieldDescriptor.Accessor); Assert.IsNull(messageDescriptor.GeneratedType); } + + // From TestFieldOrdering: + // string my_string = 11; + // int64 my_int = 1; + // float my_float = 101; + // NestedMessage single_nested_message = 200; + [Test] + public void FieldListOrderings() + { + var fields = TestFieldOrderings.Descriptor.Fields; + Assert.AreEqual(new[] { 11, 1, 101, 200 }, fields.InDeclarationOrder().Select(x => x.FieldNumber)); + Assert.AreEqual(new[] { 1, 11, 101, 200 }, fields.InFieldNumberOrder().Select(x => x.FieldNumber)); + } } } diff --git a/csharp/src/Google.Protobuf.Test/Reflection/FieldAccessTest.cs b/csharp/src/Google.Protobuf.Test/Reflection/FieldAccessTest.cs index 6e1d804e..936e41c6 100644 --- a/csharp/src/Google.Protobuf.Test/Reflection/FieldAccessTest.cs +++ b/csharp/src/Google.Protobuf.Test/Reflection/FieldAccessTest.cs @@ -213,6 +213,6 @@ namespace Google.Protobuf.Reflection var descriptor = TestAllTypes.Descriptor; Assert.Throws<KeyNotFoundException>(() => descriptor.Fields[999999].ToString()); Assert.Throws<KeyNotFoundException>(() => descriptor.Fields["not found"].ToString()); - } + } } } diff --git a/csharp/src/Google.Protobuf.Test/TestCornerCases.cs b/csharp/src/Google.Protobuf.Test/TestCornerCases.cs index b270a6f9..03fa1855 100644 --- a/csharp/src/Google.Protobuf.Test/TestCornerCases.cs +++ b/csharp/src/Google.Protobuf.Test/TestCornerCases.cs @@ -50,7 +50,7 @@ namespace Google.Protobuf Assert.AreEqual(58, msg.CalculateSize());
byte[] bytes = new byte[58];
- CodedOutputStream output = CodedOutputStream.CreateInstance(bytes);
+ CodedOutputStream output = new CodedOutputStream(bytes);
msg.WriteTo(output);
Assert.AreEqual(0, output.SpaceLeft);
diff --git a/csharp/src/Google.Protobuf.Test/TestProtos/MapUnittestProto3.cs b/csharp/src/Google.Protobuf.Test/TestProtos/MapUnittestProto3.cs index aac30ceb..e9e18193 100644 --- a/csharp/src/Google.Protobuf.Test/TestProtos/MapUnittestProto3.cs +++ b/csharp/src/Google.Protobuf.Test/TestProtos/MapUnittestProto3.cs @@ -473,14 +473,10 @@ namespace Google.Protobuf.TestProtos { public void MergeFrom(pb::CodedInputStream input) { uint tag; - while (input.ReadTag(out tag)) { + while ((tag = input.ReadTag()) != 0) { switch(tag) { - case 0: - throw pb::InvalidProtocolBufferException.InvalidTag(); default: - if (pb::WireFormat.IsEndGroupTag(tag)) { - return; - } + input.SkipLastField(); break; case 10: { mapInt32Int32_.AddEntriesFrom(input, _map_mapInt32Int32_codec); @@ -646,14 +642,10 @@ namespace Google.Protobuf.TestProtos { public void MergeFrom(pb::CodedInputStream input) { uint tag; - while (input.ReadTag(out tag)) { + while ((tag = input.ReadTag()) != 0) { switch(tag) { - case 0: - throw pb::InvalidProtocolBufferException.InvalidTag(); default: - if (pb::WireFormat.IsEndGroupTag(tag)) { - return; - } + input.SkipLastField(); break; case 10: { if (testMap_ == null) { @@ -747,14 +739,10 @@ namespace Google.Protobuf.TestProtos { public void MergeFrom(pb::CodedInputStream input) { uint tag; - while (input.ReadTag(out tag)) { + while ((tag = input.ReadTag()) != 0) { switch(tag) { - case 0: - throw pb::InvalidProtocolBufferException.InvalidTag(); default: - if (pb::WireFormat.IsEndGroupTag(tag)) { - return; - } + input.SkipLastField(); break; case 10: { mapInt32Message_.AddEntriesFrom(input, _map_mapInt32Message_codec); @@ -859,14 +847,10 @@ namespace Google.Protobuf.TestProtos { public void MergeFrom(pb::CodedInputStream input) { uint tag; - while (input.ReadTag(out tag)) { + while ((tag = input.ReadTag()) != 0) { switch(tag) { - case 0: - throw pb::InvalidProtocolBufferException.InvalidTag(); default: - if (pb::WireFormat.IsEndGroupTag(tag)) { - return; - } + input.SkipLastField(); break; case 10: { map1_.AddEntriesFrom(input, _map_map1_codec); @@ -1157,14 +1141,10 @@ namespace Google.Protobuf.TestProtos { public void MergeFrom(pb::CodedInputStream input) { uint tag; - while (input.ReadTag(out tag)) { + while ((tag = input.ReadTag()) != 0) { switch(tag) { - case 0: - throw pb::InvalidProtocolBufferException.InvalidTag(); default: - if (pb::WireFormat.IsEndGroupTag(tag)) { - return; - } + input.SkipLastField(); break; case 10: { mapInt32Int32_.AddEntriesFrom(input, _map_mapInt32Int32_codec); @@ -1311,14 +1291,10 @@ namespace Google.Protobuf.TestProtos { public void MergeFrom(pb::CodedInputStream input) { uint tag; - while (input.ReadTag(out tag)) { + while ((tag = input.ReadTag()) != 0) { switch(tag) { - case 0: - throw pb::InvalidProtocolBufferException.InvalidTag(); default: - if (pb::WireFormat.IsEndGroupTag(tag)) { - return; - } + input.SkipLastField(); break; case 10: { type_.AddEntriesFrom(input, _map_type_codec); @@ -1419,14 +1395,10 @@ namespace Google.Protobuf.TestProtos { public void MergeFrom(pb::CodedInputStream input) { uint tag; - while (input.ReadTag(out tag)) { + while ((tag = input.ReadTag()) != 0) { switch(tag) { - case 0: - throw pb::InvalidProtocolBufferException.InvalidTag(); default: - if (pb::WireFormat.IsEndGroupTag(tag)) { - return; - } + input.SkipLastField(); break; case 10: { entry_.AddEntriesFrom(input, _map_entry_codec); diff --git a/csharp/src/Google.Protobuf.Test/TestProtos/UnittestImportProto3.cs b/csharp/src/Google.Protobuf.Test/TestProtos/UnittestImportProto3.cs index fae10957..bf527ac5 100644 --- a/csharp/src/Google.Protobuf.Test/TestProtos/UnittestImportProto3.cs +++ b/csharp/src/Google.Protobuf.Test/TestProtos/UnittestImportProto3.cs @@ -136,14 +136,10 @@ namespace Google.Protobuf.TestProtos { public void MergeFrom(pb::CodedInputStream input) { uint tag; - while (input.ReadTag(out tag)) { + while ((tag = input.ReadTag()) != 0) { switch(tag) { - case 0: - throw pb::InvalidProtocolBufferException.InvalidTag(); default: - if (pb::WireFormat.IsEndGroupTag(tag)) { - return; - } + input.SkipLastField(); break; case 8: { D = input.ReadInt32(); diff --git a/csharp/src/Google.Protobuf.Test/TestProtos/UnittestImportPublicProto3.cs b/csharp/src/Google.Protobuf.Test/TestProtos/UnittestImportPublicProto3.cs index 17689f43..ec460906 100644 --- a/csharp/src/Google.Protobuf.Test/TestProtos/UnittestImportPublicProto3.cs +++ b/csharp/src/Google.Protobuf.Test/TestProtos/UnittestImportPublicProto3.cs @@ -122,14 +122,10 @@ namespace Google.Protobuf.TestProtos { public void MergeFrom(pb::CodedInputStream input) { uint tag; - while (input.ReadTag(out tag)) { + while ((tag = input.ReadTag()) != 0) { switch(tag) { - case 0: - throw pb::InvalidProtocolBufferException.InvalidTag(); default: - if (pb::WireFormat.IsEndGroupTag(tag)) { - return; - } + input.SkipLastField(); break; case 8: { E = input.ReadInt32(); diff --git a/csharp/src/Google.Protobuf.Test/TestProtos/UnittestIssues.cs b/csharp/src/Google.Protobuf.Test/TestProtos/UnittestIssues.cs index 92485c51..63119a34 100644 --- a/csharp/src/Google.Protobuf.Test/TestProtos/UnittestIssues.cs +++ b/csharp/src/Google.Protobuf.Test/TestProtos/UnittestIssues.cs @@ -36,11 +36,14 @@ namespace UnitTest.Issues.TestProtos { "NgoJRW51bUFycmF5GAYgAygOMh8udW5pdHRlc3RfaXNzdWVzLkRlcHJlY2F0", "ZWRFbnVtQgIYASIZCglJdGVtRmllbGQSDAoEaXRlbRgBIAEoBSJECg1SZXNl", "cnZlZE5hbWVzEg0KBXR5cGVzGAEgASgFEhIKCmRlc2NyaXB0b3IYAiABKAUa", - "EAoOU29tZU5lc3RlZFR5cGUqVQoMTmVnYXRpdmVFbnVtEhYKEk5FR0FUSVZF", - "X0VOVU1fWkVSTxAAEhYKCUZpdmVCZWxvdxD7//////////8BEhUKCE1pbnVz", - "T25lEP///////////wEqLgoORGVwcmVjYXRlZEVudW0SEwoPREVQUkVDQVRF", - "RF9aRVJPEAASBwoDb25lEAFCH0gBqgIaVW5pdFRlc3QuSXNzdWVzLlRlc3RQ", - "cm90b3NiBnByb3RvMw==")); + "EAoOU29tZU5lc3RlZFR5cGUioAEKFVRlc3RKc29uRmllbGRPcmRlcmluZxIT", + "CgtwbGFpbl9pbnQzMhgEIAEoBRITCglvMV9zdHJpbmcYAiABKAlIABISCghv", + "MV9pbnQzMhgFIAEoBUgAEhQKDHBsYWluX3N0cmluZxgBIAEoCRISCghvMl9p", + "bnQzMhgGIAEoBUgBEhMKCW8yX3N0cmluZxgDIAEoCUgBQgQKAm8xQgQKAm8y", + "KlUKDE5lZ2F0aXZlRW51bRIWChJORUdBVElWRV9FTlVNX1pFUk8QABIWCglG", + "aXZlQmVsb3cQ+///////////ARIVCghNaW51c09uZRD///////////8BKi4K", + "DkRlcHJlY2F0ZWRFbnVtEhMKD0RFUFJFQ0FURURfWkVSTxAAEgcKA29uZRAB", + "Qh9IAaoCGlVuaXRUZXN0Lklzc3Vlcy5UZXN0UHJvdG9zYgZwcm90bzM=")); descriptor = pbr::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData, new pbr::FileDescriptor[] { }, new pbr::GeneratedCodeInfo(new[] {typeof(global::UnitTest.Issues.TestProtos.NegativeEnum), typeof(global::UnitTest.Issues.TestProtos.DeprecatedEnum), }, new pbr::GeneratedCodeInfo[] { @@ -49,7 +52,8 @@ namespace UnitTest.Issues.TestProtos { new pbr::GeneratedCodeInfo(typeof(global::UnitTest.Issues.TestProtos.DeprecatedChild), null, null, null, null), new pbr::GeneratedCodeInfo(typeof(global::UnitTest.Issues.TestProtos.DeprecatedFieldsMessage), new[]{ "PrimitiveValue", "PrimitiveArray", "MessageValue", "MessageArray", "EnumValue", "EnumArray" }, null, null, null), new pbr::GeneratedCodeInfo(typeof(global::UnitTest.Issues.TestProtos.ItemField), new[]{ "Item" }, null, null, null), - new pbr::GeneratedCodeInfo(typeof(global::UnitTest.Issues.TestProtos.ReservedNames), new[]{ "Types_", "Descriptor_" }, null, null, new pbr::GeneratedCodeInfo[] { new pbr::GeneratedCodeInfo(typeof(global::UnitTest.Issues.TestProtos.ReservedNames.Types.SomeNestedType), null, null, null, null)}) + new pbr::GeneratedCodeInfo(typeof(global::UnitTest.Issues.TestProtos.ReservedNames), new[]{ "Types_", "Descriptor_" }, null, null, new pbr::GeneratedCodeInfo[] { new pbr::GeneratedCodeInfo(typeof(global::UnitTest.Issues.TestProtos.ReservedNames.Types.SomeNestedType), null, null, null, null)}), + new pbr::GeneratedCodeInfo(typeof(global::UnitTest.Issues.TestProtos.TestJsonFieldOrdering), new[]{ "PlainInt32", "O1String", "O1Int32", "PlainString", "O2Int32", "O2String" }, new[]{ "O1", "O2" }, null, null) })); } #endregion @@ -135,14 +139,10 @@ namespace UnitTest.Issues.TestProtos { public void MergeFrom(pb::CodedInputStream input) { uint tag; - while (input.ReadTag(out tag)) { + while ((tag = input.ReadTag()) != 0) { switch(tag) { - case 0: - throw pb::InvalidProtocolBufferException.InvalidTag(); default: - if (pb::WireFormat.IsEndGroupTag(tag)) { - return; - } + input.SkipLastField(); break; } } @@ -216,14 +216,10 @@ namespace UnitTest.Issues.TestProtos { public void MergeFrom(pb::CodedInputStream input) { uint tag; - while (input.ReadTag(out tag)) { + while ((tag = input.ReadTag()) != 0) { switch(tag) { - case 0: - throw pb::InvalidProtocolBufferException.InvalidTag(); default: - if (pb::WireFormat.IsEndGroupTag(tag)) { - return; - } + input.SkipLastField(); break; } } @@ -297,14 +293,10 @@ namespace UnitTest.Issues.TestProtos { public void MergeFrom(pb::CodedInputStream input) { uint tag; - while (input.ReadTag(out tag)) { + while ((tag = input.ReadTag()) != 0) { switch(tag) { - case 0: - throw pb::InvalidProtocolBufferException.InvalidTag(); default: - if (pb::WireFormat.IsEndGroupTag(tag)) { - return; - } + input.SkipLastField(); break; } } @@ -437,14 +429,10 @@ namespace UnitTest.Issues.TestProtos { public void MergeFrom(pb::CodedInputStream input) { uint tag; - while (input.ReadTag(out tag)) { + while ((tag = input.ReadTag()) != 0) { switch(tag) { - case 0: - throw pb::InvalidProtocolBufferException.InvalidTag(); default: - if (pb::WireFormat.IsEndGroupTag(tag)) { - return; - } + input.SkipLastField(); break; case 8: { value_ = (global::UnitTest.Issues.TestProtos.NegativeEnum) input.ReadEnum(); @@ -531,14 +519,10 @@ namespace UnitTest.Issues.TestProtos { public void MergeFrom(pb::CodedInputStream input) { uint tag; - while (input.ReadTag(out tag)) { + while ((tag = input.ReadTag()) != 0) { switch(tag) { - case 0: - throw pb::InvalidProtocolBufferException.InvalidTag(); default: - if (pb::WireFormat.IsEndGroupTag(tag)) { - return; - } + input.SkipLastField(); break; } } @@ -728,14 +712,10 @@ namespace UnitTest.Issues.TestProtos { public void MergeFrom(pb::CodedInputStream input) { uint tag; - while (input.ReadTag(out tag)) { + while ((tag = input.ReadTag()) != 0) { switch(tag) { - case 0: - throw pb::InvalidProtocolBufferException.InvalidTag(); default: - if (pb::WireFormat.IsEndGroupTag(tag)) { - return; - } + input.SkipLastField(); break; case 8: { PrimitiveValue = input.ReadInt32(); @@ -859,14 +839,10 @@ namespace UnitTest.Issues.TestProtos { public void MergeFrom(pb::CodedInputStream input) { uint tag; - while (input.ReadTag(out tag)) { + while ((tag = input.ReadTag()) != 0) { switch(tag) { - case 0: - throw pb::InvalidProtocolBufferException.InvalidTag(); default: - if (pb::WireFormat.IsEndGroupTag(tag)) { - return; - } + input.SkipLastField(); break; case 8: { Item = input.ReadInt32(); @@ -987,14 +963,10 @@ namespace UnitTest.Issues.TestProtos { public void MergeFrom(pb::CodedInputStream input) { uint tag; - while (input.ReadTag(out tag)) { + while ((tag = input.ReadTag()) != 0) { switch(tag) { - case 0: - throw pb::InvalidProtocolBufferException.InvalidTag(); default: - if (pb::WireFormat.IsEndGroupTag(tag)) { - return; - } + input.SkipLastField(); break; case 8: { Types_ = input.ReadInt32(); @@ -1076,14 +1048,10 @@ namespace UnitTest.Issues.TestProtos { public void MergeFrom(pb::CodedInputStream input) { uint tag; - while (input.ReadTag(out tag)) { + while ((tag = input.ReadTag()) != 0) { switch(tag) { - case 0: - throw pb::InvalidProtocolBufferException.InvalidTag(); default: - if (pb::WireFormat.IsEndGroupTag(tag)) { - return; - } + input.SkipLastField(); break; } } @@ -1096,6 +1064,290 @@ namespace UnitTest.Issues.TestProtos { } + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + public sealed partial class TestJsonFieldOrdering : pb::IMessage<TestJsonFieldOrdering> { + private static readonly pb::MessageParser<TestJsonFieldOrdering> _parser = new pb::MessageParser<TestJsonFieldOrdering>(() => new TestJsonFieldOrdering()); + public static pb::MessageParser<TestJsonFieldOrdering> Parser { get { return _parser; } } + + public static pbr::MessageDescriptor Descriptor { + get { return global::UnitTest.Issues.TestProtos.UnittestIssues.Descriptor.MessageTypes[6]; } + } + + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + public TestJsonFieldOrdering() { + OnConstruction(); + } + + partial void OnConstruction(); + + public TestJsonFieldOrdering(TestJsonFieldOrdering other) : this() { + plainInt32_ = other.plainInt32_; + plainString_ = other.plainString_; + switch (other.O1Case) { + case O1OneofCase.O1String: + O1String = other.O1String; + break; + case O1OneofCase.O1Int32: + O1Int32 = other.O1Int32; + break; + } + + switch (other.O2Case) { + case O2OneofCase.O2Int32: + O2Int32 = other.O2Int32; + break; + case O2OneofCase.O2String: + O2String = other.O2String; + break; + } + + } + + public TestJsonFieldOrdering Clone() { + return new TestJsonFieldOrdering(this); + } + + public const int PlainInt32FieldNumber = 4; + private int plainInt32_; + public int PlainInt32 { + get { return plainInt32_; } + set { + plainInt32_ = value; + } + } + + public const int O1StringFieldNumber = 2; + public string O1String { + get { return o1Case_ == O1OneofCase.O1String ? (string) o1_ : ""; } + set { + o1_ = pb::Preconditions.CheckNotNull(value, "value"); + o1Case_ = O1OneofCase.O1String; + } + } + + public const int O1Int32FieldNumber = 5; + public int O1Int32 { + get { return o1Case_ == O1OneofCase.O1Int32 ? (int) o1_ : 0; } + set { + o1_ = value; + o1Case_ = O1OneofCase.O1Int32; + } + } + + public const int PlainStringFieldNumber = 1; + private string plainString_ = ""; + public string PlainString { + get { return plainString_; } + set { + plainString_ = pb::Preconditions.CheckNotNull(value, "value"); + } + } + + public const int O2Int32FieldNumber = 6; + public int O2Int32 { + get { return o2Case_ == O2OneofCase.O2Int32 ? (int) o2_ : 0; } + set { + o2_ = value; + o2Case_ = O2OneofCase.O2Int32; + } + } + + public const int O2StringFieldNumber = 3; + public string O2String { + get { return o2Case_ == O2OneofCase.O2String ? (string) o2_ : ""; } + set { + o2_ = pb::Preconditions.CheckNotNull(value, "value"); + o2Case_ = O2OneofCase.O2String; + } + } + + private object o1_; + public enum O1OneofCase { + None = 0, + O1String = 2, + O1Int32 = 5, + } + private O1OneofCase o1Case_ = O1OneofCase.None; + public O1OneofCase O1Case { + get { return o1Case_; } + } + + public void ClearO1() { + o1Case_ = O1OneofCase.None; + o1_ = null; + } + + private object o2_; + public enum O2OneofCase { + None = 0, + O2Int32 = 6, + O2String = 3, + } + private O2OneofCase o2Case_ = O2OneofCase.None; + public O2OneofCase O2Case { + get { return o2Case_; } + } + + public void ClearO2() { + o2Case_ = O2OneofCase.None; + o2_ = null; + } + + public override bool Equals(object other) { + return Equals(other as TestJsonFieldOrdering); + } + + public bool Equals(TestJsonFieldOrdering other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (PlainInt32 != other.PlainInt32) return false; + if (O1String != other.O1String) return false; + if (O1Int32 != other.O1Int32) return false; + if (PlainString != other.PlainString) return false; + if (O2Int32 != other.O2Int32) return false; + if (O2String != other.O2String) return false; + return true; + } + + public override int GetHashCode() { + int hash = 1; + if (PlainInt32 != 0) hash ^= PlainInt32.GetHashCode(); + if (o1Case_ == O1OneofCase.O1String) hash ^= O1String.GetHashCode(); + if (o1Case_ == O1OneofCase.O1Int32) hash ^= O1Int32.GetHashCode(); + if (PlainString.Length != 0) hash ^= PlainString.GetHashCode(); + if (o2Case_ == O2OneofCase.O2Int32) hash ^= O2Int32.GetHashCode(); + if (o2Case_ == O2OneofCase.O2String) hash ^= O2String.GetHashCode(); + return hash; + } + + public override string ToString() { + return pb::JsonFormatter.Default.Format(this); + } + + public void WriteTo(pb::CodedOutputStream output) { + if (PlainString.Length != 0) { + output.WriteRawTag(10); + output.WriteString(PlainString); + } + if (o1Case_ == O1OneofCase.O1String) { + output.WriteRawTag(18); + output.WriteString(O1String); + } + if (o2Case_ == O2OneofCase.O2String) { + output.WriteRawTag(26); + output.WriteString(O2String); + } + if (PlainInt32 != 0) { + output.WriteRawTag(32); + output.WriteInt32(PlainInt32); + } + if (o1Case_ == O1OneofCase.O1Int32) { + output.WriteRawTag(40); + output.WriteInt32(O1Int32); + } + if (o2Case_ == O2OneofCase.O2Int32) { + output.WriteRawTag(48); + output.WriteInt32(O2Int32); + } + } + + public int CalculateSize() { + int size = 0; + if (PlainInt32 != 0) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(PlainInt32); + } + if (o1Case_ == O1OneofCase.O1String) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(O1String); + } + if (o1Case_ == O1OneofCase.O1Int32) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(O1Int32); + } + if (PlainString.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(PlainString); + } + if (o2Case_ == O2OneofCase.O2Int32) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(O2Int32); + } + if (o2Case_ == O2OneofCase.O2String) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(O2String); + } + return size; + } + + public void MergeFrom(TestJsonFieldOrdering other) { + if (other == null) { + return; + } + if (other.PlainInt32 != 0) { + PlainInt32 = other.PlainInt32; + } + if (other.PlainString.Length != 0) { + PlainString = other.PlainString; + } + switch (other.O1Case) { + case O1OneofCase.O1String: + O1String = other.O1String; + break; + case O1OneofCase.O1Int32: + O1Int32 = other.O1Int32; + break; + } + + switch (other.O2Case) { + case O2OneofCase.O2Int32: + O2Int32 = other.O2Int32; + break; + case O2OneofCase.O2String: + O2String = other.O2String; + break; + } + + } + + public void MergeFrom(pb::CodedInputStream input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + input.SkipLastField(); + break; + case 10: { + PlainString = input.ReadString(); + break; + } + case 18: { + O1String = input.ReadString(); + break; + } + case 26: { + O2String = input.ReadString(); + break; + } + case 32: { + PlainInt32 = input.ReadInt32(); + break; + } + case 40: { + O1Int32 = input.ReadInt32(); + break; + } + case 48: { + O2Int32 = input.ReadInt32(); + break; + } + } + } + } + + } + #endregion } diff --git a/csharp/src/Google.Protobuf.Test/TestProtos/UnittestProto3.cs b/csharp/src/Google.Protobuf.Test/TestProtos/UnittestProto3.cs index e360ac15..bf4590ad 100644 --- a/csharp/src/Google.Protobuf.Test/TestProtos/UnittestProto3.cs +++ b/csharp/src/Google.Protobuf.Test/TestProtos/UnittestProto3.cs @@ -1208,14 +1208,10 @@ namespace Google.Protobuf.TestProtos { public void MergeFrom(pb::CodedInputStream input) { uint tag; - while (input.ReadTag(out tag)) { + while ((tag = input.ReadTag()) != 0) { switch(tag) { - case 0: - throw pb::InvalidProtocolBufferException.InvalidTag(); default: - if (pb::WireFormat.IsEndGroupTag(tag)) { - return; - } + input.SkipLastField(); break; case 8: { SingleInt32 = input.ReadInt32(); @@ -1544,14 +1540,10 @@ namespace Google.Protobuf.TestProtos { public void MergeFrom(pb::CodedInputStream input) { uint tag; - while (input.ReadTag(out tag)) { + while ((tag = input.ReadTag()) != 0) { switch(tag) { - case 0: - throw pb::InvalidProtocolBufferException.InvalidTag(); default: - if (pb::WireFormat.IsEndGroupTag(tag)) { - return; - } + input.SkipLastField(); break; case 8: { Bb = input.ReadInt32(); @@ -1697,14 +1689,10 @@ namespace Google.Protobuf.TestProtos { public void MergeFrom(pb::CodedInputStream input) { uint tag; - while (input.ReadTag(out tag)) { + while ((tag = input.ReadTag()) != 0) { switch(tag) { - case 0: - throw pb::InvalidProtocolBufferException.InvalidTag(); default: - if (pb::WireFormat.IsEndGroupTag(tag)) { - return; - } + input.SkipLastField(); break; case 10: { if (child_ == null) { @@ -1818,14 +1806,10 @@ namespace Google.Protobuf.TestProtos { public void MergeFrom(pb::CodedInputStream input) { uint tag; - while (input.ReadTag(out tag)) { + while ((tag = input.ReadTag()) != 0) { switch(tag) { - case 0: - throw pb::InvalidProtocolBufferException.InvalidTag(); default: - if (pb::WireFormat.IsEndGroupTag(tag)) { - return; - } + input.SkipLastField(); break; case 8: { DeprecatedInt32 = input.ReadInt32(); @@ -1924,14 +1908,10 @@ namespace Google.Protobuf.TestProtos { public void MergeFrom(pb::CodedInputStream input) { uint tag; - while (input.ReadTag(out tag)) { + while ((tag = input.ReadTag()) != 0) { switch(tag) { - case 0: - throw pb::InvalidProtocolBufferException.InvalidTag(); default: - if (pb::WireFormat.IsEndGroupTag(tag)) { - return; - } + input.SkipLastField(); break; case 8: { C = input.ReadInt32(); @@ -2008,14 +1988,10 @@ namespace Google.Protobuf.TestProtos { public void MergeFrom(pb::CodedInputStream input) { uint tag; - while (input.ReadTag(out tag)) { + while ((tag = input.ReadTag()) != 0) { switch(tag) { - case 0: - throw pb::InvalidProtocolBufferException.InvalidTag(); default: - if (pb::WireFormat.IsEndGroupTag(tag)) { - return; - } + input.SkipLastField(); break; } } @@ -2113,14 +2089,10 @@ namespace Google.Protobuf.TestProtos { public void MergeFrom(pb::CodedInputStream input) { uint tag; - while (input.ReadTag(out tag)) { + while ((tag = input.ReadTag()) != 0) { switch(tag) { - case 0: - throw pb::InvalidProtocolBufferException.InvalidTag(); default: - if (pb::WireFormat.IsEndGroupTag(tag)) { - return; - } + input.SkipLastField(); break; case 10: { if (foreignNested_ == null) { @@ -2244,14 +2216,10 @@ namespace Google.Protobuf.TestProtos { public void MergeFrom(pb::CodedInputStream input) { uint tag; - while (input.ReadTag(out tag)) { + while ((tag = input.ReadTag()) != 0) { switch(tag) { - case 0: - throw pb::InvalidProtocolBufferException.InvalidTag(); default: - if (pb::WireFormat.IsEndGroupTag(tag)) { - return; - } + input.SkipLastField(); break; case 8: { A = input.ReadInt32(); @@ -2379,14 +2347,10 @@ namespace Google.Protobuf.TestProtos { public void MergeFrom(pb::CodedInputStream input) { uint tag; - while (input.ReadTag(out tag)) { + while ((tag = input.ReadTag()) != 0) { switch(tag) { - case 0: - throw pb::InvalidProtocolBufferException.InvalidTag(); default: - if (pb::WireFormat.IsEndGroupTag(tag)) { - return; - } + input.SkipLastField(); break; case 10: { if (a_ == null) { @@ -2495,14 +2459,10 @@ namespace Google.Protobuf.TestProtos { public void MergeFrom(pb::CodedInputStream input) { uint tag; - while (input.ReadTag(out tag)) { + while ((tag = input.ReadTag()) != 0) { switch(tag) { - case 0: - throw pb::InvalidProtocolBufferException.InvalidTag(); default: - if (pb::WireFormat.IsEndGroupTag(tag)) { - return; - } + input.SkipLastField(); break; case 10: { if (bb_ == null) { @@ -2629,14 +2589,10 @@ namespace Google.Protobuf.TestProtos { public void MergeFrom(pb::CodedInputStream input) { uint tag; - while (input.ReadTag(out tag)) { + while ((tag = input.ReadTag()) != 0) { switch(tag) { - case 0: - throw pb::InvalidProtocolBufferException.InvalidTag(); default: - if (pb::WireFormat.IsEndGroupTag(tag)) { - return; - } + input.SkipLastField(); break; case 10: { if (a_ == null) { @@ -2867,14 +2823,10 @@ namespace Google.Protobuf.TestProtos { public void MergeFrom(pb::CodedInputStream input) { uint tag; - while (input.ReadTag(out tag)) { + while ((tag = input.ReadTag()) != 0) { switch(tag) { - case 0: - throw pb::InvalidProtocolBufferException.InvalidTag(); default: - if (pb::WireFormat.IsEndGroupTag(tag)) { - return; - } + input.SkipLastField(); break; case 8: { PrimitiveField = input.ReadInt32(); @@ -3075,14 +3027,10 @@ namespace Google.Protobuf.TestProtos { public void MergeFrom(pb::CodedInputStream input) { uint tag; - while (input.ReadTag(out tag)) { + while ((tag = input.ReadTag()) != 0) { switch(tag) { - case 0: - throw pb::InvalidProtocolBufferException.InvalidTag(); default: - if (pb::WireFormat.IsEndGroupTag(tag)) { - return; - } + input.SkipLastField(); break; case 8: { MyInt = input.ReadInt64(); @@ -3219,14 +3167,10 @@ namespace Google.Protobuf.TestProtos { public void MergeFrom(pb::CodedInputStream input) { uint tag; - while (input.ReadTag(out tag)) { + while ((tag = input.ReadTag()) != 0) { switch(tag) { - case 0: - throw pb::InvalidProtocolBufferException.InvalidTag(); default: - if (pb::WireFormat.IsEndGroupTag(tag)) { - return; - } + input.SkipLastField(); break; case 8: { Bb = input.ReadInt32(); @@ -3334,14 +3278,10 @@ namespace Google.Protobuf.TestProtos { public void MergeFrom(pb::CodedInputStream input) { uint tag; - while (input.ReadTag(out tag)) { + while ((tag = input.ReadTag()) != 0) { switch(tag) { - case 0: - throw pb::InvalidProtocolBufferException.InvalidTag(); default: - if (pb::WireFormat.IsEndGroupTag(tag)) { - return; - } + input.SkipLastField(); break; case 8: { sparseEnum_ = (global::Google.Protobuf.TestProtos.TestSparseEnum) input.ReadEnum(); @@ -3440,14 +3380,10 @@ namespace Google.Protobuf.TestProtos { public void MergeFrom(pb::CodedInputStream input) { uint tag; - while (input.ReadTag(out tag)) { + while ((tag = input.ReadTag()) != 0) { switch(tag) { - case 0: - throw pb::InvalidProtocolBufferException.InvalidTag(); default: - if (pb::WireFormat.IsEndGroupTag(tag)) { - return; - } + input.SkipLastField(); break; case 10: { Data = input.ReadString(); @@ -3538,14 +3474,10 @@ namespace Google.Protobuf.TestProtos { public void MergeFrom(pb::CodedInputStream input) { uint tag; - while (input.ReadTag(out tag)) { + while ((tag = input.ReadTag()) != 0) { switch(tag) { - case 0: - throw pb::InvalidProtocolBufferException.InvalidTag(); default: - if (pb::WireFormat.IsEndGroupTag(tag)) { - return; - } + input.SkipLastField(); break; case 10: { data_.AddEntriesFrom(input, _repeated_data_codec); @@ -3644,14 +3576,10 @@ namespace Google.Protobuf.TestProtos { public void MergeFrom(pb::CodedInputStream input) { uint tag; - while (input.ReadTag(out tag)) { + while ((tag = input.ReadTag()) != 0) { switch(tag) { - case 0: - throw pb::InvalidProtocolBufferException.InvalidTag(); default: - if (pb::WireFormat.IsEndGroupTag(tag)) { - return; - } + input.SkipLastField(); break; case 10: { Data = input.ReadBytes(); @@ -3750,14 +3678,10 @@ namespace Google.Protobuf.TestProtos { public void MergeFrom(pb::CodedInputStream input) { uint tag; - while (input.ReadTag(out tag)) { + while ((tag = input.ReadTag()) != 0) { switch(tag) { - case 0: - throw pb::InvalidProtocolBufferException.InvalidTag(); default: - if (pb::WireFormat.IsEndGroupTag(tag)) { - return; - } + input.SkipLastField(); break; case 10: { Data = input.ReadBytes(); @@ -3856,14 +3780,10 @@ namespace Google.Protobuf.TestProtos { public void MergeFrom(pb::CodedInputStream input) { uint tag; - while (input.ReadTag(out tag)) { + while ((tag = input.ReadTag()) != 0) { switch(tag) { - case 0: - throw pb::InvalidProtocolBufferException.InvalidTag(); default: - if (pb::WireFormat.IsEndGroupTag(tag)) { - return; - } + input.SkipLastField(); break; case 8: { Data = input.ReadInt32(); @@ -3962,14 +3882,10 @@ namespace Google.Protobuf.TestProtos { public void MergeFrom(pb::CodedInputStream input) { uint tag; - while (input.ReadTag(out tag)) { + while ((tag = input.ReadTag()) != 0) { switch(tag) { - case 0: - throw pb::InvalidProtocolBufferException.InvalidTag(); default: - if (pb::WireFormat.IsEndGroupTag(tag)) { - return; - } + input.SkipLastField(); break; case 8: { Data = input.ReadUInt32(); @@ -4068,14 +3984,10 @@ namespace Google.Protobuf.TestProtos { public void MergeFrom(pb::CodedInputStream input) { uint tag; - while (input.ReadTag(out tag)) { + while ((tag = input.ReadTag()) != 0) { switch(tag) { - case 0: - throw pb::InvalidProtocolBufferException.InvalidTag(); default: - if (pb::WireFormat.IsEndGroupTag(tag)) { - return; - } + input.SkipLastField(); break; case 8: { Data = input.ReadInt64(); @@ -4174,14 +4086,10 @@ namespace Google.Protobuf.TestProtos { public void MergeFrom(pb::CodedInputStream input) { uint tag; - while (input.ReadTag(out tag)) { + while ((tag = input.ReadTag()) != 0) { switch(tag) { - case 0: - throw pb::InvalidProtocolBufferException.InvalidTag(); default: - if (pb::WireFormat.IsEndGroupTag(tag)) { - return; - } + input.SkipLastField(); break; case 8: { Data = input.ReadUInt64(); @@ -4280,14 +4188,10 @@ namespace Google.Protobuf.TestProtos { public void MergeFrom(pb::CodedInputStream input) { uint tag; - while (input.ReadTag(out tag)) { + while ((tag = input.ReadTag()) != 0) { switch(tag) { - case 0: - throw pb::InvalidProtocolBufferException.InvalidTag(); default: - if (pb::WireFormat.IsEndGroupTag(tag)) { - return; - } + input.SkipLastField(); break; case 8: { Data = input.ReadBool(); @@ -4459,14 +4363,10 @@ namespace Google.Protobuf.TestProtos { public void MergeFrom(pb::CodedInputStream input) { uint tag; - while (input.ReadTag(out tag)) { + while ((tag = input.ReadTag()) != 0) { switch(tag) { - case 0: - throw pb::InvalidProtocolBufferException.InvalidTag(); default: - if (pb::WireFormat.IsEndGroupTag(tag)) { - return; - } + input.SkipLastField(); break; case 8: { FooInt = input.ReadInt32(); @@ -4752,14 +4652,10 @@ namespace Google.Protobuf.TestProtos { public void MergeFrom(pb::CodedInputStream input) { uint tag; - while (input.ReadTag(out tag)) { + while ((tag = input.ReadTag()) != 0) { switch(tag) { - case 0: - throw pb::InvalidProtocolBufferException.InvalidTag(); default: - if (pb::WireFormat.IsEndGroupTag(tag)) { - return; - } + input.SkipLastField(); break; case 722: case 720: { @@ -5098,14 +4994,10 @@ namespace Google.Protobuf.TestProtos { public void MergeFrom(pb::CodedInputStream input) { uint tag; - while (input.ReadTag(out tag)) { + while ((tag = input.ReadTag()) != 0) { switch(tag) { - case 0: - throw pb::InvalidProtocolBufferException.InvalidTag(); default: - if (pb::WireFormat.IsEndGroupTag(tag)) { - return; - } + input.SkipLastField(); break; case 722: case 720: { @@ -5332,14 +5224,10 @@ namespace Google.Protobuf.TestProtos { public void MergeFrom(pb::CodedInputStream input) { uint tag; - while (input.ReadTag(out tag)) { + while ((tag = input.ReadTag()) != 0) { switch(tag) { - case 0: - throw pb::InvalidProtocolBufferException.InvalidTag(); default: - if (pb::WireFormat.IsEndGroupTag(tag)) { - return; - } + input.SkipLastField(); break; case 98: case 101: { @@ -5464,14 +5352,10 @@ namespace Google.Protobuf.TestProtos { public void MergeFrom(pb::CodedInputStream input) { uint tag; - while (input.ReadTag(out tag)) { + while ((tag = input.ReadTag()) != 0) { switch(tag) { - case 0: - throw pb::InvalidProtocolBufferException.InvalidTag(); default: - if (pb::WireFormat.IsEndGroupTag(tag)) { - return; - } + input.SkipLastField(); break; case 10: { A = input.ReadString(); @@ -5548,14 +5432,10 @@ namespace Google.Protobuf.TestProtos { public void MergeFrom(pb::CodedInputStream input) { uint tag; - while (input.ReadTag(out tag)) { + while ((tag = input.ReadTag()) != 0) { switch(tag) { - case 0: - throw pb::InvalidProtocolBufferException.InvalidTag(); default: - if (pb::WireFormat.IsEndGroupTag(tag)) { - return; - } + input.SkipLastField(); break; } } @@ -5628,14 +5508,10 @@ namespace Google.Protobuf.TestProtos { public void MergeFrom(pb::CodedInputStream input) { uint tag; - while (input.ReadTag(out tag)) { + while ((tag = input.ReadTag()) != 0) { switch(tag) { - case 0: - throw pb::InvalidProtocolBufferException.InvalidTag(); default: - if (pb::WireFormat.IsEndGroupTag(tag)) { - return; - } + input.SkipLastField(); break; } } @@ -5708,14 +5584,10 @@ namespace Google.Protobuf.TestProtos { public void MergeFrom(pb::CodedInputStream input) { uint tag; - while (input.ReadTag(out tag)) { + while ((tag = input.ReadTag()) != 0) { switch(tag) { - case 0: - throw pb::InvalidProtocolBufferException.InvalidTag(); default: - if (pb::WireFormat.IsEndGroupTag(tag)) { - return; - } + input.SkipLastField(); break; } } @@ -5788,14 +5660,10 @@ namespace Google.Protobuf.TestProtos { public void MergeFrom(pb::CodedInputStream input) { uint tag; - while (input.ReadTag(out tag)) { + while ((tag = input.ReadTag()) != 0) { switch(tag) { - case 0: - throw pb::InvalidProtocolBufferException.InvalidTag(); default: - if (pb::WireFormat.IsEndGroupTag(tag)) { - return; - } + input.SkipLastField(); break; } } @@ -5868,14 +5736,10 @@ namespace Google.Protobuf.TestProtos { public void MergeFrom(pb::CodedInputStream input) { uint tag; - while (input.ReadTag(out tag)) { + while ((tag = input.ReadTag()) != 0) { switch(tag) { - case 0: - throw pb::InvalidProtocolBufferException.InvalidTag(); default: - if (pb::WireFormat.IsEndGroupTag(tag)) { - return; - } + input.SkipLastField(); break; } } @@ -5948,14 +5812,10 @@ namespace Google.Protobuf.TestProtos { public void MergeFrom(pb::CodedInputStream input) { uint tag; - while (input.ReadTag(out tag)) { + while ((tag = input.ReadTag()) != 0) { switch(tag) { - case 0: - throw pb::InvalidProtocolBufferException.InvalidTag(); default: - if (pb::WireFormat.IsEndGroupTag(tag)) { - return; - } + input.SkipLastField(); break; } } diff --git a/csharp/src/Google.Protobuf.Test/TestProtos/UnittestWellKnownTypes.cs b/csharp/src/Google.Protobuf.Test/TestProtos/UnittestWellKnownTypes.cs index f18c5f1b..16634e03 100644 --- a/csharp/src/Google.Protobuf.Test/TestProtos/UnittestWellKnownTypes.cs +++ b/csharp/src/Google.Protobuf.Test/TestProtos/UnittestWellKnownTypes.cs @@ -676,14 +676,10 @@ namespace Google.Protobuf.TestProtos { public void MergeFrom(pb::CodedInputStream input) { uint tag; - while (input.ReadTag(out tag)) { + while ((tag = input.ReadTag()) != 0) { switch(tag) { - case 0: - throw pb::InvalidProtocolBufferException.InvalidTag(); default: - if (pb::WireFormat.IsEndGroupTag(tag)) { - return; - } + input.SkipLastField(); break; case 10: { if (anyField_ == null) { @@ -1134,14 +1130,10 @@ namespace Google.Protobuf.TestProtos { public void MergeFrom(pb::CodedInputStream input) { uint tag; - while (input.ReadTag(out tag)) { + while ((tag = input.ReadTag()) != 0) { switch(tag) { - case 0: - throw pb::InvalidProtocolBufferException.InvalidTag(); default: - if (pb::WireFormat.IsEndGroupTag(tag)) { - return; - } + input.SkipLastField(); break; case 10: { anyField_.AddEntriesFrom(input, _repeated_anyField_codec); @@ -1756,14 +1748,10 @@ namespace Google.Protobuf.TestProtos { public void MergeFrom(pb::CodedInputStream input) { uint tag; - while (input.ReadTag(out tag)) { + while ((tag = input.ReadTag()) != 0) { switch(tag) { - case 0: - throw pb::InvalidProtocolBufferException.InvalidTag(); default: - if (pb::WireFormat.IsEndGroupTag(tag)) { - return; - } + input.SkipLastField(); break; case 10: { global::Google.Protobuf.WellKnownTypes.Any subBuilder = new global::Google.Protobuf.WellKnownTypes.Any(); @@ -2205,14 +2193,10 @@ namespace Google.Protobuf.TestProtos { public void MergeFrom(pb::CodedInputStream input) { uint tag; - while (input.ReadTag(out tag)) { + while ((tag = input.ReadTag()) != 0) { switch(tag) { - case 0: - throw pb::InvalidProtocolBufferException.InvalidTag(); default: - if (pb::WireFormat.IsEndGroupTag(tag)) { - return; - } + input.SkipLastField(); break; case 10: { anyField_.AddEntriesFrom(input, _map_anyField_codec); diff --git a/csharp/src/Google.Protobuf.Test/WellKnownTypes/WrappersTest.cs b/csharp/src/Google.Protobuf.Test/WellKnownTypes/WrappersTest.cs index 670bc5f8..fbc0ff07 100644 --- a/csharp/src/Google.Protobuf.Test/WellKnownTypes/WrappersTest.cs +++ b/csharp/src/Google.Protobuf.Test/WellKnownTypes/WrappersTest.cs @@ -309,7 +309,7 @@ namespace Google.Protobuf.WellKnownTypes var valueTag = WireFormat.MakeTag(Int32Value.ValueFieldNumber, WireFormat.WireType.Varint); using (var stream = new MemoryStream()) { - var coded = CodedOutputStream.CreateInstance(stream); + var coded = new CodedOutputStream(stream); coded.WriteTag(wrapperTag); coded.WriteLength(2); // valueTag + a value 0, each one byte coded.WriteTag(valueTag); @@ -322,5 +322,28 @@ namespace Google.Protobuf.WellKnownTypes // A normal implementation would have 0 now, as the explicit default would have been overwritten the 5. Assert.AreEqual(5, message.Int32Field); } + + [Test] + public void UnknownFieldInWrapper() + { + var stream = new MemoryStream(); + var output = new CodedOutputStream(stream); + var wrapperTag = WireFormat.MakeTag(TestWellKnownTypes.Int32FieldFieldNumber, WireFormat.WireType.LengthDelimited); + var unknownTag = WireFormat.MakeTag(15, WireFormat.WireType.Varint); + var valueTag = WireFormat.MakeTag(Int32Value.ValueFieldNumber, WireFormat.WireType.Varint); + + output.WriteTag(wrapperTag); + output.WriteLength(4); // unknownTag + value 5 + valueType + value 6, each 1 byte + output.WriteTag(unknownTag); + output.WriteInt32((int) valueTag); // Sneakily "pretend" it's a tag when it's really a value + output.WriteTag(valueTag); + output.WriteInt32(6); + + output.Flush(); + stream.Position = 0; + + var message = TestWellKnownTypes.Parser.ParseFrom(stream); + Assert.AreEqual(6, message.Int32Field); + } } } diff --git a/csharp/src/Google.Protobuf.sln b/csharp/src/Google.Protobuf.sln index a290ae82..69ce9a47 100644 --- a/csharp/src/Google.Protobuf.sln +++ b/csharp/src/Google.Protobuf.sln @@ -1,6 +1,6 @@ Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio 14
-VisualStudioVersion = 14.0.22823.1
+# Visual Studio 2013
+VisualStudioVersion = 12.0.31101.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Google.Protobuf", "Google.Protobuf\Google.Protobuf.csproj", "{6908BDCE-D925-43F3-94AC-A531E6DF2591}"
EndProject
@@ -10,28 +10,45 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AddressBook", "AddressBook\ EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Google.Protobuf.JsonDump", "Google.Protobuf.JsonDump\Google.Protobuf.JsonDump.csproj", "{D7282E99-2DC3-405B-946F-177DB2FD2AE2}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Google.Protobuf.Conformance", "Google.Protobuf.Conformance\Google.Protobuf.Conformance.csproj", "{0607D1B8-80D6-4B35-9857-1263C1B32B94}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
+ ReleaseSigned|Any CPU = ReleaseSigned|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{6908BDCE-D925-43F3-94AC-A531E6DF2591}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6908BDCE-D925-43F3-94AC-A531E6DF2591}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6908BDCE-D925-43F3-94AC-A531E6DF2591}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6908BDCE-D925-43F3-94AC-A531E6DF2591}.Release|Any CPU.Build.0 = Release|Any CPU
+ {6908BDCE-D925-43F3-94AC-A531E6DF2591}.ReleaseSigned|Any CPU.ActiveCfg = ReleaseSigned|Any CPU
+ {6908BDCE-D925-43F3-94AC-A531E6DF2591}.ReleaseSigned|Any CPU.Build.0 = ReleaseSigned|Any CPU
{DD01ED24-3750-4567-9A23-1DB676A15610}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{DD01ED24-3750-4567-9A23-1DB676A15610}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DD01ED24-3750-4567-9A23-1DB676A15610}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DD01ED24-3750-4567-9A23-1DB676A15610}.Release|Any CPU.Build.0 = Release|Any CPU
+ {DD01ED24-3750-4567-9A23-1DB676A15610}.ReleaseSigned|Any CPU.ActiveCfg = ReleaseSigned|Any CPU
+ {DD01ED24-3750-4567-9A23-1DB676A15610}.ReleaseSigned|Any CPU.Build.0 = ReleaseSigned|Any CPU
{A31F5FB2-4FF3-432A-B35B-5CD203606311}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A31F5FB2-4FF3-432A-B35B-5CD203606311}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A31F5FB2-4FF3-432A-B35B-5CD203606311}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A31F5FB2-4FF3-432A-B35B-5CD203606311}.Release|Any CPU.Build.0 = Release|Any CPU
+ {A31F5FB2-4FF3-432A-B35B-5CD203606311}.ReleaseSigned|Any CPU.ActiveCfg = Release|Any CPU
+ {A31F5FB2-4FF3-432A-B35B-5CD203606311}.ReleaseSigned|Any CPU.Build.0 = Release|Any CPU
{D7282E99-2DC3-405B-946F-177DB2FD2AE2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D7282E99-2DC3-405B-946F-177DB2FD2AE2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D7282E99-2DC3-405B-946F-177DB2FD2AE2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D7282E99-2DC3-405B-946F-177DB2FD2AE2}.Release|Any CPU.Build.0 = Release|Any CPU
+ {D7282E99-2DC3-405B-946F-177DB2FD2AE2}.ReleaseSigned|Any CPU.ActiveCfg = Release|Any CPU
+ {D7282E99-2DC3-405B-946F-177DB2FD2AE2}.ReleaseSigned|Any CPU.Build.0 = Release|Any CPU
+ {0607D1B8-80D6-4B35-9857-1263C1B32B94}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {0607D1B8-80D6-4B35-9857-1263C1B32B94}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {0607D1B8-80D6-4B35-9857-1263C1B32B94}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {0607D1B8-80D6-4B35-9857-1263C1B32B94}.Release|Any CPU.Build.0 = Release|Any CPU
+ {0607D1B8-80D6-4B35-9857-1263C1B32B94}.ReleaseSigned|Any CPU.ActiveCfg = Release|Any CPU
+ {0607D1B8-80D6-4B35-9857-1263C1B32B94}.ReleaseSigned|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/csharp/src/Google.Protobuf/ByteString.cs b/csharp/src/Google.Protobuf/ByteString.cs index 329f47f6..3d55f02d 100644 --- a/csharp/src/Google.Protobuf/ByteString.cs +++ b/csharp/src/Google.Protobuf/ByteString.cs @@ -40,7 +40,6 @@ namespace Google.Protobuf {
/// <summary>
/// Immutable array of bytes.
- /// TODO(jonskeet): Implement the common collection interfaces?
/// </summary>
public sealed class ByteString : IEnumerable<byte>, IEquatable<ByteString>
{
@@ -105,23 +104,35 @@ namespace Google.Protobuf get { return bytes.Length; }
}
+ /// <summary>
+ /// Returns <c>true</c> if this byte string is empty, <c>false</c> otherwise.
+ /// </summary>
public bool IsEmpty
{
get { return Length == 0; }
}
+ /// <summary>
+ /// Converts this <see cref="ByteString"/> into a byte array.
+ /// </summary>
+ /// <remarks>The data is copied - changes to the returned array will not be reflected in this <c>ByteString</c>.</remarks>
+ /// <returns>A byte array with the same data as this <c>ByteString</c>.</returns>
public byte[] ToByteArray()
{
return (byte[]) bytes.Clone();
}
+ /// <summary>
+ /// Converts this <see cref="ByteString"/> into a standard base64 representation.
+ /// </summary>
+ /// <returns>A base64 representation of this <c>ByteString</c>.</returns>
public string ToBase64()
{
return Convert.ToBase64String(bytes);
}
/// <summary>
- /// Constructs a ByteString from the Base64 Encoded String.
+ /// Constructs a <see cref="ByteString" /> from the Base64 Encoded String.
/// </summary>
public static ByteString FromBase64(string bytes)
{
@@ -131,7 +142,7 @@ namespace Google.Protobuf }
/// <summary>
- /// Constructs a ByteString from the given array. The contents
+ /// Constructs a <see cref="ByteString" /> from the given array. The contents
/// are copied, so further modifications to the array will not
/// be reflected in the returned ByteString.
/// This method can also be invoked in <c>ByteString.CopyFrom(0xaa, 0xbb, ...)</c> form
@@ -143,7 +154,7 @@ namespace Google.Protobuf }
/// <summary>
- /// Constructs a ByteString from a portion of a byte array.
+ /// Constructs a <see cref="ByteString" /> from a portion of a byte array.
/// </summary>
public static ByteString CopyFrom(byte[] bytes, int offset, int count)
{
@@ -153,7 +164,7 @@ namespace Google.Protobuf }
/// <summary>
- /// Creates a new ByteString by encoding the specified text with
+ /// Creates a new <see cref="ByteString" /> by encoding the specified text with
/// the given encoding.
/// </summary>
public static ByteString CopyFrom(string text, Encoding encoding)
@@ -162,7 +173,7 @@ namespace Google.Protobuf }
/// <summary>
- /// Creates a new ByteString by encoding the specified text in UTF-8.
+ /// Creates a new <see cref="ByteString" /> by encoding the specified text in UTF-8.
/// </summary>
public static ByteString CopyFromUtf8(string text)
{
@@ -177,21 +188,46 @@ namespace Google.Protobuf get { return bytes[index]; }
}
+ /// <summary>
+ /// Converts this <see cref="ByteString"/> into a string by applying the given encoding.
+ /// </summary>
+ /// <remarks>
+ /// This method should only be used to convert binary data which was the result of encoding
+ /// text with the given encoding.
+ /// </remarks>
+ /// <param name="encoding">The encoding to use to decode the binary data into text.</param>
+ /// <returns>The result of decoding the binary data with the given decoding.</returns>
public string ToString(Encoding encoding)
{
return encoding.GetString(bytes, 0, bytes.Length);
}
+ /// <summary>
+ /// Converts this <see cref="ByteString"/> into a string by applying the UTF-8 encoding.
+ /// </summary>
+ /// <remarks>
+ /// This method should only be used to convert binary data which was the result of encoding
+ /// text with UTF-8.
+ /// </remarks>
+ /// <returns>The result of decoding the binary data with the given decoding.</returns>
public string ToStringUtf8()
{
return ToString(Encoding.UTF8);
}
+ /// <summary>
+ /// Returns an iterator over the bytes in this <see cref="ByteString"/>.
+ /// </summary>
+ /// <returns>An iterator over the bytes in this object.</returns>
public IEnumerator<byte> GetEnumerator()
{
return ((IEnumerable<byte>) bytes).GetEnumerator();
}
+ /// <summary>
+ /// Returns an iterator over the bytes in this <see cref="ByteString"/>.
+ /// </summary>
+ /// <returns>An iterator over the bytes in this object.</returns>
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
@@ -203,9 +239,15 @@ namespace Google.Protobuf public CodedInputStream CreateCodedInput()
{
// We trust CodedInputStream not to reveal the provided byte array or modify it
- return CodedInputStream.CreateInstance(bytes);
+ return new CodedInputStream(bytes);
}
+ /// <summary>
+ /// Compares two byte strings for equality.
+ /// </summary>
+ /// <param name="lhs">The first byte string to compare.</param>
+ /// <param name="rhs">The second byte string to compare.</param>
+ /// <returns><c>true</c> if the byte strings are equal; false otherwise.</returns>
public static bool operator ==(ByteString lhs, ByteString rhs)
{
if (ReferenceEquals(lhs, rhs))
@@ -230,18 +272,32 @@ namespace Google.Protobuf return true;
}
+ /// <summary>
+ /// Compares two byte strings for inequality.
+ /// </summary>
+ /// <param name="lhs">The first byte string to compare.</param>
+ /// <param name="rhs">The second byte string to compare.</param>
+ /// <returns><c>false</c> if the byte strings are equal; true otherwise.</returns>
public static bool operator !=(ByteString lhs, ByteString rhs)
{
return !(lhs == rhs);
}
- // TODO(jonskeet): CopyTo if it turns out to be required
-
+ /// <summary>
+ /// Compares this byte string with another object.
+ /// </summary>
+ /// <param name="obj">The object to compare this with.</param>
+ /// <returns><c>true</c> if <paramref name="obj"/> refers to an equal <see cref="ByteString"/>; <c>false</c> otherwise.</returns>
public override bool Equals(object obj)
{
return this == (obj as ByteString);
}
+ /// <summary>
+ /// Returns a hash code for this object. Two equal byte strings
+ /// will return the same hash code.
+ /// </summary>
+ /// <returns>A hash code for this object.</returns>
public override int GetHashCode()
{
int ret = 23;
@@ -252,6 +308,11 @@ namespace Google.Protobuf return ret;
}
+ /// <summary>
+ /// Compares this byte string with another.
+ /// </summary>
+ /// <param name="other">The <see cref="ByteString"/> to compare this with.</param>
+ /// <returns><c>true</c> if <paramref name="other"/> refers to an equal byte string; <c>false</c> otherwise.</returns>
public bool Equals(ByteString other)
{
return this == other;
diff --git a/csharp/src/Google.Protobuf/CodedInputStream.cs b/csharp/src/Google.Protobuf/CodedInputStream.cs index ef7cf114..82c6ceab 100644 --- a/csharp/src/Google.Protobuf/CodedInputStream.cs +++ b/csharp/src/Google.Protobuf/CodedInputStream.cs @@ -30,6 +30,7 @@ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#endregion
+using Google.Protobuf.Collections;
using System;
using System.Collections.Generic;
using System.IO;
@@ -40,33 +41,55 @@ namespace Google.Protobuf /// Readings and decodes protocol message fields.
/// </summary>
/// <remarks>
- /// This class contains two kinds of methods: methods that read specific
- /// protocol message constructs and field types (e.g. ReadTag and
- /// ReadInt32) and methods that read low-level values (e.g.
- /// ReadRawVarint32 and ReadRawBytes). If you are reading encoded protocol
- /// messages, you should use the former methods, but if you are reading some
- /// other format of your own design, use the latter. The names of the former
- /// methods are taken from the protocol buffer type names, not .NET types.
- /// (Hence ReadFloat instead of ReadSingle, and ReadBool instead of ReadBoolean.)
- ///
- /// TODO(jonskeet): Consider whether recursion and size limits shouldn't be readonly,
- /// set at construction time.
+ /// <para>
+ /// This class is generally used by generated code to read appropriate
+ /// primitives from the stream. It effectively encapsulates the lowest
+ /// levels of protocol buffer format.
+ /// </para>
+ /// <para>
+ /// Repeated fields and map fields are not handled by this class; use <see cref="RepeatedField{T}"/>
+ /// and <see cref="MapField{TKey, TValue}"/> to serialize such fields.
+ /// </para>
/// </remarks>
public sealed class CodedInputStream
{
+ /// <summary>
+ /// Buffer of data read from the stream or provided at construction time.
+ /// </summary>
private readonly byte[] buffer;
+
+ /// <summary>
+ /// The index of the buffer at which we need to refill from the stream (if there is one).
+ /// </summary>
private int bufferSize;
+
private int bufferSizeAfterLimit = 0;
+ /// <summary>
+ /// The position within the current buffer (i.e. the next byte to read)
+ /// </summary>
private int bufferPos = 0;
+
+ /// <summary>
+ /// The stream to read further input from, or null if the byte array buffer was provided
+ /// directly on construction, with no further data available.
+ /// </summary>
private readonly Stream input;
+
+ /// <summary>
+ /// The last tag we read. 0 indicates we've read to the end of the stream
+ /// (or haven't read anything yet).
+ /// </summary>
private uint lastTag = 0;
+ /// <summary>
+ /// The next tag, used to store the value read by PeekTag.
+ /// </summary>
private uint nextTag = 0;
private bool hasNextTag = false;
internal const int DefaultRecursionLimit = 64;
internal const int DefaultSizeLimit = 64 << 20; // 64MB
- public const int BufferSize = 4096;
+ internal const int BufferSize = 4096;
/// <summary>
/// The total number of bytes read before the current buffer. The
@@ -80,77 +103,102 @@ namespace Google.Protobuf /// </summary>
private int currentLimit = int.MaxValue;
- /// <summary>
- /// <see cref="SetRecursionLimit"/>
- /// </summary>
private int recursionDepth = 0;
- private int recursionLimit = DefaultRecursionLimit;
-
- /// <summary>
- /// <see cref="SetSizeLimit"/>
- /// </summary>
- private int sizeLimit = DefaultSizeLimit;
+ private readonly int recursionLimit;
+ private readonly int sizeLimit;
#region Construction
+ // Note that the checks are performed such that we don't end up checking obviously-valid things
+ // like non-null references for arrays we've just created.
/// <summary>
- /// Creates a new CodedInputStream reading data from the given
- /// stream.
+ /// Creates a new CodedInputStream reading data from the given byte array.
/// </summary>
- public static CodedInputStream CreateInstance(Stream input)
- {
- return new CodedInputStream(input);
+ public CodedInputStream(byte[] buffer) : this(null, Preconditions.CheckNotNull(buffer, "buffer"), 0, buffer.Length)
+ {
}
+
/// <summary>
- /// Creates a new CodedInputStream reading data from the given
- /// stream and a pre-allocated memory buffer.
+ /// Creates a new CodedInputStream that reads from the given byte array slice.
/// </summary>
- public static CodedInputStream CreateInstance(Stream input, byte[] buffer)
- {
- return new CodedInputStream(input, buffer);
+ public CodedInputStream(byte[] buffer, int offset, int length)
+ : this(null, Preconditions.CheckNotNull(buffer, "buffer"), offset, offset + length)
+ {
+ if (offset < 0 || offset > buffer.Length)
+ {
+ throw new ArgumentOutOfRangeException("offset", "Offset must be within the buffer");
+ }
+ if (length < 0 || offset + length > buffer.Length)
+ {
+ throw new ArgumentOutOfRangeException("length", "Length must be non-negative and within the buffer");
+ }
}
/// <summary>
- /// Creates a new CodedInputStream reading data from the given
- /// byte array.
+ /// Creates a new CodedInputStream reading data from the given stream.
/// </summary>
- public static CodedInputStream CreateInstance(byte[] buf)
+ public CodedInputStream(Stream input) : this(input, new byte[BufferSize], 0, 0)
{
- return new CodedInputStream(buf, 0, buf.Length);
+ Preconditions.CheckNotNull(input, "input");
}
/// <summary>
- /// Creates a new CodedInputStream that reads from the given
- /// byte array slice.
+ /// Creates a new CodedInputStream reading data from the given
+ /// stream and buffer, using the default limits.
/// </summary>
- public static CodedInputStream CreateInstance(byte[] buf, int offset, int length)
- {
- return new CodedInputStream(buf, offset, length);
- }
-
- private CodedInputStream(byte[] buffer, int offset, int length)
+ internal CodedInputStream(Stream input, byte[] buffer, int bufferPos, int bufferSize)
{
+ this.input = input;
this.buffer = buffer;
- this.bufferPos = offset;
- this.bufferSize = offset + length;
- this.input = null;
+ this.bufferPos = bufferPos;
+ this.bufferSize = bufferSize;
+ this.sizeLimit = DefaultSizeLimit;
+ this.recursionLimit = DefaultRecursionLimit;
}
- private CodedInputStream(Stream input)
+ /// <summary>
+ /// Creates a new CodedInputStream reading data from the given
+ /// stream and buffer, using the specified limits.
+ /// </summary>
+ /// <remarks>
+ /// This chains to the version with the default limits instead of vice versa to avoid
+ /// having to check that the default values are valid every time.
+ /// </remarks>
+ internal CodedInputStream(Stream input, byte[] buffer, int bufferPos, int bufferSize, int sizeLimit, int recursionLimit)
+ : this(input, buffer, bufferPos, bufferSize)
{
- this.buffer = new byte[BufferSize];
- this.bufferSize = 0;
- this.input = input;
+ if (sizeLimit <= 0)
+ {
+ throw new ArgumentOutOfRangeException("sizeLimit", "Size limit must be positive");
+ }
+ if (recursionLimit <= 0)
+ {
+ throw new ArgumentOutOfRangeException("recursionLimit!", "Recursion limit must be positive");
+ }
+ this.sizeLimit = sizeLimit;
+ this.recursionLimit = recursionLimit;
}
+ #endregion
- private CodedInputStream(Stream input, byte[] buffer)
+ /// <summary>
+ /// Creates a <see cref="CodedInputStream"/> with the specified size and recursion limits, reading
+ /// from an input stream.
+ /// </summary>
+ /// <remarks>
+ /// This method exists separately from the constructor to reduce the number of constructor overloads.
+ /// It is likely to be used considerably less frequently than the constructors, as the default limits
+ /// are suitable for most use cases.
+ /// </remarks>
+ /// <param name="input">The input stream to read from</param>
+ /// <param name="sizeLimit">The total limit of data to read from the stream.</param>
+ /// <param name="recursionLimit">The maximum recursion depth to allow while reading.</param>
+ /// <returns>A <c>CodedInputStream</c> reading from <paramref name="input"/> with the specified size
+ /// and recursion limits.</returns>
+ public static CodedInputStream CreateWithLimits(Stream input, int sizeLimit, int recursionLimit)
{
- this.buffer = buffer;
- this.bufferSize = 0;
- this.input = input;
+ return new CodedInputStream(input, new byte[BufferSize], 0, 0, sizeLimit, recursionLimit);
}
- #endregion
/// <summary>
/// Returns the current position in the input stream, or the position in the input buffer
@@ -173,73 +221,43 @@ namespace Google.Protobuf /// </summary>
internal uint LastTag { get { return lastTag; } }
- #region Limits for recursion and length
/// <summary>
- /// Set the maximum message recursion depth.
+ /// Returns the size limit for this stream.
/// </summary>
/// <remarks>
- /// In order to prevent malicious
- /// messages from causing stack overflows, CodedInputStream limits
- /// how deeply messages may be nested. The default limit is 64.
+ /// This limit is applied when reading from the underlying stream, as a sanity check. It is
+ /// not applied when reading from a byte array data source without an underlying stream.
+ /// The default value is 64MB.
/// </remarks>
- public int SetRecursionLimit(int limit)
- {
- if (limit < 0)
- {
- throw new ArgumentOutOfRangeException("Recursion limit cannot be negative: " + limit);
- }
- int oldLimit = recursionLimit;
- recursionLimit = limit;
- return oldLimit;
- }
+ /// <value>
+ /// The size limit.
+ /// </value>
+ public int SizeLimit { get { return sizeLimit; } }
/// <summary>
- /// Set the maximum message size.
+ /// Returns the recursion limit for this stream. This limit is applied whilst reading messages,
+ /// to avoid maliciously-recursive data.
/// </summary>
/// <remarks>
- /// In order to prevent malicious messages from exhausting memory or
- /// causing integer overflows, CodedInputStream limits how large a message may be.
- /// The default limit is 64MB. You should set this limit as small
- /// as you can without harming your app's functionality. Note that
- /// size limits only apply when reading from an InputStream, not
- /// when constructed around a raw byte array (nor with ByteString.NewCodedInput).
- /// If you want to read several messages from a single CodedInputStream, you
- /// can call ResetSizeCounter() after each message to avoid hitting the
- /// size limit.
+ /// The default limit is 64.
/// </remarks>
- public int SetSizeLimit(int limit)
- {
- if (limit < 0)
- {
- throw new ArgumentOutOfRangeException("Size limit cannot be negative: " + limit);
- }
- int oldLimit = sizeLimit;
- sizeLimit = limit;
- return oldLimit;
- }
-
- /// <summary>
- /// Resets the current size counter to zero (see <see cref="SetSizeLimit"/>).
- /// </summary>
- public void ResetSizeCounter()
- {
- totalBytesRetired = 0;
- }
- #endregion
+ /// <value>
+ /// The recursion limit for this stream.
+ /// </value>
+ public int RecursionLimit { get { return recursionLimit; } }
#region Validation
/// <summary>
- /// Verifies that the last call to ReadTag() returned the given tag value.
- /// This is used to verify that a nested group ended with the correct
- /// end tag.
+ /// Verifies that the last call to ReadTag() returned tag 0 - in other words,
+ /// we've reached the end of the stream when we expected to.
/// </summary>
- /// <exception cref="InvalidProtocolBufferException">The last
+ /// <exception cref="InvalidProtocolBufferException">The
/// tag read was not the one specified</exception>
- internal void CheckLastTagWas(uint value)
+ internal void CheckReadEndOfStreamTag()
{
- if (lastTag != value)
+ if (lastTag != 0)
{
- throw InvalidProtocolBufferException.InvalidEndTag();
+ throw InvalidProtocolBufferException.MoreDataAvailable();
}
}
#endregion
@@ -247,37 +265,40 @@ namespace Google.Protobuf #region Reading of tags etc
/// <summary>
- /// Attempts to peek at the next field tag.
+ /// Peeks at the next field tag. This is like calling <see cref="ReadTag"/>, but the
+ /// tag is not consumed. (So a subsequent call to <see cref="ReadTag"/> will return the
+ /// same value.)
/// </summary>
- public bool PeekNextTag(out uint fieldTag)
+ public uint PeekTag()
{
if (hasNextTag)
{
- fieldTag = nextTag;
- return true;
+ return nextTag;
}
uint savedLast = lastTag;
- hasNextTag = ReadTag(out nextTag);
- lastTag = savedLast;
- fieldTag = nextTag;
- return hasNextTag;
+ nextTag = ReadTag();
+ hasNextTag = true;
+ lastTag = savedLast; // Undo the side effect of ReadTag
+ return nextTag;
}
/// <summary>
- /// Attempts to read a field tag, returning false if we have reached the end
- /// of the input data.
+ /// Reads a field tag, returning the tag of 0 for "end of stream".
/// </summary>
- /// <param name="fieldTag">The 'tag' of the field (id * 8 + wire-format)</param>
- /// <returns>true if the next fieldTag was read</returns>
- public bool ReadTag(out uint fieldTag)
+ /// <remarks>
+ /// If this method returns 0, it doesn't necessarily mean the end of all
+ /// the data in this CodedInputStream; it may be the end of the logical stream
+ /// for an embedded message, for example.
+ /// </remarks>
+ /// <returns>The next field tag, or 0 for end of stream. (0 is never a valid tag.)</returns>
+ public uint ReadTag()
{
if (hasNextTag)
{
- fieldTag = nextTag;
- lastTag = fieldTag;
+ lastTag = nextTag;
hasNextTag = false;
- return true;
+ return lastTag;
}
// Optimize for the incredibly common case of having at least two bytes left in the buffer,
@@ -287,7 +308,7 @@ namespace Google.Protobuf int tmp = buffer[bufferPos++];
if (tmp < 128)
{
- fieldTag = (uint)tmp;
+ lastTag = (uint)tmp;
}
else
{
@@ -295,13 +316,13 @@ namespace Google.Protobuf if ((tmp = buffer[bufferPos++]) < 128)
{
result |= tmp << 7;
- fieldTag = (uint) result;
+ lastTag = (uint) result;
}
else
{
// Nope, rewind and go the potentially slow route.
bufferPos -= 2;
- fieldTag = ReadRawVarint32();
+ lastTag = ReadRawVarint32();
}
}
}
@@ -309,20 +330,76 @@ namespace Google.Protobuf {
if (IsAtEnd)
{
- fieldTag = 0;
- lastTag = fieldTag;
- return false;
+ lastTag = 0;
+ return 0; // This is the only case in which we return 0.
}
- fieldTag = ReadRawVarint32();
+ lastTag = ReadRawVarint32();
}
- lastTag = fieldTag;
if (lastTag == 0)
{
// If we actually read zero, that's not a valid tag.
throw InvalidProtocolBufferException.InvalidTag();
}
- return true;
+ return lastTag;
+ }
+
+ /// <summary>
+ /// Skips the data for the field with the tag we've just read.
+ /// This should be called directly after <see cref="ReadTag"/>, when
+ /// the caller wishes to skip an unknown field.
+ /// </summary>
+ public void SkipLastField()
+ {
+ if (lastTag == 0)
+ {
+ throw new InvalidOperationException("SkipLastField cannot be called at the end of a stream");
+ }
+ switch (WireFormat.GetTagWireType(lastTag))
+ {
+ case WireFormat.WireType.StartGroup:
+ SkipGroup();
+ break;
+ case WireFormat.WireType.EndGroup:
+ // Just ignore; there's no data following the tag.
+ break;
+ case WireFormat.WireType.Fixed32:
+ ReadFixed32();
+ break;
+ case WireFormat.WireType.Fixed64:
+ ReadFixed64();
+ break;
+ case WireFormat.WireType.LengthDelimited:
+ var length = ReadLength();
+ SkipRawBytes(length);
+ break;
+ case WireFormat.WireType.Varint:
+ ReadRawVarint32();
+ break;
+ }
+ }
+
+ private void SkipGroup()
+ {
+ // Note: Currently we expect this to be the way that groups are read. We could put the recursion
+ // depth changes into the ReadTag method instead, potentially...
+ recursionDepth++;
+ if (recursionDepth >= recursionLimit)
+ {
+ throw InvalidProtocolBufferException.RecursionLimitExceeded();
+ }
+ uint tag;
+ do
+ {
+ tag = ReadTag();
+ if (tag == 0)
+ {
+ throw InvalidProtocolBufferException.TruncatedMessage();
+ }
+ // This recursion will allow us to handle nested groups.
+ SkipLastField();
+ } while (WireFormat.GetTagWireType(tag) != WireFormat.WireType.EndGroup);
+ recursionDepth--;
}
/// <summary>
@@ -439,7 +516,12 @@ namespace Google.Protobuf int oldLimit = PushLimit(length);
++recursionDepth;
builder.MergeFrom(this);
- CheckLastTagWas(0);
+ CheckReadEndOfStreamTag();
+ // Check that we've read exactly as much data as expected.
+ if (!ReachedLimit)
+ {
+ throw InvalidProtocolBufferException.TruncatedMessage();
+ }
--recursionDepth;
PopLimit(oldLimit);
}
@@ -535,14 +617,10 @@ namespace Google.Protobuf /// </summary>
public bool MaybeConsumeTag(uint tag)
{
- uint next;
- if (PeekNextTag(out next))
+ if (PeekTag() == tag)
{
- if (next == tag)
- {
- hasNextTag = false;
- return true;
- }
+ hasNextTag = false;
+ return true;
}
return false;
}
@@ -956,7 +1034,6 @@ namespace Google.Protobuf if (totalBytesRetired + bufferPos + size > currentLimit)
{
// Read to the end of the stream (up to the current limit) anyway.
- // TODO(jonskeet): This is the only usage of SkipRawBytes. Do we really need to do it?
SkipRawBytes(currentLimit - totalBytesRetired - bufferPos);
// Then fail.
throw InvalidProtocolBufferException.TruncatedMessage();
diff --git a/csharp/src/Google.Protobuf/CodedOutputStream.cs b/csharp/src/Google.Protobuf/CodedOutputStream.cs index b91d6d70..d6355f03 100644 --- a/csharp/src/Google.Protobuf/CodedOutputStream.cs +++ b/csharp/src/Google.Protobuf/CodedOutputStream.cs @@ -30,6 +30,7 @@ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#endregion
+using Google.Protobuf.Collections;
using System;
using System.IO;
using System.Text;
@@ -40,14 +41,19 @@ namespace Google.Protobuf /// Encodes and writes protocol message fields.
/// </summary>
/// <remarks>
- /// This class contains two kinds of methods: methods that write specific
- /// protocol message constructs and field types (e.g. WriteTag and
- /// WriteInt32) and methods that write low-level values (e.g.
- /// WriteRawVarint32 and WriteRawBytes). If you are writing encoded protocol
- /// messages, you should use the former methods, but if you are writing some
- /// other format of your own design, use the latter. The names of the former
- /// methods are taken from the protocol buffer type names, not .NET types.
- /// (Hence WriteFloat instead of WriteSingle, and WriteBool instead of WriteBoolean.)
+ /// <para>
+ /// This class is generally used by generated code to write appropriate
+ /// primitives to the stream. It effectively encapsulates the lowest
+ /// levels of protocol buffer format. Unlike some other implementations,
+ /// this does not include combined "write tag and value" methods. Generated
+ /// code knows the exact byte representations of the tags they're going to write,
+ /// so there's no need to re-encode them each time. Manually-written code calling
+ /// this class should just call one of the <c>WriteTag</c> overloads before each value.
+ /// </para>
+ /// <para>
+ /// Repeated fields and map fields are not handled by this class; use <c>RepeatedField<T></c>
+ /// and <c>MapField<TKey, TValue></c> to serialize such fields.
+ /// </para>
/// </remarks>
public sealed partial class CodedOutputStream
{
@@ -65,7 +71,20 @@ namespace Google.Protobuf private readonly Stream output;
#region Construction
+ /// <summary>
+ /// Creates a new CodedOutputStream that writes directly to the given
+ /// byte array. If more bytes are written than fit in the array,
+ /// OutOfSpaceException will be thrown.
+ /// </summary>
+ public CodedOutputStream(byte[] flatArray) : this(flatArray, 0, flatArray.Length)
+ {
+ }
+ /// <summary>
+ /// Creates a new CodedOutputStream that writes directly to the given
+ /// byte array slice. If more bytes are written than fit in the array,
+ /// OutOfSpaceException will be thrown.
+ /// </summary>
private CodedOutputStream(byte[] buffer, int offset, int length)
{
this.output = null;
@@ -85,40 +104,17 @@ namespace Google.Protobuf /// <summary>
/// Creates a new CodedOutputStream which write to the given stream.
/// </summary>
- public static CodedOutputStream CreateInstance(Stream output)
+ public CodedOutputStream(Stream output) : this(output, DefaultBufferSize)
{
- return CreateInstance(output, DefaultBufferSize);
}
/// <summary>
/// Creates a new CodedOutputStream which write to the given stream and uses
/// the specified buffer size.
/// </summary>
- public static CodedOutputStream CreateInstance(Stream output, int bufferSize)
- {
- return new CodedOutputStream(output, new byte[bufferSize]);
- }
-
- /// <summary>
- /// Creates a new CodedOutputStream that writes directly to the given
- /// byte array. If more bytes are written than fit in the array,
- /// OutOfSpaceException will be thrown.
- /// </summary>
- public static CodedOutputStream CreateInstance(byte[] flatArray)
+ public CodedOutputStream(Stream output, int bufferSize) : this(output, new byte[bufferSize])
{
- return CreateInstance(flatArray, 0, flatArray.Length);
- }
-
- /// <summary>
- /// Creates a new CodedOutputStream that writes directly to the given
- /// byte array slice. If more bytes are written than fit in the array,
- /// OutOfSpaceException will be thrown.
- /// </summary>
- public static CodedOutputStream CreateInstance(byte[] flatArray, int offset, int length)
- {
- return new CodedOutputStream(flatArray, offset, length);
- }
-
+ }
#endregion
/// <summary>
@@ -307,6 +303,10 @@ namespace Google.Protobuf WriteInt32(value);
}
+ /// <summary>
+ /// Writes an sfixed32 value, without a tag, to the stream.
+ /// </summary>
+ /// <param name="value">The value to write.</param>
public void WriteSFixed32(int value)
{
WriteRawLittleEndian32((uint) value);
@@ -659,6 +659,9 @@ namespace Google.Protobuf }
}
+ /// <summary>
+ /// Flushes any buffered data to the underlying stream (if there is one).
+ /// </summary>
public void Flush()
{
if (output != null)
diff --git a/csharp/src/Google.Protobuf/Collections/MapField.cs b/csharp/src/Google.Protobuf/Collections/MapField.cs index fc94fd5c..0fa63bef 100644 --- a/csharp/src/Google.Protobuf/Collections/MapField.cs +++ b/csharp/src/Google.Protobuf/Collections/MapField.cs @@ -42,14 +42,14 @@ namespace Google.Protobuf.Collections /// <summary> /// Representation of a map field in a Protocol Buffer message. /// </summary> + /// <typeparam name="TKey">Key type in the map. Must be a type supported by Protocol Buffer map keys.</typeparam> + /// <typeparam name="TValue">Value type in the map. Must be a type supported by Protocol Buffers.</typeparam> /// <remarks> /// This implementation preserves insertion order for simplicity of testing /// code using maps fields. Overwriting an existing entry does not change the /// position of that entry within the map. Equality is not order-sensitive. - /// For string keys, the equality comparison is provided by <see cref="StringComparer.Ordinal"/>. + /// For string keys, the equality comparison is provided by <see cref="StringComparer.Ordinal" />. /// </remarks> - /// <typeparam name="TKey">Key type in the map. Must be a type supported by Protocol Buffer map keys.</typeparam> - /// <typeparam name="TValue">Value type in the map. Must be a type supported by Protocol Buffers.</typeparam> 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.) @@ -81,6 +81,12 @@ namespace Google.Protobuf.Collections this.allowNullValues = allowNullValues; } + /// <summary> + /// Creates a deep clone of this object. + /// </summary> + /// <returns> + /// A deep clone of this object. + /// </returns> public MapField<TKey, TValue> Clone() { var clone = new MapField<TKey, TValue>(allowNullValues); @@ -100,6 +106,15 @@ namespace Google.Protobuf.Collections return clone; } + /// <summary> + /// Adds the specified key/value pair to the map. + /// </summary> + /// <remarks> + /// This operation fails if the key already exists in the map. To replace an existing entry, use the indexer. + /// </remarks> + /// <param name="key">The key to add</param> + /// <param name="value">The value to add.</param> + /// <exception cref="System.ArgumentException">The given key already exists in map.</exception> public void Add(TKey key, TValue value) { // Validation of arguments happens in ContainsKey and the indexer @@ -110,12 +125,28 @@ namespace Google.Protobuf.Collections this[key] = value; } + /// <summary> + /// Determines whether the specified key is present in the map. + /// </summary> + /// <param name="key">The key to check.</param> + /// <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"); return map.ContainsKey(key); } + private bool ContainsValue(TValue value) + { + var comparer = EqualityComparer<TValue>.Default; + return list.Any(pair => comparer.Equals(pair.Value, value)); + } + + /// <summary> + /// Removes the entry identified by the given key from the map. + /// </summary> + /// <param name="key">The key indicating the entry to remove from the map.</param> + /// <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"); @@ -132,6 +163,14 @@ namespace Google.Protobuf.Collections } } + /// <summary> + /// Gets the value associated with the specified key. + /// </summary> + /// <param name="key">The key whose value to get.</param> + /// <param name="value">When this method returns, the value associated with the specified key, if the key is found; + /// otherwise, the default value for the type of the <paramref name="value"/> parameter. + /// This parameter is passed uninitialized.</param> + /// <returns><c>true</c> if the map contains an element with the specified key; otherwise, <c>false</c>.</returns> public bool TryGetValue(TKey key, out TValue value) { LinkedListNode<KeyValuePair<TKey, TValue>> node; @@ -147,6 +186,13 @@ namespace Google.Protobuf.Collections } } + /// <summary> + /// Gets or sets the value associated with the specified key. + /// </summary> + /// <param name="key">The key of the value to get or set.</param> + /// <exception cref="KeyNotFoundException">The property is retrieved and key does not exist in the collection.</exception> + /// <returns>The value associated with the specified key. If the specified key is not found, + /// a get operation throws a <see cref="KeyNotFoundException"/>, and a set operation creates a new element with the specified key.</returns> public TValue this[TKey key] { get @@ -181,10 +227,20 @@ namespace Google.Protobuf.Collections } } - // TODO: Make these views? - public ICollection<TKey> Keys { get { return list.Select(t => t.Key).ToList(); } } - public ICollection<TValue> Values { get { return list.Select(t => t.Value).ToList(); } } + /// <summary> + /// Gets a collection containing the keys in the map. + /// </summary> + public ICollection<TKey> Keys { get { return new MapView<TKey>(this, pair => pair.Key, ContainsKey); } } + + /// <summary> + /// Gets a collection containing the values in the map. + /// </summary> + public ICollection<TValue> Values { get { return new MapView<TValue>(this, pair => pair.Value, ContainsValue); } } + /// <summary> + /// Adds the specified entries to the map. + /// </summary> + /// <param name="entries">The entries to add to the map.</param> public void Add(IDictionary<TKey, TValue> entries) { Preconditions.CheckNotNull(entries, "entries"); @@ -194,27 +250,51 @@ namespace Google.Protobuf.Collections } } + /// <summary> + /// Returns an enumerator that iterates through the collection. + /// </summary> + /// <returns> + /// An enumerator that can be used to iterate through the collection. + /// </returns> public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator() { return list.GetEnumerator(); } + /// <summary> + /// Returns an enumerator that iterates through a collection. + /// </summary> + /// <returns> + /// An <see cref="T:System.Collections.IEnumerator" /> object that can be used to iterate through the collection. + /// </returns> IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } + /// <summary> + /// Adds the specified item to the map. + /// </summary> + /// <param name="item">The item to add to the map.</param> void ICollection<KeyValuePair<TKey, TValue>>.Add(KeyValuePair<TKey, TValue> item) { Add(item.Key, item.Value); } + /// <summary> + /// Removes all items from the map. + /// </summary> public void Clear() { list.Clear(); map.Clear(); } + /// <summary> + /// Determines whether map contains an entry equivalent to the given key/value pair. + /// </summary> + /// <param name="item">The key/value pair to find.</param> + /// <returns></returns> bool ICollection<KeyValuePair<TKey, TValue>>.Contains(KeyValuePair<TKey, TValue> item) { TValue value; @@ -222,11 +302,22 @@ namespace Google.Protobuf.Collections && EqualityComparer<TValue>.Default.Equals(item.Value, value); } + /// <summary> + /// Copies the key/value pairs in this map to an array. + /// </summary> + /// <param name="array">The array to copy the entries into.</param> + /// <param name="arrayIndex">The index of the array at which to start copying values.</param> void ICollection<KeyValuePair<TKey, TValue>>.CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex) { list.CopyTo(array, arrayIndex); } + /// <summary> + /// Removes the specified key/value pair from the map. + /// </summary> + /// <remarks>Both the key and the value must be found for the entry to be removed.</remarks> + /// <param name="item">The key/value pair to remove.</param> + /// <returns><c>true</c> if the key/value pair was found and removed; <c>false</c> otherwise.</returns> bool ICollection<KeyValuePair<TKey, TValue>>.Remove(KeyValuePair<TKey, TValue> item) { if (item.Key == null) @@ -252,14 +343,34 @@ namespace Google.Protobuf.Collections /// </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; } } + + /// <summary> + /// Gets a value indicating whether the map is read-only. + /// </summary> public bool IsReadOnly { get { return false; } } + /// <summary> + /// Determines whether the specified <see cref="System.Object" />, is equal to this instance. + /// </summary> + /// <param name="other">The <see cref="System.Object" /> to compare with this instance.</param> + /// <returns> + /// <c>true</c> if the specified <see cref="System.Object" /> is equal to this instance; otherwise, <c>false</c>. + /// </returns> public override bool Equals(object other) { return Equals(other as MapField<TKey, TValue>); } + /// <summary> + /// Returns a hash code for this instance. + /// </summary> + /// <returns> + /// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. + /// </returns> public override int GetHashCode() { var valueComparer = EqualityComparer<TValue>.Default; @@ -271,6 +382,14 @@ namespace Google.Protobuf.Collections return hash; } + /// <summary> + /// Compares this map with another for equality. + /// </summary> + /// <remarks> + /// The order of the key/value pairs in the maps is not deemed significant in this comparison. + /// </remarks> + /// <param name="other">The map to compare this with.</param> + /// <returns><c>true</c> if <paramref name="other"/> refers to an equal map; <c>false</c> otherwise.</returns> public bool Equals(MapField<TKey, TValue> other) { if (other == null) @@ -322,6 +441,12 @@ namespace Google.Protobuf.Collections } while (input.MaybeConsumeTag(codec.MapTag)); } + /// <summary> + /// Writes the contents of this map to the given coded output stream, using the specified codec + /// to encode each entry. + /// </summary> + /// <param name="output">The output stream to write to.</param> + /// <param name="codec">The codec to use for each entry.</param> public void WriteTo(CodedOutputStream output, Codec codec) { var message = new Codec.MessageAdapter(codec); @@ -334,6 +459,11 @@ namespace Google.Protobuf.Collections } } + /// <summary> + /// Calculates the size of this map based on the given entry codec. + /// </summary> + /// <param name="codec">The codec to use to encode each entry.</param> + /// <returns></returns> public int CalculateSize(Codec codec) { if (Count == 0) @@ -446,7 +576,7 @@ namespace Google.Protobuf.Collections } /// <summary> - /// A codec for a specific map field. This contains all the information required to encoded and + /// A codec for a specific map field. This contains all the information required to encode and /// decode the nested messages. /// </summary> public sealed class Codec @@ -455,6 +585,13 @@ namespace Google.Protobuf.Collections private readonly FieldCodec<TValue> valueCodec; private readonly uint mapTag; + /// <summary> + /// Creates a new entry codec based on a separate key codec and value codec, + /// and the tag to use for each map entry. + /// </summary> + /// <param name="keyCodec">The key codec.</param> + /// <param name="valueCodec">The value codec.</param> + /// <param name="mapTag">The map tag to use to introduce each map entry.</param> public Codec(FieldCodec<TKey> keyCodec, FieldCodec<TValue> valueCodec, uint mapTag) { this.keyCodec = keyCodec; @@ -494,12 +631,8 @@ namespace Google.Protobuf.Collections public void MergeFrom(CodedInputStream input) { uint tag; - while (input.ReadTag(out tag)) + while ((tag = input.ReadTag()) != 0) { - if (tag == 0) - { - throw InvalidProtocolBufferException.InvalidTag(); - } if (tag == codec.keyCodec.Tag) { Key = codec.keyCodec.Read(input); @@ -508,10 +641,9 @@ namespace Google.Protobuf.Collections { Value = codec.valueCodec.Read(input); } - else if (WireFormat.IsEndGroupTag(tag)) + else { - // TODO(jonskeet): Do we need this? (Given that we don't support groups...) - return; + input.SkipLastField(); } } } @@ -530,5 +662,92 @@ namespace Google.Protobuf.Collections MessageDescriptor IMessage.Descriptor { get { return null; } } } } + + private class MapView<T> : ICollection<T>, ICollection + { + private readonly MapField<TKey, TValue> parent; + private readonly Func<KeyValuePair<TKey, TValue>, T> projection; + private readonly Func<T, bool> containsCheck; + + internal MapView( + MapField<TKey, TValue> parent, + Func<KeyValuePair<TKey, TValue>, T> projection, + Func<T, bool> containsCheck) + { + this.parent = parent; + this.projection = projection; + this.containsCheck = containsCheck; + } + + public int Count { get { return parent.Count; } } + + public bool IsReadOnly { get { return true; } } + + public bool IsSynchronized { get { return false; } } + + public object SyncRoot { get { return parent; } } + + public void Add(T item) + { + throw new NotSupportedException(); + } + + public void Clear() + { + throw new NotSupportedException(); + } + + public bool Contains(T item) + { + return containsCheck(item); + } + + public void CopyTo(T[] array, int arrayIndex) + { + if (arrayIndex < 0) + { + throw new ArgumentOutOfRangeException("arrayIndex"); + } + if (arrayIndex + Count >= array.Length) + { + throw new ArgumentException("Not enough space in the array", "array"); + } + foreach (var item in this) + { + array[arrayIndex++] = item; + } + } + + public IEnumerator<T> GetEnumerator() + { + return parent.list.Select(projection).GetEnumerator(); + } + + public bool Remove(T item) + { + throw new NotSupportedException(); + } + + IEnumerator IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + + public void CopyTo(Array array, int index) + { + if (index < 0) + { + throw new ArgumentOutOfRangeException("index"); + } + if (index + Count >= array.Length) + { + throw new ArgumentException("Not enough space in the array", "array"); + } + foreach (var item in this) + { + array.SetValue(item, index++); + } + } + } } } diff --git a/csharp/src/Google.Protobuf/Collections/RepeatedField.cs b/csharp/src/Google.Protobuf/Collections/RepeatedField.cs index 3ce19c81..d9ced6ec 100644 --- a/csharp/src/Google.Protobuf/Collections/RepeatedField.cs +++ b/csharp/src/Google.Protobuf/Collections/RepeatedField.cs @@ -30,7 +30,6 @@ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion -using Google.Protobuf.Reflection; using System; using System.Collections; using System.Collections.Generic; @@ -81,10 +80,15 @@ namespace Google.Protobuf.Collections return clone; } + /// <summary> + /// Adds the entries from the given input stream, decoding them with the specified codec. + /// </summary> + /// <param name="input">The input stream to read from.</param> + /// <param name="codec">The codec to use in order to read each entry.</param> public void AddEntriesFrom(CodedInputStream input, FieldCodec<T> codec) { // TODO: Inline some of the Add code, so we can avoid checking the size on every - // iteration and the mutability. + // iteration. uint tag = input.LastTag; var reader = codec.ValueReader; // Value types can be packed or not. @@ -112,6 +116,12 @@ namespace Google.Protobuf.Collections } } + /// <summary> + /// Calculates the size of this collection based on the given codec. + /// </summary> + /// <param name="codec">The codec to use when encoding each field.</param> + /// <returns>The number of bytes that would be written to a <see cref="CodedOutputStream"/> by <see cref="WriteTo"/>, + /// using the same codec.</returns> public int CalculateSize(FieldCodec<T> codec) { if (count == 0) @@ -157,6 +167,12 @@ namespace Google.Protobuf.Collections } } + /// <summary> + /// Writes the contents of this collection to the given <see cref="CodedOutputStream"/>, + /// encoding each value using the specified codec. + /// </summary> + /// <param name="output">The output stream to write to.</param> + /// <param name="codec">The codec to use when encoding each value.</param> public void WriteTo(CodedOutputStream output, FieldCodec<T> codec) { if (count == 0) @@ -200,6 +216,10 @@ namespace Google.Protobuf.Collections } } + /// <summary> + /// Adds the specified item to the collection. + /// </summary> + /// <param name="item">The item to add.</param> public void Add(T item) { if (item == null) @@ -210,22 +230,40 @@ namespace Google.Protobuf.Collections array[count++] = item; } + /// <summary> + /// Removes all items from the collection. + /// </summary> public void Clear() { array = EmptyArray; count = 0; } + /// <summary> + /// Determines whether this collection contains the given item. + /// </summary> + /// <param name="item">The item to find.</param> + /// <returns><c>true</c> if this collection contains the given item; <c>false</c> otherwise.</returns> public bool Contains(T item) { return IndexOf(item) != -1; } + /// <summary> + /// Copies this collection to the given array. + /// </summary> + /// <param name="array">The array to copy to.</param> + /// <param name="arrayIndex">The first index of the array to copy to.</param> public void CopyTo(T[] array, int arrayIndex) { Array.Copy(this.array, 0, array, arrayIndex, count); } + /// <summary> + /// Removes the specified item from the collection + /// </summary> + /// <param name="item">The item to remove.</param> + /// <returns><c>true</c> if the item was found and removed; <c>false</c> otherwise.</returns> public bool Remove(T item) { int index = IndexOf(item); @@ -239,10 +277,22 @@ namespace Google.Protobuf.Collections return true; } + /// <summary> + /// Gets the number of elements contained in the collection. + /// </summary> public int Count { get { return count; } } + /// <summary> + /// Gets a value indicating whether the collection is read-only. + /// </summary> public bool IsReadOnly { get { return false; } } + // TODO: Remove this overload and just handle it in the one below, at execution time? + + /// <summary> + /// Adds all of the specified values into this collection. + /// </summary> + /// <param name="values">The values to add to this collection.</param> public void Add(RepeatedField<T> values) { if (values == null) @@ -255,19 +305,29 @@ namespace Google.Protobuf.Collections count += values.count; } + /// <summary> + /// Adds all of the specified values into this collection. + /// </summary> + /// <param name="values">The values to add to this collection.</param> public void Add(IEnumerable<T> values) { if (values == null) { throw new ArgumentNullException("values"); } - // TODO: Check for ICollection and get the Count? + // TODO: Check for ICollection and get the Count, to optimize? foreach (T item in values) { Add(item); } } + /// <summary> + /// Returns an enumerator that iterates through the collection. + /// </summary> + /// <returns> + /// An enumerator that can be used to iterate through the collection. + /// </returns> public IEnumerator<T> GetEnumerator() { for (int i = 0; i < count; i++) @@ -276,16 +336,35 @@ namespace Google.Protobuf.Collections } } + /// <summary> + /// Determines whether the specified <see cref="System.Object" />, is equal to this instance. + /// </summary> + /// <param name="obj">The <see cref="System.Object" /> to compare with this instance.</param> + /// <returns> + /// <c>true</c> if the specified <see cref="System.Object" /> is equal to this instance; otherwise, <c>false</c>. + /// </returns> public override bool Equals(object obj) { return Equals(obj as RepeatedField<T>); } + /// <summary> + /// Returns an enumerator that iterates through a collection. + /// </summary> + /// <returns> + /// An <see cref="T:System.Collections.IEnumerator" /> object that can be used to iterate through the collection. + /// </returns> IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); - } + } + /// <summary> + /// Returns a hash code for this instance. + /// </summary> + /// <returns> + /// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. + /// </returns> public override int GetHashCode() { int hash = 0; @@ -296,6 +375,11 @@ namespace Google.Protobuf.Collections return hash; } + /// <summary> + /// Compares this repeated field with another for equality. + /// </summary> + /// <param name="other">The repeated field to compare this with.</param> + /// <returns><c>true</c> if <paramref name="other"/> refers to an equal repeated field; <c>false</c> otherwise.</returns> public bool Equals(RepeatedField<T> other) { if (ReferenceEquals(other, null)) @@ -310,7 +394,6 @@ namespace Google.Protobuf.Collections { return false; } - // TODO(jonskeet): Does this box for enums? EqualityComparer<T> comparer = EqualityComparer<T>.Default; for (int i = 0; i < count; i++) { @@ -322,13 +405,18 @@ namespace Google.Protobuf.Collections return true; } + /// <summary> + /// Returns the index of the given item within the collection, or -1 if the item is not + /// present. + /// </summary> + /// <param name="item">The item to find in the collection.</param> + /// <returns>The zero-based index of the item, or -1 if it is not found.</returns> public int IndexOf(T item) { if (item == null) { throw new ArgumentNullException("item"); } - // TODO(jonskeet): Does this box for enums? EqualityComparer<T> comparer = EqualityComparer<T>.Default; for (int i = 0; i < count; i++) { @@ -340,6 +428,11 @@ namespace Google.Protobuf.Collections return -1; } + /// <summary> + /// Inserts the given item at the specified index. + /// </summary> + /// <param name="index">The index at which to insert the item.</param> + /// <param name="item">The item to insert.</param> public void Insert(int index, T item) { if (item == null) @@ -356,6 +449,10 @@ namespace Google.Protobuf.Collections count++; } + /// <summary> + /// Removes the item at the given index. + /// </summary> + /// <param name="index">The zero-based index of the item to remove.</param> public void RemoveAt(int index) { if (index < 0 || index >= count) @@ -367,6 +464,14 @@ namespace Google.Protobuf.Collections array[count] = default(T); } + /// <summary> + /// Gets or sets the item at the specified index. + /// </summary> + /// <value> + /// The element at the specified index. + /// </value> + /// <param name="index">The zero-based index of the element to get or set.</param> + /// <returns>The item at the specified index.</returns> public T this[int index] { get diff --git a/csharp/src/Google.Protobuf/FieldCodec.cs b/csharp/src/Google.Protobuf/FieldCodec.cs index 85462787..20a1f438 100644 --- a/csharp/src/Google.Protobuf/FieldCodec.cs +++ b/csharp/src/Google.Protobuf/FieldCodec.cs @@ -41,76 +41,152 @@ namespace Google.Protobuf public static class FieldCodec { // TODO: Avoid the "dual hit" of lambda expressions: create open delegates instead. (At least test...) + + /// <summary> + /// Retrieves a codec suitable for a string field with the given tag. + /// </summary> + /// <param name="tag">The tag.</param> + /// <returns>A codec for the given tag.</returns> public static FieldCodec<string> ForString(uint tag) { return new FieldCodec<string>(input => input.ReadString(), (output, value) => output.WriteString(value), CodedOutputStream.ComputeStringSize, tag); } + /// <summary> + /// Retrieves a codec suitable for a bytes field with the given tag. + /// </summary> + /// <param name="tag">The tag.</param> + /// <returns>A codec for the given tag.</returns> public static FieldCodec<ByteString> ForBytes(uint tag) { return new FieldCodec<ByteString>(input => input.ReadBytes(), (output, value) => output.WriteBytes(value), CodedOutputStream.ComputeBytesSize, tag); } + /// <summary> + /// Retrieves a codec suitable for a bool field with the given tag. + /// </summary> + /// <param name="tag">The tag.</param> + /// <returns>A codec for the given tag.</returns> public static FieldCodec<bool> ForBool(uint tag) { return new FieldCodec<bool>(input => input.ReadBool(), (output, value) => output.WriteBool(value), CodedOutputStream.ComputeBoolSize, tag); } + /// <summary> + /// Retrieves a codec suitable for an int32 field with the given tag. + /// </summary> + /// <param name="tag">The tag.</param> + /// <returns>A codec for the given tag.</returns> public static FieldCodec<int> ForInt32(uint tag) { return new FieldCodec<int>(input => input.ReadInt32(), (output, value) => output.WriteInt32(value), CodedOutputStream.ComputeInt32Size, tag); } + /// <summary> + /// Retrieves a codec suitable for an sint32 field with the given tag. + /// </summary> + /// <param name="tag">The tag.</param> + /// <returns>A codec for the given tag.</returns> public static FieldCodec<int> ForSInt32(uint tag) { return new FieldCodec<int>(input => input.ReadSInt32(), (output, value) => output.WriteSInt32(value), CodedOutputStream.ComputeSInt32Size, tag); } + /// <summary> + /// Retrieves a codec suitable for a fixed32 field with the given tag. + /// </summary> + /// <param name="tag">The tag.</param> + /// <returns>A codec for the given tag.</returns> public static FieldCodec<uint> ForFixed32(uint tag) { return new FieldCodec<uint>(input => input.ReadFixed32(), (output, value) => output.WriteFixed32(value), 4, tag); } + /// <summary> + /// Retrieves a codec suitable for an sfixed32 field with the given tag. + /// </summary> + /// <param name="tag">The tag.</param> + /// <returns>A codec for the given tag.</returns> public static FieldCodec<int> ForSFixed32(uint tag) { return new FieldCodec<int>(input => input.ReadSFixed32(), (output, value) => output.WriteSFixed32(value), 4, tag); } + /// <summary> + /// Retrieves a codec suitable for a uint32 field with the given tag. + /// </summary> + /// <param name="tag">The tag.</param> + /// <returns>A codec for the given tag.</returns> public static FieldCodec<uint> ForUInt32(uint tag) { return new FieldCodec<uint>(input => input.ReadUInt32(), (output, value) => output.WriteUInt32(value), CodedOutputStream.ComputeUInt32Size, tag); } + /// <summary> + /// Retrieves a codec suitable for an int64 field with the given tag. + /// </summary> + /// <param name="tag">The tag.</param> + /// <returns>A codec for the given tag.</returns> public static FieldCodec<long> ForInt64(uint tag) { return new FieldCodec<long>(input => input.ReadInt64(), (output, value) => output.WriteInt64(value), CodedOutputStream.ComputeInt64Size, tag); } + /// <summary> + /// Retrieves a codec suitable for an sint64 field with the given tag. + /// </summary> + /// <param name="tag">The tag.</param> + /// <returns>A codec for the given tag.</returns> public static FieldCodec<long> ForSInt64(uint tag) { return new FieldCodec<long>(input => input.ReadSInt64(), (output, value) => output.WriteSInt64(value), CodedOutputStream.ComputeSInt64Size, tag); } + /// <summary> + /// Retrieves a codec suitable for a fixed64 field with the given tag. + /// </summary> + /// <param name="tag">The tag.</param> + /// <returns>A codec for the given tag.</returns> public static FieldCodec<ulong> ForFixed64(uint tag) { return new FieldCodec<ulong>(input => input.ReadFixed64(), (output, value) => output.WriteFixed64(value), 8, tag); } + /// <summary> + /// Retrieves a codec suitable for an sfixed64 field with the given tag. + /// </summary> + /// <param name="tag">The tag.</param> + /// <returns>A codec for the given tag.</returns> public static FieldCodec<long> ForSFixed64(uint tag) { return new FieldCodec<long>(input => input.ReadSFixed64(), (output, value) => output.WriteSFixed64(value), 8, tag); } + /// <summary> + /// Retrieves a codec suitable for a uint64 field with the given tag. + /// </summary> + /// <param name="tag">The tag.</param> + /// <returns>A codec for the given tag.</returns> public static FieldCodec<ulong> ForUInt64(uint tag) { return new FieldCodec<ulong>(input => input.ReadUInt64(), (output, value) => output.WriteUInt64(value), CodedOutputStream.ComputeUInt64Size, tag); } + /// <summary> + /// Retrieves a codec suitable for a float field with the given tag. + /// </summary> + /// <param name="tag">The tag.</param> + /// <returns>A codec for the given tag.</returns> public static FieldCodec<float> ForFloat(uint tag) { return new FieldCodec<float>(input => input.ReadFloat(), (output, value) => output.WriteFloat(value), CodedOutputStream.ComputeFloatSize, tag); } + /// <summary> + /// Retrieves a codec suitable for a double field with the given tag. + /// </summary> + /// <param name="tag">The tag.</param> + /// <returns>A codec for the given tag.</returns> public static FieldCodec<double> ForDouble(uint tag) { return new FieldCodec<double>(input => input.ReadDouble(), (output, value) => output.WriteDouble(value), CodedOutputStream.ComputeDoubleSize, tag); @@ -118,6 +194,14 @@ namespace Google.Protobuf // Enums are tricky. We can probably use expression trees to build these delegates automatically, // but it's easy to generate the code for it. + + /// <summary> + /// Retrieves a codec suitable for an enum field with the given tag. + /// </summary> + /// <param name="tag">The tag.</param> + /// <param name="toInt32">A conversion function from <see cref="Int32"/> to the enum type.</param> + /// <param name="fromInt32">A conversion function from the enum type to <see cref="Int32"/>.</param> + /// <returns>A codec for the given tag.</returns> public static FieldCodec<T> ForEnum<T>(uint tag, Func<T, int> toInt32, Func<int, T> fromInt32) { return new FieldCodec<T>(input => fromInt32( @@ -126,6 +210,12 @@ namespace Google.Protobuf value => CodedOutputStream.ComputeEnumSize(toInt32(value)), tag); } + /// <summary> + /// Retrieves a codec suitable for a message field with the given tag. + /// </summary> + /// <param name="tag">The tag.</param> + /// <param name="parser">A parser to use for the message type.</param> + /// <returns>A codec for the given tag.</returns> public static FieldCodec<T> ForMessage<T>(uint tag, MessageParser<T> parser) where T : IMessage<T> { return new FieldCodec<T>(input => { T message = parser.CreateTemplate(); input.ReadMessage(message); return message; }, @@ -208,22 +298,19 @@ namespace Google.Protobuf uint tag; T value = codec.DefaultValue; - while (input.ReadTag(out tag)) + while ((tag = input.ReadTag()) != 0) { - if (tag == 0) - { - throw InvalidProtocolBufferException.InvalidTag(); - } if (tag == codec.Tag) { value = codec.Read(input); } - if (WireFormat.IsEndGroupTag(tag)) + else { - break; + input.SkipLastField(); } + } - input.CheckLastTagWas(0); + input.CheckReadEndOfStreamTag(); input.PopLimit(oldLimit); return value; @@ -344,8 +431,20 @@ namespace Google.Protobuf /// </summary> internal int FixedSize { get { return fixedSize; } } + /// <summary> + /// Gets the tag of the codec. + /// </summary> + /// <value> + /// The tag of the codec. + /// </value> public uint Tag { get { return tag; } } + /// <summary> + /// Gets the default value of the codec's type. + /// </summary> + /// <value> + /// The default value of the codec's type. + /// </value> public T DefaultValue { get { return defaultValue; } } /// <summary> @@ -360,6 +459,11 @@ namespace Google.Protobuf } } + /// <summary> + /// Reads a value of the codec type from the given <see cref="CodedInputStream"/>. + /// </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); diff --git a/csharp/src/Google.Protobuf/FrameworkPortability.cs b/csharp/src/Google.Protobuf/FrameworkPortability.cs index 082eb2e1..9498dbe4 100644 --- a/csharp/src/Google.Protobuf/FrameworkPortability.cs +++ b/csharp/src/Google.Protobuf/FrameworkPortability.cs @@ -40,10 +40,9 @@ namespace Google.Protobuf /// </summary>
internal static class FrameworkPortability
{
- // TODO(jtattermusch): is this still a thing?
// The value of RegexOptions.Compiled is 8. We can test for the presence at
// execution time using Enum.IsDefined, so a single build will do the right thing
- // on each platform.
+ // on each platform. (RegexOptions.Compiled isn't supported by PCLs.)
internal static readonly RegexOptions CompiledRegexWhereAvailable =
Enum.IsDefined(typeof(RegexOptions), 8) ? (RegexOptions)8 : RegexOptions.None;
}
diff --git a/csharp/src/Google.Protobuf/Google.Protobuf.csproj b/csharp/src/Google.Protobuf/Google.Protobuf.csproj index c7038eb4..a17bf81c 100644 --- a/csharp/src/Google.Protobuf/Google.Protobuf.csproj +++ b/csharp/src/Google.Protobuf/Google.Protobuf.csproj @@ -14,8 +14,6 @@ <TargetFrameworkProfile>Profile259</TargetFrameworkProfile>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
- <SignAssembly>true</SignAssembly>
- <AssemblyOriginatorKeyFile>..\..\keys\Google.Protobuf.snk</AssemblyOriginatorKeyFile>
<OldToolsVersion>3.5</OldToolsVersion>
<MinimumVisualStudioVersion>10.0</MinimumVisualStudioVersion>
</PropertyGroup>
@@ -26,12 +24,14 @@ <OutputPath>bin\Debug</OutputPath>
<IntermediateOutputPath>obj\Debug\</IntermediateOutputPath>
<DocumentationFile>bin\Debug\Google.Protobuf.xml</DocumentationFile>
- <NoWarn>1591, 1570, 1571, 1572, 1573, 1574</NoWarn>
- <DefineConstants>DEBUG;TRACE;$(EnvironmentFlavor);$(EnvironmentTemplate)</DefineConstants>
+ <NoWarn>
+ </NoWarn>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<NoStdLib>true</NoStdLib>
<GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
+ <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
@@ -39,12 +39,31 @@ <OutputPath>bin\Release</OutputPath>
<IntermediateOutputPath>obj\Release\</IntermediateOutputPath>
<DocumentationFile>$(OutputPath)\$(AssemblyName).xml</DocumentationFile>
- <NoWarn>1591, 1570, 1571, 1572, 1573, 1574</NoWarn>
- <DefineConstants>TRACE;$(EnvironmentFlavor);$(EnvironmentTemplate)</DefineConstants>
+ <NoWarn>
+ </NoWarn>
+ <DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<NoStdLib>true</NoStdLib>
<GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
+ <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'ReleaseSigned|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\ReleaseSigned</OutputPath>
+ <IntermediateOutputPath>obj\ReleaseSigned\</IntermediateOutputPath>
+ <DocumentationFile>$(OutputPath)\$(AssemblyName).xml</DocumentationFile>
+ <NoWarn>
+ </NoWarn>
+ <DefineConstants>TRACE;SIGNED</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <NoStdLib>true</NoStdLib>
+ <GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
+ <SignAssembly>True</SignAssembly>
+ <AssemblyOriginatorKeyFile>C:\keys\Google.Protobuf.snk</AssemblyOriginatorKeyFile>
+ <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
</PropertyGroup>
<ItemGroup>
<Reference Include="mscorlib" />
@@ -64,6 +83,7 @@ <Compile Include="Compatibility\TypeExtensions.cs" />
<Compile Include="FieldCodec.cs" />
<Compile Include="FrameworkPortability.cs" />
+ <Compile Include="IDeepCloneable.cs" />
<Compile Include="JsonFormatter.cs" />
<Compile Include="MessageExtensions.cs" />
<Compile Include="IMessage.cs" />
diff --git a/csharp/src/Google.Protobuf/Google.Protobuf.nuspec b/csharp/src/Google.Protobuf/Google.Protobuf.nuspec index 09ec5cf0..228457a3 100644 --- a/csharp/src/Google.Protobuf/Google.Protobuf.nuspec +++ b/csharp/src/Google.Protobuf/Google.Protobuf.nuspec @@ -5,20 +5,32 @@ <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-beta*</version> + <version>3.0.0-alpha4</version> <authors>Google Inc.</authors> <owners>protobuf-packages</owners> <licenseUrl>https://github.com/google/protobuf/blob/master/LICENSE</licenseUrl> <projectUrl>https://github.com/google/protobuf</projectUrl> <requireLicenseAcceptance>false</requireLicenseAcceptance> - <releaseNotes>Experimental version of C# Protocol Buffers</releaseNotes> + <releaseNotes>C# proto3 support</releaseNotes> <copyright>Copyright 2015, Google Inc.</copyright> <tags>Protocol Buffers Binary Serialization Format Google proto proto3</tags> </metadata> <files> - <file src="bin/Release/Google.Protobuf.dll" target="lib/portable-net45+netcore45+wpa81+wp8" /> - <file src="bin/Release/Google.Protobuf.pdb" target="lib/portable-net45+netcore45+wpa81+wp8" /> - <file src="bin/Release/Google.Protobuf.xml" target="lib/portable-net45+netcore45+wpa81+wp8" /> + <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\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> diff --git a/csharp/src/Google.Protobuf/IDeepCloneable.cs b/csharp/src/Google.Protobuf/IDeepCloneable.cs new file mode 100644 index 00000000..c9c71bbe --- /dev/null +++ b/csharp/src/Google.Protobuf/IDeepCloneable.cs @@ -0,0 +1,54 @@ +#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 + +namespace Google.Protobuf +{ + /// <summary> + /// Generic interface for a deeply cloneable type. + /// </summary> + /// <remarks> + /// <para> + /// All generated messages implement this interface, but so do some non-message types. + /// Additionally, due to the type constraint on <c>T</c> in <see cref="IMessage{T}"/>, + /// it is simpler to keep this as a separate interface. + /// </para> + /// </remarks> + /// <typeparam name="T">The type itself, returned by the <see cref="Clone"/> method.</typeparam> + public interface IDeepCloneable<T> + { + /// <summary> + /// Creates a deep clone of this object. + /// </summary> + /// <returns>A deep clone of this object.</returns> + T Clone(); + } +} diff --git a/csharp/src/Google.Protobuf/IMessage.cs b/csharp/src/Google.Protobuf/IMessage.cs index 60c6f8c3..d089f946 100644 --- a/csharp/src/Google.Protobuf/IMessage.cs +++ b/csharp/src/Google.Protobuf/IMessage.cs @@ -35,10 +35,6 @@ using Google.Protobuf.Reflection; namespace Google.Protobuf
{
-
- // TODO(jonskeet): Do we want a "weak" (non-generic) version of IReflectedMessage?
- // TODO(jonskeet): Split these interfaces into separate files when we're happy with them.
-
/// <summary>
/// Interface for a Protocol Buffers message, supporting
/// basic operations required for serialization.
@@ -88,23 +84,4 @@ namespace Google.Protobuf /// <param name="message">The message to merge with this one. Must not be null.</param>
void MergeFrom(T message);
}
-
- /// <summary>
- /// Generic interface for a deeply cloneable type.
- /// <summary>
- /// <remarks>
- /// All generated messages implement this interface, but so do some non-message types.
- /// Additionally, due to the type constraint on <c>T</c> in <see cref="IMessage{T}"/>,
- /// it is simpler to keep this as a separate interface.
- /// </para>
- /// </remarks>
- /// <typeparam name="T">The type itself, returned by the <see cref="Clone"/> method.</typeparam>
- public interface IDeepCloneable<T>
- {
- /// <summary>
- /// Creates a deep clone of this object.
- /// </summary>
- /// <returns>A deep clone of this object.</returns>
- T Clone();
- }
}
diff --git a/csharp/src/Google.Protobuf/InvalidProtocolBufferException.cs b/csharp/src/Google.Protobuf/InvalidProtocolBufferException.cs index 4f89347d..01d55395 100644 --- a/csharp/src/Google.Protobuf/InvalidProtocolBufferException.cs +++ b/csharp/src/Google.Protobuf/InvalidProtocolBufferException.cs @@ -45,7 +45,13 @@ namespace Google.Protobuf {
}
- public static InvalidProtocolBufferException TruncatedMessage()
+ internal static InvalidProtocolBufferException MoreDataAvailable()
+ {
+ return new InvalidProtocolBufferException(
+ "Completed reading a message while more data was available in the stream.");
+ }
+
+ internal static InvalidProtocolBufferException TruncatedMessage()
{
return new InvalidProtocolBufferException(
"While parsing a protocol message, the input ended unexpectedly " +
@@ -61,13 +67,16 @@ namespace Google.Protobuf "which claimed to have negative size.");
}
- public static InvalidProtocolBufferException MalformedVarint()
+ internal static InvalidProtocolBufferException MalformedVarint()
{
return new InvalidProtocolBufferException(
"CodedInputStream encountered a malformed varint.");
}
- public static InvalidProtocolBufferException InvalidTag()
+ /// <summary>
+ /// Creates an exception for an error condition of an invalid tag being encountered.
+ /// </summary>
+ internal static InvalidProtocolBufferException InvalidTag()
{
return new InvalidProtocolBufferException(
"Protocol message contained an invalid tag (zero).");
diff --git a/csharp/src/Google.Protobuf/JsonFormatter.cs b/csharp/src/Google.Protobuf/JsonFormatter.cs index 438af4df..12bbdfdd 100644 --- a/csharp/src/Google.Protobuf/JsonFormatter.cs +++ b/csharp/src/Google.Protobuf/JsonFormatter.cs @@ -36,6 +36,7 @@ using System.Globalization; using System.Text; using Google.Protobuf.Reflection; using Google.Protobuf.WellKnownTypes; +using System.Linq; namespace Google.Protobuf { @@ -113,19 +114,32 @@ namespace Google.Protobuf private readonly Settings settings; + /// <summary> + /// Creates a new formatted with the given settings. + /// </summary> + /// <param name="settings">The settings.</param> public JsonFormatter(Settings settings) { this.settings = settings; } + /// <summary> + /// Formats the specified message as JSON. + /// </summary> + /// <param name="message">The message to format.</param> + /// <returns>The formatted message.</returns> public string Format(IMessage message) { Preconditions.CheckNotNull(message, "message"); StringBuilder builder = new StringBuilder(); - // TODO(jonskeet): Handle well-known types here. - // Our reflection support needs improving so that we can get at the descriptor - // to find out whether *this* message is a well-known type. - WriteMessage(builder, message); + if (message.Descriptor.IsWellKnownType) + { + WriteWellKnownTypeValue(builder, message.Descriptor, message, false); + } + else + { + WriteMessage(builder, message); + } return builder.ToString(); } @@ -144,14 +158,14 @@ namespace Google.Protobuf { var accessor = field.Accessor; // Oneofs are written later - // TODO: Change to write out fields in order, interleaving oneofs appropriately (as per binary format) - if (field.ContainingOneof != null) + if (field.ContainingOneof != null && field.ContainingOneof.Accessor.GetCaseFieldDescriptor(message) != field) { continue; } - // Omit default values unless we're asked to format them + // Omit default values unless we're asked to format them, or they're oneofs (where the default + // value is still formatted regardless, because that's how we preserve the oneof case). object value = accessor.GetValue(message); - if (!settings.FormatDefaultValues && IsDefaultValue(accessor, value)) + if (field.ContainingOneof == null && !settings.FormatDefaultValues && IsDefaultValue(accessor, value)) { continue; } @@ -170,33 +184,7 @@ namespace Google.Protobuf builder.Append(": "); WriteValue(builder, accessor, value); first = false; - } - - // Now oneofs - foreach (var oneof in message.Descriptor.Oneofs) - { - var accessor = oneof.Accessor; - var fieldDescriptor = accessor.GetCaseFieldDescriptor(message); - if (fieldDescriptor == null) - { - continue; - } - object value = fieldDescriptor.Accessor.GetValue(message); - // Omit awkward (single) values such as unknown enum values - if (!fieldDescriptor.IsRepeated && !fieldDescriptor.IsMap && !CanWriteSingleValue(fieldDescriptor, value)) - { - continue; - } - - if (!first) - { - builder.Append(", "); - } - WriteString(builder, ToCamelCase(fieldDescriptor.Name)); - builder.Append(": "); - WriteValue(builder, fieldDescriptor.Accessor, value); - first = false; - } + } builder.Append(first ? "}" : " }"); } @@ -381,7 +369,7 @@ namespace Google.Protobuf case FieldType.Group: // Never expect to get this, but... if (descriptor.MessageType.IsWellKnownType) { - WriteWellKnownTypeValue(builder, descriptor, value); + WriteWellKnownTypeValue(builder, descriptor.MessageType, value, true); } else { @@ -395,20 +383,204 @@ namespace Google.Protobuf /// <summary> /// Central interception point for well-known type formatting. Any well-known types which - /// don't need special handling can fall back to WriteMessage. + /// don't need special handling can fall back to WriteMessage. We avoid assuming that the + /// values are using the embedded well-known types, in order to allow for dynamic messages + /// in the future. /// </summary> - private void WriteWellKnownTypeValue(StringBuilder builder, FieldDescriptor descriptor, object value) + private void WriteWellKnownTypeValue(StringBuilder builder, MessageDescriptor descriptor, object value, bool inField) { + if (value == null) + { + WriteNull(builder); + return; + } // For wrapper types, the value will be the (possibly boxed) "native" value, // so we can write it as if we were unconditionally writing the Value field for the wrapper type. - if (descriptor.MessageType.File == Int32Value.Descriptor.File && value != null) + if (descriptor.File == Int32Value.Descriptor.File) { - WriteSingleValue(builder, descriptor.MessageType.FindFieldByNumber(1), value); + WriteSingleValue(builder, descriptor.FindFieldByNumber(1), value); + return; + } + if (descriptor.FullName == Timestamp.Descriptor.FullName) + { + MaybeWrapInString(builder, value, WriteTimestamp, inField); + return; + } + if (descriptor.FullName == Duration.Descriptor.FullName) + { + MaybeWrapInString(builder, value, WriteDuration, inField); + return; + } + if (descriptor.FullName == FieldMask.Descriptor.FullName) + { + MaybeWrapInString(builder, value, WriteFieldMask, inField); + return; + } + if (descriptor.FullName == Struct.Descriptor.FullName) + { + WriteStruct(builder, (IMessage) value); + return; + } + if (descriptor.FullName == ListValue.Descriptor.FullName) + { + var fieldAccessor = descriptor.Fields[ListValue.ValuesFieldNumber].Accessor; + WriteList(builder, fieldAccessor, (IList) fieldAccessor.GetValue((IMessage) value)); + return; + } + if (descriptor.FullName == Value.Descriptor.FullName) + { + 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) + { + builder.Append('"'); + action(builder, (IMessage) value); + builder.Append('"'); + } + else + { + action(builder, (IMessage) value); + } + } + + private void WriteTimestamp(StringBuilder builder, IMessage value) + { + // TODO: In the common case where this *is* using the built-in Timestamp type, we could + // avoid all the reflection at this point, by casting to Timestamp. In the interests of + // avoiding subtle bugs, don't do that until we've implemented DynamicMessage so that we can prove + // 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'); + } + + private void WriteDuration(StringBuilder builder, IMessage value) + { + // 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); + + // 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); + + // 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) + { + builder.Append('-'); + } + + builder.Append(normalized.Seconds.ToString("d", CultureInfo.InvariantCulture)); + AppendNanoseconds(builder, Math.Abs(normalized.Nanos)); + builder.Append('s'); + } + + private void WriteFieldMask(StringBuilder builder, IMessage value) + { + IList paths = (IList) value.Descriptor.Fields[FieldMask.PathsFieldNumber].Accessor.GetValue(value); + AppendEscapedString(builder, string.Join(",", paths.Cast<string>().Select(ToCamelCase))); + } + + /// <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) + { + if (nanos != 0) + { + 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)); + } + } + } + + private void WriteStruct(StringBuilder builder, IMessage message) + { + builder.Append("{ "); + IDictionary fields = (IDictionary) message.Descriptor.Fields[Struct.FieldsFieldNumber].Accessor.GetValue(message); + bool first = true; + foreach (DictionaryEntry entry in fields) + { + string key = (string) entry.Key; + IMessage value = (IMessage) entry.Value; + if (string.IsNullOrEmpty(key) || value == null) + { + throw new InvalidOperationException("Struct fields cannot have an empty key or a null value."); + } + + if (!first) + { + builder.Append(", "); + } + WriteString(builder, key); + builder.Append(": "); + WriteStructFieldValue(builder, value); + first = false; + } + builder.Append(first ? "}" : " }"); + } + + private void WriteStructFieldValue(StringBuilder builder, IMessage message) + { + var specifiedField = message.Descriptor.Oneofs[0].Accessor.GetCaseFieldDescriptor(message); + if (specifiedField == null) + { + throw new InvalidOperationException("Value message must contain a value for the oneof."); + } + + object value = specifiedField.Accessor.GetValue(message); + + switch (specifiedField.FieldNumber) + { + case Value.BoolValueFieldNumber: + case Value.StringValueFieldNumber: + case Value.NumberValueFieldNumber: + WriteSingleValue(builder, specifiedField, value); + return; + case Value.StructValueFieldNumber: + 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); + return; + case Value.NullValueFieldNumber: + WriteNull(builder); + return; + default: + throw new InvalidOperationException("Unexpected case in struct field: " + specifiedField.FieldNumber); + } + } + private void WriteList(StringBuilder builder, IFieldAccessor accessor, IList list) { builder.Append("[ "); @@ -502,6 +674,15 @@ namespace Google.Protobuf private 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]; @@ -561,13 +742,11 @@ namespace Google.Protobuf break; } } - builder.Append('"'); } private const string Hex = "0123456789abcdef"; private static void HexEncodeUtf16CodeUnit(StringBuilder builder, char c) { - uint utf16 = c; builder.Append("\\u"); builder.Append(Hex[(c >> 12) & 0xf]); builder.Append(Hex[(c >> 8) & 0xf]); @@ -596,6 +775,10 @@ namespace Google.Protobuf /// </summary> public bool FormatDefaultValues { get { return formatDefaultValues; } } + /// <summary> + /// Creates a new <see cref="Settings"/> object with the specified formatting of default values. + /// </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 = formatDefaultValues; diff --git a/csharp/src/Google.Protobuf/MessageExtensions.cs b/csharp/src/Google.Protobuf/MessageExtensions.cs index 7bd79930..d2d057c0 100644 --- a/csharp/src/Google.Protobuf/MessageExtensions.cs +++ b/csharp/src/Google.Protobuf/MessageExtensions.cs @@ -39,33 +39,57 @@ namespace Google.Protobuf /// </summary> public static class MessageExtensions { + /// <summary> + /// Merges data from the given byte array into an existing message. + /// </summary> + /// <param name="message">The message to merge the data into.</param> + /// <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"); - CodedInputStream input = CodedInputStream.CreateInstance(data); + CodedInputStream input = new CodedInputStream(data); message.MergeFrom(input); - input.CheckLastTagWas(0); + input.CheckReadEndOfStreamTag(); } + /// <summary> + /// Merges data from the given byte string into an existing message. + /// </summary> + /// <param name="message">The message to merge the data into.</param> + /// <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"); CodedInputStream input = data.CreateCodedInput(); message.MergeFrom(input); - input.CheckLastTagWas(0); + input.CheckReadEndOfStreamTag(); } + /// <summary> + /// Merges data from the given stream into an existing message. + /// </summary> + /// <param name="message">The message to merge the data into.</param> + /// <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"); - CodedInputStream codedInput = CodedInputStream.CreateInstance(input); + CodedInputStream codedInput = new CodedInputStream(input); message.MergeFrom(codedInput); - codedInput.CheckLastTagWas(0); + codedInput.CheckReadEndOfStreamTag(); } + /// <summary> + /// Merges length-delimited data from the given stream into an existing message. + /// </summary> + /// <remarks> + /// The stream is expected to contain a length and then the data. Only the amount of data + /// specified by the length will be consumed. + /// </remarks> + /// <param name="message">The message to merge the data into.</param> + /// <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"); @@ -75,35 +99,55 @@ namespace Google.Protobuf message.MergeFrom(limitedStream); } + /// <summary> + /// Converts the given message into a byte array in protobuf encoding. + /// </summary> + /// <param name="message">The message to convert.</param> + /// <returns>The message data as a byte array.</returns> public static byte[] ToByteArray(this IMessage message) { Preconditions.CheckNotNull(message, "message"); byte[] result = new byte[message.CalculateSize()]; - CodedOutputStream output = CodedOutputStream.CreateInstance(result); + CodedOutputStream output = new CodedOutputStream(result); message.WriteTo(output); output.CheckNoSpaceLeft(); return result; } + /// <summary> + /// Writes the given message data to the given stream in protobuf encoding. + /// </summary> + /// <param name="message">The message to write to the stream.</param> + /// <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"); - CodedOutputStream codedOutput = CodedOutputStream.CreateInstance(output); + CodedOutputStream codedOutput = new CodedOutputStream(output); message.WriteTo(codedOutput); codedOutput.Flush(); } + /// <summary> + /// Writes the length and then data of the given message to a stream. + /// </summary> + /// <param name="message">The message to write.</param> + /// <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"); - CodedOutputStream codedOutput = CodedOutputStream.CreateInstance(output); + CodedOutputStream codedOutput = new CodedOutputStream(output); codedOutput.WriteRawVarint32((uint)message.CalculateSize()); message.WriteTo(codedOutput); codedOutput.Flush(); } + /// <summary> + /// Converts the given message into a byte string in protobuf encoding. + /// </summary> + /// <param name="message">The message to convert.</param> + /// <returns>The message data as a byte string.</returns> public static ByteString ToByteString(this IMessage message) { Preconditions.CheckNotNull(message, "message"); diff --git a/csharp/src/Google.Protobuf/MessageParser.cs b/csharp/src/Google.Protobuf/MessageParser.cs index bfa63ae5..6a6f1017 100644 --- a/csharp/src/Google.Protobuf/MessageParser.cs +++ b/csharp/src/Google.Protobuf/MessageParser.cs @@ -90,6 +90,11 @@ namespace Google.Protobuf return message; } + /// <summary> + /// Parses a message from the given byte string. + /// </summary> + /// <param name="data">The data to parse.</param> + /// <returns>The parsed message.</returns> public T ParseFrom(ByteString data) { Preconditions.CheckNotNull(data, "data"); @@ -98,6 +103,11 @@ namespace Google.Protobuf return message; } + /// <summary> + /// Parses a message from the given stream. + /// </summary> + /// <param name="input">The stream to parse.</param> + /// <returns>The parsed message.</returns> public T ParseFrom(Stream input) { T message = factory(); @@ -105,6 +115,15 @@ namespace Google.Protobuf return message; } + /// <summary> + /// Parses a length-delimited message from the given stream. + /// </summary> + /// <remarks> + /// The stream is expected to contain a length and then the data. Only the amount of data + /// specified by the length will be consumed. + /// </remarks> + /// <param name="input">The stream to parse.</param> + /// <returns>The parsed message.</returns> public T ParseDelimitedFrom(Stream input) { T message = factory(); @@ -112,6 +131,11 @@ namespace Google.Protobuf return message; } + /// <summary> + /// Parses a message from the given coded input stream. + /// </summary> + /// <param name="input">The stream to parse.</param> + /// <returns>The parsed message.</returns> public T ParseFrom(CodedInputStream input) { T message = factory(); diff --git a/csharp/src/Google.Protobuf/Preconditions.cs b/csharp/src/Google.Protobuf/Preconditions.cs index ff3bd0f1..2db35ff6 100644 --- a/csharp/src/Google.Protobuf/Preconditions.cs +++ b/csharp/src/Google.Protobuf/Preconditions.cs @@ -57,7 +57,7 @@ namespace Google.Protobuf /// return the value to the caller. /// </summary> /// <remarks> - /// This is equivalent to <see cref="CheckNotNull"/> but without the type parameter + /// This is equivalent to <see cref="CheckNotNull{T}(T, string)"/> but without the type parameter /// constraint. In most cases, the constraint is useful to prevent you from calling CheckNotNull /// with a value type - but it gets in the way if either you want to use it with a nullable /// value type, or you want to use it with an unconstrained type parameter. diff --git a/csharp/src/Google.Protobuf/Properties/AssemblyInfo.cs b/csharp/src/Google.Protobuf/Properties/AssemblyInfo.cs index a957e8b3..9a484ad6 100644 --- a/csharp/src/Google.Protobuf/Properties/AssemblyInfo.cs +++ b/csharp/src/Google.Protobuf/Properties/AssemblyInfo.cs @@ -32,6 +32,7 @@ using System.Reflection;
using System.Runtime.CompilerServices;
+using System.Security;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
@@ -42,31 +43,22 @@ using System.Runtime.CompilerServices; [assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Google.Protobuf")]
-[assembly: AssemblyCopyright("Copyright © 2008")]
+[assembly: AssemblyCopyright("Copyright © 2015")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
+[assembly: AllowPartiallyTrustedCallers]
-// Version information for an assembly consists of the following four values:
-//
-// Major Version
-// Minor Version
-// Build Number
-// Revision
-//
-// You can specify all the values or you can default the Build and Revision Numbers
-// by using the '*' as shown below:
-// [assembly: AssemblyVersion("2.4.1.555")]
-
-[assembly: AssemblyVersion("2.4.1.555")]
-
+#if SIGNED
[assembly: InternalsVisibleTo("Google.Protobuf.Test, PublicKey=" +
- "00240000048000009400000006020000002400005253413100040000110000003b4611704c5379" +
- "39c3e0fbe9447dd6fa5462507f9dd4fd9fbf0712457e415b037da6d2c4eb5d2c7d29c86380af68" +
- "7cf400401bb183f2a70bd3b631c1fcb7db8aa66c766694a9fb53fa765df6303104da8c978f3b6d" +
- "53909cd30685b8bc9922c726cd82b5995e9e2cfca6df7a2d189d851492e49f4b76f269ce6dfd08" +
- "c34a7d98")]
-
-#if !NOFILEVERSION
-[assembly: AssemblyFileVersion("2.4.1.555")]
+ "002400000480000094000000060200000024000052534131000400000100010025800fbcfc63a1" +
+ "7c66b303aae80b03a6beaa176bb6bef883be436f2a1579edd80ce23edf151a1f4ced97af83abcd" +
+ "981207041fd5b2da3b498346fcfcd94910d52f25537c4a43ce3fbe17dc7d43e6cbdb4d8f1242dc" +
+ "b6bd9b5906be74da8daa7d7280f97130f318a16c07baf118839b156299a48522f9fae2371c9665" +
+ "c5ae9cb6")]
+#else
+[assembly: InternalsVisibleTo("Google.Protobuf.Test")]
#endif
+[assembly: AssemblyVersion("3.0.0.0")]
+[assembly: AssemblyFileVersion("3.0.0.0")]
+[assembly: AssemblyInformationalVersion("3.0.0-alpha4")]
diff --git a/csharp/src/Google.Protobuf/Reflection/DescriptorBase.cs b/csharp/src/Google.Protobuf/Reflection/DescriptorBase.cs index 0300cd58..194041a8 100644 --- a/csharp/src/Google.Protobuf/Reflection/DescriptorBase.cs +++ b/csharp/src/Google.Protobuf/Reflection/DescriptorBase.cs @@ -61,6 +61,9 @@ namespace Google.Protobuf.Reflection get { return index; } } + /// <summary> + /// Returns the name of the entity (field, message etc) being described. + /// </summary> public abstract string Name { get; } /// <summary> diff --git a/csharp/src/Google.Protobuf/Reflection/DescriptorPool.cs b/csharp/src/Google.Protobuf/Reflection/DescriptorPool.cs index 157ea400..759955e6 100644 --- a/csharp/src/Google.Protobuf/Reflection/DescriptorPool.cs +++ b/csharp/src/Google.Protobuf/Reflection/DescriptorPool.cs @@ -257,10 +257,12 @@ namespace Google.Protobuf.Reflection /// or unqualified. C++-like name lookup semantics are used to search for the /// matching descriptor. /// </summary> + /// <remarks> + /// This isn't heavily optimized, but it's only used during cross linking anyway. + /// If it starts being used more widely, we should look at performance more carefully. + /// </remarks> internal IDescriptor LookupSymbol(string name, IDescriptor relativeTo) { - // TODO(jonskeet): This could be optimized in a number of ways. - IDescriptor result; if (name.StartsWith(".")) { @@ -282,7 +284,6 @@ namespace Google.Protobuf.Reflection { // Chop off the last component of the scope. - // TODO(jonskeet): Make this more efficient. May not be worth using StringBuilder at all int dotpos = scopeToTry.ToString().LastIndexOf("."); if (dotpos == -1) { diff --git a/csharp/src/Google.Protobuf/Reflection/DescriptorProtoFile.cs b/csharp/src/Google.Protobuf/Reflection/DescriptorProtoFile.cs index e40472cb..59c5e69b 100644 --- a/csharp/src/Google.Protobuf/Reflection/DescriptorProtoFile.cs +++ b/csharp/src/Google.Protobuf/Reflection/DescriptorProtoFile.cs @@ -239,14 +239,10 @@ namespace Google.Protobuf.Reflection { public void MergeFrom(pb::CodedInputStream input) { uint tag; - while (input.ReadTag(out tag)) { + while ((tag = input.ReadTag()) != 0) { switch(tag) { - case 0: - throw pb::InvalidProtocolBufferException.InvalidTag(); default: - if (pb::WireFormat.IsEndGroupTag(tag)) { - return; - } + input.SkipLastField(); break; case 10: { file_.AddEntriesFrom(input, _repeated_file_codec); @@ -537,14 +533,10 @@ namespace Google.Protobuf.Reflection { public void MergeFrom(pb::CodedInputStream input) { uint tag; - while (input.ReadTag(out tag)) { + while ((tag = input.ReadTag()) != 0) { switch(tag) { - case 0: - throw pb::InvalidProtocolBufferException.InvalidTag(); default: - if (pb::WireFormat.IsEndGroupTag(tag)) { - return; - } + input.SkipLastField(); break; case 10: { Name = input.ReadString(); @@ -832,14 +824,10 @@ namespace Google.Protobuf.Reflection { public void MergeFrom(pb::CodedInputStream input) { uint tag; - while (input.ReadTag(out tag)) { + while ((tag = input.ReadTag()) != 0) { switch(tag) { - case 0: - throw pb::InvalidProtocolBufferException.InvalidTag(); default: - if (pb::WireFormat.IsEndGroupTag(tag)) { - return; - } + input.SkipLastField(); break; case 10: { Name = input.ReadString(); @@ -1000,14 +988,10 @@ namespace Google.Protobuf.Reflection { public void MergeFrom(pb::CodedInputStream input) { uint tag; - while (input.ReadTag(out tag)) { + while ((tag = input.ReadTag()) != 0) { switch(tag) { - case 0: - throw pb::InvalidProtocolBufferException.InvalidTag(); default: - if (pb::WireFormat.IsEndGroupTag(tag)) { - return; - } + input.SkipLastField(); break; case 8: { Start = input.ReadInt32(); @@ -1132,14 +1116,10 @@ namespace Google.Protobuf.Reflection { public void MergeFrom(pb::CodedInputStream input) { uint tag; - while (input.ReadTag(out tag)) { + while ((tag = input.ReadTag()) != 0) { switch(tag) { - case 0: - throw pb::InvalidProtocolBufferException.InvalidTag(); default: - if (pb::WireFormat.IsEndGroupTag(tag)) { - return; - } + input.SkipLastField(); break; case 8: { Start = input.ReadInt32(); @@ -1426,14 +1406,10 @@ namespace Google.Protobuf.Reflection { public void MergeFrom(pb::CodedInputStream input) { uint tag; - while (input.ReadTag(out tag)) { + while ((tag = input.ReadTag()) != 0) { switch(tag) { - case 0: - throw pb::InvalidProtocolBufferException.InvalidTag(); default: - if (pb::WireFormat.IsEndGroupTag(tag)) { - return; - } + input.SkipLastField(); break; case 10: { Name = input.ReadString(); @@ -1600,14 +1576,10 @@ namespace Google.Protobuf.Reflection { public void MergeFrom(pb::CodedInputStream input) { uint tag; - while (input.ReadTag(out tag)) { + while ((tag = input.ReadTag()) != 0) { switch(tag) { - case 0: - throw pb::InvalidProtocolBufferException.InvalidTag(); default: - if (pb::WireFormat.IsEndGroupTag(tag)) { - return; - } + input.SkipLastField(); break; case 10: { Name = input.ReadString(); @@ -1745,14 +1717,10 @@ namespace Google.Protobuf.Reflection { public void MergeFrom(pb::CodedInputStream input) { uint tag; - while (input.ReadTag(out tag)) { + while ((tag = input.ReadTag()) != 0) { switch(tag) { - case 0: - throw pb::InvalidProtocolBufferException.InvalidTag(); default: - if (pb::WireFormat.IsEndGroupTag(tag)) { - return; - } + input.SkipLastField(); break; case 10: { Name = input.ReadString(); @@ -1909,14 +1877,10 @@ namespace Google.Protobuf.Reflection { public void MergeFrom(pb::CodedInputStream input) { uint tag; - while (input.ReadTag(out tag)) { + while ((tag = input.ReadTag()) != 0) { switch(tag) { - case 0: - throw pb::InvalidProtocolBufferException.InvalidTag(); default: - if (pb::WireFormat.IsEndGroupTag(tag)) { - return; - } + input.SkipLastField(); break; case 10: { Name = input.ReadString(); @@ -2065,14 +2029,10 @@ namespace Google.Protobuf.Reflection { public void MergeFrom(pb::CodedInputStream input) { uint tag; - while (input.ReadTag(out tag)) { + while ((tag = input.ReadTag()) != 0) { switch(tag) { - case 0: - throw pb::InvalidProtocolBufferException.InvalidTag(); default: - if (pb::WireFormat.IsEndGroupTag(tag)) { - return; - } + input.SkipLastField(); break; case 10: { Name = input.ReadString(); @@ -2295,14 +2255,10 @@ namespace Google.Protobuf.Reflection { public void MergeFrom(pb::CodedInputStream input) { uint tag; - while (input.ReadTag(out tag)) { + while ((tag = input.ReadTag()) != 0) { switch(tag) { - case 0: - throw pb::InvalidProtocolBufferException.InvalidTag(); default: - if (pb::WireFormat.IsEndGroupTag(tag)) { - return; - } + input.SkipLastField(); break; case 10: { Name = input.ReadString(); @@ -2724,14 +2680,10 @@ namespace Google.Protobuf.Reflection { public void MergeFrom(pb::CodedInputStream input) { uint tag; - while (input.ReadTag(out tag)) { + while ((tag = input.ReadTag()) != 0) { switch(tag) { - case 0: - throw pb::InvalidProtocolBufferException.InvalidTag(); default: - if (pb::WireFormat.IsEndGroupTag(tag)) { - return; - } + input.SkipLastField(); break; case 10: { JavaPackage = input.ReadString(); @@ -2978,14 +2930,10 @@ namespace Google.Protobuf.Reflection { public void MergeFrom(pb::CodedInputStream input) { uint tag; - while (input.ReadTag(out tag)) { + while ((tag = input.ReadTag()) != 0) { switch(tag) { - case 0: - throw pb::InvalidProtocolBufferException.InvalidTag(); default: - if (pb::WireFormat.IsEndGroupTag(tag)) { - return; - } + input.SkipLastField(); break; case 8: { MessageSetWireFormat = input.ReadBool(); @@ -3224,14 +3172,10 @@ namespace Google.Protobuf.Reflection { public void MergeFrom(pb::CodedInputStream input) { uint tag; - while (input.ReadTag(out tag)) { + while ((tag = input.ReadTag()) != 0) { switch(tag) { - case 0: - throw pb::InvalidProtocolBufferException.InvalidTag(); default: - if (pb::WireFormat.IsEndGroupTag(tag)) { - return; - } + input.SkipLastField(); break; case 8: { ctype_ = (global::Google.Protobuf.Reflection.FieldOptions.Types.CType) input.ReadEnum(); @@ -3408,14 +3352,10 @@ namespace Google.Protobuf.Reflection { public void MergeFrom(pb::CodedInputStream input) { uint tag; - while (input.ReadTag(out tag)) { + while ((tag = input.ReadTag()) != 0) { switch(tag) { - case 0: - throw pb::InvalidProtocolBufferException.InvalidTag(); default: - if (pb::WireFormat.IsEndGroupTag(tag)) { - return; - } + input.SkipLastField(); break; case 16: { AllowAlias = input.ReadBool(); @@ -3536,14 +3476,10 @@ namespace Google.Protobuf.Reflection { public void MergeFrom(pb::CodedInputStream input) { uint tag; - while (input.ReadTag(out tag)) { + while ((tag = input.ReadTag()) != 0) { switch(tag) { - case 0: - throw pb::InvalidProtocolBufferException.InvalidTag(); default: - if (pb::WireFormat.IsEndGroupTag(tag)) { - return; - } + input.SkipLastField(); break; case 8: { Deprecated = input.ReadBool(); @@ -3660,14 +3596,10 @@ namespace Google.Protobuf.Reflection { public void MergeFrom(pb::CodedInputStream input) { uint tag; - while (input.ReadTag(out tag)) { + while ((tag = input.ReadTag()) != 0) { switch(tag) { - case 0: - throw pb::InvalidProtocolBufferException.InvalidTag(); default: - if (pb::WireFormat.IsEndGroupTag(tag)) { - return; - } + input.SkipLastField(); break; case 264: { Deprecated = input.ReadBool(); @@ -3784,14 +3716,10 @@ namespace Google.Protobuf.Reflection { public void MergeFrom(pb::CodedInputStream input) { uint tag; - while (input.ReadTag(out tag)) { + while ((tag = input.ReadTag()) != 0) { switch(tag) { - case 0: - throw pb::InvalidProtocolBufferException.InvalidTag(); default: - if (pb::WireFormat.IsEndGroupTag(tag)) { - return; - } + input.SkipLastField(); break; case 264: { Deprecated = input.ReadBool(); @@ -4018,14 +3946,10 @@ namespace Google.Protobuf.Reflection { public void MergeFrom(pb::CodedInputStream input) { uint tag; - while (input.ReadTag(out tag)) { + while ((tag = input.ReadTag()) != 0) { switch(tag) { - case 0: - throw pb::InvalidProtocolBufferException.InvalidTag(); default: - if (pb::WireFormat.IsEndGroupTag(tag)) { - return; - } + input.SkipLastField(); break; case 18: { name_.AddEntriesFrom(input, _repeated_name_codec); @@ -4171,14 +4095,10 @@ namespace Google.Protobuf.Reflection { public void MergeFrom(pb::CodedInputStream input) { uint tag; - while (input.ReadTag(out tag)) { + while ((tag = input.ReadTag()) != 0) { switch(tag) { - case 0: - throw pb::InvalidProtocolBufferException.InvalidTag(); default: - if (pb::WireFormat.IsEndGroupTag(tag)) { - return; - } + input.SkipLastField(); break; case 10: { NamePart_ = input.ReadString(); @@ -4278,14 +4198,10 @@ namespace Google.Protobuf.Reflection { public void MergeFrom(pb::CodedInputStream input) { uint tag; - while (input.ReadTag(out tag)) { + while ((tag = input.ReadTag()) != 0) { switch(tag) { - case 0: - throw pb::InvalidProtocolBufferException.InvalidTag(); default: - if (pb::WireFormat.IsEndGroupTag(tag)) { - return; - } + input.SkipLastField(); break; case 10: { location_.AddEntriesFrom(input, _repeated_location_codec); @@ -4449,14 +4365,10 @@ namespace Google.Protobuf.Reflection { public void MergeFrom(pb::CodedInputStream input) { uint tag; - while (input.ReadTag(out tag)) { + while ((tag = input.ReadTag()) != 0) { switch(tag) { - case 0: - throw pb::InvalidProtocolBufferException.InvalidTag(); default: - if (pb::WireFormat.IsEndGroupTag(tag)) { - return; - } + input.SkipLastField(); break; case 10: case 8: { diff --git a/csharp/src/Google.Protobuf/Reflection/EnumValueDescriptor.cs b/csharp/src/Google.Protobuf/Reflection/EnumValueDescriptor.cs index 29833c4a..b212ce96 100644 --- a/csharp/src/Google.Protobuf/Reflection/EnumValueDescriptor.cs +++ b/csharp/src/Google.Protobuf/Reflection/EnumValueDescriptor.cs @@ -51,11 +51,20 @@ namespace Google.Protobuf.Reflection } internal EnumValueDescriptorProto Proto { get { return proto; } } - + + /// <summary> + /// Returns the name of the enum value described by this object. + /// </summary> public override string Name { get { return proto.Name; } } + /// <summary> + /// Returns the number associated with this enum value. + /// </summary> public int Number { get { return Proto.Number; } } + /// <summary> + /// Returns the enum descriptor that this value is part of. + /// </summary> public EnumDescriptor EnumDescriptor { get { return enumDescriptor; } } } }
\ No newline at end of file diff --git a/csharp/src/Google.Protobuf/Reflection/FieldAccessorBase.cs b/csharp/src/Google.Protobuf/Reflection/FieldAccessorBase.cs index 3fccf884..82ce5051 100644 --- a/csharp/src/Google.Protobuf/Reflection/FieldAccessorBase.cs +++ b/csharp/src/Google.Protobuf/Reflection/FieldAccessorBase.cs @@ -41,23 +41,23 @@ namespace Google.Protobuf.Reflection /// </summary> internal abstract class FieldAccessorBase : IFieldAccessor { - private readonly Func<object, object> getValueDelegate; + private readonly Func<IMessage, object> getValueDelegate; private readonly FieldDescriptor descriptor; internal FieldAccessorBase(PropertyInfo property, FieldDescriptor descriptor) { this.descriptor = descriptor; - getValueDelegate = ReflectionUtil.CreateFuncObjectObject(property.GetGetMethod()); + getValueDelegate = ReflectionUtil.CreateFuncIMessageObject(property.GetGetMethod()); } public FieldDescriptor Descriptor { get { return descriptor; } } - public object GetValue(object message) + public object GetValue(IMessage message) { return getValueDelegate(message); } - public abstract void Clear(object message); - public abstract void SetValue(object message, object value); + public abstract void Clear(IMessage message); + public abstract void SetValue(IMessage message, object value); } } diff --git a/csharp/src/Google.Protobuf/Reflection/FieldDescriptor.cs b/csharp/src/Google.Protobuf/Reflection/FieldDescriptor.cs index 60f2bb8b..901cbf47 100644 --- a/csharp/src/Google.Protobuf/Reflection/FieldDescriptor.cs +++ b/csharp/src/Google.Protobuf/Reflection/FieldDescriptor.cs @@ -93,6 +93,15 @@ 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. + /// </summary> + /// <remarks> + /// 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. + /// </remarks> public IFieldAccessor Accessor { get { return accessor; } } /// <summary> @@ -141,43 +150,63 @@ namespace Google.Protobuf.Reflection default: throw new ArgumentException("Invalid type specified"); } - } + } + /// <summary> + /// Returns <c>true</c> if this field is a repeated field; <c>false</c> otherwise. + /// </summary> public bool IsRepeated { get { return Proto.Label == FieldDescriptorProto.Types.Label.LABEL_REPEATED; } } + /// <summary> + /// Returns <c>true</c> if this field is a map field; <c>false</c> otherwise. + /// </summary> public bool IsMap { get { return fieldType == FieldType.Message && messageType.Proto.Options != null && messageType.Proto.Options.MapEntry; } } + /// <summary> + /// Returns <c>true</c> if this field is a packed, repeated field; <c>false</c> otherwise. + /// </summary> public bool IsPacked { - get { return Proto.Options != null && Proto.Options.Packed; } + // Note the || rather than && here - we're effectively defaulting to packed, because that *is* + // the default in proto3, which is all we support. We may give the wrong result for the protos + // within descriptor.proto, but that's okay, as they're never exposed and we don't use IsPacked + // within the runtime. + get { return Proto.Options == null || Proto.Options.Packed; } } /// <summary> - /// Get the field's containing type. For extensions, this is the type being - /// extended, not the location where the extension was defined. See - /// <see cref="ExtensionScope" />. + /// Get the field's containing message type. /// </summary> public MessageDescriptor ContainingType { get { return containingType; } } + /// <summary> + /// Returns the oneof containing this field, or <c>null</c> if it is not part of a oneof. + /// </summary> public OneofDescriptor ContainingOneof { get { return containingOneof; } - } + } + /// <summary> + /// Returns the type of the field. + /// </summary> public FieldType FieldType { get { return fieldType; } } + /// <summary> + /// Returns the field number declared in the proto file. + /// </summary> public int FieldNumber { get { return Proto.Number; } diff --git a/csharp/src/Google.Protobuf/Reflection/FieldType.cs b/csharp/src/Google.Protobuf/Reflection/FieldType.cs index 41fa702d..1658e34c 100644 --- a/csharp/src/Google.Protobuf/Reflection/FieldType.cs +++ b/csharp/src/Google.Protobuf/Reflection/FieldType.cs @@ -33,28 +33,81 @@ namespace Google.Protobuf.Reflection { /// <summary> - /// Enumeration of all the possible field types. The odd formatting is to make it very clear - /// which attribute applies to which value, while maintaining a compact format. + /// Enumeration of all the possible field types. /// </summary> public enum FieldType { + /// <summary> + /// The <c>double</c> field type. + /// </summary> Double, + /// <summary> + /// The <c>float</c> field type. + /// </summary> Float, + /// <summary> + /// The <c>int64</c> field type. + /// </summary> Int64, + /// <summary> + /// The <c>uint64</c> field type. + /// </summary> UInt64, + /// <summary> + /// The <c>int32</c> field type. + /// </summary> Int32, + /// <summary> + /// The <c>fixed64</c> field type. + /// </summary> Fixed64, + /// <summary> + /// The <c>fixed32</c> field type. + /// </summary> Fixed32, + /// <summary> + /// The <c>bool</c> field type. + /// </summary> Bool, + /// <summary> + /// The <c>string</c> field type. + /// </summary> String, + /// <summary> + /// The field type used for groups (not supported in this implementation). + /// </summary> Group, + /// <summary> + /// The field type used for message fields. + /// </summary> Message, + /// <summary> + /// The <c>bytes</c> field type. + /// </summary> Bytes, + /// <summary> + /// The <c>uint32</c> field type. + /// </summary> UInt32, + /// <summary> + /// The <c>sfixed32</c> field type. + /// </summary> SFixed32, + /// <summary> + /// The <c>sfixed64</c> field type. + /// </summary> SFixed64, + /// <summary> + /// The <c>sint32</c> field type. + /// </summary> SInt32, + /// <summary> + /// The <c>sint64</c> field type. + /// </summary> SInt64, + /// <summary> + /// The field type used for enum fields. + /// </summary> Enum } }
\ No newline at end of file diff --git a/csharp/src/Google.Protobuf/Reflection/FileDescriptor.cs b/csharp/src/Google.Protobuf/Reflection/FileDescriptor.cs index c17c4cc4..500e467c 100644 --- a/csharp/src/Google.Protobuf/Reflection/FileDescriptor.cs +++ b/csharp/src/Google.Protobuf/Reflection/FileDescriptor.cs @@ -51,18 +51,7 @@ namespace Google.Protobuf.Reflection private readonly IList<FileDescriptor> dependencies; private readonly IList<FileDescriptor> publicDependencies; private readonly DescriptorPool pool; - - public enum ProtoSyntax - { - Proto2, - Proto3 - } - - public ProtoSyntax Syntax - { - get { return proto.Syntax == "proto3" ? ProtoSyntax.Proto3 : ProtoSyntax.Proto2; } - } - + private FileDescriptor(ByteString descriptorData, FileDescriptorProto proto, FileDescriptor[] dependencies, DescriptorPool pool, bool allowUnknownDependencies, GeneratedCodeInfo generatedCodeInfo) { this.descriptorData = descriptorData; @@ -298,23 +287,23 @@ namespace Google.Protobuf.Reflection DescriptorPool pool = new DescriptorPool(dependencies); FileDescriptor result = new FileDescriptor(descriptorData, proto, dependencies, pool, allowUnknownDependencies, generatedCodeInfo); - // TODO(jonskeet): Reinstate these checks, or get rid of them entirely. They aren't in the Java code, - // and fail for the CustomOptions test right now. (We get "descriptor.proto" vs "google/protobuf/descriptor.proto".) - //if (dependencies.Length != proto.DependencyCount) - //{ - // throw new DescriptorValidationException(result, - // "Dependencies passed to FileDescriptor.BuildFrom() don't match " + - // "those listed in the FileDescriptorProto."); - //} - //for (int i = 0; i < proto.DependencyCount; i++) - //{ - // if (dependencies[i].Name != proto.DependencyList[i]) - // { - // throw new DescriptorValidationException(result, - // "Dependencies passed to FileDescriptor.BuildFrom() don't match " + - // "those listed in the FileDescriptorProto."); - // } - //} + // Validate that the dependencies we've been passed (as FileDescriptors) are actually the ones we + // need. + if (dependencies.Length != proto.Dependency.Count) + { + 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, + "Dependencies passed to FileDescriptor.BuildFrom() don't match " + + "those listed in the FileDescriptorProto."); + } + } result.CrossLink(); return result; @@ -368,7 +357,13 @@ namespace Google.Protobuf.Reflection throw new ArgumentException("Invalid embedded descriptor for \"" + proto.Name + "\".", e); } } - + + /// <summary> + /// Returns a <see cref="System.String" /> that represents this instance. + /// </summary> + /// <returns> + /// A <see cref="System.String" /> that represents this instance. + /// </returns> public override string ToString() { return "FileDescriptor for " + proto.Name; diff --git a/csharp/src/Google.Protobuf/Reflection/IDescriptor.cs b/csharp/src/Google.Protobuf/Reflection/IDescriptor.cs index 6506db1b..318d58c9 100644 --- a/csharp/src/Google.Protobuf/Reflection/IDescriptor.cs +++ b/csharp/src/Google.Protobuf/Reflection/IDescriptor.cs @@ -37,8 +37,19 @@ namespace Google.Protobuf.Reflection /// </summary> public interface IDescriptor { + /// <summary> + /// Returns the name of the entity (message, field etc) being described. + /// </summary> string Name { get; } + + /// <summary> + /// Returns the fully-qualified name of the entity being described. + /// </summary> string FullName { get; } + + /// <summary> + /// Returns the descriptor for the .proto file that this entity is part of. + /// </summary> FileDescriptor File { get; } } }
\ No newline at end of file diff --git a/csharp/src/Google.Protobuf/Reflection/IFieldAccessor.cs b/csharp/src/Google.Protobuf/Reflection/IFieldAccessor.cs index 3f4f05f4..cfe56fde 100644 --- a/csharp/src/Google.Protobuf/Reflection/IFieldAccessor.cs +++ b/csharp/src/Google.Protobuf/Reflection/IFieldAccessor.cs @@ -30,6 +30,9 @@ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion +using System; +using System.Collections; + namespace Google.Protobuf.Reflection { /// <summary> @@ -42,20 +45,18 @@ namespace Google.Protobuf.Reflection /// </summary> FieldDescriptor Descriptor { get; } - // TODO: Should the argument type for these messages be IReflectedMessage? - /// <summary> /// Clears the field in the specified message. (For repeated fields, /// this clears the list.) /// </summary> - void Clear(object message); + void Clear(IMessage message); /// <summary> /// Fetches the field value. For repeated values, this will be an /// <see cref="IList"/> implementation. For map values, this will be an /// <see cref="IDictionary"/> implementation. /// </summary> - object GetValue(object message); + object GetValue(IMessage message); /// <summary> /// Mutator for single "simple" fields only. @@ -64,7 +65,7 @@ namespace Google.Protobuf.Reflection /// Repeated fields are mutated by fetching the value and manipulating it as a list. /// Map fields are mutated by fetching the value and manipulating it as a dictionary. /// </remarks> - /// <exception cref="InvalidOperationException">The field is not a "simple" field, or the message is frozen.</exception> - void SetValue(object message, object value); + /// <exception cref="InvalidOperationException">The field is not a "simple" field.</exception> + void SetValue(IMessage message, object value); } }
\ No newline at end of file diff --git a/csharp/src/Google.Protobuf/Reflection/MapFieldAccessor.cs b/csharp/src/Google.Protobuf/Reflection/MapFieldAccessor.cs index 6df4c5f0..9ed7f8c4 100644 --- a/csharp/src/Google.Protobuf/Reflection/MapFieldAccessor.cs +++ b/csharp/src/Google.Protobuf/Reflection/MapFieldAccessor.cs @@ -45,13 +45,13 @@ namespace Google.Protobuf.Reflection { } - public override void Clear(object message) + public override void Clear(IMessage message) { IDictionary list = (IDictionary) GetValue(message); list.Clear(); } - public override void SetValue(object message, object value) + public override void SetValue(IMessage message, object value) { throw new InvalidOperationException("SetValue is not implemented for map fields"); } diff --git a/csharp/src/Google.Protobuf/Reflection/MessageDescriptor.cs b/csharp/src/Google.Protobuf/Reflection/MessageDescriptor.cs index 1250774d..82901f1b 100644 --- a/csharp/src/Google.Protobuf/Reflection/MessageDescriptor.cs +++ b/csharp/src/Google.Protobuf/Reflection/MessageDescriptor.cs @@ -30,7 +30,6 @@ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion -using Google.Protobuf.Collections; using System; using System.Collections.Generic; using System.Collections.ObjectModel; @@ -163,6 +162,9 @@ namespace Google.Protobuf.Reflection get { return enumTypes; } } + /// <value> + /// An unmodifiable list of the "oneof" field collections in this message type. + /// </value> public IList<OneofDescriptor> Oneofs { get { return oneofs; } @@ -250,7 +252,7 @@ namespace Google.Protobuf.Reflection /// </value> public IList<FieldDescriptor> InFieldNumberOrder() { - return messageDescriptor.fieldsInDeclarationOrder; + return messageDescriptor.fieldsInNumberOrder; } /// <summary> @@ -276,7 +278,7 @@ namespace Google.Protobuf.Reflection /// <summary> /// Retrieves the descriptor for the field with the given name. /// </summary> - /// <param name="number">Number of the field to retrieve the descriptor for</param> + /// <param name="name">Name of the field to retrieve the descriptor for</param> /// <returns>The descriptor for the given field</returns> /// <exception cref="KeyNotFoundException">The message descriptor does not contain a field /// with the given name</exception> diff --git a/csharp/src/Google.Protobuf/Reflection/OneofAccessor.cs b/csharp/src/Google.Protobuf/Reflection/OneofAccessor.cs index 8631a1c5..8714ab18 100644 --- a/csharp/src/Google.Protobuf/Reflection/OneofAccessor.cs +++ b/csharp/src/Google.Protobuf/Reflection/OneofAccessor.cs @@ -41,8 +41,8 @@ namespace Google.Protobuf.Reflection /// </summary> public sealed class OneofAccessor { - private readonly Func<object, int> caseDelegate; - private readonly Action<object> clearDelegate; + private readonly Func<IMessage, int> caseDelegate; + private readonly Action<IMessage> clearDelegate; private OneofDescriptor descriptor; internal OneofAccessor(PropertyInfo caseProperty, MethodInfo clearMethod, OneofDescriptor descriptor) @@ -52,18 +52,24 @@ namespace Google.Protobuf.Reflection throw new ArgumentException("Cannot read from property"); } this.descriptor = descriptor; - caseDelegate = ReflectionUtil.CreateFuncObjectT<int>(caseProperty.GetGetMethod()); + caseDelegate = ReflectionUtil.CreateFuncIMessageT<int>(caseProperty.GetGetMethod()); this.descriptor = descriptor; - clearDelegate = ReflectionUtil.CreateActionObject(clearMethod); + clearDelegate = ReflectionUtil.CreateActionIMessage(clearMethod); } + /// <summary> + /// Gets the descriptor for this oneof. + /// </summary> + /// <value> + /// The descriptor of the oneof. + /// </value> public OneofDescriptor Descriptor { get { return descriptor; } } /// <summary> /// Clears the oneof in the specified message. /// </summary> - public void Clear(object message) + public void Clear(IMessage message) { clearDelegate(message); } @@ -71,7 +77,7 @@ namespace Google.Protobuf.Reflection /// <summary> /// Indicates which field in the oneof is set for specified message /// </summary> - public FieldDescriptor GetCaseFieldDescriptor(object message) + public FieldDescriptor GetCaseFieldDescriptor(IMessage message) { int fieldNumber = caseDelegate(message); if (fieldNumber > 0) diff --git a/csharp/src/Google.Protobuf/Reflection/OneofDescriptor.cs b/csharp/src/Google.Protobuf/Reflection/OneofDescriptor.cs index 8571a5eb..d51ee526 100644 --- a/csharp/src/Google.Protobuf/Reflection/OneofDescriptor.cs +++ b/csharp/src/Google.Protobuf/Reflection/OneofDescriptor.cs @@ -32,11 +32,14 @@ using System.Collections.Generic; using System.Collections.ObjectModel; -using System.Linq; using Google.Protobuf.Compatibility; namespace Google.Protobuf.Reflection { + /// <summary> + /// Describes a "oneof" field collection in a message type: a set of + /// fields of which at most one can be set in any particular message. + /// </summary> public sealed class OneofDescriptor : DescriptorBase { private readonly OneofDescriptorProto proto; @@ -59,13 +62,33 @@ namespace Google.Protobuf.Reflection /// </summary> public override string Name { get { return proto.Name; } } + /// <summary> + /// Gets the message type containing this oneof. + /// </summary> + /// <value> + /// The message type containing this oneof. + /// </value> public MessageDescriptor ContainingType { get { return containingType; } } + /// <summary> + /// Gets the fields within this oneof, in declaration order. + /// </summary> + /// <value> + /// The fields within this oneof, in declaration order. + /// </value> public IList<FieldDescriptor> Fields { get { return fields; } } + /// <summary> + /// Gets an accessor for reflective access to the values associated with the oneof + /// in a particular message. + /// </summary> + /// <value> + /// The accessor used for reflective access, or <c>null</c> if reflection is not + /// supported by this descriptor. + /// </value> public OneofAccessor Accessor { get { return accessor; } } internal void CrossLink() diff --git a/csharp/src/Google.Protobuf/Reflection/PartialClasses.cs b/csharp/src/Google.Protobuf/Reflection/PartialClasses.cs index c7ed4342..8c055d6d 100644 --- a/csharp/src/Google.Protobuf/Reflection/PartialClasses.cs +++ b/csharp/src/Google.Protobuf/Reflection/PartialClasses.cs @@ -44,4 +44,16 @@ namespace Google.Protobuf.Reflection OneofIndex = -1;
}
}
+
+ internal partial class FieldOptions
+ {
+ // We can't tell the difference between "explicitly set to false" and "not set"
+ // in proto3, but we need to tell the difference for FieldDescriptor.IsPacked.
+ // This won't work if we ever need to support proto2, but at that point we'll be
+ // able to remove this hack and use field presence instead.
+ partial void OnConstruction()
+ {
+ Packed = true;
+ }
+ }
}
\ No newline at end of file diff --git a/csharp/src/Google.Protobuf/Reflection/ReflectionUtil.cs b/csharp/src/Google.Protobuf/Reflection/ReflectionUtil.cs index 5b3cbb36..df820ca3 100644 --- a/csharp/src/Google.Protobuf/Reflection/ReflectionUtil.cs +++ b/csharp/src/Google.Protobuf/Reflection/ReflectionUtil.cs @@ -56,52 +56,52 @@ namespace Google.Protobuf.Reflection /// Creates a delegate which will cast the argument to the appropriate method target type, /// call the method on it, then convert the result to object. /// </summary> - internal static Func<object, object> CreateFuncObjectObject(MethodInfo method) + internal static Func<IMessage, object> CreateFuncIMessageObject(MethodInfo method) { - ParameterExpression parameter = Expression.Parameter(typeof(object), "p"); + ParameterExpression parameter = Expression.Parameter(typeof(IMessage), "p"); Expression downcast = Expression.Convert(parameter, method.DeclaringType); Expression call = Expression.Call(downcast, method); Expression upcast = Expression.Convert(call, typeof(object)); - return Expression.Lambda<Func<object, object>>(upcast, parameter).Compile(); + return Expression.Lambda<Func<IMessage, object>>(upcast, parameter).Compile(); } /// <summary> /// Creates a delegate which will cast the argument to the appropriate method target type, /// call the method on it, then convert the result to the specified type. /// </summary> - internal static Func<object, T> CreateFuncObjectT<T>(MethodInfo method) + internal static Func<IMessage, T> CreateFuncIMessageT<T>(MethodInfo method) { - ParameterExpression parameter = Expression.Parameter(typeof(object), "p"); + ParameterExpression parameter = Expression.Parameter(typeof(IMessage), "p"); Expression downcast = Expression.Convert(parameter, method.DeclaringType); Expression call = Expression.Call(downcast, method); Expression upcast = Expression.Convert(call, typeof(T)); - return Expression.Lambda<Func<object, T>>(upcast, parameter).Compile(); + return Expression.Lambda<Func<IMessage, T>>(upcast, parameter).Compile(); } /// <summary> /// Creates a delegate which will execute the given method after casting the first argument to /// the target type of the method, and the second argument to the first parameter type of the method. /// </summary> - internal static Action<object, object> CreateActionObjectObject(MethodInfo method) + internal static Action<IMessage, object> CreateActionIMessageObject(MethodInfo method) { - ParameterExpression targetParameter = Expression.Parameter(typeof(object), "target"); + ParameterExpression targetParameter = Expression.Parameter(typeof(IMessage), "target"); ParameterExpression argParameter = Expression.Parameter(typeof(object), "arg"); Expression castTarget = Expression.Convert(targetParameter, method.DeclaringType); Expression castArgument = Expression.Convert(argParameter, method.GetParameters()[0].ParameterType); Expression call = Expression.Call(castTarget, method, castArgument); - return Expression.Lambda<Action<object, object>>(call, targetParameter, argParameter).Compile(); + return Expression.Lambda<Action<IMessage, object>>(call, targetParameter, argParameter).Compile(); } /// <summary> /// Creates a delegate which will execute the given method after casting the first argument to /// the target type of the method. /// </summary> - internal static Action<object> CreateActionObject(MethodInfo method) + internal static Action<IMessage> CreateActionIMessage(MethodInfo method) { - ParameterExpression targetParameter = Expression.Parameter(typeof(object), "target"); + ParameterExpression targetParameter = Expression.Parameter(typeof(IMessage), "target"); Expression castTarget = Expression.Convert(targetParameter, method.DeclaringType); Expression call = Expression.Call(castTarget, method); - return Expression.Lambda<Action<object>>(call, targetParameter).Compile(); + return Expression.Lambda<Action<IMessage>>(call, targetParameter).Compile(); } } }
\ No newline at end of file diff --git a/csharp/src/Google.Protobuf/Reflection/RepeatedFieldAccessor.cs b/csharp/src/Google.Protobuf/Reflection/RepeatedFieldAccessor.cs index acb3c8d5..bd408470 100644 --- a/csharp/src/Google.Protobuf/Reflection/RepeatedFieldAccessor.cs +++ b/csharp/src/Google.Protobuf/Reflection/RepeatedFieldAccessor.cs @@ -45,13 +45,13 @@ namespace Google.Protobuf.Reflection { } - public override void Clear(object message) + public override void Clear(IMessage message) { IList list = (IList) GetValue(message); list.Clear(); } - public override void SetValue(object message, object value) + public override void SetValue(IMessage message, object value) { throw new InvalidOperationException("SetValue is not implemented for repeated fields"); } diff --git a/csharp/src/Google.Protobuf/Reflection/SingleFieldAccessor.cs b/csharp/src/Google.Protobuf/Reflection/SingleFieldAccessor.cs index 851efc26..de92fbc1 100644 --- a/csharp/src/Google.Protobuf/Reflection/SingleFieldAccessor.cs +++ b/csharp/src/Google.Protobuf/Reflection/SingleFieldAccessor.cs @@ -46,8 +46,8 @@ namespace Google.Protobuf.Reflection // and proto2 vs proto3 for non-message types, as proto3 doesn't support "full" presence detection or default // values. - private readonly Action<object, object> setValueDelegate; - private readonly Action<object> clearDelegate; + private readonly Action<IMessage, object> setValueDelegate; + private readonly Action<IMessage> clearDelegate; internal SingleFieldAccessor(PropertyInfo property, FieldDescriptor descriptor) : base(property, descriptor) { @@ -55,12 +55,10 @@ namespace Google.Protobuf.Reflection { throw new ArgumentException("Not all required properties/methods available"); } - setValueDelegate = ReflectionUtil.CreateActionObjectObject(property.GetSetMethod()); + setValueDelegate = ReflectionUtil.CreateActionIMessageObject(property.GetSetMethod()); var clrType = property.PropertyType; - // TODO: What should clear on a oneof member do? Clear the oneof? - // TODO: Validate that this is a reasonable single field? (Should be a value type, a message type, or string/ByteString.) object defaultValue = typeof(IMessage).IsAssignableFrom(clrType) ? null @@ -70,12 +68,12 @@ namespace Google.Protobuf.Reflection clearDelegate = message => SetValue(message, defaultValue); } - public override void Clear(object message) + public override void Clear(IMessage message) { clearDelegate(message); } - public override void SetValue(object message, object value) + public override void SetValue(IMessage message, object value) { setValueDelegate(message, value); } diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/Any.cs b/csharp/src/Google.Protobuf/WellKnownTypes/Any.cs index 93395871..204b37cf 100644 --- a/csharp/src/Google.Protobuf/WellKnownTypes/Any.cs +++ b/csharp/src/Google.Protobuf/WellKnownTypes/Any.cs @@ -147,14 +147,10 @@ namespace Google.Protobuf.WellKnownTypes { public void MergeFrom(pb::CodedInputStream input) { uint tag; - while (input.ReadTag(out tag)) { + while ((tag = input.ReadTag()) != 0) { switch(tag) { - case 0: - throw pb::InvalidProtocolBufferException.InvalidTag(); default: - if (pb::WireFormat.IsEndGroupTag(tag)) { - return; - } + input.SkipLastField(); break; case 10: { TypeUrl = input.ReadString(); diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/Api.cs b/csharp/src/Google.Protobuf/WellKnownTypes/Api.cs index 366bba21..a5f95093 100644 --- a/csharp/src/Google.Protobuf/WellKnownTypes/Api.cs +++ b/csharp/src/Google.Protobuf/WellKnownTypes/Api.cs @@ -210,14 +210,10 @@ namespace Google.Protobuf.WellKnownTypes { public void MergeFrom(pb::CodedInputStream input) { uint tag; - while (input.ReadTag(out tag)) { + while ((tag = input.ReadTag()) != 0) { switch(tag) { - case 0: - throw pb::InvalidProtocolBufferException.InvalidTag(); default: - if (pb::WireFormat.IsEndGroupTag(tag)) { - return; - } + input.SkipLastField(); break; case 10: { Name = input.ReadString(); @@ -437,14 +433,10 @@ namespace Google.Protobuf.WellKnownTypes { public void MergeFrom(pb::CodedInputStream input) { uint tag; - while (input.ReadTag(out tag)) { + while ((tag = input.ReadTag()) != 0) { switch(tag) { - case 0: - throw pb::InvalidProtocolBufferException.InvalidTag(); default: - if (pb::WireFormat.IsEndGroupTag(tag)) { - return; - } + input.SkipLastField(); break; case 10: { Name = input.ReadString(); diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/Duration.cs b/csharp/src/Google.Protobuf/WellKnownTypes/Duration.cs index 26c8d2b6..aa34f2d8 100644 --- a/csharp/src/Google.Protobuf/WellKnownTypes/Duration.cs +++ b/csharp/src/Google.Protobuf/WellKnownTypes/Duration.cs @@ -148,14 +148,10 @@ namespace Google.Protobuf.WellKnownTypes { public void MergeFrom(pb::CodedInputStream input) { uint tag; - while (input.ReadTag(out tag)) { + while ((tag = input.ReadTag()) != 0) { switch(tag) { - case 0: - throw pb::InvalidProtocolBufferException.InvalidTag(); default: - if (pb::WireFormat.IsEndGroupTag(tag)) { - return; - } + input.SkipLastField(); break; case 8: { Seconds = input.ReadInt64(); diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/DurationPartial.cs b/csharp/src/Google.Protobuf/WellKnownTypes/DurationPartial.cs index c69d1b23..18ebefd2 100644 --- a/csharp/src/Google.Protobuf/WellKnownTypes/DurationPartial.cs +++ b/csharp/src/Google.Protobuf/WellKnownTypes/DurationPartial.cs @@ -38,7 +38,13 @@ namespace Google.Protobuf.WellKnownTypes // providing a conversion to TimeSpan and convenience operators. public partial class Duration { + /// <summary> + /// The number of nanoseconds in a second. + /// </summary> public const int NanosecondsPerSecond = 1000000000; + /// <summary> + /// The number of nanoseconds in a BCL tick (as used by <see cref="TimeSpan"/> and <see cref="DateTime"/>). + /// </summary> public const int NanosecondsPerTick = 100; /// <summary> diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/Empty.cs b/csharp/src/Google.Protobuf/WellKnownTypes/Empty.cs index e14992f4..7d699c1d 100644 --- a/csharp/src/Google.Protobuf/WellKnownTypes/Empty.cs +++ b/csharp/src/Google.Protobuf/WellKnownTypes/Empty.cs @@ -103,14 +103,10 @@ namespace Google.Protobuf.WellKnownTypes { public void MergeFrom(pb::CodedInputStream input) { uint tag; - while (input.ReadTag(out tag)) { + while ((tag = input.ReadTag()) != 0) { switch(tag) { - case 0: - throw pb::InvalidProtocolBufferException.InvalidTag(); default: - if (pb::WireFormat.IsEndGroupTag(tag)) { - return; - } + input.SkipLastField(); break; } } diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/FieldMask.cs b/csharp/src/Google.Protobuf/WellKnownTypes/FieldMask.cs index 45ef9859..0dac4403 100644 --- a/csharp/src/Google.Protobuf/WellKnownTypes/FieldMask.cs +++ b/csharp/src/Google.Protobuf/WellKnownTypes/FieldMask.cs @@ -117,14 +117,10 @@ namespace Google.Protobuf.WellKnownTypes { public void MergeFrom(pb::CodedInputStream input) { uint tag; - while (input.ReadTag(out tag)) { + while ((tag = input.ReadTag()) != 0) { switch(tag) { - case 0: - throw pb::InvalidProtocolBufferException.InvalidTag(); default: - if (pb::WireFormat.IsEndGroupTag(tag)) { - return; - } + input.SkipLastField(); break; case 10: { paths_.AddEntriesFrom(input, _repeated_paths_codec); diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/SourceContext.cs b/csharp/src/Google.Protobuf/WellKnownTypes/SourceContext.cs index 04fb6350..8347999d 100644 --- a/csharp/src/Google.Protobuf/WellKnownTypes/SourceContext.cs +++ b/csharp/src/Google.Protobuf/WellKnownTypes/SourceContext.cs @@ -126,14 +126,10 @@ namespace Google.Protobuf.WellKnownTypes { public void MergeFrom(pb::CodedInputStream input) { uint tag; - while (input.ReadTag(out tag)) { + while ((tag = input.ReadTag()) != 0) { switch(tag) { - case 0: - throw pb::InvalidProtocolBufferException.InvalidTag(); default: - if (pb::WireFormat.IsEndGroupTag(tag)) { - return; - } + input.SkipLastField(); break; case 10: { FileName = input.ReadString(); diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/Struct.cs b/csharp/src/Google.Protobuf/WellKnownTypes/Struct.cs index 15dd6dcd..1e8a8236 100644 --- a/csharp/src/Google.Protobuf/WellKnownTypes/Struct.cs +++ b/csharp/src/Google.Protobuf/WellKnownTypes/Struct.cs @@ -136,14 +136,10 @@ namespace Google.Protobuf.WellKnownTypes { public void MergeFrom(pb::CodedInputStream input) { uint tag; - while (input.ReadTag(out tag)) { + while ((tag = input.ReadTag()) != 0) { switch(tag) { - case 0: - throw pb::InvalidProtocolBufferException.InvalidTag(); default: - if (pb::WireFormat.IsEndGroupTag(tag)) { - return; - } + input.SkipLastField(); break; case 10: { fields_.AddEntriesFrom(input, _map_fields_codec); @@ -390,14 +386,10 @@ namespace Google.Protobuf.WellKnownTypes { public void MergeFrom(pb::CodedInputStream input) { uint tag; - while (input.ReadTag(out tag)) { + while ((tag = input.ReadTag()) != 0) { switch(tag) { - case 0: - throw pb::InvalidProtocolBufferException.InvalidTag(); default: - if (pb::WireFormat.IsEndGroupTag(tag)) { - return; - } + input.SkipLastField(); break; case 8: { kind_ = input.ReadEnum(); @@ -519,14 +511,10 @@ namespace Google.Protobuf.WellKnownTypes { public void MergeFrom(pb::CodedInputStream input) { uint tag; - while (input.ReadTag(out tag)) { + while ((tag = input.ReadTag()) != 0) { switch(tag) { - case 0: - throw pb::InvalidProtocolBufferException.InvalidTag(); default: - if (pb::WireFormat.IsEndGroupTag(tag)) { - return; - } + input.SkipLastField(); break; case 10: { values_.AddEntriesFrom(input, _repeated_values_codec); diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/TimeExtensions.cs b/csharp/src/Google.Protobuf/WellKnownTypes/TimeExtensions.cs index a3806b5c..dd485d32 100644 --- a/csharp/src/Google.Protobuf/WellKnownTypes/TimeExtensions.cs +++ b/csharp/src/Google.Protobuf/WellKnownTypes/TimeExtensions.cs @@ -43,16 +43,35 @@ namespace Google.Protobuf.WellKnownTypes /// </summary> public static class TimeExtensions { + /// <summary> + /// Converts the given <see cref="DateTime"/> to a <see cref="Timestamp"/>. + /// </summary> + /// <param name="dateTime">The date and time to convert to a timestamp.</param> + /// <exception cref="ArgumentException">The <paramref name="dateTime"/> value has a <see cref="DateTime.Kind"/>other than <c>Utc</c>.</exception> + /// <returns>The converted timestamp.</returns> public static Timestamp ToTimestamp(this DateTime dateTime) { return Timestamp.FromDateTime(dateTime); } + /// <summary> + /// Converts the given <see cref="DateTimeOffset"/> to a <see cref="Timestamp"/> + /// </summary> + /// <remarks>The offset is taken into consideration when converting the value (so the same instant in time + /// is represented) but is not a separate part of the resulting value. In other words, there is no + /// roundtrip operation to retrieve the original <c>DateTimeOffset</c>.</remarks> + /// <param name="dateTimeOffset">The date and time (with UTC offset) to convert to a timestamp.</param> + /// <returns>The converted timestamp.</returns> public static Timestamp ToTimestamp(this DateTimeOffset dateTimeOffset) { return Timestamp.FromDateTimeOffset(dateTimeOffset); } + /// <summary> + /// Converts the given <see cref="TimeSpan"/> to a <see cref="Duration"/>. + /// </summary> + /// <param name="timeSpan">The time span to convert.</param> + /// <returns>The converted duration.</returns> public static Duration ToDuration(this TimeSpan timeSpan) { return Duration.FromTimeSpan(timeSpan); diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/Timestamp.cs b/csharp/src/Google.Protobuf/WellKnownTypes/Timestamp.cs index 3c42068a..d7c0954f 100644 --- a/csharp/src/Google.Protobuf/WellKnownTypes/Timestamp.cs +++ b/csharp/src/Google.Protobuf/WellKnownTypes/Timestamp.cs @@ -148,14 +148,10 @@ namespace Google.Protobuf.WellKnownTypes { public void MergeFrom(pb::CodedInputStream input) { uint tag; - while (input.ReadTag(out tag)) { + while ((tag = input.ReadTag()) != 0) { switch(tag) { - case 0: - throw pb::InvalidProtocolBufferException.InvalidTag(); default: - if (pb::WireFormat.IsEndGroupTag(tag)) { - return; - } + input.SkipLastField(); break; case 8: { Seconds = input.ReadInt64(); diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/TimestampPartial.cs b/csharp/src/Google.Protobuf/WellKnownTypes/TimestampPartial.cs index f682d093..68584358 100644 --- a/csharp/src/Google.Protobuf/WellKnownTypes/TimestampPartial.cs +++ b/csharp/src/Google.Protobuf/WellKnownTypes/TimestampPartial.cs @@ -136,9 +136,12 @@ namespace Google.Protobuf.WellKnownTypes } /// <summary> - /// Converts the specified <see cref="DateTimeOffset"/> to a <see cref="Timestamp"/>. + /// Converts the given <see cref="DateTimeOffset"/> to a <see cref="Timestamp"/> /// </summary> - /// <param name="dateTime"></param> + /// <remarks>The offset is taken into consideration when converting the value (so the same instant in time + /// is represented) but is not a separate part of the resulting value. In other words, there is no + /// roundtrip operation to retrieve the original <c>DateTimeOffset</c>.</remarks> + /// <param name="dateTimeOffset">The date and time (with UTC offset) to convert to a timestamp.</param> /// <returns>The converted timestamp.</returns> public static Timestamp FromDateTimeOffset(DateTimeOffset dateTimeOffset) { @@ -147,7 +150,7 @@ namespace Google.Protobuf.WellKnownTypes return FromDateTime(dateTimeOffset.UtcDateTime); } - private static Timestamp Normalize(long seconds, int nanoseconds) + internal static Timestamp Normalize(long seconds, int nanoseconds) { int extraSeconds = nanoseconds / Duration.NanosecondsPerSecond; seconds += extraSeconds; diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/Type.cs b/csharp/src/Google.Protobuf/WellKnownTypes/Type.cs index 64142934..ff2ecc57 100644 --- a/csharp/src/Google.Protobuf/WellKnownTypes/Type.cs +++ b/csharp/src/Google.Protobuf/WellKnownTypes/Type.cs @@ -223,14 +223,10 @@ namespace Google.Protobuf.WellKnownTypes { public void MergeFrom(pb::CodedInputStream input) { uint tag; - while (input.ReadTag(out tag)) { + while ((tag = input.ReadTag()) != 0) { switch(tag) { - case 0: - throw pb::InvalidProtocolBufferException.InvalidTag(); default: - if (pb::WireFormat.IsEndGroupTag(tag)) { - return; - } + input.SkipLastField(); break; case 10: { Name = input.ReadString(); @@ -494,14 +490,10 @@ namespace Google.Protobuf.WellKnownTypes { public void MergeFrom(pb::CodedInputStream input) { uint tag; - while (input.ReadTag(out tag)) { + while ((tag = input.ReadTag()) != 0) { switch(tag) { - case 0: - throw pb::InvalidProtocolBufferException.InvalidTag(); default: - if (pb::WireFormat.IsEndGroupTag(tag)) { - return; - } + input.SkipLastField(); break; case 8: { kind_ = (global::Google.Protobuf.WellKnownTypes.Field.Types.Kind) input.ReadEnum(); @@ -715,14 +707,10 @@ namespace Google.Protobuf.WellKnownTypes { public void MergeFrom(pb::CodedInputStream input) { uint tag; - while (input.ReadTag(out tag)) { + while ((tag = input.ReadTag()) != 0) { switch(tag) { - case 0: - throw pb::InvalidProtocolBufferException.InvalidTag(); default: - if (pb::WireFormat.IsEndGroupTag(tag)) { - return; - } + input.SkipLastField(); break; case 10: { Name = input.ReadString(); @@ -872,14 +860,10 @@ namespace Google.Protobuf.WellKnownTypes { public void MergeFrom(pb::CodedInputStream input) { uint tag; - while (input.ReadTag(out tag)) { + while ((tag = input.ReadTag()) != 0) { switch(tag) { - case 0: - throw pb::InvalidProtocolBufferException.InvalidTag(); default: - if (pb::WireFormat.IsEndGroupTag(tag)) { - return; - } + input.SkipLastField(); break; case 10: { Name = input.ReadString(); @@ -1011,14 +995,10 @@ namespace Google.Protobuf.WellKnownTypes { public void MergeFrom(pb::CodedInputStream input) { uint tag; - while (input.ReadTag(out tag)) { + while ((tag = input.ReadTag()) != 0) { switch(tag) { - case 0: - throw pb::InvalidProtocolBufferException.InvalidTag(); default: - if (pb::WireFormat.IsEndGroupTag(tag)) { - return; - } + input.SkipLastField(); break; case 10: { Name = input.ReadString(); diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/Wrappers.cs b/csharp/src/Google.Protobuf/WellKnownTypes/Wrappers.cs index c9dd6ea6..9ecaf47c 100644 --- a/csharp/src/Google.Protobuf/WellKnownTypes/Wrappers.cs +++ b/csharp/src/Google.Protobuf/WellKnownTypes/Wrappers.cs @@ -135,14 +135,10 @@ namespace Google.Protobuf.WellKnownTypes { public void MergeFrom(pb::CodedInputStream input) { uint tag; - while (input.ReadTag(out tag)) { + while ((tag = input.ReadTag()) != 0) { switch(tag) { - case 0: - throw pb::InvalidProtocolBufferException.InvalidTag(); default: - if (pb::WireFormat.IsEndGroupTag(tag)) { - return; - } + input.SkipLastField(); break; case 9: { Value = input.ReadDouble(); @@ -241,14 +237,10 @@ namespace Google.Protobuf.WellKnownTypes { public void MergeFrom(pb::CodedInputStream input) { uint tag; - while (input.ReadTag(out tag)) { + while ((tag = input.ReadTag()) != 0) { switch(tag) { - case 0: - throw pb::InvalidProtocolBufferException.InvalidTag(); default: - if (pb::WireFormat.IsEndGroupTag(tag)) { - return; - } + input.SkipLastField(); break; case 13: { Value = input.ReadFloat(); @@ -347,14 +339,10 @@ namespace Google.Protobuf.WellKnownTypes { public void MergeFrom(pb::CodedInputStream input) { uint tag; - while (input.ReadTag(out tag)) { + while ((tag = input.ReadTag()) != 0) { switch(tag) { - case 0: - throw pb::InvalidProtocolBufferException.InvalidTag(); default: - if (pb::WireFormat.IsEndGroupTag(tag)) { - return; - } + input.SkipLastField(); break; case 8: { Value = input.ReadInt64(); @@ -453,14 +441,10 @@ namespace Google.Protobuf.WellKnownTypes { public void MergeFrom(pb::CodedInputStream input) { uint tag; - while (input.ReadTag(out tag)) { + while ((tag = input.ReadTag()) != 0) { switch(tag) { - case 0: - throw pb::InvalidProtocolBufferException.InvalidTag(); default: - if (pb::WireFormat.IsEndGroupTag(tag)) { - return; - } + input.SkipLastField(); break; case 8: { Value = input.ReadUInt64(); @@ -559,14 +543,10 @@ namespace Google.Protobuf.WellKnownTypes { public void MergeFrom(pb::CodedInputStream input) { uint tag; - while (input.ReadTag(out tag)) { + while ((tag = input.ReadTag()) != 0) { switch(tag) { - case 0: - throw pb::InvalidProtocolBufferException.InvalidTag(); default: - if (pb::WireFormat.IsEndGroupTag(tag)) { - return; - } + input.SkipLastField(); break; case 8: { Value = input.ReadInt32(); @@ -665,14 +645,10 @@ namespace Google.Protobuf.WellKnownTypes { public void MergeFrom(pb::CodedInputStream input) { uint tag; - while (input.ReadTag(out tag)) { + while ((tag = input.ReadTag()) != 0) { switch(tag) { - case 0: - throw pb::InvalidProtocolBufferException.InvalidTag(); default: - if (pb::WireFormat.IsEndGroupTag(tag)) { - return; - } + input.SkipLastField(); break; case 8: { Value = input.ReadUInt32(); @@ -771,14 +747,10 @@ namespace Google.Protobuf.WellKnownTypes { public void MergeFrom(pb::CodedInputStream input) { uint tag; - while (input.ReadTag(out tag)) { + while ((tag = input.ReadTag()) != 0) { switch(tag) { - case 0: - throw pb::InvalidProtocolBufferException.InvalidTag(); default: - if (pb::WireFormat.IsEndGroupTag(tag)) { - return; - } + input.SkipLastField(); break; case 8: { Value = input.ReadBool(); @@ -877,14 +849,10 @@ namespace Google.Protobuf.WellKnownTypes { public void MergeFrom(pb::CodedInputStream input) { uint tag; - while (input.ReadTag(out tag)) { + while ((tag = input.ReadTag()) != 0) { switch(tag) { - case 0: - throw pb::InvalidProtocolBufferException.InvalidTag(); default: - if (pb::WireFormat.IsEndGroupTag(tag)) { - return; - } + input.SkipLastField(); break; case 10: { Value = input.ReadString(); @@ -983,14 +951,10 @@ namespace Google.Protobuf.WellKnownTypes { public void MergeFrom(pb::CodedInputStream input) { uint tag; - while (input.ReadTag(out tag)) { + while ((tag = input.ReadTag()) != 0) { switch(tag) { - case 0: - throw pb::InvalidProtocolBufferException.InvalidTag(); default: - if (pb::WireFormat.IsEndGroupTag(tag)) { - return; - } + input.SkipLastField(); break; case 10: { Value = input.ReadBytes(); diff --git a/csharp/src/Google.Protobuf/WireFormat.cs b/csharp/src/Google.Protobuf/WireFormat.cs index c1712daa..faf1e715 100644 --- a/csharp/src/Google.Protobuf/WireFormat.cs +++ b/csharp/src/Google.Protobuf/WireFormat.cs @@ -30,9 +30,6 @@ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#endregion
-using System;
-using Google.Protobuf.Reflection;
-
namespace Google.Protobuf
{
/// <summary>
@@ -46,26 +43,34 @@ namespace Google.Protobuf /// </summary>
public static class WireFormat
{
- #region Fixed sizes.
-
- // TODO(jonskeet): Move these somewhere else. They're messy. Consider making FieldType a smarter kind of enum
- internal const int Fixed32Size = 4;
- internal const int Fixed64Size = 8;
- internal const int SFixed32Size = 4;
- internal const int SFixed64Size = 8;
- internal const int FloatSize = 4;
- internal const int DoubleSize = 8;
- internal const int BoolSize = 1;
-
- #endregion
-
+ /// <summary>
+ /// Wire types within protobuf encoding.
+ /// </summary>
public enum WireType : uint
{
+ /// <summary>
+ /// Variable-length integer.
+ /// </summary>
Varint = 0,
+ /// <summary>
+ /// A fixed-length 64-bit value.
+ /// </summary>
Fixed64 = 1,
+ /// <summary>
+ /// A length-delimited value, i.e. a length followed by that many bytes of data.
+ /// </summary>
LengthDelimited = 2,
+ /// <summary>
+ /// A "start group" value - not supported by this implementation.
+ /// </summary>
StartGroup = 3,
+ /// <summary>
+ /// An "end group" value - not supported by this implementation.
+ /// </summary>
EndGroup = 4,
+ /// <summary>
+ /// A fixed-length 32-bit value.
+ /// </summary>
Fixed32 = 5
}
@@ -80,11 +85,6 @@ namespace Google.Protobuf return (WireType) (tag & TagTypeMask);
}
- public static bool IsEndGroupTag(uint tag)
- {
- return (WireType) (tag & TagTypeMask) == WireType.EndGroup;
- }
-
/// <summary>
/// Given a tag value, determines the field number (the upper 29 bits).
/// </summary>
@@ -99,64 +99,6 @@ namespace Google.Protobuf public static uint MakeTag(int fieldNumber, WireType wireType)
{
return (uint) (fieldNumber << TagTypeBits) | (uint) wireType;
- }
-
- public static uint MakeTag(FieldDescriptor field)
- {
- return MakeTag(field.FieldNumber, GetWireType(field));
- }
-
- /// <summary>
- /// Returns the wire type for the given field descriptor. This differs
- /// from GetWireType(FieldType) for packed repeated fields.
- /// </summary>
- internal static WireType GetWireType(FieldDescriptor descriptor)
- {
- return descriptor.IsPacked ? WireType.LengthDelimited : GetWireType(descriptor.FieldType);
- }
-
- /// <summary>
- /// Converts a field type to its wire type. Done with a switch for the sake
- /// of speed - this is significantly faster than a dictionary lookup.
- /// </summary>
- public static WireType GetWireType(FieldType fieldType)
- {
- switch (fieldType)
- {
- case FieldType.Double:
- return WireType.Fixed64;
- case FieldType.Float:
- return WireType.Fixed32;
- case FieldType.Int64:
- case FieldType.UInt64:
- case FieldType.Int32:
- return WireType.Varint;
- case FieldType.Fixed64:
- return WireType.Fixed64;
- case FieldType.Fixed32:
- return WireType.Fixed32;
- case FieldType.Bool:
- return WireType.Varint;
- case FieldType.String:
- return WireType.LengthDelimited;
- case FieldType.Group:
- return WireType.StartGroup;
- case FieldType.Message:
- case FieldType.Bytes:
- return WireType.LengthDelimited;
- case FieldType.UInt32:
- return WireType.Varint;
- case FieldType.SFixed32:
- return WireType.Fixed32;
- case FieldType.SFixed64:
- return WireType.Fixed64;
- case FieldType.SInt32:
- case FieldType.SInt64:
- case FieldType.Enum:
- return WireType.Varint;
- default:
- throw new ArgumentOutOfRangeException("fieldType", "No such field type");
- }
- }
+ }
}
}
\ No newline at end of file |