Browse Source

Merge branch 'master' of https://github.com/google/protobuf into JavaCaliper

Yilun Chong 7 years ago
parent
commit
cd32aae377
68 changed files with 3014 additions and 428 deletions
  1. 2 0
      BUILD
  2. 8 1
      Makefile.am
  3. 1 0
      cmake/extract_includes.bat.in
  4. 0 1
      conformance/failure_list_csharp.txt
  5. 7 5
      csharp/compatibility_tests/v3.0.0/src/Google.Protobuf.Test/GeneratedMessageTest.cs
  6. 1 0
      csharp/protos/unittest_proto3.proto
  7. 46 8
      csharp/src/AddressBook/Addressbook.cs
  8. 32 6
      csharp/src/Google.Protobuf.Conformance/Conformance.cs
  9. 43 0
      csharp/src/Google.Protobuf.Test/Collections/MapFieldTest.cs
  10. 124 0
      csharp/src/Google.Protobuf.Test/Collections/ProtobufEqualityComparersTest.cs
  11. 13 0
      csharp/src/Google.Protobuf.Test/Collections/RepeatedFieldTest.cs
  12. 17 4
      csharp/src/Google.Protobuf.Test/GeneratedMessageTest.cs
  13. 53 0
      csharp/src/Google.Protobuf.Test/SampleNaNs.cs
  14. 102 16
      csharp/src/Google.Protobuf.Test/TestProtos/MapUnittestProto3.cs
  15. 58 20
      csharp/src/Google.Protobuf.Test/TestProtos/TestMessagesProto3.cs
  16. 206 31
      csharp/src/Google.Protobuf.Test/TestProtos/UnittestCustomOptionsProto3.cs
  17. 18 4
      csharp/src/Google.Protobuf.Test/TestProtos/UnittestImportProto3.cs
  18. 18 4
      csharp/src/Google.Protobuf.Test/TestProtos/UnittestImportPublicProto3.cs
  19. 186 28
      csharp/src/Google.Protobuf.Test/TestProtos/UnittestIssues.cs
  20. 206 47
      csharp/src/Google.Protobuf.Test/TestProtos/UnittestProto3.cs
  21. 68 18
      csharp/src/Google.Protobuf.Test/TestProtos/UnittestWellKnownTypes.cs
  22. 128 0
      csharp/src/Google.Protobuf.Test/UnknownFieldSetTest.cs
  23. 11 0
      csharp/src/Google.Protobuf.Test/WellKnownTypes/WrappersTest.cs
  24. 4 2
      csharp/src/Google.Protobuf/CodedInputStream.cs
  25. 89 0
      csharp/src/Google.Protobuf/Collections/Lists.cs
  26. 11 11
      csharp/src/Google.Protobuf/Collections/MapField.cs
  27. 130 0
      csharp/src/Google.Protobuf/Collections/ProtobufEqualityComparers.cs
  28. 3 2
      csharp/src/Google.Protobuf/Collections/RepeatedField.cs
  29. 3 1
      csharp/src/Google.Protobuf/FieldCodec.cs
  30. 199 29
      csharp/src/Google.Protobuf/Reflection/Descriptor.cs
  31. 263 0
      csharp/src/Google.Protobuf/UnknownField.cs
  32. 324 0
      csharp/src/Google.Protobuf/UnknownFieldSet.cs
  33. 18 4
      csharp/src/Google.Protobuf/WellKnownTypes/Any.cs
  34. 46 8
      csharp/src/Google.Protobuf/WellKnownTypes/Api.cs
  35. 18 4
      csharp/src/Google.Protobuf/WellKnownTypes/Duration.cs
  36. 18 4
      csharp/src/Google.Protobuf/WellKnownTypes/Empty.cs
  37. 18 4
      csharp/src/Google.Protobuf/WellKnownTypes/FieldMask.cs
  38. 18 4
      csharp/src/Google.Protobuf/WellKnownTypes/SourceContext.cs
  39. 48 10
      csharp/src/Google.Protobuf/WellKnownTypes/Struct.cs
  40. 21 5
      csharp/src/Google.Protobuf/WellKnownTypes/Timestamp.cs
  41. 74 12
      csharp/src/Google.Protobuf/WellKnownTypes/Type.cs
  42. 134 24
      csharp/src/Google.Protobuf/WellKnownTypes/Wrappers.cs
  43. 3 1
      objectivec/google/protobuf/Timestamp.pbobjc.h
  44. 0 4
      ruby/README.md
  45. 3 3
      src/google/protobuf/any.pb.h
  46. 3 3
      src/google/protobuf/api.pb.h
  47. 3 3
      src/google/protobuf/compiler/cpp/cpp_file.cc
  48. 65 37
      src/google/protobuf/compiler/csharp/csharp_message.cc
  49. 14 6
      src/google/protobuf/compiler/csharp/csharp_primitive_field.cc
  50. 4 2
      src/google/protobuf/compiler/csharp/csharp_reflection_class.cc
  51. 16 6
      src/google/protobuf/compiler/csharp/csharp_wrapper_field.cc
  52. 3 3
      src/google/protobuf/compiler/plugin.pb.h
  53. 3 3
      src/google/protobuf/descriptor.pb.h
  54. 3 3
      src/google/protobuf/duration.pb.h
  55. 3 3
      src/google/protobuf/empty.pb.h
  56. 3 3
      src/google/protobuf/field_mask.pb.h
  57. 3 3
      src/google/protobuf/source_context.pb.h
  58. 3 3
      src/google/protobuf/struct.pb.h
  59. 5 4
      src/google/protobuf/stubs/io_win32.cc
  60. 12 4
      src/google/protobuf/stubs/port.h
  61. 30 1
      src/google/protobuf/stubs/structurally_valid.cc
  62. 30 0
      src/google/protobuf/stubs/structurally_valid_unittest.cc
  63. 3 3
      src/google/protobuf/timestamp.pb.h
  64. 3 1
      src/google/protobuf/timestamp.proto
  65. 3 3
      src/google/protobuf/type.pb.h
  66. 4 4
      src/google/protobuf/util/json_util.h
  67. 2 2
      src/google/protobuf/wire_format_lite.h
  68. 3 3
      src/google/protobuf/wrappers.pb.h

+ 2 - 0
BUILD

@@ -72,6 +72,7 @@ cc_library(
         "src/google/protobuf/extension_set.cc",
         "src/google/protobuf/extension_set.cc",
         "src/google/protobuf/generated_message_table_driven_lite.cc",
         "src/google/protobuf/generated_message_table_driven_lite.cc",
         "src/google/protobuf/generated_message_util.cc",
         "src/google/protobuf/generated_message_util.cc",
+        "src/google/protobuf/implicit_weak_message.cc",
         "src/google/protobuf/io/coded_stream.cc",
         "src/google/protobuf/io/coded_stream.cc",
         "src/google/protobuf/io/zero_copy_stream.cc",
         "src/google/protobuf/io/zero_copy_stream.cc",
         "src/google/protobuf/io/zero_copy_stream_impl_lite.cc",
         "src/google/protobuf/io/zero_copy_stream_impl_lite.cc",
@@ -734,6 +735,7 @@ py_proto_library(
         ":python_srcs",
         ":python_srcs",
         "//external:six",
         "//external:six",
     ],
     ],
+    py_extra_srcs = glob(["python/**/__init__.py"]),
     srcs_version = "PY2AND3",
     srcs_version = "PY2AND3",
     visibility = ["//visibility:public"],
     visibility = ["//visibility:public"],
 )
 )

+ 8 - 1
Makefile.am

@@ -84,6 +84,7 @@ csharp_EXTRA_DIST=                                                           \
   csharp/src/Google.Protobuf.Test/CodedInputStreamTest.cs                    \
   csharp/src/Google.Protobuf.Test/CodedInputStreamTest.cs                    \
   csharp/src/Google.Protobuf.Test/CodedOutputStreamTest.cs                   \
   csharp/src/Google.Protobuf.Test/CodedOutputStreamTest.cs                   \
   csharp/src/Google.Protobuf.Test/Collections/MapFieldTest.cs                \
   csharp/src/Google.Protobuf.Test/Collections/MapFieldTest.cs                \
+  csharp/src/Google.Protobuf.Test/Collections/ProtobufEqualityComparersTest.cs \
   csharp/src/Google.Protobuf.Test/Collections/RepeatedFieldTest.cs           \
   csharp/src/Google.Protobuf.Test/Collections/RepeatedFieldTest.cs           \
   csharp/src/Google.Protobuf.Test/Compatibility/PropertyInfoExtensionsTest.cs \
   csharp/src/Google.Protobuf.Test/Compatibility/PropertyInfoExtensionsTest.cs \
   csharp/src/Google.Protobuf.Test/Compatibility/StreamExtensionsTest.cs      \
   csharp/src/Google.Protobuf.Test/Compatibility/StreamExtensionsTest.cs      \
@@ -104,6 +105,7 @@ csharp_EXTRA_DIST=                                                           \
   csharp/src/Google.Protobuf.Test/Reflection/TypeRegistryTest.cs             \
   csharp/src/Google.Protobuf.Test/Reflection/TypeRegistryTest.cs             \
   csharp/src/Google.Protobuf.Test/SampleEnum.cs                              \
   csharp/src/Google.Protobuf.Test/SampleEnum.cs                              \
   csharp/src/Google.Protobuf.Test/SampleMessages.cs                          \
   csharp/src/Google.Protobuf.Test/SampleMessages.cs                          \
+  csharp/src/Google.Protobuf.Test/SampleNaNs.cs                              \
   csharp/src/Google.Protobuf.Test/TestCornerCases.cs                         \
   csharp/src/Google.Protobuf.Test/TestCornerCases.cs                         \
   csharp/src/Google.Protobuf.Test/TestProtos/ForeignMessagePartial.cs        \
   csharp/src/Google.Protobuf.Test/TestProtos/ForeignMessagePartial.cs        \
   csharp/src/Google.Protobuf.Test/TestProtos/MapUnittestProto3.cs            \
   csharp/src/Google.Protobuf.Test/TestProtos/MapUnittestProto3.cs            \
@@ -119,13 +121,16 @@ csharp_EXTRA_DIST=                                                           \
   csharp/src/Google.Protobuf.Test/WellKnownTypes/FieldMaskTest.cs            \
   csharp/src/Google.Protobuf.Test/WellKnownTypes/FieldMaskTest.cs            \
   csharp/src/Google.Protobuf.Test/WellKnownTypes/TimestampTest.cs            \
   csharp/src/Google.Protobuf.Test/WellKnownTypes/TimestampTest.cs            \
   csharp/src/Google.Protobuf.Test/WellKnownTypes/WrappersTest.cs             \
   csharp/src/Google.Protobuf.Test/WellKnownTypes/WrappersTest.cs             \
+  csharp/src/Google.Protobuf.Test/UnknownFieldSetTest.cs                     \
   csharp/src/Google.Protobuf.sln                                             \
   csharp/src/Google.Protobuf.sln                                             \
   csharp/src/Google.Protobuf/ByteArray.cs                                    \
   csharp/src/Google.Protobuf/ByteArray.cs                                    \
   csharp/src/Google.Protobuf/ByteString.cs                                   \
   csharp/src/Google.Protobuf/ByteString.cs                                   \
   csharp/src/Google.Protobuf/CodedInputStream.cs                             \
   csharp/src/Google.Protobuf/CodedInputStream.cs                             \
   csharp/src/Google.Protobuf/CodedOutputStream.ComputeSize.cs                \
   csharp/src/Google.Protobuf/CodedOutputStream.ComputeSize.cs                \
   csharp/src/Google.Protobuf/CodedOutputStream.cs                            \
   csharp/src/Google.Protobuf/CodedOutputStream.cs                            \
+  csharp/src/Google.Protobuf/Collections/Lists.cs                            \
   csharp/src/Google.Protobuf/Collections/MapField.cs                         \
   csharp/src/Google.Protobuf/Collections/MapField.cs                         \
+  csharp/src/Google.Protobuf/Collections/ProtobufEqualityComparers.cs        \
   csharp/src/Google.Protobuf/Collections/ReadOnlyDictionary.cs               \
   csharp/src/Google.Protobuf/Collections/ReadOnlyDictionary.cs               \
   csharp/src/Google.Protobuf/Collections/RepeatedField.cs                    \
   csharp/src/Google.Protobuf/Collections/RepeatedField.cs                    \
   csharp/src/Google.Protobuf/Compatibility/PropertyInfoExtensions.cs         \
   csharp/src/Google.Protobuf/Compatibility/PropertyInfoExtensions.cs         \
@@ -193,7 +198,9 @@ csharp_EXTRA_DIST=                                                           \
   csharp/src/Google.Protobuf/WellKnownTypes/ValuePartial.cs                  \
   csharp/src/Google.Protobuf/WellKnownTypes/ValuePartial.cs                  \
   csharp/src/Google.Protobuf/WellKnownTypes/Wrappers.cs                      \
   csharp/src/Google.Protobuf/WellKnownTypes/Wrappers.cs                      \
   csharp/src/Google.Protobuf/WellKnownTypes/WrappersPartial.cs               \
   csharp/src/Google.Protobuf/WellKnownTypes/WrappersPartial.cs               \
-  csharp/src/Google.Protobuf/WireFormat.cs
+  csharp/src/Google.Protobuf/WireFormat.cs                                   \
+  csharp/src/Google.Protobuf/UnknownField.cs                                 \
+  csharp/src/Google.Protobuf/UnknownFieldSet.cs
 
 
 java_EXTRA_DIST=                                                                   \
 java_EXTRA_DIST=                                                                   \
   java/README.md                                                                   \
   java/README.md                                                                   \

+ 1 - 0
cmake/extract_includes.bat.in

@@ -53,6 +53,7 @@ copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\generated_message_ref
 copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\generated_message_table_driven.h" include\google\protobuf\generated_message_table_driven.h
 copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\generated_message_table_driven.h" include\google\protobuf\generated_message_table_driven.h
 copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\generated_message_util.h" include\google\protobuf\generated_message_util.h
 copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\generated_message_util.h" include\google\protobuf\generated_message_util.h
 copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\has_bits.h" include\google\protobuf\has_bits.h
 copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\has_bits.h" include\google\protobuf\has_bits.h
+copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\implicit_weak_message.h" include\google\protobuf\implicit_weak_message.h
 copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\io\coded_stream.h" include\google\protobuf\io\coded_stream.h
 copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\io\coded_stream.h" include\google\protobuf\io\coded_stream.h
 copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\io\gzip_stream.h" include\google\protobuf\io\gzip_stream.h
 copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\io\gzip_stream.h" include\google\protobuf\io\gzip_stream.h
 copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\io\printer.h" include\google\protobuf\io\printer.h
 copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\io\printer.h" include\google\protobuf\io\printer.h

+ 0 - 1
conformance/failure_list_csharp.txt

@@ -1,3 +1,2 @@
 Recommended.Proto3.JsonInput.BytesFieldBase64Url.JsonOutput
 Recommended.Proto3.JsonInput.BytesFieldBase64Url.JsonOutput
 Recommended.Proto3.JsonInput.BytesFieldBase64Url.ProtobufOutput
 Recommended.Proto3.JsonInput.BytesFieldBase64Url.ProtobufOutput
-Required.Proto3.ProtobufInput.UnknownVarint.ProtobufOutput

+ 7 - 5
csharp/compatibility_tests/v3.0.0/src/Google.Protobuf.Test/GeneratedMessageTest.cs

@@ -638,7 +638,7 @@ namespace Google.Protobuf
         }
         }
 
 
         [Test]
         [Test]
-        public void IgnoreUnknownFields_RealDataStillRead()
+        public void DiscardUnknownFields_RealDataStillRead()
         {
         {
             var message = SampleMessages.CreateFullTestAllTypes();
             var message = SampleMessages.CreateFullTestAllTypes();
             var stream = new MemoryStream();
             var stream = new MemoryStream();
@@ -652,16 +652,18 @@ namespace Google.Protobuf
 
 
             stream.Position = 0;
             stream.Position = 0;
             var parsed = TestAllTypes.Parser.ParseFrom(stream);
             var parsed = TestAllTypes.Parser.ParseFrom(stream);
-            Assert.AreEqual(message, parsed);
+	    // TODO(jieluo): Add test back after DiscardUnknownFields is supported
+            // Assert.AreEqual(message, parsed);
         }
         }
 
 
         [Test]
         [Test]
-        public void IgnoreUnknownFields_AllTypes()
+        public void DiscardUnknownFields_AllTypes()
         {
         {
             // Simple way of ensuring we can skip all kinds of fields.
             // Simple way of ensuring we can skip all kinds of fields.
             var data = SampleMessages.CreateFullTestAllTypes().ToByteArray();
             var data = SampleMessages.CreateFullTestAllTypes().ToByteArray();
             var empty = Empty.Parser.ParseFrom(data);
             var empty = Empty.Parser.ParseFrom(data);
-            Assert.AreEqual(new Empty(), empty);
+	    // TODO(jieluo): Add test back after DiscardUnknownField is supported.
+            // Assert.AreEqual(new Empty(), empty);
         }
         }
 
 
         // This was originally seen as a conformance test failure.
         // This was originally seen as a conformance test failure.
@@ -720,4 +722,4 @@ namespace Google.Protobuf
             Assert.AreEqual("{ \"c\": 31 }", writer.ToString());
             Assert.AreEqual("{ \"c\": 31 }", writer.ToString());
         }
         }
     }
     }
-}
+}

+ 1 - 0
csharp/protos/unittest_proto3.proto

@@ -377,3 +377,4 @@ service TestService {
 message BarRequest  {}
 message BarRequest  {}
 message BarResponse {}
 message BarResponse {}
 
 
+message TestEmptyMessage {}

+ 46 - 8
csharp/src/AddressBook/Addressbook.cs

@@ -1,5 +1,7 @@
-// Generated by the protocol buffer compiler.  DO NOT EDIT!
-// source: addressbook.proto
+// <auto-generated>
+//     Generated by the protocol buffer compiler.  DO NOT EDIT!
+//     source: addressbook.proto
+// </auto-generated>
 #pragma warning disable 1591, 0612, 3021
 #pragma warning disable 1591, 0612, 3021
 #region Designer generated code
 #region Designer generated code
 
 
@@ -49,6 +51,7 @@ namespace Google.Protobuf.Examples.AddressBook {
   /// </summary>
   /// </summary>
   public sealed partial class Person : pb::IMessage<Person> {
   public sealed partial class Person : pb::IMessage<Person> {
     private static readonly pb::MessageParser<Person> _parser = new pb::MessageParser<Person>(() => new Person());
     private static readonly pb::MessageParser<Person> _parser = new pb::MessageParser<Person>(() => new Person());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<Person> Parser { get { return _parser; } }
     public static pb::MessageParser<Person> Parser { get { return _parser; } }
 
 
@@ -76,6 +79,7 @@ namespace Google.Protobuf.Examples.AddressBook {
       email_ = other.email_;
       email_ = other.email_;
       phones_ = other.phones_.Clone();
       phones_ = other.phones_.Clone();
       LastUpdated = other.lastUpdated_ != null ? other.LastUpdated.Clone() : null;
       LastUpdated = other.lastUpdated_ != null ? other.LastUpdated.Clone() : null;
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -158,7 +162,7 @@ namespace Google.Protobuf.Examples.AddressBook {
       if (Email != other.Email) return false;
       if (Email != other.Email) return false;
       if(!phones_.Equals(other.phones_)) return false;
       if(!phones_.Equals(other.phones_)) return false;
       if (!object.Equals(LastUpdated, other.LastUpdated)) return false;
       if (!object.Equals(LastUpdated, other.LastUpdated)) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -169,6 +173,9 @@ namespace Google.Protobuf.Examples.AddressBook {
       if (Email.Length != 0) hash ^= Email.GetHashCode();
       if (Email.Length != 0) hash ^= Email.GetHashCode();
       hash ^= phones_.GetHashCode();
       hash ^= phones_.GetHashCode();
       if (lastUpdated_ != null) hash ^= LastUpdated.GetHashCode();
       if (lastUpdated_ != null) hash ^= LastUpdated.GetHashCode();
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
       return hash;
     }
     }
 
 
@@ -196,6 +203,9 @@ namespace Google.Protobuf.Examples.AddressBook {
         output.WriteRawTag(42);
         output.WriteRawTag(42);
         output.WriteMessage(LastUpdated);
         output.WriteMessage(LastUpdated);
       }
       }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -214,6 +224,9 @@ namespace Google.Protobuf.Examples.AddressBook {
       if (lastUpdated_ != null) {
       if (lastUpdated_ != null) {
         size += 1 + pb::CodedOutputStream.ComputeMessageSize(LastUpdated);
         size += 1 + pb::CodedOutputStream.ComputeMessageSize(LastUpdated);
       }
       }
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
       return size;
     }
     }
 
 
@@ -238,6 +251,7 @@ namespace Google.Protobuf.Examples.AddressBook {
         }
         }
         LastUpdated.MergeFrom(other.LastUpdated);
         LastUpdated.MergeFrom(other.LastUpdated);
       }
       }
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -246,7 +260,7 @@ namespace Google.Protobuf.Examples.AddressBook {
       while ((tag = input.ReadTag()) != 0) {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
         switch(tag) {
           default:
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
             break;
           case 10: {
           case 10: {
             Name = input.ReadString();
             Name = input.ReadString();
@@ -287,6 +301,7 @@ namespace Google.Protobuf.Examples.AddressBook {
 
 
       public sealed partial class PhoneNumber : pb::IMessage<PhoneNumber> {
       public sealed partial class PhoneNumber : pb::IMessage<PhoneNumber> {
         private static readonly pb::MessageParser<PhoneNumber> _parser = new pb::MessageParser<PhoneNumber>(() => new PhoneNumber());
         private static readonly pb::MessageParser<PhoneNumber> _parser = new pb::MessageParser<PhoneNumber>(() => new PhoneNumber());
+        private pb::UnknownFieldSet _unknownFields;
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
         public static pb::MessageParser<PhoneNumber> Parser { get { return _parser; } }
         public static pb::MessageParser<PhoneNumber> Parser { get { return _parser; } }
 
 
@@ -311,6 +326,7 @@ namespace Google.Protobuf.Examples.AddressBook {
         public PhoneNumber(PhoneNumber other) : this() {
         public PhoneNumber(PhoneNumber other) : this() {
           number_ = other.number_;
           number_ = other.number_;
           type_ = other.type_;
           type_ = other.type_;
+          _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
         }
         }
 
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -355,7 +371,7 @@ namespace Google.Protobuf.Examples.AddressBook {
           }
           }
           if (Number != other.Number) return false;
           if (Number != other.Number) return false;
           if (Type != other.Type) return false;
           if (Type != other.Type) return false;
-          return true;
+          return Equals(_unknownFields, other._unknownFields);
         }
         }
 
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -363,6 +379,9 @@ namespace Google.Protobuf.Examples.AddressBook {
           int hash = 1;
           int hash = 1;
           if (Number.Length != 0) hash ^= Number.GetHashCode();
           if (Number.Length != 0) hash ^= Number.GetHashCode();
           if (Type != 0) hash ^= Type.GetHashCode();
           if (Type != 0) hash ^= Type.GetHashCode();
+          if (_unknownFields != null) {
+            hash ^= _unknownFields.GetHashCode();
+          }
           return hash;
           return hash;
         }
         }
 
 
@@ -381,6 +400,9 @@ namespace Google.Protobuf.Examples.AddressBook {
             output.WriteRawTag(16);
             output.WriteRawTag(16);
             output.WriteEnum((int) Type);
             output.WriteEnum((int) Type);
           }
           }
+          if (_unknownFields != null) {
+            _unknownFields.WriteTo(output);
+          }
         }
         }
 
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -392,6 +414,9 @@ namespace Google.Protobuf.Examples.AddressBook {
           if (Type != 0) {
           if (Type != 0) {
             size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Type);
             size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Type);
           }
           }
+          if (_unknownFields != null) {
+            size += _unknownFields.CalculateSize();
+          }
           return size;
           return size;
         }
         }
 
 
@@ -406,6 +431,7 @@ namespace Google.Protobuf.Examples.AddressBook {
           if (other.Type != 0) {
           if (other.Type != 0) {
             Type = other.Type;
             Type = other.Type;
           }
           }
+          _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
         }
         }
 
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -414,7 +440,7 @@ namespace Google.Protobuf.Examples.AddressBook {
           while ((tag = input.ReadTag()) != 0) {
           while ((tag = input.ReadTag()) != 0) {
             switch(tag) {
             switch(tag) {
               default:
               default:
-                input.SkipLastField();
+                _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
                 break;
                 break;
               case 10: {
               case 10: {
                 Number = input.ReadString();
                 Number = input.ReadString();
@@ -440,6 +466,7 @@ namespace Google.Protobuf.Examples.AddressBook {
   /// </summary>
   /// </summary>
   public sealed partial class AddressBook : pb::IMessage<AddressBook> {
   public sealed partial class AddressBook : pb::IMessage<AddressBook> {
     private static readonly pb::MessageParser<AddressBook> _parser = new pb::MessageParser<AddressBook>(() => new AddressBook());
     private static readonly pb::MessageParser<AddressBook> _parser = new pb::MessageParser<AddressBook>(() => new AddressBook());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<AddressBook> Parser { get { return _parser; } }
     public static pb::MessageParser<AddressBook> Parser { get { return _parser; } }
 
 
@@ -463,6 +490,7 @@ namespace Google.Protobuf.Examples.AddressBook {
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public AddressBook(AddressBook other) : this() {
     public AddressBook(AddressBook other) : this() {
       people_ = other.people_.Clone();
       people_ = other.people_.Clone();
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -494,13 +522,16 @@ namespace Google.Protobuf.Examples.AddressBook {
         return true;
         return true;
       }
       }
       if(!people_.Equals(other.people_)) return false;
       if(!people_.Equals(other.people_)) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public override int GetHashCode() {
     public override int GetHashCode() {
       int hash = 1;
       int hash = 1;
       hash ^= people_.GetHashCode();
       hash ^= people_.GetHashCode();
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
       return hash;
     }
     }
 
 
@@ -512,12 +543,18 @@ namespace Google.Protobuf.Examples.AddressBook {
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public void WriteTo(pb::CodedOutputStream output) {
     public void WriteTo(pb::CodedOutputStream output) {
       people_.WriteTo(output, _repeated_people_codec);
       people_.WriteTo(output, _repeated_people_codec);
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public int CalculateSize() {
     public int CalculateSize() {
       int size = 0;
       int size = 0;
       size += people_.CalculateSize(_repeated_people_codec);
       size += people_.CalculateSize(_repeated_people_codec);
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
       return size;
     }
     }
 
 
@@ -527,6 +564,7 @@ namespace Google.Protobuf.Examples.AddressBook {
         return;
         return;
       }
       }
       people_.Add(other.people_);
       people_.Add(other.people_);
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -535,7 +573,7 @@ namespace Google.Protobuf.Examples.AddressBook {
       while ((tag = input.ReadTag()) != 0) {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
         switch(tag) {
           default:
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
             break;
           case 10: {
           case 10: {
             people_.AddEntriesFrom(input, _repeated_people_codec);
             people_.AddEntriesFrom(input, _repeated_people_codec);

+ 32 - 6
csharp/src/Google.Protobuf.Conformance/Conformance.cs

@@ -1,5 +1,7 @@
-// Generated by the protocol buffer compiler.  DO NOT EDIT!
-// source: conformance.proto
+// <auto-generated>
+//     Generated by the protocol buffer compiler.  DO NOT EDIT!
+//     source: conformance.proto
+// </auto-generated>
 #pragma warning disable 1591, 0612, 3021
 #pragma warning disable 1591, 0612, 3021
 #region Designer generated code
 #region Designer generated code
 
 
@@ -62,6 +64,7 @@ namespace Conformance {
   /// </summary>
   /// </summary>
   public sealed partial class ConformanceRequest : pb::IMessage<ConformanceRequest> {
   public sealed partial class ConformanceRequest : pb::IMessage<ConformanceRequest> {
     private static readonly pb::MessageParser<ConformanceRequest> _parser = new pb::MessageParser<ConformanceRequest>(() => new ConformanceRequest());
     private static readonly pb::MessageParser<ConformanceRequest> _parser = new pb::MessageParser<ConformanceRequest>(() => new ConformanceRequest());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<ConformanceRequest> Parser { get { return _parser; } }
     public static pb::MessageParser<ConformanceRequest> Parser { get { return _parser; } }
 
 
@@ -95,6 +98,7 @@ namespace Conformance {
           break;
           break;
       }
       }
 
 
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -191,7 +195,7 @@ namespace Conformance {
       if (RequestedOutputFormat != other.RequestedOutputFormat) return false;
       if (RequestedOutputFormat != other.RequestedOutputFormat) return false;
       if (MessageType != other.MessageType) return false;
       if (MessageType != other.MessageType) return false;
       if (PayloadCase != other.PayloadCase) return false;
       if (PayloadCase != other.PayloadCase) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -202,6 +206,9 @@ namespace Conformance {
       if (RequestedOutputFormat != 0) hash ^= RequestedOutputFormat.GetHashCode();
       if (RequestedOutputFormat != 0) hash ^= RequestedOutputFormat.GetHashCode();
       if (MessageType.Length != 0) hash ^= MessageType.GetHashCode();
       if (MessageType.Length != 0) hash ^= MessageType.GetHashCode();
       hash ^= (int) payloadCase_;
       hash ^= (int) payloadCase_;
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
       return hash;
     }
     }
 
 
@@ -228,6 +235,9 @@ namespace Conformance {
         output.WriteRawTag(34);
         output.WriteRawTag(34);
         output.WriteString(MessageType);
         output.WriteString(MessageType);
       }
       }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -245,6 +255,9 @@ namespace Conformance {
       if (MessageType.Length != 0) {
       if (MessageType.Length != 0) {
         size += 1 + pb::CodedOutputStream.ComputeStringSize(MessageType);
         size += 1 + pb::CodedOutputStream.ComputeStringSize(MessageType);
       }
       }
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
       return size;
     }
     }
 
 
@@ -268,6 +281,7 @@ namespace Conformance {
           break;
           break;
       }
       }
 
 
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -276,7 +290,7 @@ namespace Conformance {
       while ((tag = input.ReadTag()) != 0) {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
         switch(tag) {
           default:
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
             break;
           case 10: {
           case 10: {
             ProtobufPayload = input.ReadBytes();
             ProtobufPayload = input.ReadBytes();
@@ -305,6 +319,7 @@ namespace Conformance {
   /// </summary>
   /// </summary>
   public sealed partial class ConformanceResponse : pb::IMessage<ConformanceResponse> {
   public sealed partial class ConformanceResponse : pb::IMessage<ConformanceResponse> {
     private static readonly pb::MessageParser<ConformanceResponse> _parser = new pb::MessageParser<ConformanceResponse>(() => new ConformanceResponse());
     private static readonly pb::MessageParser<ConformanceResponse> _parser = new pb::MessageParser<ConformanceResponse>(() => new ConformanceResponse());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<ConformanceResponse> Parser { get { return _parser; } }
     public static pb::MessageParser<ConformanceResponse> Parser { get { return _parser; } }
 
 
@@ -348,6 +363,7 @@ namespace Conformance {
           break;
           break;
       }
       }
 
 
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -493,7 +509,7 @@ namespace Conformance {
       if (JsonPayload != other.JsonPayload) return false;
       if (JsonPayload != other.JsonPayload) return false;
       if (Skipped != other.Skipped) return false;
       if (Skipped != other.Skipped) return false;
       if (ResultCase != other.ResultCase) return false;
       if (ResultCase != other.ResultCase) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -506,6 +522,9 @@ namespace Conformance {
       if (resultCase_ == ResultOneofCase.JsonPayload) hash ^= JsonPayload.GetHashCode();
       if (resultCase_ == ResultOneofCase.JsonPayload) hash ^= JsonPayload.GetHashCode();
       if (resultCase_ == ResultOneofCase.Skipped) hash ^= Skipped.GetHashCode();
       if (resultCase_ == ResultOneofCase.Skipped) hash ^= Skipped.GetHashCode();
       hash ^= (int) resultCase_;
       hash ^= (int) resultCase_;
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
       return hash;
     }
     }
 
 
@@ -540,6 +559,9 @@ namespace Conformance {
         output.WriteRawTag(50);
         output.WriteRawTag(50);
         output.WriteString(SerializeError);
         output.WriteString(SerializeError);
       }
       }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -563,6 +585,9 @@ namespace Conformance {
       if (resultCase_ == ResultOneofCase.Skipped) {
       if (resultCase_ == ResultOneofCase.Skipped) {
         size += 1 + pb::CodedOutputStream.ComputeStringSize(Skipped);
         size += 1 + pb::CodedOutputStream.ComputeStringSize(Skipped);
       }
       }
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
       return size;
     }
     }
 
 
@@ -592,6 +617,7 @@ namespace Conformance {
           break;
           break;
       }
       }
 
 
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -600,7 +626,7 @@ namespace Conformance {
       while ((tag = input.ReadTag()) != 0) {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
         switch(tag) {
           default:
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
             break;
           case 10: {
           case 10: {
             ParseError = input.ReadString();
             ParseError = input.ReadString();

+ 43 - 0
csharp/src/Google.Protobuf.Test/Collections/MapFieldTest.cs

@@ -540,6 +540,49 @@ namespace Google.Protobuf.Collections
             Assert.Throws<ArgumentException>(() => map.ToString());
             Assert.Throws<ArgumentException>(() => map.ToString());
         }
         }
 
 
+        [Test]
+        public void NaNValuesComparedBitwise()
+        {
+            var map1 = new MapField<string, double>
+            {
+                { "x", SampleNaNs.Regular },
+                { "y", SampleNaNs.SignallingFlipped }
+            };
+
+            var map2 = new MapField<string, double>
+            {
+                { "x", SampleNaNs.Regular },
+                { "y", SampleNaNs.PayloadFlipped }
+            };
+
+            var map3 = new MapField<string, double>
+            {
+                { "x", SampleNaNs.Regular },
+                { "y", SampleNaNs.SignallingFlipped }
+            };
+
+            EqualityTester.AssertInequality(map1, map2);
+            EqualityTester.AssertEquality(map1, map3);
+            Assert.True(map1.Values.Contains(SampleNaNs.SignallingFlipped));
+            Assert.False(map2.Values.Contains(SampleNaNs.SignallingFlipped));
+        }
+
+        // This wouldn't usually happen, as protos can't use doubles as map keys,
+        // but let's be consistent.
+        [Test]
+        public void NaNKeysComparedBitwise()
+        {
+            var map = new MapField<double, string>
+            {
+                { SampleNaNs.Regular, "x" },
+                { SampleNaNs.SignallingFlipped, "y" }
+            };
+            Assert.AreEqual("x", map[SampleNaNs.Regular]);
+            Assert.AreEqual("y", map[SampleNaNs.SignallingFlipped]);
+            string ignored;
+            Assert.False(map.TryGetValue(SampleNaNs.PayloadFlipped, out ignored));
+        }
+
 #if !NET35
 #if !NET35
         [Test]
         [Test]
         public void IDictionaryKeys_Equals_IReadOnlyDictionaryKeys()
         public void IDictionaryKeys_Equals_IReadOnlyDictionaryKeys()

+ 124 - 0
csharp/src/Google.Protobuf.Test/Collections/ProtobufEqualityComparersTest.cs

@@ -0,0 +1,124 @@
+#region Copyright notice and license
+// Protocol Buffers - Google's data interchange format
+// Copyright 2017 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#endregion
+
+using NUnit.Framework;
+using System.Collections.Generic;
+using System.Linq;
+using static Google.Protobuf.Collections.ProtobufEqualityComparers;
+
+namespace Google.Protobuf.Collections
+{
+    public class ProtobufEqualityComparersTest
+    {
+        private static readonly double[] doubles =
+        {
+            0,
+            1,
+            1.5,
+            -1.5,
+            double.PositiveInfinity,
+            double.NegativeInfinity,
+            // Three different types of NaN...
+            SampleNaNs.Regular,
+            SampleNaNs.SignallingFlipped,
+            SampleNaNs.PayloadFlipped
+        };
+
+        [Test]
+        public void GetEqualityComparer_Default()
+        {
+            // It's more pain than it's worth to try to parameterize these tests.
+            Assert.AreSame(EqualityComparer<object>.Default, GetEqualityComparer<object>());
+            Assert.AreSame(EqualityComparer<string>.Default, GetEqualityComparer<string>());
+            Assert.AreSame(EqualityComparer<int>.Default, GetEqualityComparer<int>());
+            Assert.AreSame(EqualityComparer<int?>.Default, GetEqualityComparer<int?>());
+        }
+
+        [Test]
+        public void GetEqualityComparer_NotDefault()
+        {
+            // It's more pain than it's worth to try to parameterize these tests.
+            Assert.AreSame(BitwiseDoubleEqualityComparer, GetEqualityComparer<double>());
+            Assert.AreSame(BitwiseSingleEqualityComparer, GetEqualityComparer<float>());
+            Assert.AreSame(BitwiseNullableDoubleEqualityComparer, GetEqualityComparer<double?>());
+            Assert.AreSame(BitwiseNullableSingleEqualityComparer, GetEqualityComparer<float?>());
+        }
+
+        [Test]
+        public void DoubleComparisons()
+        {
+            ValidateEqualityComparer(BitwiseDoubleEqualityComparer, doubles);
+        }
+
+        [Test]
+        public void NullableDoubleComparisons()
+        {
+            ValidateEqualityComparer(BitwiseNullableDoubleEqualityComparer, doubles.Select(d => (double?) d).Concat(new double?[] { null }));
+        }
+
+        [Test]
+        public void SingleComparisons()
+        {
+            ValidateEqualityComparer(BitwiseSingleEqualityComparer, doubles.Select(d => (float) d));
+        }
+
+        [Test]
+        public void NullableSingleComparisons()
+        {
+            ValidateEqualityComparer(BitwiseNullableSingleEqualityComparer, doubles.Select(d => (float?) d).Concat(new float?[] { null }));
+        }
+
+        private static void ValidateEqualityComparer<T>(EqualityComparer<T> comparer, IEnumerable<T> values)
+        {
+            var array = values.ToArray();
+            // Each value should be equal to itself, but not to any other value.
+            for (int i = 0; i < array.Length; i++)
+            {
+                for (int j = 0; j < array.Length; j++)
+                {
+                    if (i == j)
+                    {
+                        Assert.IsTrue(comparer.Equals(array[i], array[j]),
+                            "{0} should be equal to itself", array[i], array[j]);
+                    }
+                    else
+                    {
+                        Assert.IsFalse(comparer.Equals(array[i], array[j]),
+                            "{0} and {1} should not be equal", array[i], array[j]);
+                        Assert.AreNotEqual(comparer.GetHashCode(array[i]), comparer.GetHashCode(array[j]),
+                            "Hash codes for {0} and {1} should not be equal", array[i], array[j]);
+                    }
+                }
+            }
+        }
+    }    
+}

+ 13 - 0
csharp/src/Google.Protobuf.Test/Collections/RepeatedFieldTest.cs

@@ -742,5 +742,18 @@ namespace Google.Protobuf.Collections
             var text = list.ToString();
             var text = list.ToString();
             Assert.AreEqual(text, "[ { \"foo\": 20 } ]", message.ToString());
             Assert.AreEqual(text, "[ { \"foo\": 20 } ]", message.ToString());
         }
         }
+
+        [Test]
+        public void NaNValuesComparedBitwise()
+        {
+            var list1 = new RepeatedField<double> { SampleNaNs.Regular, SampleNaNs.SignallingFlipped };
+            var list2 = new RepeatedField<double> { SampleNaNs.Regular, SampleNaNs.PayloadFlipped };
+            var list3 = new RepeatedField<double> { SampleNaNs.Regular, SampleNaNs.SignallingFlipped };
+
+            EqualityTester.AssertInequality(list1, list2);
+            EqualityTester.AssertEquality(list1, list3);
+            Assert.True(list1.Contains(SampleNaNs.SignallingFlipped));
+            Assert.False(list2.Contains(SampleNaNs.SignallingFlipped));
+        }
     }
     }
 }
 }

+ 17 - 4
csharp/src/Google.Protobuf.Test/GeneratedMessageTest.cs

@@ -638,7 +638,7 @@ namespace Google.Protobuf
         }
         }
 
 
         [Test]
         [Test]
-        public void IgnoreUnknownFields_RealDataStillRead()
+        public void DiscardUnknownFields_RealDataStillRead()
         {
         {
             var message = SampleMessages.CreateFullTestAllTypes();
             var message = SampleMessages.CreateFullTestAllTypes();
             var stream = new MemoryStream();
             var stream = new MemoryStream();
@@ -652,16 +652,18 @@ namespace Google.Protobuf
 
 
             stream.Position = 0;
             stream.Position = 0;
             var parsed = TestAllTypes.Parser.ParseFrom(stream);
             var parsed = TestAllTypes.Parser.ParseFrom(stream);
-            Assert.AreEqual(message, parsed);
+            // TODO(jieluo): Add test back when DiscardUnknownFields API is supported.
+            // Assert.AreEqual(message, parsed);
         }
         }
 
 
         [Test]
         [Test]
-        public void IgnoreUnknownFields_AllTypes()
+        public void DiscardUnknownFields_AllTypes()
         {
         {
             // Simple way of ensuring we can skip all kinds of fields.
             // Simple way of ensuring we can skip all kinds of fields.
             var data = SampleMessages.CreateFullTestAllTypes().ToByteArray();
             var data = SampleMessages.CreateFullTestAllTypes().ToByteArray();
             var empty = Empty.Parser.ParseFrom(data);
             var empty = Empty.Parser.ParseFrom(data);
-            Assert.AreEqual(new Empty(), empty);
+            // TODO(jieluo): Add test back when DiscardUnknownFields API is supported.
+            // Assert.AreNotEqual(new Empty(), empty);
         }
         }
 
 
         // This was originally seen as a conformance test failure.
         // This was originally seen as a conformance test failure.
@@ -719,5 +721,16 @@ namespace Google.Protobuf
             JsonFormatter.Default.Format(message, writer);
             JsonFormatter.Default.Format(message, writer);
             Assert.AreEqual("{ \"c\": 31 }", writer.ToString());
             Assert.AreEqual("{ \"c\": 31 }", writer.ToString());
         }
         }
+
+        [Test]
+        public void NaNComparisons()
+        {
+            var message1 = new TestAllTypes { SingleDouble = SampleNaNs.Regular };
+            var message2 = new TestAllTypes { SingleDouble = SampleNaNs.PayloadFlipped };
+            var message3 = new TestAllTypes { SingleDouble = SampleNaNs.Regular };
+
+            EqualityTester.AssertInequality(message1, message2);
+            EqualityTester.AssertEquality(message1, message3);
+        }
     }
     }
 }
 }

+ 53 - 0
csharp/src/Google.Protobuf.Test/SampleNaNs.cs

@@ -0,0 +1,53 @@
+#region Copyright notice and license
+// Protocol Buffers - Google's data interchange format
+// Copyright 2017 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#endregion
+
+using System;
+
+namespace Google.Protobuf
+{
+    /// <summary>
+    /// Samples of different not-a-number values, for testing equality comparisons.
+    /// </summary>
+    public static class SampleNaNs
+    {
+        public static double Regular { get; } = double.NaN;
+
+        // Signalling bit is inverted compared with double.NaN. Doesn't really matter
+        // whether that makes it quiet or signalling - it's different.
+        public static double SignallingFlipped { get; } = 
+            BitConverter.Int64BitsToDouble(BitConverter.DoubleToInt64Bits(double.NaN) ^ -0x8000_0000_0000_0000L);
+
+        // A bit in the middle of the mantissa is flipped; this difference is preserved when casting to float.
+        public static double PayloadFlipped { get; } =
+            BitConverter.Int64BitsToDouble(BitConverter.DoubleToInt64Bits(double.NaN) ^ 0x1_0000_0000L);
+    }
+}

+ 102 - 16
csharp/src/Google.Protobuf.Test/TestProtos/MapUnittestProto3.cs

@@ -1,5 +1,7 @@
-// Generated by the protocol buffer compiler.  DO NOT EDIT!
-// source: map_unittest_proto3.proto
+// <auto-generated>
+//     Generated by the protocol buffer compiler.  DO NOT EDIT!
+//     source: map_unittest_proto3.proto
+// </auto-generated>
 #pragma warning disable 1591, 0612, 3021
 #pragma warning disable 1591, 0612, 3021
 #region Designer generated code
 #region Designer generated code
 
 
@@ -176,6 +178,7 @@ namespace Google.Protobuf.TestProtos {
   /// </summary>
   /// </summary>
   public sealed partial class TestMap : pb::IMessage<TestMap> {
   public sealed partial class TestMap : pb::IMessage<TestMap> {
     private static readonly pb::MessageParser<TestMap> _parser = new pb::MessageParser<TestMap>(() => new TestMap());
     private static readonly pb::MessageParser<TestMap> _parser = new pb::MessageParser<TestMap>(() => new TestMap());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<TestMap> Parser { get { return _parser; } }
     public static pb::MessageParser<TestMap> Parser { get { return _parser; } }
 
 
@@ -215,6 +218,7 @@ namespace Google.Protobuf.TestProtos {
       mapInt32Bytes_ = other.mapInt32Bytes_.Clone();
       mapInt32Bytes_ = other.mapInt32Bytes_.Clone();
       mapInt32Enum_ = other.mapInt32Enum_.Clone();
       mapInt32Enum_ = other.mapInt32Enum_.Clone();
       mapInt32ForeignMessage_ = other.mapInt32ForeignMessage_.Clone();
       mapInt32ForeignMessage_ = other.mapInt32ForeignMessage_.Clone();
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -422,7 +426,7 @@ namespace Google.Protobuf.TestProtos {
       if (!MapInt32Bytes.Equals(other.MapInt32Bytes)) return false;
       if (!MapInt32Bytes.Equals(other.MapInt32Bytes)) return false;
       if (!MapInt32Enum.Equals(other.MapInt32Enum)) return false;
       if (!MapInt32Enum.Equals(other.MapInt32Enum)) return false;
       if (!MapInt32ForeignMessage.Equals(other.MapInt32ForeignMessage)) return false;
       if (!MapInt32ForeignMessage.Equals(other.MapInt32ForeignMessage)) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -445,6 +449,9 @@ namespace Google.Protobuf.TestProtos {
       hash ^= MapInt32Bytes.GetHashCode();
       hash ^= MapInt32Bytes.GetHashCode();
       hash ^= MapInt32Enum.GetHashCode();
       hash ^= MapInt32Enum.GetHashCode();
       hash ^= MapInt32ForeignMessage.GetHashCode();
       hash ^= MapInt32ForeignMessage.GetHashCode();
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
       return hash;
     }
     }
 
 
@@ -472,6 +479,9 @@ namespace Google.Protobuf.TestProtos {
       mapInt32Bytes_.WriteTo(output, _map_mapInt32Bytes_codec);
       mapInt32Bytes_.WriteTo(output, _map_mapInt32Bytes_codec);
       mapInt32Enum_.WriteTo(output, _map_mapInt32Enum_codec);
       mapInt32Enum_.WriteTo(output, _map_mapInt32Enum_codec);
       mapInt32ForeignMessage_.WriteTo(output, _map_mapInt32ForeignMessage_codec);
       mapInt32ForeignMessage_.WriteTo(output, _map_mapInt32ForeignMessage_codec);
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -494,6 +504,9 @@ namespace Google.Protobuf.TestProtos {
       size += mapInt32Bytes_.CalculateSize(_map_mapInt32Bytes_codec);
       size += mapInt32Bytes_.CalculateSize(_map_mapInt32Bytes_codec);
       size += mapInt32Enum_.CalculateSize(_map_mapInt32Enum_codec);
       size += mapInt32Enum_.CalculateSize(_map_mapInt32Enum_codec);
       size += mapInt32ForeignMessage_.CalculateSize(_map_mapInt32ForeignMessage_codec);
       size += mapInt32ForeignMessage_.CalculateSize(_map_mapInt32ForeignMessage_codec);
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
       return size;
     }
     }
 
 
@@ -519,6 +532,7 @@ namespace Google.Protobuf.TestProtos {
       mapInt32Bytes_.Add(other.mapInt32Bytes_);
       mapInt32Bytes_.Add(other.mapInt32Bytes_);
       mapInt32Enum_.Add(other.mapInt32Enum_);
       mapInt32Enum_.Add(other.mapInt32Enum_);
       mapInt32ForeignMessage_.Add(other.mapInt32ForeignMessage_);
       mapInt32ForeignMessage_.Add(other.mapInt32ForeignMessage_);
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -527,7 +541,7 @@ namespace Google.Protobuf.TestProtos {
       while ((tag = input.ReadTag()) != 0) {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
         switch(tag) {
           default:
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
             break;
           case 10: {
           case 10: {
             mapInt32Int32_.AddEntriesFrom(input, _map_mapInt32Int32_codec);
             mapInt32Int32_.AddEntriesFrom(input, _map_mapInt32Int32_codec);
@@ -605,6 +619,7 @@ namespace Google.Protobuf.TestProtos {
 
 
   public sealed partial class TestMapSubmessage : pb::IMessage<TestMapSubmessage> {
   public sealed partial class TestMapSubmessage : pb::IMessage<TestMapSubmessage> {
     private static readonly pb::MessageParser<TestMapSubmessage> _parser = new pb::MessageParser<TestMapSubmessage>(() => new TestMapSubmessage());
     private static readonly pb::MessageParser<TestMapSubmessage> _parser = new pb::MessageParser<TestMapSubmessage>(() => new TestMapSubmessage());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<TestMapSubmessage> Parser { get { return _parser; } }
     public static pb::MessageParser<TestMapSubmessage> Parser { get { return _parser; } }
 
 
@@ -628,6 +643,7 @@ namespace Google.Protobuf.TestProtos {
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public TestMapSubmessage(TestMapSubmessage other) : this() {
     public TestMapSubmessage(TestMapSubmessage other) : this() {
       TestMap = other.testMap_ != null ? other.TestMap.Clone() : null;
       TestMap = other.testMap_ != null ? other.TestMap.Clone() : null;
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -660,13 +676,16 @@ namespace Google.Protobuf.TestProtos {
         return true;
         return true;
       }
       }
       if (!object.Equals(TestMap, other.TestMap)) return false;
       if (!object.Equals(TestMap, other.TestMap)) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public override int GetHashCode() {
     public override int GetHashCode() {
       int hash = 1;
       int hash = 1;
       if (testMap_ != null) hash ^= TestMap.GetHashCode();
       if (testMap_ != null) hash ^= TestMap.GetHashCode();
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
       return hash;
     }
     }
 
 
@@ -681,6 +700,9 @@ namespace Google.Protobuf.TestProtos {
         output.WriteRawTag(10);
         output.WriteRawTag(10);
         output.WriteMessage(TestMap);
         output.WriteMessage(TestMap);
       }
       }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -689,6 +711,9 @@ namespace Google.Protobuf.TestProtos {
       if (testMap_ != null) {
       if (testMap_ != null) {
         size += 1 + pb::CodedOutputStream.ComputeMessageSize(TestMap);
         size += 1 + pb::CodedOutputStream.ComputeMessageSize(TestMap);
       }
       }
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
       return size;
     }
     }
 
 
@@ -703,6 +728,7 @@ namespace Google.Protobuf.TestProtos {
         }
         }
         TestMap.MergeFrom(other.TestMap);
         TestMap.MergeFrom(other.TestMap);
       }
       }
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -711,7 +737,7 @@ namespace Google.Protobuf.TestProtos {
       while ((tag = input.ReadTag()) != 0) {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
         switch(tag) {
           default:
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
             break;
           case 10: {
           case 10: {
             if (testMap_ == null) {
             if (testMap_ == null) {
@@ -728,6 +754,7 @@ namespace Google.Protobuf.TestProtos {
 
 
   public sealed partial class TestMessageMap : pb::IMessage<TestMessageMap> {
   public sealed partial class TestMessageMap : pb::IMessage<TestMessageMap> {
     private static readonly pb::MessageParser<TestMessageMap> _parser = new pb::MessageParser<TestMessageMap>(() => new TestMessageMap());
     private static readonly pb::MessageParser<TestMessageMap> _parser = new pb::MessageParser<TestMessageMap>(() => new TestMessageMap());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<TestMessageMap> Parser { get { return _parser; } }
     public static pb::MessageParser<TestMessageMap> Parser { get { return _parser; } }
 
 
@@ -751,6 +778,7 @@ namespace Google.Protobuf.TestProtos {
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public TestMessageMap(TestMessageMap other) : this() {
     public TestMessageMap(TestMessageMap other) : this() {
       mapInt32Message_ = other.mapInt32Message_.Clone();
       mapInt32Message_ = other.mapInt32Message_.Clone();
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -782,13 +810,16 @@ namespace Google.Protobuf.TestProtos {
         return true;
         return true;
       }
       }
       if (!MapInt32Message.Equals(other.MapInt32Message)) return false;
       if (!MapInt32Message.Equals(other.MapInt32Message)) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public override int GetHashCode() {
     public override int GetHashCode() {
       int hash = 1;
       int hash = 1;
       hash ^= MapInt32Message.GetHashCode();
       hash ^= MapInt32Message.GetHashCode();
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
       return hash;
     }
     }
 
 
@@ -800,12 +831,18 @@ namespace Google.Protobuf.TestProtos {
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public void WriteTo(pb::CodedOutputStream output) {
     public void WriteTo(pb::CodedOutputStream output) {
       mapInt32Message_.WriteTo(output, _map_mapInt32Message_codec);
       mapInt32Message_.WriteTo(output, _map_mapInt32Message_codec);
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public int CalculateSize() {
     public int CalculateSize() {
       int size = 0;
       int size = 0;
       size += mapInt32Message_.CalculateSize(_map_mapInt32Message_codec);
       size += mapInt32Message_.CalculateSize(_map_mapInt32Message_codec);
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
       return size;
     }
     }
 
 
@@ -815,6 +852,7 @@ namespace Google.Protobuf.TestProtos {
         return;
         return;
       }
       }
       mapInt32Message_.Add(other.mapInt32Message_);
       mapInt32Message_.Add(other.mapInt32Message_);
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -823,7 +861,7 @@ namespace Google.Protobuf.TestProtos {
       while ((tag = input.ReadTag()) != 0) {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
         switch(tag) {
           default:
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
             break;
           case 10: {
           case 10: {
             mapInt32Message_.AddEntriesFrom(input, _map_mapInt32Message_codec);
             mapInt32Message_.AddEntriesFrom(input, _map_mapInt32Message_codec);
@@ -840,6 +878,7 @@ namespace Google.Protobuf.TestProtos {
   /// </summary>
   /// </summary>
   public sealed partial class TestSameTypeMap : pb::IMessage<TestSameTypeMap> {
   public sealed partial class TestSameTypeMap : pb::IMessage<TestSameTypeMap> {
     private static readonly pb::MessageParser<TestSameTypeMap> _parser = new pb::MessageParser<TestSameTypeMap>(() => new TestSameTypeMap());
     private static readonly pb::MessageParser<TestSameTypeMap> _parser = new pb::MessageParser<TestSameTypeMap>(() => new TestSameTypeMap());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<TestSameTypeMap> Parser { get { return _parser; } }
     public static pb::MessageParser<TestSameTypeMap> Parser { get { return _parser; } }
 
 
@@ -864,6 +903,7 @@ namespace Google.Protobuf.TestProtos {
     public TestSameTypeMap(TestSameTypeMap other) : this() {
     public TestSameTypeMap(TestSameTypeMap other) : this() {
       map1_ = other.map1_.Clone();
       map1_ = other.map1_.Clone();
       map2_ = other.map2_.Clone();
       map2_ = other.map2_.Clone();
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -906,7 +946,7 @@ namespace Google.Protobuf.TestProtos {
       }
       }
       if (!Map1.Equals(other.Map1)) return false;
       if (!Map1.Equals(other.Map1)) return false;
       if (!Map2.Equals(other.Map2)) return false;
       if (!Map2.Equals(other.Map2)) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -914,6 +954,9 @@ namespace Google.Protobuf.TestProtos {
       int hash = 1;
       int hash = 1;
       hash ^= Map1.GetHashCode();
       hash ^= Map1.GetHashCode();
       hash ^= Map2.GetHashCode();
       hash ^= Map2.GetHashCode();
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
       return hash;
     }
     }
 
 
@@ -926,6 +969,9 @@ namespace Google.Protobuf.TestProtos {
     public void WriteTo(pb::CodedOutputStream output) {
     public void WriteTo(pb::CodedOutputStream output) {
       map1_.WriteTo(output, _map_map1_codec);
       map1_.WriteTo(output, _map_map1_codec);
       map2_.WriteTo(output, _map_map2_codec);
       map2_.WriteTo(output, _map_map2_codec);
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -933,6 +979,9 @@ namespace Google.Protobuf.TestProtos {
       int size = 0;
       int size = 0;
       size += map1_.CalculateSize(_map_map1_codec);
       size += map1_.CalculateSize(_map_map1_codec);
       size += map2_.CalculateSize(_map_map2_codec);
       size += map2_.CalculateSize(_map_map2_codec);
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
       return size;
     }
     }
 
 
@@ -943,6 +992,7 @@ namespace Google.Protobuf.TestProtos {
       }
       }
       map1_.Add(other.map1_);
       map1_.Add(other.map1_);
       map2_.Add(other.map2_);
       map2_.Add(other.map2_);
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -951,7 +1001,7 @@ namespace Google.Protobuf.TestProtos {
       while ((tag = input.ReadTag()) != 0) {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
         switch(tag) {
           default:
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
             break;
           case 10: {
           case 10: {
             map1_.AddEntriesFrom(input, _map_map1_codec);
             map1_.AddEntriesFrom(input, _map_map1_codec);
@@ -969,6 +1019,7 @@ namespace Google.Protobuf.TestProtos {
 
 
   public sealed partial class TestArenaMap : pb::IMessage<TestArenaMap> {
   public sealed partial class TestArenaMap : pb::IMessage<TestArenaMap> {
     private static readonly pb::MessageParser<TestArenaMap> _parser = new pb::MessageParser<TestArenaMap>(() => new TestArenaMap());
     private static readonly pb::MessageParser<TestArenaMap> _parser = new pb::MessageParser<TestArenaMap>(() => new TestArenaMap());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<TestArenaMap> Parser { get { return _parser; } }
     public static pb::MessageParser<TestArenaMap> Parser { get { return _parser; } }
 
 
@@ -1006,6 +1057,7 @@ namespace Google.Protobuf.TestProtos {
       mapBoolBool_ = other.mapBoolBool_.Clone();
       mapBoolBool_ = other.mapBoolBool_.Clone();
       mapInt32Enum_ = other.mapInt32Enum_.Clone();
       mapInt32Enum_ = other.mapInt32Enum_.Clone();
       mapInt32ForeignMessage_ = other.mapInt32ForeignMessage_.Clone();
       mapInt32ForeignMessage_ = other.mapInt32ForeignMessage_.Clone();
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1191,7 +1243,7 @@ namespace Google.Protobuf.TestProtos {
       if (!MapBoolBool.Equals(other.MapBoolBool)) return false;
       if (!MapBoolBool.Equals(other.MapBoolBool)) return false;
       if (!MapInt32Enum.Equals(other.MapInt32Enum)) return false;
       if (!MapInt32Enum.Equals(other.MapInt32Enum)) return false;
       if (!MapInt32ForeignMessage.Equals(other.MapInt32ForeignMessage)) return false;
       if (!MapInt32ForeignMessage.Equals(other.MapInt32ForeignMessage)) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1212,6 +1264,9 @@ namespace Google.Protobuf.TestProtos {
       hash ^= MapBoolBool.GetHashCode();
       hash ^= MapBoolBool.GetHashCode();
       hash ^= MapInt32Enum.GetHashCode();
       hash ^= MapInt32Enum.GetHashCode();
       hash ^= MapInt32ForeignMessage.GetHashCode();
       hash ^= MapInt32ForeignMessage.GetHashCode();
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
       return hash;
     }
     }
 
 
@@ -1237,6 +1292,9 @@ namespace Google.Protobuf.TestProtos {
       mapBoolBool_.WriteTo(output, _map_mapBoolBool_codec);
       mapBoolBool_.WriteTo(output, _map_mapBoolBool_codec);
       mapInt32Enum_.WriteTo(output, _map_mapInt32Enum_codec);
       mapInt32Enum_.WriteTo(output, _map_mapInt32Enum_codec);
       mapInt32ForeignMessage_.WriteTo(output, _map_mapInt32ForeignMessage_codec);
       mapInt32ForeignMessage_.WriteTo(output, _map_mapInt32ForeignMessage_codec);
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1257,6 +1315,9 @@ namespace Google.Protobuf.TestProtos {
       size += mapBoolBool_.CalculateSize(_map_mapBoolBool_codec);
       size += mapBoolBool_.CalculateSize(_map_mapBoolBool_codec);
       size += mapInt32Enum_.CalculateSize(_map_mapInt32Enum_codec);
       size += mapInt32Enum_.CalculateSize(_map_mapInt32Enum_codec);
       size += mapInt32ForeignMessage_.CalculateSize(_map_mapInt32ForeignMessage_codec);
       size += mapInt32ForeignMessage_.CalculateSize(_map_mapInt32ForeignMessage_codec);
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
       return size;
     }
     }
 
 
@@ -1280,6 +1341,7 @@ namespace Google.Protobuf.TestProtos {
       mapBoolBool_.Add(other.mapBoolBool_);
       mapBoolBool_.Add(other.mapBoolBool_);
       mapInt32Enum_.Add(other.mapInt32Enum_);
       mapInt32Enum_.Add(other.mapInt32Enum_);
       mapInt32ForeignMessage_.Add(other.mapInt32ForeignMessage_);
       mapInt32ForeignMessage_.Add(other.mapInt32ForeignMessage_);
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1288,7 +1350,7 @@ namespace Google.Protobuf.TestProtos {
       while ((tag = input.ReadTag()) != 0) {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
         switch(tag) {
           default:
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
             break;
           case 10: {
           case 10: {
             mapInt32Int32_.AddEntriesFrom(input, _map_mapInt32Int32_codec);
             mapInt32Int32_.AddEntriesFrom(input, _map_mapInt32Int32_codec);
@@ -1362,6 +1424,7 @@ namespace Google.Protobuf.TestProtos {
   /// </summary>
   /// </summary>
   public sealed partial class MessageContainingEnumCalledType : pb::IMessage<MessageContainingEnumCalledType> {
   public sealed partial class MessageContainingEnumCalledType : pb::IMessage<MessageContainingEnumCalledType> {
     private static readonly pb::MessageParser<MessageContainingEnumCalledType> _parser = new pb::MessageParser<MessageContainingEnumCalledType>(() => new MessageContainingEnumCalledType());
     private static readonly pb::MessageParser<MessageContainingEnumCalledType> _parser = new pb::MessageParser<MessageContainingEnumCalledType>(() => new MessageContainingEnumCalledType());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<MessageContainingEnumCalledType> Parser { get { return _parser; } }
     public static pb::MessageParser<MessageContainingEnumCalledType> Parser { get { return _parser; } }
 
 
@@ -1385,6 +1448,7 @@ namespace Google.Protobuf.TestProtos {
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public MessageContainingEnumCalledType(MessageContainingEnumCalledType other) : this() {
     public MessageContainingEnumCalledType(MessageContainingEnumCalledType other) : this() {
       type_ = other.type_.Clone();
       type_ = other.type_.Clone();
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1416,13 +1480,16 @@ namespace Google.Protobuf.TestProtos {
         return true;
         return true;
       }
       }
       if (!Type.Equals(other.Type)) return false;
       if (!Type.Equals(other.Type)) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public override int GetHashCode() {
     public override int GetHashCode() {
       int hash = 1;
       int hash = 1;
       hash ^= Type.GetHashCode();
       hash ^= Type.GetHashCode();
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
       return hash;
     }
     }
 
 
@@ -1434,12 +1501,18 @@ namespace Google.Protobuf.TestProtos {
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public void WriteTo(pb::CodedOutputStream output) {
     public void WriteTo(pb::CodedOutputStream output) {
       type_.WriteTo(output, _map_type_codec);
       type_.WriteTo(output, _map_type_codec);
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public int CalculateSize() {
     public int CalculateSize() {
       int size = 0;
       int size = 0;
       size += type_.CalculateSize(_map_type_codec);
       size += type_.CalculateSize(_map_type_codec);
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
       return size;
     }
     }
 
 
@@ -1449,6 +1522,7 @@ namespace Google.Protobuf.TestProtos {
         return;
         return;
       }
       }
       type_.Add(other.type_);
       type_.Add(other.type_);
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1457,7 +1531,7 @@ namespace Google.Protobuf.TestProtos {
       while ((tag = input.ReadTag()) != 0) {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
         switch(tag) {
           default:
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
             break;
           case 10: {
           case 10: {
             type_.AddEntriesFrom(input, _map_type_codec);
             type_.AddEntriesFrom(input, _map_type_codec);
@@ -1485,6 +1559,7 @@ namespace Google.Protobuf.TestProtos {
   /// </summary>
   /// </summary>
   public sealed partial class MessageContainingMapCalledEntry : pb::IMessage<MessageContainingMapCalledEntry> {
   public sealed partial class MessageContainingMapCalledEntry : pb::IMessage<MessageContainingMapCalledEntry> {
     private static readonly pb::MessageParser<MessageContainingMapCalledEntry> _parser = new pb::MessageParser<MessageContainingMapCalledEntry>(() => new MessageContainingMapCalledEntry());
     private static readonly pb::MessageParser<MessageContainingMapCalledEntry> _parser = new pb::MessageParser<MessageContainingMapCalledEntry>(() => new MessageContainingMapCalledEntry());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<MessageContainingMapCalledEntry> Parser { get { return _parser; } }
     public static pb::MessageParser<MessageContainingMapCalledEntry> Parser { get { return _parser; } }
 
 
@@ -1508,6 +1583,7 @@ namespace Google.Protobuf.TestProtos {
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public MessageContainingMapCalledEntry(MessageContainingMapCalledEntry other) : this() {
     public MessageContainingMapCalledEntry(MessageContainingMapCalledEntry other) : this() {
       entry_ = other.entry_.Clone();
       entry_ = other.entry_.Clone();
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1539,13 +1615,16 @@ namespace Google.Protobuf.TestProtos {
         return true;
         return true;
       }
       }
       if (!Entry.Equals(other.Entry)) return false;
       if (!Entry.Equals(other.Entry)) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public override int GetHashCode() {
     public override int GetHashCode() {
       int hash = 1;
       int hash = 1;
       hash ^= Entry.GetHashCode();
       hash ^= Entry.GetHashCode();
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
       return hash;
     }
     }
 
 
@@ -1557,12 +1636,18 @@ namespace Google.Protobuf.TestProtos {
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public void WriteTo(pb::CodedOutputStream output) {
     public void WriteTo(pb::CodedOutputStream output) {
       entry_.WriteTo(output, _map_entry_codec);
       entry_.WriteTo(output, _map_entry_codec);
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public int CalculateSize() {
     public int CalculateSize() {
       int size = 0;
       int size = 0;
       size += entry_.CalculateSize(_map_entry_codec);
       size += entry_.CalculateSize(_map_entry_codec);
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
       return size;
     }
     }
 
 
@@ -1572,6 +1657,7 @@ namespace Google.Protobuf.TestProtos {
         return;
         return;
       }
       }
       entry_.Add(other.entry_);
       entry_.Add(other.entry_);
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1580,7 +1666,7 @@ namespace Google.Protobuf.TestProtos {
       while ((tag = input.ReadTag()) != 0) {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
         switch(tag) {
           default:
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
             break;
           case 10: {
           case 10: {
             entry_.AddEntriesFrom(input, _map_entry_codec);
             entry_.AddEntriesFrom(input, _map_entry_codec);

+ 58 - 20
csharp/src/Google.Protobuf.Test/TestProtos/TestMessagesProto3.cs

@@ -1,5 +1,7 @@
-// Generated by the protocol buffer compiler.  DO NOT EDIT!
-// source: google/protobuf/test_messages_proto3.proto
+// <auto-generated>
+//     Generated by the protocol buffer compiler.  DO NOT EDIT!
+//     source: google/protobuf/test_messages_proto3.proto
+// </auto-generated>
 #pragma warning disable 1591, 0612, 3021
 #pragma warning disable 1591, 0612, 3021
 #region Designer generated code
 #region Designer generated code
 
 
@@ -233,6 +235,7 @@ namespace ProtobufTestMessages.Proto3 {
   /// </summary>
   /// </summary>
   public sealed partial class TestAllTypesProto3 : pb::IMessage<TestAllTypesProto3> {
   public sealed partial class TestAllTypesProto3 : pb::IMessage<TestAllTypesProto3> {
     private static readonly pb::MessageParser<TestAllTypesProto3> _parser = new pb::MessageParser<TestAllTypesProto3>(() => new TestAllTypesProto3());
     private static readonly pb::MessageParser<TestAllTypesProto3> _parser = new pb::MessageParser<TestAllTypesProto3>(() => new TestAllTypesProto3());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<TestAllTypesProto3> Parser { get { return _parser; } }
     public static pb::MessageParser<TestAllTypesProto3> Parser { get { return _parser; } }
 
 
@@ -395,6 +398,7 @@ namespace ProtobufTestMessages.Proto3 {
           break;
           break;
       }
       }
 
 
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1730,8 +1734,8 @@ namespace ProtobufTestMessages.Proto3 {
       if (OptionalFixed64 != other.OptionalFixed64) return false;
       if (OptionalFixed64 != other.OptionalFixed64) return false;
       if (OptionalSfixed32 != other.OptionalSfixed32) return false;
       if (OptionalSfixed32 != other.OptionalSfixed32) return false;
       if (OptionalSfixed64 != other.OptionalSfixed64) return false;
       if (OptionalSfixed64 != other.OptionalSfixed64) return false;
-      if (OptionalFloat != other.OptionalFloat) return false;
-      if (OptionalDouble != other.OptionalDouble) return false;
+      if (!pbc::ProtobufEqualityComparers.BitwiseSingleEqualityComparer.Equals(OptionalFloat, other.OptionalFloat)) return false;
+      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(OptionalDouble, other.OptionalDouble)) return false;
       if (OptionalBool != other.OptionalBool) return false;
       if (OptionalBool != other.OptionalBool) return false;
       if (OptionalString != other.OptionalString) return false;
       if (OptionalString != other.OptionalString) return false;
       if (OptionalBytes != other.OptionalBytes) return false;
       if (OptionalBytes != other.OptionalBytes) return false;
@@ -1788,16 +1792,16 @@ namespace ProtobufTestMessages.Proto3 {
       if (OneofBytes != other.OneofBytes) return false;
       if (OneofBytes != other.OneofBytes) return false;
       if (OneofBool != other.OneofBool) return false;
       if (OneofBool != other.OneofBool) return false;
       if (OneofUint64 != other.OneofUint64) return false;
       if (OneofUint64 != other.OneofUint64) return false;
-      if (OneofFloat != other.OneofFloat) return false;
-      if (OneofDouble != other.OneofDouble) return false;
+      if (!pbc::ProtobufEqualityComparers.BitwiseSingleEqualityComparer.Equals(OneofFloat, other.OneofFloat)) return false;
+      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(OneofDouble, other.OneofDouble)) return false;
       if (OneofEnum != other.OneofEnum) return false;
       if (OneofEnum != other.OneofEnum) return false;
       if (OptionalBoolWrapper != other.OptionalBoolWrapper) return false;
       if (OptionalBoolWrapper != other.OptionalBoolWrapper) return false;
       if (OptionalInt32Wrapper != other.OptionalInt32Wrapper) return false;
       if (OptionalInt32Wrapper != other.OptionalInt32Wrapper) return false;
       if (OptionalInt64Wrapper != other.OptionalInt64Wrapper) return false;
       if (OptionalInt64Wrapper != other.OptionalInt64Wrapper) return false;
       if (OptionalUint32Wrapper != other.OptionalUint32Wrapper) return false;
       if (OptionalUint32Wrapper != other.OptionalUint32Wrapper) return false;
       if (OptionalUint64Wrapper != other.OptionalUint64Wrapper) return false;
       if (OptionalUint64Wrapper != other.OptionalUint64Wrapper) return false;
-      if (OptionalFloatWrapper != other.OptionalFloatWrapper) return false;
-      if (OptionalDoubleWrapper != other.OptionalDoubleWrapper) return false;
+      if (!pbc::ProtobufEqualityComparers.BitwiseNullableSingleEqualityComparer.Equals(OptionalFloatWrapper, other.OptionalFloatWrapper)) return false;
+      if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(OptionalDoubleWrapper, other.OptionalDoubleWrapper)) return false;
       if (OptionalStringWrapper != other.OptionalStringWrapper) return false;
       if (OptionalStringWrapper != other.OptionalStringWrapper) return false;
       if (OptionalBytesWrapper != other.OptionalBytesWrapper) return false;
       if (OptionalBytesWrapper != other.OptionalBytesWrapper) return false;
       if(!repeatedBoolWrapper_.Equals(other.repeatedBoolWrapper_)) return false;
       if(!repeatedBoolWrapper_.Equals(other.repeatedBoolWrapper_)) return false;
@@ -1840,7 +1844,7 @@ namespace ProtobufTestMessages.Proto3 {
       if (FieldName17 != other.FieldName17) return false;
       if (FieldName17 != other.FieldName17) return false;
       if (FieldName18 != other.FieldName18) return false;
       if (FieldName18 != other.FieldName18) return false;
       if (OneofFieldCase != other.OneofFieldCase) return false;
       if (OneofFieldCase != other.OneofFieldCase) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1856,8 +1860,8 @@ namespace ProtobufTestMessages.Proto3 {
       if (OptionalFixed64 != 0UL) hash ^= OptionalFixed64.GetHashCode();
       if (OptionalFixed64 != 0UL) hash ^= OptionalFixed64.GetHashCode();
       if (OptionalSfixed32 != 0) hash ^= OptionalSfixed32.GetHashCode();
       if (OptionalSfixed32 != 0) hash ^= OptionalSfixed32.GetHashCode();
       if (OptionalSfixed64 != 0L) hash ^= OptionalSfixed64.GetHashCode();
       if (OptionalSfixed64 != 0L) hash ^= OptionalSfixed64.GetHashCode();
-      if (OptionalFloat != 0F) hash ^= OptionalFloat.GetHashCode();
-      if (OptionalDouble != 0D) hash ^= OptionalDouble.GetHashCode();
+      if (OptionalFloat != 0F) hash ^= pbc::ProtobufEqualityComparers.BitwiseSingleEqualityComparer.GetHashCode(OptionalFloat);
+      if (OptionalDouble != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(OptionalDouble);
       if (OptionalBool != false) hash ^= OptionalBool.GetHashCode();
       if (OptionalBool != false) hash ^= OptionalBool.GetHashCode();
       if (OptionalString.Length != 0) hash ^= OptionalString.GetHashCode();
       if (OptionalString.Length != 0) hash ^= OptionalString.GetHashCode();
       if (OptionalBytes.Length != 0) hash ^= OptionalBytes.GetHashCode();
       if (OptionalBytes.Length != 0) hash ^= OptionalBytes.GetHashCode();
@@ -1914,16 +1918,16 @@ namespace ProtobufTestMessages.Proto3 {
       if (oneofFieldCase_ == OneofFieldOneofCase.OneofBytes) hash ^= OneofBytes.GetHashCode();
       if (oneofFieldCase_ == OneofFieldOneofCase.OneofBytes) hash ^= OneofBytes.GetHashCode();
       if (oneofFieldCase_ == OneofFieldOneofCase.OneofBool) hash ^= OneofBool.GetHashCode();
       if (oneofFieldCase_ == OneofFieldOneofCase.OneofBool) hash ^= OneofBool.GetHashCode();
       if (oneofFieldCase_ == OneofFieldOneofCase.OneofUint64) hash ^= OneofUint64.GetHashCode();
       if (oneofFieldCase_ == OneofFieldOneofCase.OneofUint64) hash ^= OneofUint64.GetHashCode();
-      if (oneofFieldCase_ == OneofFieldOneofCase.OneofFloat) hash ^= OneofFloat.GetHashCode();
-      if (oneofFieldCase_ == OneofFieldOneofCase.OneofDouble) hash ^= OneofDouble.GetHashCode();
+      if (oneofFieldCase_ == OneofFieldOneofCase.OneofFloat) hash ^= pbc::ProtobufEqualityComparers.BitwiseSingleEqualityComparer.GetHashCode(OneofFloat);
+      if (oneofFieldCase_ == OneofFieldOneofCase.OneofDouble) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(OneofDouble);
       if (oneofFieldCase_ == OneofFieldOneofCase.OneofEnum) hash ^= OneofEnum.GetHashCode();
       if (oneofFieldCase_ == OneofFieldOneofCase.OneofEnum) hash ^= OneofEnum.GetHashCode();
       if (optionalBoolWrapper_ != null) hash ^= OptionalBoolWrapper.GetHashCode();
       if (optionalBoolWrapper_ != null) hash ^= OptionalBoolWrapper.GetHashCode();
       if (optionalInt32Wrapper_ != null) hash ^= OptionalInt32Wrapper.GetHashCode();
       if (optionalInt32Wrapper_ != null) hash ^= OptionalInt32Wrapper.GetHashCode();
       if (optionalInt64Wrapper_ != null) hash ^= OptionalInt64Wrapper.GetHashCode();
       if (optionalInt64Wrapper_ != null) hash ^= OptionalInt64Wrapper.GetHashCode();
       if (optionalUint32Wrapper_ != null) hash ^= OptionalUint32Wrapper.GetHashCode();
       if (optionalUint32Wrapper_ != null) hash ^= OptionalUint32Wrapper.GetHashCode();
       if (optionalUint64Wrapper_ != null) hash ^= OptionalUint64Wrapper.GetHashCode();
       if (optionalUint64Wrapper_ != null) hash ^= OptionalUint64Wrapper.GetHashCode();
-      if (optionalFloatWrapper_ != null) hash ^= OptionalFloatWrapper.GetHashCode();
-      if (optionalDoubleWrapper_ != null) hash ^= OptionalDoubleWrapper.GetHashCode();
+      if (optionalFloatWrapper_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableSingleEqualityComparer.GetHashCode(OptionalFloatWrapper);
+      if (optionalDoubleWrapper_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(OptionalDoubleWrapper);
       if (optionalStringWrapper_ != null) hash ^= OptionalStringWrapper.GetHashCode();
       if (optionalStringWrapper_ != null) hash ^= OptionalStringWrapper.GetHashCode();
       if (optionalBytesWrapper_ != null) hash ^= OptionalBytesWrapper.GetHashCode();
       if (optionalBytesWrapper_ != null) hash ^= OptionalBytesWrapper.GetHashCode();
       hash ^= repeatedBoolWrapper_.GetHashCode();
       hash ^= repeatedBoolWrapper_.GetHashCode();
@@ -1966,6 +1970,9 @@ namespace ProtobufTestMessages.Proto3 {
       if (FieldName17 != 0) hash ^= FieldName17.GetHashCode();
       if (FieldName17 != 0) hash ^= FieldName17.GetHashCode();
       if (FieldName18 != 0) hash ^= FieldName18.GetHashCode();
       if (FieldName18 != 0) hash ^= FieldName18.GetHashCode();
       hash ^= (int) oneofFieldCase_;
       hash ^= (int) oneofFieldCase_;
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
       return hash;
     }
     }
 
 
@@ -2278,6 +2285,9 @@ namespace ProtobufTestMessages.Proto3 {
         output.WriteRawTag(144, 26);
         output.WriteRawTag(144, 26);
         output.WriteInt32(FieldName18);
         output.WriteInt32(FieldName18);
       }
       }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -2530,6 +2540,9 @@ namespace ProtobufTestMessages.Proto3 {
       if (FieldName18 != 0) {
       if (FieldName18 != 0) {
         size += 2 + pb::CodedOutputStream.ComputeInt32Size(FieldName18);
         size += 2 + pb::CodedOutputStream.ComputeInt32Size(FieldName18);
       }
       }
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
       return size;
     }
     }
 
 
@@ -2836,6 +2849,7 @@ namespace ProtobufTestMessages.Proto3 {
           break;
           break;
       }
       }
 
 
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -2844,7 +2858,7 @@ namespace ProtobufTestMessages.Proto3 {
       while ((tag = input.ReadTag()) != 0) {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
         switch(tag) {
           default:
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
             break;
           case 8: {
           case 8: {
             OptionalInt32 = input.ReadInt32();
             OptionalInt32 = input.ReadInt32();
@@ -3417,6 +3431,7 @@ namespace ProtobufTestMessages.Proto3 {
 
 
       public sealed partial class NestedMessage : pb::IMessage<NestedMessage> {
       public sealed partial class NestedMessage : pb::IMessage<NestedMessage> {
         private static readonly pb::MessageParser<NestedMessage> _parser = new pb::MessageParser<NestedMessage>(() => new NestedMessage());
         private static readonly pb::MessageParser<NestedMessage> _parser = new pb::MessageParser<NestedMessage>(() => new NestedMessage());
+        private pb::UnknownFieldSet _unknownFields;
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
         public static pb::MessageParser<NestedMessage> Parser { get { return _parser; } }
         public static pb::MessageParser<NestedMessage> Parser { get { return _parser; } }
 
 
@@ -3441,6 +3456,7 @@ namespace ProtobufTestMessages.Proto3 {
         public NestedMessage(NestedMessage other) : this() {
         public NestedMessage(NestedMessage other) : this() {
           a_ = other.a_;
           a_ = other.a_;
           Corecursive = other.corecursive_ != null ? other.Corecursive.Clone() : null;
           Corecursive = other.corecursive_ != null ? other.Corecursive.Clone() : null;
+          _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
         }
         }
 
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -3485,7 +3501,7 @@ namespace ProtobufTestMessages.Proto3 {
           }
           }
           if (A != other.A) return false;
           if (A != other.A) return false;
           if (!object.Equals(Corecursive, other.Corecursive)) return false;
           if (!object.Equals(Corecursive, other.Corecursive)) return false;
-          return true;
+          return Equals(_unknownFields, other._unknownFields);
         }
         }
 
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -3493,6 +3509,9 @@ namespace ProtobufTestMessages.Proto3 {
           int hash = 1;
           int hash = 1;
           if (A != 0) hash ^= A.GetHashCode();
           if (A != 0) hash ^= A.GetHashCode();
           if (corecursive_ != null) hash ^= Corecursive.GetHashCode();
           if (corecursive_ != null) hash ^= Corecursive.GetHashCode();
+          if (_unknownFields != null) {
+            hash ^= _unknownFields.GetHashCode();
+          }
           return hash;
           return hash;
         }
         }
 
 
@@ -3511,6 +3530,9 @@ namespace ProtobufTestMessages.Proto3 {
             output.WriteRawTag(18);
             output.WriteRawTag(18);
             output.WriteMessage(Corecursive);
             output.WriteMessage(Corecursive);
           }
           }
+          if (_unknownFields != null) {
+            _unknownFields.WriteTo(output);
+          }
         }
         }
 
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -3522,6 +3544,9 @@ namespace ProtobufTestMessages.Proto3 {
           if (corecursive_ != null) {
           if (corecursive_ != null) {
             size += 1 + pb::CodedOutputStream.ComputeMessageSize(Corecursive);
             size += 1 + pb::CodedOutputStream.ComputeMessageSize(Corecursive);
           }
           }
+          if (_unknownFields != null) {
+            size += _unknownFields.CalculateSize();
+          }
           return size;
           return size;
         }
         }
 
 
@@ -3539,6 +3564,7 @@ namespace ProtobufTestMessages.Proto3 {
             }
             }
             Corecursive.MergeFrom(other.Corecursive);
             Corecursive.MergeFrom(other.Corecursive);
           }
           }
+          _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
         }
         }
 
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -3547,7 +3573,7 @@ namespace ProtobufTestMessages.Proto3 {
           while ((tag = input.ReadTag()) != 0) {
           while ((tag = input.ReadTag()) != 0) {
             switch(tag) {
             switch(tag) {
               default:
               default:
-                input.SkipLastField();
+                _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
                 break;
                 break;
               case 8: {
               case 8: {
                 A = input.ReadInt32();
                 A = input.ReadInt32();
@@ -3573,6 +3599,7 @@ namespace ProtobufTestMessages.Proto3 {
 
 
   public sealed partial class ForeignMessage : pb::IMessage<ForeignMessage> {
   public sealed partial class ForeignMessage : pb::IMessage<ForeignMessage> {
     private static readonly pb::MessageParser<ForeignMessage> _parser = new pb::MessageParser<ForeignMessage>(() => new ForeignMessage());
     private static readonly pb::MessageParser<ForeignMessage> _parser = new pb::MessageParser<ForeignMessage>(() => new ForeignMessage());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<ForeignMessage> Parser { get { return _parser; } }
     public static pb::MessageParser<ForeignMessage> Parser { get { return _parser; } }
 
 
@@ -3596,6 +3623,7 @@ namespace ProtobufTestMessages.Proto3 {
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public ForeignMessage(ForeignMessage other) : this() {
     public ForeignMessage(ForeignMessage other) : this() {
       c_ = other.c_;
       c_ = other.c_;
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -3628,13 +3656,16 @@ namespace ProtobufTestMessages.Proto3 {
         return true;
         return true;
       }
       }
       if (C != other.C) return false;
       if (C != other.C) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public override int GetHashCode() {
     public override int GetHashCode() {
       int hash = 1;
       int hash = 1;
       if (C != 0) hash ^= C.GetHashCode();
       if (C != 0) hash ^= C.GetHashCode();
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
       return hash;
     }
     }
 
 
@@ -3649,6 +3680,9 @@ namespace ProtobufTestMessages.Proto3 {
         output.WriteRawTag(8);
         output.WriteRawTag(8);
         output.WriteInt32(C);
         output.WriteInt32(C);
       }
       }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -3657,6 +3691,9 @@ namespace ProtobufTestMessages.Proto3 {
       if (C != 0) {
       if (C != 0) {
         size += 1 + pb::CodedOutputStream.ComputeInt32Size(C);
         size += 1 + pb::CodedOutputStream.ComputeInt32Size(C);
       }
       }
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
       return size;
     }
     }
 
 
@@ -3668,6 +3705,7 @@ namespace ProtobufTestMessages.Proto3 {
       if (other.C != 0) {
       if (other.C != 0) {
         C = other.C;
         C = other.C;
       }
       }
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -3676,7 +3714,7 @@ namespace ProtobufTestMessages.Proto3 {
       while ((tag = input.ReadTag()) != 0) {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
         switch(tag) {
           default:
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
             break;
           case 8: {
           case 8: {
             C = input.ReadInt32();
             C = input.ReadInt32();

File diff suppressed because it is too large
+ 206 - 31
csharp/src/Google.Protobuf.Test/TestProtos/UnittestCustomOptionsProto3.cs


+ 18 - 4
csharp/src/Google.Protobuf.Test/TestProtos/UnittestImportProto3.cs

@@ -1,5 +1,7 @@
-// Generated by the protocol buffer compiler.  DO NOT EDIT!
-// source: unittest_import_proto3.proto
+// <auto-generated>
+//     Generated by the protocol buffer compiler.  DO NOT EDIT!
+//     source: unittest_import_proto3.proto
+// </auto-generated>
 #pragma warning disable 1591, 0612, 3021
 #pragma warning disable 1591, 0612, 3021
 #region Designer generated code
 #region Designer generated code
 
 
@@ -50,6 +52,7 @@ namespace Google.Protobuf.TestProtos {
   #region Messages
   #region Messages
   public sealed partial class ImportMessage : pb::IMessage<ImportMessage> {
   public sealed partial class ImportMessage : pb::IMessage<ImportMessage> {
     private static readonly pb::MessageParser<ImportMessage> _parser = new pb::MessageParser<ImportMessage>(() => new ImportMessage());
     private static readonly pb::MessageParser<ImportMessage> _parser = new pb::MessageParser<ImportMessage>(() => new ImportMessage());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<ImportMessage> Parser { get { return _parser; } }
     public static pb::MessageParser<ImportMessage> Parser { get { return _parser; } }
 
 
@@ -73,6 +76,7 @@ namespace Google.Protobuf.TestProtos {
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public ImportMessage(ImportMessage other) : this() {
     public ImportMessage(ImportMessage other) : this() {
       d_ = other.d_;
       d_ = other.d_;
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -105,13 +109,16 @@ namespace Google.Protobuf.TestProtos {
         return true;
         return true;
       }
       }
       if (D != other.D) return false;
       if (D != other.D) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public override int GetHashCode() {
     public override int GetHashCode() {
       int hash = 1;
       int hash = 1;
       if (D != 0) hash ^= D.GetHashCode();
       if (D != 0) hash ^= D.GetHashCode();
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
       return hash;
     }
     }
 
 
@@ -126,6 +133,9 @@ namespace Google.Protobuf.TestProtos {
         output.WriteRawTag(8);
         output.WriteRawTag(8);
         output.WriteInt32(D);
         output.WriteInt32(D);
       }
       }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -134,6 +144,9 @@ namespace Google.Protobuf.TestProtos {
       if (D != 0) {
       if (D != 0) {
         size += 1 + pb::CodedOutputStream.ComputeInt32Size(D);
         size += 1 + pb::CodedOutputStream.ComputeInt32Size(D);
       }
       }
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
       return size;
     }
     }
 
 
@@ -145,6 +158,7 @@ namespace Google.Protobuf.TestProtos {
       if (other.D != 0) {
       if (other.D != 0) {
         D = other.D;
         D = other.D;
       }
       }
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -153,7 +167,7 @@ namespace Google.Protobuf.TestProtos {
       while ((tag = input.ReadTag()) != 0) {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
         switch(tag) {
           default:
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
             break;
           case 8: {
           case 8: {
             D = input.ReadInt32();
             D = input.ReadInt32();

+ 18 - 4
csharp/src/Google.Protobuf.Test/TestProtos/UnittestImportPublicProto3.cs

@@ -1,5 +1,7 @@
-// Generated by the protocol buffer compiler.  DO NOT EDIT!
-// source: unittest_import_public_proto3.proto
+// <auto-generated>
+//     Generated by the protocol buffer compiler.  DO NOT EDIT!
+//     source: unittest_import_public_proto3.proto
+// </auto-generated>
 #pragma warning disable 1591, 0612, 3021
 #pragma warning disable 1591, 0612, 3021
 #region Designer generated code
 #region Designer generated code
 
 
@@ -38,6 +40,7 @@ namespace Google.Protobuf.TestProtos {
   #region Messages
   #region Messages
   public sealed partial class PublicImportMessage : pb::IMessage<PublicImportMessage> {
   public sealed partial class PublicImportMessage : pb::IMessage<PublicImportMessage> {
     private static readonly pb::MessageParser<PublicImportMessage> _parser = new pb::MessageParser<PublicImportMessage>(() => new PublicImportMessage());
     private static readonly pb::MessageParser<PublicImportMessage> _parser = new pb::MessageParser<PublicImportMessage>(() => new PublicImportMessage());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<PublicImportMessage> Parser { get { return _parser; } }
     public static pb::MessageParser<PublicImportMessage> Parser { get { return _parser; } }
 
 
@@ -61,6 +64,7 @@ namespace Google.Protobuf.TestProtos {
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public PublicImportMessage(PublicImportMessage other) : this() {
     public PublicImportMessage(PublicImportMessage other) : this() {
       e_ = other.e_;
       e_ = other.e_;
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -93,13 +97,16 @@ namespace Google.Protobuf.TestProtos {
         return true;
         return true;
       }
       }
       if (E != other.E) return false;
       if (E != other.E) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public override int GetHashCode() {
     public override int GetHashCode() {
       int hash = 1;
       int hash = 1;
       if (E != 0) hash ^= E.GetHashCode();
       if (E != 0) hash ^= E.GetHashCode();
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
       return hash;
     }
     }
 
 
@@ -114,6 +121,9 @@ namespace Google.Protobuf.TestProtos {
         output.WriteRawTag(8);
         output.WriteRawTag(8);
         output.WriteInt32(E);
         output.WriteInt32(E);
       }
       }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -122,6 +132,9 @@ namespace Google.Protobuf.TestProtos {
       if (E != 0) {
       if (E != 0) {
         size += 1 + pb::CodedOutputStream.ComputeInt32Size(E);
         size += 1 + pb::CodedOutputStream.ComputeInt32Size(E);
       }
       }
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
       return size;
     }
     }
 
 
@@ -133,6 +146,7 @@ namespace Google.Protobuf.TestProtos {
       if (other.E != 0) {
       if (other.E != 0) {
         E = other.E;
         E = other.E;
       }
       }
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -141,7 +155,7 @@ namespace Google.Protobuf.TestProtos {
       while ((tag = input.ReadTag()) != 0) {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
         switch(tag) {
           default:
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
             break;
           case 8: {
           case 8: {
             E = input.ReadInt32();
             E = input.ReadInt32();

+ 186 - 28
csharp/src/Google.Protobuf.Test/TestProtos/UnittestIssues.cs

@@ -1,5 +1,7 @@
-// Generated by the protocol buffer compiler.  DO NOT EDIT!
-// source: unittest_issues.proto
+// <auto-generated>
+//     Generated by the protocol buffer compiler.  DO NOT EDIT!
+//     source: unittest_issues.proto
+// </auto-generated>
 #pragma warning disable 1591, 0612, 3021
 #pragma warning disable 1591, 0612, 3021
 #region Designer generated code
 #region Designer generated code
 
 
@@ -88,6 +90,7 @@ namespace UnitTest.Issues.TestProtos {
   /// </summary>
   /// </summary>
   public sealed partial class Issue307 : pb::IMessage<Issue307> {
   public sealed partial class Issue307 : pb::IMessage<Issue307> {
     private static readonly pb::MessageParser<Issue307> _parser = new pb::MessageParser<Issue307>(() => new Issue307());
     private static readonly pb::MessageParser<Issue307> _parser = new pb::MessageParser<Issue307>(() => new Issue307());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<Issue307> Parser { get { return _parser; } }
     public static pb::MessageParser<Issue307> Parser { get { return _parser; } }
 
 
@@ -110,6 +113,7 @@ namespace UnitTest.Issues.TestProtos {
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public Issue307(Issue307 other) : this() {
     public Issue307(Issue307 other) : this() {
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -130,12 +134,15 @@ namespace UnitTest.Issues.TestProtos {
       if (ReferenceEquals(other, this)) {
       if (ReferenceEquals(other, this)) {
         return true;
         return true;
       }
       }
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public override int GetHashCode() {
     public override int GetHashCode() {
       int hash = 1;
       int hash = 1;
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
       return hash;
     }
     }
 
 
@@ -146,11 +153,17 @@ namespace UnitTest.Issues.TestProtos {
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public void WriteTo(pb::CodedOutputStream output) {
     public void WriteTo(pb::CodedOutputStream output) {
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public int CalculateSize() {
     public int CalculateSize() {
       int size = 0;
       int size = 0;
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
       return size;
     }
     }
 
 
@@ -159,6 +172,7 @@ namespace UnitTest.Issues.TestProtos {
       if (other == null) {
       if (other == null) {
         return;
         return;
       }
       }
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -167,7 +181,7 @@ namespace UnitTest.Issues.TestProtos {
       while ((tag = input.ReadTag()) != 0) {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
         switch(tag) {
           default:
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
             break;
         }
         }
       }
       }
@@ -179,6 +193,7 @@ namespace UnitTest.Issues.TestProtos {
     public static partial class Types {
     public static partial class Types {
       public sealed partial class NestedOnce : pb::IMessage<NestedOnce> {
       public sealed partial class NestedOnce : pb::IMessage<NestedOnce> {
         private static readonly pb::MessageParser<NestedOnce> _parser = new pb::MessageParser<NestedOnce>(() => new NestedOnce());
         private static readonly pb::MessageParser<NestedOnce> _parser = new pb::MessageParser<NestedOnce>(() => new NestedOnce());
+        private pb::UnknownFieldSet _unknownFields;
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
         public static pb::MessageParser<NestedOnce> Parser { get { return _parser; } }
         public static pb::MessageParser<NestedOnce> Parser { get { return _parser; } }
 
 
@@ -201,6 +216,7 @@ namespace UnitTest.Issues.TestProtos {
 
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
         public NestedOnce(NestedOnce other) : this() {
         public NestedOnce(NestedOnce other) : this() {
+          _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
         }
         }
 
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -221,12 +237,15 @@ namespace UnitTest.Issues.TestProtos {
           if (ReferenceEquals(other, this)) {
           if (ReferenceEquals(other, this)) {
             return true;
             return true;
           }
           }
-          return true;
+          return Equals(_unknownFields, other._unknownFields);
         }
         }
 
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
         public override int GetHashCode() {
         public override int GetHashCode() {
           int hash = 1;
           int hash = 1;
+          if (_unknownFields != null) {
+            hash ^= _unknownFields.GetHashCode();
+          }
           return hash;
           return hash;
         }
         }
 
 
@@ -237,11 +256,17 @@ namespace UnitTest.Issues.TestProtos {
 
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
         public void WriteTo(pb::CodedOutputStream output) {
         public void WriteTo(pb::CodedOutputStream output) {
+          if (_unknownFields != null) {
+            _unknownFields.WriteTo(output);
+          }
         }
         }
 
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
         public int CalculateSize() {
         public int CalculateSize() {
           int size = 0;
           int size = 0;
+          if (_unknownFields != null) {
+            size += _unknownFields.CalculateSize();
+          }
           return size;
           return size;
         }
         }
 
 
@@ -250,6 +275,7 @@ namespace UnitTest.Issues.TestProtos {
           if (other == null) {
           if (other == null) {
             return;
             return;
           }
           }
+          _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
         }
         }
 
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -258,7 +284,7 @@ namespace UnitTest.Issues.TestProtos {
           while ((tag = input.ReadTag()) != 0) {
           while ((tag = input.ReadTag()) != 0) {
             switch(tag) {
             switch(tag) {
               default:
               default:
-                input.SkipLastField();
+                _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
                 break;
                 break;
             }
             }
           }
           }
@@ -270,6 +296,7 @@ namespace UnitTest.Issues.TestProtos {
         public static partial class Types {
         public static partial class Types {
           public sealed partial class NestedTwice : pb::IMessage<NestedTwice> {
           public sealed partial class NestedTwice : pb::IMessage<NestedTwice> {
             private static readonly pb::MessageParser<NestedTwice> _parser = new pb::MessageParser<NestedTwice>(() => new NestedTwice());
             private static readonly pb::MessageParser<NestedTwice> _parser = new pb::MessageParser<NestedTwice>(() => new NestedTwice());
+            private pb::UnknownFieldSet _unknownFields;
             [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
             [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
             public static pb::MessageParser<NestedTwice> Parser { get { return _parser; } }
             public static pb::MessageParser<NestedTwice> Parser { get { return _parser; } }
 
 
@@ -292,6 +319,7 @@ namespace UnitTest.Issues.TestProtos {
 
 
             [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
             [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
             public NestedTwice(NestedTwice other) : this() {
             public NestedTwice(NestedTwice other) : this() {
+              _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
             }
             }
 
 
             [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
             [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -312,12 +340,15 @@ namespace UnitTest.Issues.TestProtos {
               if (ReferenceEquals(other, this)) {
               if (ReferenceEquals(other, this)) {
                 return true;
                 return true;
               }
               }
-              return true;
+              return Equals(_unknownFields, other._unknownFields);
             }
             }
 
 
             [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
             [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
             public override int GetHashCode() {
             public override int GetHashCode() {
               int hash = 1;
               int hash = 1;
+              if (_unknownFields != null) {
+                hash ^= _unknownFields.GetHashCode();
+              }
               return hash;
               return hash;
             }
             }
 
 
@@ -328,11 +359,17 @@ namespace UnitTest.Issues.TestProtos {
 
 
             [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
             [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
             public void WriteTo(pb::CodedOutputStream output) {
             public void WriteTo(pb::CodedOutputStream output) {
+              if (_unknownFields != null) {
+                _unknownFields.WriteTo(output);
+              }
             }
             }
 
 
             [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
             [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
             public int CalculateSize() {
             public int CalculateSize() {
               int size = 0;
               int size = 0;
+              if (_unknownFields != null) {
+                size += _unknownFields.CalculateSize();
+              }
               return size;
               return size;
             }
             }
 
 
@@ -341,6 +378,7 @@ namespace UnitTest.Issues.TestProtos {
               if (other == null) {
               if (other == null) {
                 return;
                 return;
               }
               }
+              _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
             }
             }
 
 
             [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
             [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -349,7 +387,7 @@ namespace UnitTest.Issues.TestProtos {
               while ((tag = input.ReadTag()) != 0) {
               while ((tag = input.ReadTag()) != 0) {
                 switch(tag) {
                 switch(tag) {
                   default:
                   default:
-                    input.SkipLastField();
+                    _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
                     break;
                     break;
                 }
                 }
               }
               }
@@ -369,6 +407,7 @@ namespace UnitTest.Issues.TestProtos {
 
 
   public sealed partial class NegativeEnumMessage : pb::IMessage<NegativeEnumMessage> {
   public sealed partial class NegativeEnumMessage : pb::IMessage<NegativeEnumMessage> {
     private static readonly pb::MessageParser<NegativeEnumMessage> _parser = new pb::MessageParser<NegativeEnumMessage>(() => new NegativeEnumMessage());
     private static readonly pb::MessageParser<NegativeEnumMessage> _parser = new pb::MessageParser<NegativeEnumMessage>(() => new NegativeEnumMessage());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<NegativeEnumMessage> Parser { get { return _parser; } }
     public static pb::MessageParser<NegativeEnumMessage> Parser { get { return _parser; } }
 
 
@@ -394,6 +433,7 @@ namespace UnitTest.Issues.TestProtos {
       value_ = other.value_;
       value_ = other.value_;
       values_ = other.values_.Clone();
       values_ = other.values_.Clone();
       packedValues_ = other.packedValues_.Clone();
       packedValues_ = other.packedValues_.Clone();
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -448,7 +488,7 @@ namespace UnitTest.Issues.TestProtos {
       if (Value != other.Value) return false;
       if (Value != other.Value) return false;
       if(!values_.Equals(other.values_)) return false;
       if(!values_.Equals(other.values_)) return false;
       if(!packedValues_.Equals(other.packedValues_)) return false;
       if(!packedValues_.Equals(other.packedValues_)) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -457,6 +497,9 @@ namespace UnitTest.Issues.TestProtos {
       if (Value != 0) hash ^= Value.GetHashCode();
       if (Value != 0) hash ^= Value.GetHashCode();
       hash ^= values_.GetHashCode();
       hash ^= values_.GetHashCode();
       hash ^= packedValues_.GetHashCode();
       hash ^= packedValues_.GetHashCode();
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
       return hash;
     }
     }
 
 
@@ -473,6 +516,9 @@ namespace UnitTest.Issues.TestProtos {
       }
       }
       values_.WriteTo(output, _repeated_values_codec);
       values_.WriteTo(output, _repeated_values_codec);
       packedValues_.WriteTo(output, _repeated_packedValues_codec);
       packedValues_.WriteTo(output, _repeated_packedValues_codec);
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -483,6 +529,9 @@ namespace UnitTest.Issues.TestProtos {
       }
       }
       size += values_.CalculateSize(_repeated_values_codec);
       size += values_.CalculateSize(_repeated_values_codec);
       size += packedValues_.CalculateSize(_repeated_packedValues_codec);
       size += packedValues_.CalculateSize(_repeated_packedValues_codec);
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
       return size;
     }
     }
 
 
@@ -496,6 +545,7 @@ namespace UnitTest.Issues.TestProtos {
       }
       }
       values_.Add(other.values_);
       values_.Add(other.values_);
       packedValues_.Add(other.packedValues_);
       packedValues_.Add(other.packedValues_);
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -504,7 +554,7 @@ namespace UnitTest.Issues.TestProtos {
       while ((tag = input.ReadTag()) != 0) {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
         switch(tag) {
           default:
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
             break;
           case 8: {
           case 8: {
             value_ = (global::UnitTest.Issues.TestProtos.NegativeEnum) input.ReadEnum();
             value_ = (global::UnitTest.Issues.TestProtos.NegativeEnum) input.ReadEnum();
@@ -528,6 +578,7 @@ namespace UnitTest.Issues.TestProtos {
 
 
   public sealed partial class DeprecatedChild : pb::IMessage<DeprecatedChild> {
   public sealed partial class DeprecatedChild : pb::IMessage<DeprecatedChild> {
     private static readonly pb::MessageParser<DeprecatedChild> _parser = new pb::MessageParser<DeprecatedChild>(() => new DeprecatedChild());
     private static readonly pb::MessageParser<DeprecatedChild> _parser = new pb::MessageParser<DeprecatedChild>(() => new DeprecatedChild());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<DeprecatedChild> Parser { get { return _parser; } }
     public static pb::MessageParser<DeprecatedChild> Parser { get { return _parser; } }
 
 
@@ -550,6 +601,7 @@ namespace UnitTest.Issues.TestProtos {
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public DeprecatedChild(DeprecatedChild other) : this() {
     public DeprecatedChild(DeprecatedChild other) : this() {
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -570,12 +622,15 @@ namespace UnitTest.Issues.TestProtos {
       if (ReferenceEquals(other, this)) {
       if (ReferenceEquals(other, this)) {
         return true;
         return true;
       }
       }
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public override int GetHashCode() {
     public override int GetHashCode() {
       int hash = 1;
       int hash = 1;
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
       return hash;
     }
     }
 
 
@@ -586,11 +641,17 @@ namespace UnitTest.Issues.TestProtos {
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public void WriteTo(pb::CodedOutputStream output) {
     public void WriteTo(pb::CodedOutputStream output) {
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public int CalculateSize() {
     public int CalculateSize() {
       int size = 0;
       int size = 0;
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
       return size;
     }
     }
 
 
@@ -599,6 +660,7 @@ namespace UnitTest.Issues.TestProtos {
       if (other == null) {
       if (other == null) {
         return;
         return;
       }
       }
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -607,7 +669,7 @@ namespace UnitTest.Issues.TestProtos {
       while ((tag = input.ReadTag()) != 0) {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
         switch(tag) {
           default:
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
             break;
         }
         }
       }
       }
@@ -617,6 +679,7 @@ namespace UnitTest.Issues.TestProtos {
 
 
   public sealed partial class DeprecatedFieldsMessage : pb::IMessage<DeprecatedFieldsMessage> {
   public sealed partial class DeprecatedFieldsMessage : pb::IMessage<DeprecatedFieldsMessage> {
     private static readonly pb::MessageParser<DeprecatedFieldsMessage> _parser = new pb::MessageParser<DeprecatedFieldsMessage>(() => new DeprecatedFieldsMessage());
     private static readonly pb::MessageParser<DeprecatedFieldsMessage> _parser = new pb::MessageParser<DeprecatedFieldsMessage>(() => new DeprecatedFieldsMessage());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<DeprecatedFieldsMessage> Parser { get { return _parser; } }
     public static pb::MessageParser<DeprecatedFieldsMessage> Parser { get { return _parser; } }
 
 
@@ -645,6 +708,7 @@ namespace UnitTest.Issues.TestProtos {
       messageArray_ = other.messageArray_.Clone();
       messageArray_ = other.messageArray_.Clone();
       enumValue_ = other.enumValue_;
       enumValue_ = other.enumValue_;
       enumArray_ = other.enumArray_.Clone();
       enumArray_ = other.enumArray_.Clone();
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -740,7 +804,7 @@ namespace UnitTest.Issues.TestProtos {
       if(!messageArray_.Equals(other.messageArray_)) return false;
       if(!messageArray_.Equals(other.messageArray_)) return false;
       if (EnumValue != other.EnumValue) return false;
       if (EnumValue != other.EnumValue) return false;
       if(!enumArray_.Equals(other.enumArray_)) return false;
       if(!enumArray_.Equals(other.enumArray_)) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -752,6 +816,9 @@ namespace UnitTest.Issues.TestProtos {
       hash ^= messageArray_.GetHashCode();
       hash ^= messageArray_.GetHashCode();
       if (EnumValue != 0) hash ^= EnumValue.GetHashCode();
       if (EnumValue != 0) hash ^= EnumValue.GetHashCode();
       hash ^= enumArray_.GetHashCode();
       hash ^= enumArray_.GetHashCode();
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
       return hash;
     }
     }
 
 
@@ -777,6 +844,9 @@ namespace UnitTest.Issues.TestProtos {
         output.WriteEnum((int) EnumValue);
         output.WriteEnum((int) EnumValue);
       }
       }
       enumArray_.WriteTo(output, _repeated_enumArray_codec);
       enumArray_.WriteTo(output, _repeated_enumArray_codec);
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -794,6 +864,9 @@ namespace UnitTest.Issues.TestProtos {
         size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) EnumValue);
         size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) EnumValue);
       }
       }
       size += enumArray_.CalculateSize(_repeated_enumArray_codec);
       size += enumArray_.CalculateSize(_repeated_enumArray_codec);
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
       return size;
     }
     }
 
 
@@ -817,6 +890,7 @@ namespace UnitTest.Issues.TestProtos {
         EnumValue = other.EnumValue;
         EnumValue = other.EnumValue;
       }
       }
       enumArray_.Add(other.enumArray_);
       enumArray_.Add(other.enumArray_);
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -825,7 +899,7 @@ namespace UnitTest.Issues.TestProtos {
       while ((tag = input.ReadTag()) != 0) {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
         switch(tag) {
           default:
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
             break;
           case 8: {
           case 8: {
             PrimitiveValue = input.ReadInt32();
             PrimitiveValue = input.ReadInt32();
@@ -867,6 +941,7 @@ namespace UnitTest.Issues.TestProtos {
   /// </summary>
   /// </summary>
   public sealed partial class ItemField : pb::IMessage<ItemField> {
   public sealed partial class ItemField : pb::IMessage<ItemField> {
     private static readonly pb::MessageParser<ItemField> _parser = new pb::MessageParser<ItemField>(() => new ItemField());
     private static readonly pb::MessageParser<ItemField> _parser = new pb::MessageParser<ItemField>(() => new ItemField());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<ItemField> Parser { get { return _parser; } }
     public static pb::MessageParser<ItemField> Parser { get { return _parser; } }
 
 
@@ -890,6 +965,7 @@ namespace UnitTest.Issues.TestProtos {
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public ItemField(ItemField other) : this() {
     public ItemField(ItemField other) : this() {
       item_ = other.item_;
       item_ = other.item_;
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -922,13 +998,16 @@ namespace UnitTest.Issues.TestProtos {
         return true;
         return true;
       }
       }
       if (Item != other.Item) return false;
       if (Item != other.Item) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public override int GetHashCode() {
     public override int GetHashCode() {
       int hash = 1;
       int hash = 1;
       if (Item != 0) hash ^= Item.GetHashCode();
       if (Item != 0) hash ^= Item.GetHashCode();
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
       return hash;
     }
     }
 
 
@@ -943,6 +1022,9 @@ namespace UnitTest.Issues.TestProtos {
         output.WriteRawTag(8);
         output.WriteRawTag(8);
         output.WriteInt32(Item);
         output.WriteInt32(Item);
       }
       }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -951,6 +1033,9 @@ namespace UnitTest.Issues.TestProtos {
       if (Item != 0) {
       if (Item != 0) {
         size += 1 + pb::CodedOutputStream.ComputeInt32Size(Item);
         size += 1 + pb::CodedOutputStream.ComputeInt32Size(Item);
       }
       }
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
       return size;
     }
     }
 
 
@@ -962,6 +1047,7 @@ namespace UnitTest.Issues.TestProtos {
       if (other.Item != 0) {
       if (other.Item != 0) {
         Item = other.Item;
         Item = other.Item;
       }
       }
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -970,7 +1056,7 @@ namespace UnitTest.Issues.TestProtos {
       while ((tag = input.ReadTag()) != 0) {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
         switch(tag) {
           default:
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
             break;
           case 8: {
           case 8: {
             Item = input.ReadInt32();
             Item = input.ReadInt32();
@@ -984,6 +1070,7 @@ namespace UnitTest.Issues.TestProtos {
 
 
   public sealed partial class ReservedNames : pb::IMessage<ReservedNames> {
   public sealed partial class ReservedNames : pb::IMessage<ReservedNames> {
     private static readonly pb::MessageParser<ReservedNames> _parser = new pb::MessageParser<ReservedNames>(() => new ReservedNames());
     private static readonly pb::MessageParser<ReservedNames> _parser = new pb::MessageParser<ReservedNames>(() => new ReservedNames());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<ReservedNames> Parser { get { return _parser; } }
     public static pb::MessageParser<ReservedNames> Parser { get { return _parser; } }
 
 
@@ -1008,6 +1095,7 @@ namespace UnitTest.Issues.TestProtos {
     public ReservedNames(ReservedNames other) : this() {
     public ReservedNames(ReservedNames other) : this() {
       types_ = other.types_;
       types_ = other.types_;
       descriptor_ = other.descriptor_;
       descriptor_ = other.descriptor_;
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1052,7 +1140,7 @@ namespace UnitTest.Issues.TestProtos {
       }
       }
       if (Types_ != other.Types_) return false;
       if (Types_ != other.Types_) return false;
       if (Descriptor_ != other.Descriptor_) return false;
       if (Descriptor_ != other.Descriptor_) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1060,6 +1148,9 @@ namespace UnitTest.Issues.TestProtos {
       int hash = 1;
       int hash = 1;
       if (Types_ != 0) hash ^= Types_.GetHashCode();
       if (Types_ != 0) hash ^= Types_.GetHashCode();
       if (Descriptor_ != 0) hash ^= Descriptor_.GetHashCode();
       if (Descriptor_ != 0) hash ^= Descriptor_.GetHashCode();
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
       return hash;
     }
     }
 
 
@@ -1078,6 +1169,9 @@ namespace UnitTest.Issues.TestProtos {
         output.WriteRawTag(16);
         output.WriteRawTag(16);
         output.WriteInt32(Descriptor_);
         output.WriteInt32(Descriptor_);
       }
       }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1089,6 +1183,9 @@ namespace UnitTest.Issues.TestProtos {
       if (Descriptor_ != 0) {
       if (Descriptor_ != 0) {
         size += 1 + pb::CodedOutputStream.ComputeInt32Size(Descriptor_);
         size += 1 + pb::CodedOutputStream.ComputeInt32Size(Descriptor_);
       }
       }
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
       return size;
     }
     }
 
 
@@ -1103,6 +1200,7 @@ namespace UnitTest.Issues.TestProtos {
       if (other.Descriptor_ != 0) {
       if (other.Descriptor_ != 0) {
         Descriptor_ = other.Descriptor_;
         Descriptor_ = other.Descriptor_;
       }
       }
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1111,7 +1209,7 @@ namespace UnitTest.Issues.TestProtos {
       while ((tag = input.ReadTag()) != 0) {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
         switch(tag) {
           default:
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
             break;
           case 8: {
           case 8: {
             Types_ = input.ReadInt32();
             Types_ = input.ReadInt32();
@@ -1134,6 +1232,7 @@ namespace UnitTest.Issues.TestProtos {
       /// </summary>
       /// </summary>
       public sealed partial class SomeNestedType : pb::IMessage<SomeNestedType> {
       public sealed partial class SomeNestedType : pb::IMessage<SomeNestedType> {
         private static readonly pb::MessageParser<SomeNestedType> _parser = new pb::MessageParser<SomeNestedType>(() => new SomeNestedType());
         private static readonly pb::MessageParser<SomeNestedType> _parser = new pb::MessageParser<SomeNestedType>(() => new SomeNestedType());
+        private pb::UnknownFieldSet _unknownFields;
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
         public static pb::MessageParser<SomeNestedType> Parser { get { return _parser; } }
         public static pb::MessageParser<SomeNestedType> Parser { get { return _parser; } }
 
 
@@ -1156,6 +1255,7 @@ namespace UnitTest.Issues.TestProtos {
 
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
         public SomeNestedType(SomeNestedType other) : this() {
         public SomeNestedType(SomeNestedType other) : this() {
+          _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
         }
         }
 
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1176,12 +1276,15 @@ namespace UnitTest.Issues.TestProtos {
           if (ReferenceEquals(other, this)) {
           if (ReferenceEquals(other, this)) {
             return true;
             return true;
           }
           }
-          return true;
+          return Equals(_unknownFields, other._unknownFields);
         }
         }
 
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
         public override int GetHashCode() {
         public override int GetHashCode() {
           int hash = 1;
           int hash = 1;
+          if (_unknownFields != null) {
+            hash ^= _unknownFields.GetHashCode();
+          }
           return hash;
           return hash;
         }
         }
 
 
@@ -1192,11 +1295,17 @@ namespace UnitTest.Issues.TestProtos {
 
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
         public void WriteTo(pb::CodedOutputStream output) {
         public void WriteTo(pb::CodedOutputStream output) {
+          if (_unknownFields != null) {
+            _unknownFields.WriteTo(output);
+          }
         }
         }
 
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
         public int CalculateSize() {
         public int CalculateSize() {
           int size = 0;
           int size = 0;
+          if (_unknownFields != null) {
+            size += _unknownFields.CalculateSize();
+          }
           return size;
           return size;
         }
         }
 
 
@@ -1205,6 +1314,7 @@ namespace UnitTest.Issues.TestProtos {
           if (other == null) {
           if (other == null) {
             return;
             return;
           }
           }
+          _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
         }
         }
 
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1213,7 +1323,7 @@ namespace UnitTest.Issues.TestProtos {
           while ((tag = input.ReadTag()) != 0) {
           while ((tag = input.ReadTag()) != 0) {
             switch(tag) {
             switch(tag) {
               default:
               default:
-                input.SkipLastField();
+                _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
                 break;
                 break;
             }
             }
           }
           }
@@ -1240,6 +1350,7 @@ namespace UnitTest.Issues.TestProtos {
   /// </summary>
   /// </summary>
   public sealed partial class TestJsonFieldOrdering : pb::IMessage<TestJsonFieldOrdering> {
   public sealed partial class TestJsonFieldOrdering : pb::IMessage<TestJsonFieldOrdering> {
     private static readonly pb::MessageParser<TestJsonFieldOrdering> _parser = new pb::MessageParser<TestJsonFieldOrdering>(() => new TestJsonFieldOrdering());
     private static readonly pb::MessageParser<TestJsonFieldOrdering> _parser = new pb::MessageParser<TestJsonFieldOrdering>(() => new TestJsonFieldOrdering());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<TestJsonFieldOrdering> Parser { get { return _parser; } }
     public static pb::MessageParser<TestJsonFieldOrdering> Parser { get { return _parser; } }
 
 
@@ -1282,6 +1393,7 @@ namespace UnitTest.Issues.TestProtos {
           break;
           break;
       }
       }
 
 
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1414,7 +1526,7 @@ namespace UnitTest.Issues.TestProtos {
       if (O2String != other.O2String) return false;
       if (O2String != other.O2String) return false;
       if (O1Case != other.O1Case) return false;
       if (O1Case != other.O1Case) return false;
       if (O2Case != other.O2Case) return false;
       if (O2Case != other.O2Case) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1428,6 +1540,9 @@ namespace UnitTest.Issues.TestProtos {
       if (o2Case_ == O2OneofCase.O2String) hash ^= O2String.GetHashCode();
       if (o2Case_ == O2OneofCase.O2String) hash ^= O2String.GetHashCode();
       hash ^= (int) o1Case_;
       hash ^= (int) o1Case_;
       hash ^= (int) o2Case_;
       hash ^= (int) o2Case_;
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
       return hash;
     }
     }
 
 
@@ -1462,6 +1577,9 @@ namespace UnitTest.Issues.TestProtos {
         output.WriteRawTag(48);
         output.WriteRawTag(48);
         output.WriteInt32(O2Int32);
         output.WriteInt32(O2Int32);
       }
       }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1485,6 +1603,9 @@ namespace UnitTest.Issues.TestProtos {
       if (o2Case_ == O2OneofCase.O2String) {
       if (o2Case_ == O2OneofCase.O2String) {
         size += 1 + pb::CodedOutputStream.ComputeStringSize(O2String);
         size += 1 + pb::CodedOutputStream.ComputeStringSize(O2String);
       }
       }
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
       return size;
     }
     }
 
 
@@ -1517,6 +1638,7 @@ namespace UnitTest.Issues.TestProtos {
           break;
           break;
       }
       }
 
 
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1525,7 +1647,7 @@ namespace UnitTest.Issues.TestProtos {
       while ((tag = input.ReadTag()) != 0) {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
         switch(tag) {
           default:
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
             break;
           case 10: {
           case 10: {
             PlainString = input.ReadString();
             PlainString = input.ReadString();
@@ -1559,6 +1681,7 @@ namespace UnitTest.Issues.TestProtos {
 
 
   public sealed partial class TestJsonName : pb::IMessage<TestJsonName> {
   public sealed partial class TestJsonName : pb::IMessage<TestJsonName> {
     private static readonly pb::MessageParser<TestJsonName> _parser = new pb::MessageParser<TestJsonName>(() => new TestJsonName());
     private static readonly pb::MessageParser<TestJsonName> _parser = new pb::MessageParser<TestJsonName>(() => new TestJsonName());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<TestJsonName> Parser { get { return _parser; } }
     public static pb::MessageParser<TestJsonName> Parser { get { return _parser; } }
 
 
@@ -1584,6 +1707,7 @@ namespace UnitTest.Issues.TestProtos {
       name_ = other.name_;
       name_ = other.name_;
       description_ = other.description_;
       description_ = other.description_;
       guid_ = other.guid_;
       guid_ = other.guid_;
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1643,7 +1767,7 @@ namespace UnitTest.Issues.TestProtos {
       if (Name != other.Name) return false;
       if (Name != other.Name) return false;
       if (Description != other.Description) return false;
       if (Description != other.Description) return false;
       if (Guid != other.Guid) return false;
       if (Guid != other.Guid) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1652,6 +1776,9 @@ namespace UnitTest.Issues.TestProtos {
       if (Name.Length != 0) hash ^= Name.GetHashCode();
       if (Name.Length != 0) hash ^= Name.GetHashCode();
       if (Description.Length != 0) hash ^= Description.GetHashCode();
       if (Description.Length != 0) hash ^= Description.GetHashCode();
       if (Guid.Length != 0) hash ^= Guid.GetHashCode();
       if (Guid.Length != 0) hash ^= Guid.GetHashCode();
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
       return hash;
     }
     }
 
 
@@ -1674,6 +1801,9 @@ namespace UnitTest.Issues.TestProtos {
         output.WriteRawTag(26);
         output.WriteRawTag(26);
         output.WriteString(Guid);
         output.WriteString(Guid);
       }
       }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1688,6 +1818,9 @@ namespace UnitTest.Issues.TestProtos {
       if (Guid.Length != 0) {
       if (Guid.Length != 0) {
         size += 1 + pb::CodedOutputStream.ComputeStringSize(Guid);
         size += 1 + pb::CodedOutputStream.ComputeStringSize(Guid);
       }
       }
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
       return size;
     }
     }
 
 
@@ -1705,6 +1838,7 @@ namespace UnitTest.Issues.TestProtos {
       if (other.Guid.Length != 0) {
       if (other.Guid.Length != 0) {
         Guid = other.Guid;
         Guid = other.Guid;
       }
       }
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1713,7 +1847,7 @@ namespace UnitTest.Issues.TestProtos {
       while ((tag = input.ReadTag()) != 0) {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
         switch(tag) {
           default:
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
             break;
           case 10: {
           case 10: {
             Name = input.ReadString();
             Name = input.ReadString();
@@ -1740,6 +1874,7 @@ namespace UnitTest.Issues.TestProtos {
   /// </summary>
   /// </summary>
   public sealed partial class OneofMerging : pb::IMessage<OneofMerging> {
   public sealed partial class OneofMerging : pb::IMessage<OneofMerging> {
     private static readonly pb::MessageParser<OneofMerging> _parser = new pb::MessageParser<OneofMerging>(() => new OneofMerging());
     private static readonly pb::MessageParser<OneofMerging> _parser = new pb::MessageParser<OneofMerging>(() => new OneofMerging());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<OneofMerging> Parser { get { return _parser; } }
     public static pb::MessageParser<OneofMerging> Parser { get { return _parser; } }
 
 
@@ -1771,6 +1906,7 @@ namespace UnitTest.Issues.TestProtos {
           break;
           break;
       }
       }
 
 
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1835,7 +1971,7 @@ namespace UnitTest.Issues.TestProtos {
       if (Text != other.Text) return false;
       if (Text != other.Text) return false;
       if (!object.Equals(Nested, other.Nested)) return false;
       if (!object.Equals(Nested, other.Nested)) return false;
       if (ValueCase != other.ValueCase) return false;
       if (ValueCase != other.ValueCase) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1844,6 +1980,9 @@ namespace UnitTest.Issues.TestProtos {
       if (valueCase_ == ValueOneofCase.Text) hash ^= Text.GetHashCode();
       if (valueCase_ == ValueOneofCase.Text) hash ^= Text.GetHashCode();
       if (valueCase_ == ValueOneofCase.Nested) hash ^= Nested.GetHashCode();
       if (valueCase_ == ValueOneofCase.Nested) hash ^= Nested.GetHashCode();
       hash ^= (int) valueCase_;
       hash ^= (int) valueCase_;
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
       return hash;
     }
     }
 
 
@@ -1862,6 +2001,9 @@ namespace UnitTest.Issues.TestProtos {
         output.WriteRawTag(18);
         output.WriteRawTag(18);
         output.WriteMessage(Nested);
         output.WriteMessage(Nested);
       }
       }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1873,6 +2015,9 @@ namespace UnitTest.Issues.TestProtos {
       if (valueCase_ == ValueOneofCase.Nested) {
       if (valueCase_ == ValueOneofCase.Nested) {
         size += 1 + pb::CodedOutputStream.ComputeMessageSize(Nested);
         size += 1 + pb::CodedOutputStream.ComputeMessageSize(Nested);
       }
       }
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
       return size;
     }
     }
 
 
@@ -1893,6 +2038,7 @@ namespace UnitTest.Issues.TestProtos {
           break;
           break;
       }
       }
 
 
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1901,7 +2047,7 @@ namespace UnitTest.Issues.TestProtos {
       while ((tag = input.ReadTag()) != 0) {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
         switch(tag) {
           default:
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
             break;
           case 10: {
           case 10: {
             Text = input.ReadString();
             Text = input.ReadString();
@@ -1926,6 +2072,7 @@ namespace UnitTest.Issues.TestProtos {
     public static partial class Types {
     public static partial class Types {
       public sealed partial class Nested : pb::IMessage<Nested> {
       public sealed partial class Nested : pb::IMessage<Nested> {
         private static readonly pb::MessageParser<Nested> _parser = new pb::MessageParser<Nested>(() => new Nested());
         private static readonly pb::MessageParser<Nested> _parser = new pb::MessageParser<Nested>(() => new Nested());
+        private pb::UnknownFieldSet _unknownFields;
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
         public static pb::MessageParser<Nested> Parser { get { return _parser; } }
         public static pb::MessageParser<Nested> Parser { get { return _parser; } }
 
 
@@ -1950,6 +2097,7 @@ namespace UnitTest.Issues.TestProtos {
         public Nested(Nested other) : this() {
         public Nested(Nested other) : this() {
           x_ = other.x_;
           x_ = other.x_;
           y_ = other.y_;
           y_ = other.y_;
+          _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
         }
         }
 
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1994,7 +2142,7 @@ namespace UnitTest.Issues.TestProtos {
           }
           }
           if (X != other.X) return false;
           if (X != other.X) return false;
           if (Y != other.Y) return false;
           if (Y != other.Y) return false;
-          return true;
+          return Equals(_unknownFields, other._unknownFields);
         }
         }
 
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -2002,6 +2150,9 @@ namespace UnitTest.Issues.TestProtos {
           int hash = 1;
           int hash = 1;
           if (X != 0) hash ^= X.GetHashCode();
           if (X != 0) hash ^= X.GetHashCode();
           if (Y != 0) hash ^= Y.GetHashCode();
           if (Y != 0) hash ^= Y.GetHashCode();
+          if (_unknownFields != null) {
+            hash ^= _unknownFields.GetHashCode();
+          }
           return hash;
           return hash;
         }
         }
 
 
@@ -2020,6 +2171,9 @@ namespace UnitTest.Issues.TestProtos {
             output.WriteRawTag(16);
             output.WriteRawTag(16);
             output.WriteInt32(Y);
             output.WriteInt32(Y);
           }
           }
+          if (_unknownFields != null) {
+            _unknownFields.WriteTo(output);
+          }
         }
         }
 
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -2031,6 +2185,9 @@ namespace UnitTest.Issues.TestProtos {
           if (Y != 0) {
           if (Y != 0) {
             size += 1 + pb::CodedOutputStream.ComputeInt32Size(Y);
             size += 1 + pb::CodedOutputStream.ComputeInt32Size(Y);
           }
           }
+          if (_unknownFields != null) {
+            size += _unknownFields.CalculateSize();
+          }
           return size;
           return size;
         }
         }
 
 
@@ -2045,6 +2202,7 @@ namespace UnitTest.Issues.TestProtos {
           if (other.Y != 0) {
           if (other.Y != 0) {
             Y = other.Y;
             Y = other.Y;
           }
           }
+          _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
         }
         }
 
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -2053,7 +2211,7 @@ namespace UnitTest.Issues.TestProtos {
           while ((tag = input.ReadTag()) != 0) {
           while ((tag = input.ReadTag()) != 0) {
             switch(tag) {
             switch(tag) {
               default:
               default:
-                input.SkipLastField();
+                _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
                 break;
                 break;
               case 8: {
               case 8: {
                 X = input.ReadInt32();
                 X = input.ReadInt32();

File diff suppressed because it is too large
+ 206 - 47
csharp/src/Google.Protobuf.Test/TestProtos/UnittestProto3.cs


+ 68 - 18
csharp/src/Google.Protobuf.Test/TestProtos/UnittestWellKnownTypes.cs

@@ -1,5 +1,7 @@
-// Generated by the protocol buffer compiler.  DO NOT EDIT!
-// source: google/protobuf/unittest_well_known_types.proto
+// <auto-generated>
+//     Generated by the protocol buffer compiler.  DO NOT EDIT!
+//     source: google/protobuf/unittest_well_known_types.proto
+// </auto-generated>
 #pragma warning disable 1591, 0612, 3021
 #pragma warning disable 1591, 0612, 3021
 #region Designer generated code
 #region Designer generated code
 
 
@@ -179,6 +181,7 @@ namespace Google.Protobuf.TestProtos {
   /// </summary>
   /// </summary>
   public sealed partial class TestWellKnownTypes : pb::IMessage<TestWellKnownTypes> {
   public sealed partial class TestWellKnownTypes : pb::IMessage<TestWellKnownTypes> {
     private static readonly pb::MessageParser<TestWellKnownTypes> _parser = new pb::MessageParser<TestWellKnownTypes>(() => new TestWellKnownTypes());
     private static readonly pb::MessageParser<TestWellKnownTypes> _parser = new pb::MessageParser<TestWellKnownTypes>(() => new TestWellKnownTypes());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<TestWellKnownTypes> Parser { get { return _parser; } }
     public static pb::MessageParser<TestWellKnownTypes> Parser { get { return _parser; } }
 
 
@@ -220,6 +223,7 @@ namespace Google.Protobuf.TestProtos {
       StringField = other.StringField;
       StringField = other.StringField;
       BytesField = other.BytesField;
       BytesField = other.BytesField;
       ValueField = other.valueField_ != null ? other.ValueField.Clone() : null;
       ValueField = other.valueField_ != null ? other.ValueField.Clone() : null;
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -470,8 +474,8 @@ namespace Google.Protobuf.TestProtos {
       if (!object.Equals(StructField, other.StructField)) return false;
       if (!object.Equals(StructField, other.StructField)) return false;
       if (!object.Equals(TimestampField, other.TimestampField)) return false;
       if (!object.Equals(TimestampField, other.TimestampField)) return false;
       if (!object.Equals(TypeField, other.TypeField)) return false;
       if (!object.Equals(TypeField, other.TypeField)) return false;
-      if (DoubleField != other.DoubleField) return false;
-      if (FloatField != other.FloatField) return false;
+      if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField, other.DoubleField)) return false;
+      if (!pbc::ProtobufEqualityComparers.BitwiseNullableSingleEqualityComparer.Equals(FloatField, other.FloatField)) return false;
       if (Int64Field != other.Int64Field) return false;
       if (Int64Field != other.Int64Field) return false;
       if (Uint64Field != other.Uint64Field) return false;
       if (Uint64Field != other.Uint64Field) return false;
       if (Int32Field != other.Int32Field) return false;
       if (Int32Field != other.Int32Field) return false;
@@ -480,7 +484,7 @@ namespace Google.Protobuf.TestProtos {
       if (StringField != other.StringField) return false;
       if (StringField != other.StringField) return false;
       if (BytesField != other.BytesField) return false;
       if (BytesField != other.BytesField) return false;
       if (!object.Equals(ValueField, other.ValueField)) return false;
       if (!object.Equals(ValueField, other.ValueField)) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -495,8 +499,8 @@ namespace Google.Protobuf.TestProtos {
       if (structField_ != null) hash ^= StructField.GetHashCode();
       if (structField_ != null) hash ^= StructField.GetHashCode();
       if (timestampField_ != null) hash ^= TimestampField.GetHashCode();
       if (timestampField_ != null) hash ^= TimestampField.GetHashCode();
       if (typeField_ != null) hash ^= TypeField.GetHashCode();
       if (typeField_ != null) hash ^= TypeField.GetHashCode();
-      if (doubleField_ != null) hash ^= DoubleField.GetHashCode();
-      if (floatField_ != null) hash ^= FloatField.GetHashCode();
+      if (doubleField_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField);
+      if (floatField_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableSingleEqualityComparer.GetHashCode(FloatField);
       if (int64Field_ != null) hash ^= Int64Field.GetHashCode();
       if (int64Field_ != null) hash ^= Int64Field.GetHashCode();
       if (uint64Field_ != null) hash ^= Uint64Field.GetHashCode();
       if (uint64Field_ != null) hash ^= Uint64Field.GetHashCode();
       if (int32Field_ != null) hash ^= Int32Field.GetHashCode();
       if (int32Field_ != null) hash ^= Int32Field.GetHashCode();
@@ -505,6 +509,9 @@ namespace Google.Protobuf.TestProtos {
       if (stringField_ != null) hash ^= StringField.GetHashCode();
       if (stringField_ != null) hash ^= StringField.GetHashCode();
       if (bytesField_ != null) hash ^= BytesField.GetHashCode();
       if (bytesField_ != null) hash ^= BytesField.GetHashCode();
       if (valueField_ != null) hash ^= ValueField.GetHashCode();
       if (valueField_ != null) hash ^= ValueField.GetHashCode();
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
       return hash;
     }
     }
 
 
@@ -582,6 +589,9 @@ namespace Google.Protobuf.TestProtos {
         output.WriteRawTag(154, 1);
         output.WriteRawTag(154, 1);
         output.WriteMessage(ValueField);
         output.WriteMessage(ValueField);
       }
       }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -644,6 +654,9 @@ namespace Google.Protobuf.TestProtos {
       if (valueField_ != null) {
       if (valueField_ != null) {
         size += 2 + pb::CodedOutputStream.ComputeMessageSize(ValueField);
         size += 2 + pb::CodedOutputStream.ComputeMessageSize(ValueField);
       }
       }
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
       return size;
     }
     }
 
 
@@ -757,6 +770,7 @@ namespace Google.Protobuf.TestProtos {
         }
         }
         ValueField.MergeFrom(other.ValueField);
         ValueField.MergeFrom(other.ValueField);
       }
       }
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -765,7 +779,7 @@ namespace Google.Protobuf.TestProtos {
       while ((tag = input.ReadTag()) != 0) {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
         switch(tag) {
           default:
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
             break;
           case 10: {
           case 10: {
             if (anyField_ == null) {
             if (anyField_ == null) {
@@ -911,6 +925,7 @@ namespace Google.Protobuf.TestProtos {
   /// </summary>
   /// </summary>
   public sealed partial class RepeatedWellKnownTypes : pb::IMessage<RepeatedWellKnownTypes> {
   public sealed partial class RepeatedWellKnownTypes : pb::IMessage<RepeatedWellKnownTypes> {
     private static readonly pb::MessageParser<RepeatedWellKnownTypes> _parser = new pb::MessageParser<RepeatedWellKnownTypes>(() => new RepeatedWellKnownTypes());
     private static readonly pb::MessageParser<RepeatedWellKnownTypes> _parser = new pb::MessageParser<RepeatedWellKnownTypes>(() => new RepeatedWellKnownTypes());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<RepeatedWellKnownTypes> Parser { get { return _parser; } }
     public static pb::MessageParser<RepeatedWellKnownTypes> Parser { get { return _parser; } }
 
 
@@ -951,6 +966,7 @@ namespace Google.Protobuf.TestProtos {
       boolField_ = other.boolField_.Clone();
       boolField_ = other.boolField_.Clone();
       stringField_ = other.stringField_.Clone();
       stringField_ = other.stringField_.Clone();
       bytesField_ = other.bytesField_.Clone();
       bytesField_ = other.bytesField_.Clone();
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1172,7 +1188,7 @@ namespace Google.Protobuf.TestProtos {
       if(!boolField_.Equals(other.boolField_)) return false;
       if(!boolField_.Equals(other.boolField_)) return false;
       if(!stringField_.Equals(other.stringField_)) return false;
       if(!stringField_.Equals(other.stringField_)) return false;
       if(!bytesField_.Equals(other.bytesField_)) return false;
       if(!bytesField_.Equals(other.bytesField_)) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1196,6 +1212,9 @@ namespace Google.Protobuf.TestProtos {
       hash ^= boolField_.GetHashCode();
       hash ^= boolField_.GetHashCode();
       hash ^= stringField_.GetHashCode();
       hash ^= stringField_.GetHashCode();
       hash ^= bytesField_.GetHashCode();
       hash ^= bytesField_.GetHashCode();
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
       return hash;
     }
     }
 
 
@@ -1224,6 +1243,9 @@ namespace Google.Protobuf.TestProtos {
       boolField_.WriteTo(output, _repeated_boolField_codec);
       boolField_.WriteTo(output, _repeated_boolField_codec);
       stringField_.WriteTo(output, _repeated_stringField_codec);
       stringField_.WriteTo(output, _repeated_stringField_codec);
       bytesField_.WriteTo(output, _repeated_bytesField_codec);
       bytesField_.WriteTo(output, _repeated_bytesField_codec);
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1247,6 +1269,9 @@ namespace Google.Protobuf.TestProtos {
       size += boolField_.CalculateSize(_repeated_boolField_codec);
       size += boolField_.CalculateSize(_repeated_boolField_codec);
       size += stringField_.CalculateSize(_repeated_stringField_codec);
       size += stringField_.CalculateSize(_repeated_stringField_codec);
       size += bytesField_.CalculateSize(_repeated_bytesField_codec);
       size += bytesField_.CalculateSize(_repeated_bytesField_codec);
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
       return size;
     }
     }
 
 
@@ -1273,6 +1298,7 @@ namespace Google.Protobuf.TestProtos {
       boolField_.Add(other.boolField_);
       boolField_.Add(other.boolField_);
       stringField_.Add(other.stringField_);
       stringField_.Add(other.stringField_);
       bytesField_.Add(other.bytesField_);
       bytesField_.Add(other.bytesField_);
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1281,7 +1307,7 @@ namespace Google.Protobuf.TestProtos {
       while ((tag = input.ReadTag()) != 0) {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
         switch(tag) {
           default:
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
             break;
           case 10: {
           case 10: {
             anyField_.AddEntriesFrom(input, _repeated_anyField_codec);
             anyField_.AddEntriesFrom(input, _repeated_anyField_codec);
@@ -1363,6 +1389,7 @@ namespace Google.Protobuf.TestProtos {
 
 
   public sealed partial class OneofWellKnownTypes : pb::IMessage<OneofWellKnownTypes> {
   public sealed partial class OneofWellKnownTypes : pb::IMessage<OneofWellKnownTypes> {
     private static readonly pb::MessageParser<OneofWellKnownTypes> _parser = new pb::MessageParser<OneofWellKnownTypes>(() => new OneofWellKnownTypes());
     private static readonly pb::MessageParser<OneofWellKnownTypes> _parser = new pb::MessageParser<OneofWellKnownTypes>(() => new OneofWellKnownTypes());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<OneofWellKnownTypes> Parser { get { return _parser; } }
     public static pb::MessageParser<OneofWellKnownTypes> Parser { get { return _parser; } }
 
 
@@ -1442,6 +1469,7 @@ namespace Google.Protobuf.TestProtos {
           break;
           break;
       }
       }
 
 
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1713,8 +1741,8 @@ namespace Google.Protobuf.TestProtos {
       if (!object.Equals(StructField, other.StructField)) return false;
       if (!object.Equals(StructField, other.StructField)) return false;
       if (!object.Equals(TimestampField, other.TimestampField)) return false;
       if (!object.Equals(TimestampField, other.TimestampField)) return false;
       if (!object.Equals(TypeField, other.TypeField)) return false;
       if (!object.Equals(TypeField, other.TypeField)) return false;
-      if (DoubleField != other.DoubleField) return false;
-      if (FloatField != other.FloatField) return false;
+      if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField, other.DoubleField)) return false;
+      if (!pbc::ProtobufEqualityComparers.BitwiseNullableSingleEqualityComparer.Equals(FloatField, other.FloatField)) return false;
       if (Int64Field != other.Int64Field) return false;
       if (Int64Field != other.Int64Field) return false;
       if (Uint64Field != other.Uint64Field) return false;
       if (Uint64Field != other.Uint64Field) return false;
       if (Int32Field != other.Int32Field) return false;
       if (Int32Field != other.Int32Field) return false;
@@ -1723,7 +1751,7 @@ namespace Google.Protobuf.TestProtos {
       if (StringField != other.StringField) return false;
       if (StringField != other.StringField) return false;
       if (BytesField != other.BytesField) return false;
       if (BytesField != other.BytesField) return false;
       if (OneofFieldCase != other.OneofFieldCase) return false;
       if (OneofFieldCase != other.OneofFieldCase) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1738,8 +1766,8 @@ namespace Google.Protobuf.TestProtos {
       if (oneofFieldCase_ == OneofFieldOneofCase.StructField) hash ^= StructField.GetHashCode();
       if (oneofFieldCase_ == OneofFieldOneofCase.StructField) hash ^= StructField.GetHashCode();
       if (oneofFieldCase_ == OneofFieldOneofCase.TimestampField) hash ^= TimestampField.GetHashCode();
       if (oneofFieldCase_ == OneofFieldOneofCase.TimestampField) hash ^= TimestampField.GetHashCode();
       if (oneofFieldCase_ == OneofFieldOneofCase.TypeField) hash ^= TypeField.GetHashCode();
       if (oneofFieldCase_ == OneofFieldOneofCase.TypeField) hash ^= TypeField.GetHashCode();
-      if (oneofFieldCase_ == OneofFieldOneofCase.DoubleField) hash ^= DoubleField.GetHashCode();
-      if (oneofFieldCase_ == OneofFieldOneofCase.FloatField) hash ^= FloatField.GetHashCode();
+      if (oneofFieldCase_ == OneofFieldOneofCase.DoubleField) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField);
+      if (oneofFieldCase_ == OneofFieldOneofCase.FloatField) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableSingleEqualityComparer.GetHashCode(FloatField);
       if (oneofFieldCase_ == OneofFieldOneofCase.Int64Field) hash ^= Int64Field.GetHashCode();
       if (oneofFieldCase_ == OneofFieldOneofCase.Int64Field) hash ^= Int64Field.GetHashCode();
       if (oneofFieldCase_ == OneofFieldOneofCase.Uint64Field) hash ^= Uint64Field.GetHashCode();
       if (oneofFieldCase_ == OneofFieldOneofCase.Uint64Field) hash ^= Uint64Field.GetHashCode();
       if (oneofFieldCase_ == OneofFieldOneofCase.Int32Field) hash ^= Int32Field.GetHashCode();
       if (oneofFieldCase_ == OneofFieldOneofCase.Int32Field) hash ^= Int32Field.GetHashCode();
@@ -1748,6 +1776,9 @@ namespace Google.Protobuf.TestProtos {
       if (oneofFieldCase_ == OneofFieldOneofCase.StringField) hash ^= StringField.GetHashCode();
       if (oneofFieldCase_ == OneofFieldOneofCase.StringField) hash ^= StringField.GetHashCode();
       if (oneofFieldCase_ == OneofFieldOneofCase.BytesField) hash ^= BytesField.GetHashCode();
       if (oneofFieldCase_ == OneofFieldOneofCase.BytesField) hash ^= BytesField.GetHashCode();
       hash ^= (int) oneofFieldCase_;
       hash ^= (int) oneofFieldCase_;
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
       return hash;
     }
     }
 
 
@@ -1821,6 +1852,9 @@ namespace Google.Protobuf.TestProtos {
       if (oneofFieldCase_ == OneofFieldOneofCase.BytesField) {
       if (oneofFieldCase_ == OneofFieldOneofCase.BytesField) {
         _oneof_bytesField_codec.WriteTagAndValue(output, (pb::ByteString) oneofField_);
         _oneof_bytesField_codec.WriteTagAndValue(output, (pb::ByteString) oneofField_);
       }
       }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1880,6 +1914,9 @@ namespace Google.Protobuf.TestProtos {
       if (oneofFieldCase_ == OneofFieldOneofCase.BytesField) {
       if (oneofFieldCase_ == OneofFieldOneofCase.BytesField) {
         size += _oneof_bytesField_codec.CalculateSizeWithTag(BytesField);
         size += _oneof_bytesField_codec.CalculateSizeWithTag(BytesField);
       }
       }
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
       return size;
     }
     }
 
 
@@ -1972,6 +2009,7 @@ namespace Google.Protobuf.TestProtos {
           break;
           break;
       }
       }
 
 
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1980,7 +2018,7 @@ namespace Google.Protobuf.TestProtos {
       while ((tag = input.ReadTag()) != 0) {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
         switch(tag) {
           default:
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
             break;
           case 10: {
           case 10: {
             global::Google.Protobuf.WellKnownTypes.Any subBuilder = new global::Google.Protobuf.WellKnownTypes.Any();
             global::Google.Protobuf.WellKnownTypes.Any subBuilder = new global::Google.Protobuf.WellKnownTypes.Any();
@@ -2112,6 +2150,7 @@ namespace Google.Protobuf.TestProtos {
   /// </summary>
   /// </summary>
   public sealed partial class MapWellKnownTypes : pb::IMessage<MapWellKnownTypes> {
   public sealed partial class MapWellKnownTypes : pb::IMessage<MapWellKnownTypes> {
     private static readonly pb::MessageParser<MapWellKnownTypes> _parser = new pb::MessageParser<MapWellKnownTypes>(() => new MapWellKnownTypes());
     private static readonly pb::MessageParser<MapWellKnownTypes> _parser = new pb::MessageParser<MapWellKnownTypes>(() => new MapWellKnownTypes());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<MapWellKnownTypes> Parser { get { return _parser; } }
     public static pb::MessageParser<MapWellKnownTypes> Parser { get { return _parser; } }
 
 
@@ -2152,6 +2191,7 @@ namespace Google.Protobuf.TestProtos {
       boolField_ = other.boolField_.Clone();
       boolField_ = other.boolField_.Clone();
       stringField_ = other.stringField_.Clone();
       stringField_ = other.stringField_.Clone();
       bytesField_ = other.bytesField_.Clone();
       bytesField_ = other.bytesField_.Clone();
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -2370,7 +2410,7 @@ namespace Google.Protobuf.TestProtos {
       if (!BoolField.Equals(other.BoolField)) return false;
       if (!BoolField.Equals(other.BoolField)) return false;
       if (!StringField.Equals(other.StringField)) return false;
       if (!StringField.Equals(other.StringField)) return false;
       if (!BytesField.Equals(other.BytesField)) return false;
       if (!BytesField.Equals(other.BytesField)) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -2394,6 +2434,9 @@ namespace Google.Protobuf.TestProtos {
       hash ^= BoolField.GetHashCode();
       hash ^= BoolField.GetHashCode();
       hash ^= StringField.GetHashCode();
       hash ^= StringField.GetHashCode();
       hash ^= BytesField.GetHashCode();
       hash ^= BytesField.GetHashCode();
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
       return hash;
     }
     }
 
 
@@ -2422,6 +2465,9 @@ namespace Google.Protobuf.TestProtos {
       boolField_.WriteTo(output, _map_boolField_codec);
       boolField_.WriteTo(output, _map_boolField_codec);
       stringField_.WriteTo(output, _map_stringField_codec);
       stringField_.WriteTo(output, _map_stringField_codec);
       bytesField_.WriteTo(output, _map_bytesField_codec);
       bytesField_.WriteTo(output, _map_bytesField_codec);
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -2445,6 +2491,9 @@ namespace Google.Protobuf.TestProtos {
       size += boolField_.CalculateSize(_map_boolField_codec);
       size += boolField_.CalculateSize(_map_boolField_codec);
       size += stringField_.CalculateSize(_map_stringField_codec);
       size += stringField_.CalculateSize(_map_stringField_codec);
       size += bytesField_.CalculateSize(_map_bytesField_codec);
       size += bytesField_.CalculateSize(_map_bytesField_codec);
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
       return size;
     }
     }
 
 
@@ -2471,6 +2520,7 @@ namespace Google.Protobuf.TestProtos {
       boolField_.Add(other.boolField_);
       boolField_.Add(other.boolField_);
       stringField_.Add(other.stringField_);
       stringField_.Add(other.stringField_);
       bytesField_.Add(other.bytesField_);
       bytesField_.Add(other.bytesField_);
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -2479,7 +2529,7 @@ namespace Google.Protobuf.TestProtos {
       while ((tag = input.ReadTag()) != 0) {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
         switch(tag) {
           default:
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
             break;
           case 10: {
           case 10: {
             anyField_.AddEntriesFrom(input, _map_anyField_codec);
             anyField_.AddEntriesFrom(input, _map_anyField_codec);

+ 128 - 0
csharp/src/Google.Protobuf.Test/UnknownFieldSetTest.cs

@@ -0,0 +1,128 @@
+#region Copyright notice and license
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#endregion
+
+using System;
+using Google.Protobuf.TestProtos;
+using NUnit.Framework;
+
+namespace Google.Protobuf
+{
+    public class UnknownFieldSetTest
+    {
+        [Test]
+        public void EmptyUnknownFieldSet()
+        {
+            UnknownFieldSet unknownFields = new UnknownFieldSet();
+            Assert.AreEqual(0, unknownFields.CalculateSize());
+        }
+
+        [Test]
+        public void MergeUnknownFieldSet()
+        {
+            UnknownFieldSet unknownFields = new UnknownFieldSet();
+            UnknownField field = new UnknownField();
+            field.AddFixed32(123);
+            unknownFields.AddOrReplaceField(1, field);
+            UnknownFieldSet otherUnknownFields = new UnknownFieldSet();
+            Assert.IsFalse(otherUnknownFields.HasField(1));
+            UnknownFieldSet.MergeFrom(otherUnknownFields, unknownFields);
+            Assert.IsTrue(otherUnknownFields.HasField(1));
+        }
+
+        [Test]
+        public void TestMergeCodedInput()
+        {
+            var message = SampleMessages.CreateFullTestAllTypes();
+            var emptyMessage = new TestEmptyMessage();
+            emptyMessage.MergeFrom(message.ToByteArray());
+            Assert.AreEqual(message.CalculateSize(), emptyMessage.CalculateSize());
+            Assert.AreEqual(message.ToByteArray(), emptyMessage.ToByteArray());
+
+            var newMessage = new TestAllTypes();
+            newMessage.MergeFrom(emptyMessage.ToByteArray());
+            Assert.AreEqual(message, newMessage);
+            Assert.AreEqual(message.CalculateSize(), newMessage.CalculateSize());
+        }
+
+        [Test]
+        public void TestMergeMessage()
+        {
+            var message = SampleMessages.CreateFullTestAllTypes();
+            var emptyMessage = new TestEmptyMessage();
+            var otherEmptyMessage = new TestEmptyMessage();
+            emptyMessage.MergeFrom(message.ToByteArray());
+            otherEmptyMessage.MergeFrom(emptyMessage);
+
+            Assert.AreEqual(message.CalculateSize(), otherEmptyMessage.CalculateSize());
+            Assert.AreEqual(message.ToByteArray(), otherEmptyMessage.ToByteArray());
+        }
+
+        [Test]
+        public void TestEquals()
+        {
+            var message = SampleMessages.CreateFullTestAllTypes();
+            var emptyMessage = new TestEmptyMessage();
+            var otherEmptyMessage = new TestEmptyMessage();
+            Assert.AreEqual(emptyMessage, otherEmptyMessage);
+            emptyMessage.MergeFrom(message.ToByteArray());
+            Assert.AreNotEqual(emptyMessage.CalculateSize(),
+                               otherEmptyMessage.CalculateSize());
+            Assert.AreNotEqual(emptyMessage, otherEmptyMessage);
+        }
+
+        [Test]
+        public void TestHashCode()
+        {
+            var message = SampleMessages.CreateFullTestAllTypes();
+            var emptyMessage = new TestEmptyMessage();
+            int hashCode = emptyMessage.GetHashCode();
+            emptyMessage.MergeFrom(message.ToByteArray());
+            Assert.AreNotEqual(hashCode, emptyMessage.GetHashCode());
+        }
+
+        [Test]
+        public void TestClone()
+        {
+            var emptyMessage = new TestEmptyMessage();
+            var otherEmptyMessage = new TestEmptyMessage();
+            otherEmptyMessage = emptyMessage.Clone();
+            Assert.AreEqual(emptyMessage.CalculateSize(), otherEmptyMessage.CalculateSize());
+            Assert.AreEqual(emptyMessage.ToByteArray(), otherEmptyMessage.ToByteArray());
+
+            var message = SampleMessages.CreateFullTestAllTypes();
+            emptyMessage.MergeFrom(message.ToByteArray());
+            otherEmptyMessage = emptyMessage.Clone();
+            Assert.AreEqual(message.CalculateSize(), otherEmptyMessage.CalculateSize());
+            Assert.AreEqual(message.ToByteArray(), otherEmptyMessage.ToByteArray());
+        }
+    }
+}

+ 11 - 0
csharp/src/Google.Protobuf.Test/WellKnownTypes/WrappersTest.cs

@@ -417,5 +417,16 @@ namespace Google.Protobuf.WellKnownTypes
             TestWellKnownTypes.Descriptor.Fields[TestWellKnownTypes.StringFieldFieldNumber].Accessor.Clear(message);
             TestWellKnownTypes.Descriptor.Fields[TestWellKnownTypes.StringFieldFieldNumber].Accessor.Clear(message);
             Assert.IsNull(message.StringField);
             Assert.IsNull(message.StringField);
         }
         }
+
+        [Test]
+        public void NaNComparisons()
+        {
+            var message1 = new TestWellKnownTypes { DoubleField = SampleNaNs.Regular };
+            var message2 = new TestWellKnownTypes { DoubleField = SampleNaNs.PayloadFlipped };
+            var message3 = new TestWellKnownTypes { DoubleField = SampleNaNs.Regular };
+
+            EqualityTester.AssertInequality(message1, message2);
+            EqualityTester.AssertEquality(message1, message3);
+        }
     }
     }
 }
 }

+ 4 - 2
csharp/src/Google.Protobuf/CodedInputStream.cs

@@ -424,7 +424,10 @@ namespace Google.Protobuf
             }
             }
         }
         }
 
 
-        private void SkipGroup(uint startGroupTag)
+        /// <summary>
+        /// Skip a group.
+        /// </summary>
+        internal void SkipGroup(uint startGroupTag)
         {
         {
             // Note: Currently we expect this to be the way that groups are read. We could put the recursion
             // 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...
             // depth changes into the ReadTag method instead, potentially...
@@ -1270,7 +1273,6 @@ namespace Google.Protobuf
                 }
                 }
             }
             }
         }
         }
-
         #endregion
         #endregion
     }
     }
 }
 }

+ 89 - 0
csharp/src/Google.Protobuf/Collections/Lists.cs

@@ -0,0 +1,89 @@
+#region Copyright notice and license
+// Protocol Buffers - Google's data interchange format
+// Copyright 2017 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#endregion
+
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+
+namespace Google.Protobuf.Collections
+{
+    /// <summary>
+    /// Utility to compare if two Lists are the same, and the hash code
+    /// of a List.
+    /// </summary>
+    public static class Lists
+    {
+        /// <summary>
+        /// Checks if two lists are equal.
+        /// </summary>
+        public static bool Equals<T>(List<T> left, List<T> right)
+        {
+            if (left == right)
+            {
+                return true;
+            }
+            if (left == null || right == null)
+            {
+                return false;
+            }
+            if (left.Count != right.Count)
+            {
+                return false;
+            }
+            IEqualityComparer<T> comparer = EqualityComparer<T>.Default;
+            for (int i = 0; i < left.Count; i++)
+            {
+                if (!comparer.Equals(left[i], right[i]))
+                {
+                    return false;
+                }
+            }
+            return true;
+        }
+
+        /// <summary>
+        /// Gets the list's hash code.
+        /// </summary>
+        public static int GetHashCode<T>(List<T> list)
+        {
+            if (list == null)
+            {
+                return 0;
+            }
+            int hash = 31;
+            foreach (T element in list)
+            {
+                hash = hash * 29 + element.GetHashCode();
+            }
+            return hash;
+        }
+    }
+}

+ 11 - 11
csharp/src/Google.Protobuf/Collections/MapField.cs

@@ -71,9 +71,12 @@ namespace Google.Protobuf.Collections
         , IReadOnlyDictionary<TKey, TValue>
         , IReadOnlyDictionary<TKey, TValue>
 #endif
 #endif
     {
     {
+        private static readonly EqualityComparer<TValue> ValueEqualityComparer = ProtobufEqualityComparers.GetEqualityComparer<TValue>();
+        private static readonly EqualityComparer<TKey> KeyEqualityComparer = ProtobufEqualityComparers.GetEqualityComparer<TKey>();
+
         // TODO: Don't create the map/list until we have an entry. (Assume many maps will be empty.)
         // TODO: Don't create the map/list until we have an entry. (Assume many maps will be empty.)
         private readonly Dictionary<TKey, LinkedListNode<KeyValuePair<TKey, TValue>>> map =
         private readonly Dictionary<TKey, LinkedListNode<KeyValuePair<TKey, TValue>>> map =
-            new Dictionary<TKey, LinkedListNode<KeyValuePair<TKey, TValue>>>();
+            new Dictionary<TKey, LinkedListNode<KeyValuePair<TKey, TValue>>>(KeyEqualityComparer);
         private readonly LinkedList<KeyValuePair<TKey, TValue>> list = new LinkedList<KeyValuePair<TKey, TValue>>();
         private readonly LinkedList<KeyValuePair<TKey, TValue>> list = new LinkedList<KeyValuePair<TKey, TValue>>();
 
 
         /// <summary>
         /// <summary>
@@ -131,11 +134,8 @@ namespace Google.Protobuf.Collections
             return map.ContainsKey(key);
             return map.ContainsKey(key);
         }
         }
 
 
-        private bool ContainsValue(TValue value)
-        {
-            var comparer = EqualityComparer<TValue>.Default;
-            return list.Any(pair => comparer.Equals(pair.Value, value));
-        }
+        private bool ContainsValue(TValue value) =>
+            list.Any(pair => ValueEqualityComparer.Equals(pair.Value, value));
 
 
         /// <summary>
         /// <summary>
         /// Removes the entry identified by the given key from the map.
         /// Removes the entry identified by the given key from the map.
@@ -293,8 +293,7 @@ namespace Google.Protobuf.Collections
         bool ICollection<KeyValuePair<TKey, TValue>>.Contains(KeyValuePair<TKey, TValue> item)
         bool ICollection<KeyValuePair<TKey, TValue>>.Contains(KeyValuePair<TKey, TValue> item)
         {
         {
             TValue value;
             TValue value;
-            return TryGetValue(item.Key, out value)
-                && EqualityComparer<TValue>.Default.Equals(item.Value, value);
+            return TryGetValue(item.Key, out value) && ValueEqualityComparer.Equals(item.Value, value);
         }
         }
 
 
         /// <summary>
         /// <summary>
@@ -363,11 +362,12 @@ namespace Google.Protobuf.Collections
         /// </returns>
         /// </returns>
         public override int GetHashCode()
         public override int GetHashCode()
         {
         {
-            var valueComparer = EqualityComparer<TValue>.Default;
+            var keyComparer = KeyEqualityComparer;
+            var valueComparer = ValueEqualityComparer;
             int hash = 0;
             int hash = 0;
             foreach (var pair in list)
             foreach (var pair in list)
             {
             {
-                hash ^= pair.Key.GetHashCode() * 31 + valueComparer.GetHashCode(pair.Value);
+                hash ^= keyComparer.GetHashCode(pair.Key) * 31 + valueComparer.GetHashCode(pair.Value);
             }
             }
             return hash;
             return hash;
         }
         }
@@ -394,7 +394,7 @@ namespace Google.Protobuf.Collections
             {
             {
                 return false;
                 return false;
             }
             }
-            var valueComparer = EqualityComparer<TValue>.Default;
+            var valueComparer = ValueEqualityComparer;
             foreach (var pair in this)
             foreach (var pair in this)
             {
             {
                 TValue value;
                 TValue value;

+ 130 - 0
csharp/src/Google.Protobuf/Collections/ProtobufEqualityComparers.cs

@@ -0,0 +1,130 @@
+#region Copyright notice and license
+// Protocol Buffers - Google's data interchange format
+// Copyright 2017 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#endregion
+
+using System;
+using System.Collections.Generic;
+
+namespace Google.Protobuf.Collections
+{
+    /// <summary>
+    /// Provides a central place to implement equality comparisons, primarily for bitwise float/double equality.
+    /// </summary>
+    public static class ProtobufEqualityComparers
+    {
+        /// <summary>
+        /// Returns an equality comparer for <typeparamref name="T"/> suitable for Protobuf equality comparisons.
+        /// This is usually just the default equality comparer for the type, but floating point numbers are compared
+        /// bitwise.
+        /// </summary>
+        /// <typeparam name="T">The type of equality comparer to return.</typeparam>
+        /// <returns>The equality comparer.</returns>
+        public static EqualityComparer<T> GetEqualityComparer<T>()
+        {
+            return typeof(T) == typeof(double) ? (EqualityComparer<T>) (object) BitwiseDoubleEqualityComparer
+                : typeof(T) == typeof(float) ? (EqualityComparer<T>) (object) BitwiseSingleEqualityComparer
+                : typeof(T) == typeof(double?) ? (EqualityComparer<T>) (object) BitwiseNullableDoubleEqualityComparer
+                : typeof(T) == typeof(float?) ? (EqualityComparer<T>) (object) BitwiseNullableSingleEqualityComparer
+                : EqualityComparer<T>.Default;
+        }
+
+        /// <summary>
+        /// Returns an equality comparer suitable for comparing 64-bit floating point values, by bitwise comparison.
+        /// (NaN values are considered equal, but only when they have the same representation.)
+        /// </summary>
+        public static EqualityComparer<double> BitwiseDoubleEqualityComparer { get; } = new BitwiseDoubleEqualityComparerImpl();
+
+        /// <summary>
+        /// Returns an equality comparer suitable for comparing 32-bit floating point values, by bitwise comparison.
+        /// (NaN values are considered equal, but only when they have the same representation.)
+        /// </summary>
+        public static EqualityComparer<float> BitwiseSingleEqualityComparer { get; } = new BitwiseSingleEqualityComparerImpl();
+
+        /// <summary>
+        /// Returns an equality comparer suitable for comparing nullable 64-bit floating point values, by bitwise comparison.
+        /// (NaN values are considered equal, but only when they have the same representation.)
+        /// </summary>
+        public static EqualityComparer<double?> BitwiseNullableDoubleEqualityComparer { get; } = new BitwiseNullableDoubleEqualityComparerImpl();
+
+        /// <summary>
+        /// Returns an equality comparer suitable for comparing nullable 32-bit floating point values, by bitwise comparison.
+        /// (NaN values are considered equal, but only when they have the same representation.)
+        /// </summary>
+        public static EqualityComparer<float?> BitwiseNullableSingleEqualityComparer { get; } = new BitwiseNullableSingleEqualityComparerImpl();
+
+        private class BitwiseDoubleEqualityComparerImpl : EqualityComparer<double>
+        {
+            public override bool Equals(double x, double y) =>
+                BitConverter.DoubleToInt64Bits(x) == BitConverter.DoubleToInt64Bits(y);
+
+            public override int GetHashCode(double obj) =>
+                BitConverter.DoubleToInt64Bits(obj).GetHashCode();
+        }
+
+        private class BitwiseSingleEqualityComparerImpl : EqualityComparer<float>
+        {
+            // Just promote values to double and use BitConverter.DoubleToInt64Bits,
+            // as there's no BitConverter.SingleToInt32Bits, unfortunately.
+
+            public override bool Equals(float x, float y) =>
+                BitConverter.DoubleToInt64Bits(x) == BitConverter.DoubleToInt64Bits(y);
+
+            public override int GetHashCode(float obj) =>
+                BitConverter.DoubleToInt64Bits(obj).GetHashCode();
+        }
+
+        private class BitwiseNullableDoubleEqualityComparerImpl : EqualityComparer<double?>
+        {
+            public override bool Equals(double? x, double? y) =>
+                x == null && y == null ? true
+                : x == null || y == null ? false
+                : BitwiseDoubleEqualityComparer.Equals(x.Value, y.Value);
+
+            // The hash code for null is just a constant which is at least *unlikely* to be used
+            // elsewhere. (Compared with 0, say.)
+            public override int GetHashCode(double? obj) =>
+                obj == null ? 293864 : BitwiseDoubleEqualityComparer.GetHashCode(obj.Value);
+        }
+
+        private class BitwiseNullableSingleEqualityComparerImpl : EqualityComparer<float?>
+        {
+            public override bool Equals(float? x, float? y) =>
+                x == null && y == null ? true
+                : x == null || y == null ? false
+                : BitwiseSingleEqualityComparer.Equals(x.Value, y.Value);
+
+            // The hash code for null is just a constant which is at least *unlikely* to be used
+            // elsewhere. (Compared with 0, say.)
+            public override int GetHashCode(float? obj) =>
+                obj == null ? 293864 : BitwiseSingleEqualityComparer.GetHashCode(obj.Value);
+        }
+    }
+}

+ 3 - 2
csharp/src/Google.Protobuf/Collections/RepeatedField.cs

@@ -51,6 +51,7 @@ namespace Google.Protobuf.Collections
         , IReadOnlyList<T>
         , IReadOnlyList<T>
 #endif
 #endif
     {
     {
+        private static readonly EqualityComparer<T> EqualityComparer = ProtobufEqualityComparers.GetEqualityComparer<T>();
         private static readonly T[] EmptyArray = new T[0];
         private static readonly T[] EmptyArray = new T[0];
         private const int MinArraySize = 8;
         private const int MinArraySize = 8;
 
 
@@ -434,7 +435,7 @@ namespace Google.Protobuf.Collections
             {
             {
                 return false;
                 return false;
             }
             }
-            EqualityComparer<T> comparer = EqualityComparer<T>.Default;
+            EqualityComparer<T> comparer = EqualityComparer;
             for (int i = 0; i < count; i++)
             for (int i = 0; i < count; i++)
             {
             {
                 if (!comparer.Equals(array[i], other.array[i]))
                 if (!comparer.Equals(array[i], other.array[i]))
@@ -454,7 +455,7 @@ namespace Google.Protobuf.Collections
         public int IndexOf(T item)
         public int IndexOf(T item)
         {
         {
             ProtoPreconditions.CheckNotNullUnconstrained(item, nameof(item));
             ProtoPreconditions.CheckNotNullUnconstrained(item, nameof(item));
-            EqualityComparer<T> comparer = EqualityComparer<T>.Default;
+            EqualityComparer<T> comparer = EqualityComparer;
             for (int i = 0; i < count; i++)
             for (int i = 0; i < count; i++)
             {
             {
                 if (comparer.Equals(array[i], item))
                 if (comparer.Equals(array[i], item))

+ 3 - 1
csharp/src/Google.Protobuf/FieldCodec.cs

@@ -30,6 +30,7 @@
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #endregion
 #endregion
 
 
+using Google.Protobuf.Collections;
 using Google.Protobuf.Compatibility;
 using Google.Protobuf.Compatibility;
 using Google.Protobuf.WellKnownTypes;
 using Google.Protobuf.WellKnownTypes;
 using System;
 using System;
@@ -346,6 +347,7 @@ namespace Google.Protobuf
     /// </remarks>
     /// </remarks>
     public sealed class FieldCodec<T>
     public sealed class FieldCodec<T>
     {
     {
+        private static readonly EqualityComparer<T> EqualityComparer = ProtobufEqualityComparers.GetEqualityComparer<T>();
         private static readonly T DefaultDefault;
         private static readonly T DefaultDefault;
         // Only non-nullable value types support packing. This is the simplest way of detecting that.
         // Only non-nullable value types support packing. This is the simplest way of detecting that.
         private static readonly bool TypeSupportsPacking = default(T) != null;
         private static readonly bool TypeSupportsPacking = default(T) != null;
@@ -469,6 +471,6 @@ namespace Google.Protobuf
         /// </summary>
         /// </summary>
         public int CalculateSizeWithTag(T value) => IsDefault(value) ? 0 : ValueSizeCalculator(value) + tagSize;
         public int CalculateSizeWithTag(T value) => IsDefault(value) ? 0 : ValueSizeCalculator(value) + tagSize;
 
 
-        private bool IsDefault(T value) => EqualityComparer<T>.Default.Equals(value, DefaultValue);
+        private bool IsDefault(T value) => EqualityComparer.Equals(value, DefaultValue);
     }
     }
 }
 }

File diff suppressed because it is too large
+ 199 - 29
csharp/src/Google.Protobuf/Reflection/Descriptor.cs


+ 263 - 0
csharp/src/Google.Protobuf/UnknownField.cs

@@ -0,0 +1,263 @@
+#region Copyright notice and license
+// Protocol Buffers - Google's data interchange format
+// Copyright 2017 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using Google.Protobuf.Collections;
+
+namespace Google.Protobuf
+{
+    /// <summary>
+    /// Represents a single field in an UnknownFieldSet.
+    ///
+    /// An UnknownField consists of four lists of values. The lists correspond
+    /// to the four "wire types" used in the protocol buffer binary format.
+    /// Normally, only one of the four lists will contain any values, since it
+    /// is impossible to define a valid message type that declares two different
+    /// types for the same field number. However, the code is designed to allow
+    /// for the case where the same unknown field number is encountered using
+    /// multiple different wire types.
+    ///
+    /// </summary>
+    internal sealed class UnknownField
+    {
+        private List<ulong> varintList;
+        private List<uint> fixed32List;
+        private List<ulong> fixed64List;
+        private List<ByteString> lengthDelimitedList;
+
+        /// <summary>
+        /// Creates a new UnknownField.
+        /// </summary>
+        public UnknownField()
+        {
+        }
+
+        /// <summary>
+        /// Checks if two unknown field are equal.
+        /// </summary>
+        public override bool Equals(object other)
+        {
+            if (ReferenceEquals(this, other))
+            {
+                return true;
+            }
+            UnknownField otherField = other as UnknownField;
+            return otherField != null
+                   && Lists.Equals(varintList, otherField.varintList)
+                   && Lists.Equals(fixed32List, otherField.fixed32List)
+                   && Lists.Equals(fixed64List, otherField.fixed64List)
+                   && Lists.Equals(lengthDelimitedList, otherField.lengthDelimitedList);
+        }
+
+        /// <summary>
+        /// Get the hash code of the unknown field.
+        /// </summary>
+        public override int GetHashCode()
+        {
+            int hash = 43;
+            hash = hash * 47 + Lists.GetHashCode(varintList);
+            hash = hash * 47 + Lists.GetHashCode(fixed32List);
+            hash = hash * 47 + Lists.GetHashCode(fixed64List);
+            hash = hash * 47 + Lists.GetHashCode(lengthDelimitedList);
+            return hash;
+        }
+
+        /// <summary>
+        /// Serializes the field, including the field number, and writes it to
+        /// <paramref name="output"/>
+        /// </summary>
+        /// <param name="fieldNumber">The unknown field number.</param>
+        /// <param name="output">The CodedOutputStream to write to.</param>
+        internal void WriteTo(int fieldNumber, CodedOutputStream output)
+        {
+            if (varintList != null)
+            {
+                foreach (ulong value in varintList)
+                {
+                    output.WriteTag(fieldNumber, WireFormat.WireType.Varint);
+                    output.WriteUInt64(value);
+                }
+            }
+            if (fixed32List != null)
+            {
+                foreach (uint value in fixed32List)
+                {
+                    output.WriteTag(fieldNumber, WireFormat.WireType.Fixed32);
+                    output.WriteFixed32(value);
+                }
+            }
+            if (fixed64List != null)
+            {
+                foreach (ulong value in fixed64List)
+                {
+                    output.WriteTag(fieldNumber, WireFormat.WireType.Fixed64);
+                    output.WriteFixed64(value);
+                }
+            }
+            if (lengthDelimitedList != null)
+            {
+                foreach (ByteString value in lengthDelimitedList)
+                {
+                    output.WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
+                    output.WriteBytes(value);
+                }
+            }
+        }
+
+        /// <summary>
+        /// Computes the number of bytes required to encode this field, including field
+        /// number.
+        /// </summary>
+        internal int GetSerializedSize(int fieldNumber)
+        {
+            int result = 0;
+            if (varintList != null)
+            {
+                result += CodedOutputStream.ComputeTagSize(fieldNumber) * varintList.Count;
+                foreach (ulong value in varintList)
+                {
+                    result += CodedOutputStream.ComputeUInt64Size(value);
+                }
+            }
+            if (fixed32List != null)
+            {
+                result += CodedOutputStream.ComputeTagSize(fieldNumber) * fixed32List.Count;
+                result += CodedOutputStream.ComputeFixed32Size(1) * fixed32List.Count;
+            }
+            if (fixed64List != null)
+            {
+                result += CodedOutputStream.ComputeTagSize(fieldNumber) * fixed64List.Count;
+                result += CodedOutputStream.ComputeFixed64Size(1) * fixed64List.Count;
+            }                
+            if (lengthDelimitedList != null)
+            {
+                result += CodedOutputStream.ComputeTagSize(fieldNumber) * lengthDelimitedList.Count;
+                foreach (ByteString value in lengthDelimitedList)
+                {
+                    result += CodedOutputStream.ComputeBytesSize(value);
+                }
+            }
+            return result;
+        }
+
+        /// <summary>
+        /// Merge the values in <paramref name="other" /> into this field.  For each list
+        /// of values, <paramref name="other"/>'s values are append to the ones in this
+        /// field.
+        /// </summary>
+        internal UnknownField MergeFrom(UnknownField other)
+        {
+            varintList = AddAll(varintList, other.varintList);
+            fixed32List = AddAll(fixed32List, other.fixed32List);
+            fixed64List = AddAll(fixed64List, other.fixed64List);
+            lengthDelimitedList = AddAll(lengthDelimitedList, other.lengthDelimitedList);
+            return this;
+        }
+
+        /// <summary>
+        /// Returns a new list containing all of the given specified values from
+        /// both the <paramref name="current"/> and <paramref name="extras"/> lists.
+        /// If <paramref name="current" /> is null and <paramref name="extras"/> is empty,
+        /// null is returned. Otherwise, either a new list is created (if <paramref name="current" />
+        /// is null) or the elements of <paramref name="extras"/> are added to <paramref name="current" />.
+        /// </summary>
+        private static List<T> AddAll<T>(List<T> current, IList<T> extras)
+        {
+            if (extras.Count == 0)
+            {
+                return current;
+            }
+            if (current == null)
+            {
+                current = new List<T>(extras);
+            }
+            else
+            {
+                current.AddRange(extras);
+            }
+            return current;
+        }
+
+        /// <summary>
+        /// Adds a varint value.
+        /// </summary>
+        internal UnknownField AddVarint(ulong value)
+        {
+            varintList = Add(varintList, value);
+            return this;
+        }
+
+        /// <summary>
+        /// Adds a fixed32 value.
+        /// </summary>
+        internal UnknownField AddFixed32(uint value)
+        {
+            fixed32List = Add(fixed32List, value);
+            return this;
+        }
+
+        /// <summary>
+        /// Adds a fixed64 value.
+        /// </summary>
+        internal UnknownField AddFixed64(ulong value)
+        {
+            fixed64List = Add(fixed64List, value);
+            return this;
+        }
+
+        /// <summary>
+        /// Adds a length-delimited value.
+        /// </summary>
+        internal UnknownField AddLengthDelimited(ByteString value)
+        {
+            lengthDelimitedList = Add(lengthDelimitedList, value);
+            return this;
+        }
+
+        /// <summary>
+        /// Adds <paramref name="value"/> to the <paramref name="list"/>, creating
+        /// a new list if <paramref name="list"/> is null. The list is returned - either
+        /// the original reference or the new list.
+        /// </summary>
+        private static List<T> Add<T>(List<T> list, T value)
+        {
+            if (list == null)
+            {
+                list = new List<T>();
+            }
+            list.Add(value);
+            return list;
+        }
+    }
+}

+ 324 - 0
csharp/src/Google.Protobuf/UnknownFieldSet.cs

@@ -0,0 +1,324 @@
+#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;
+using System.Collections.Generic;
+using System.IO;
+using Google.Protobuf.Reflection;
+
+namespace Google.Protobuf
+{
+    /// <summary>
+    /// Used to keep track of fields which were seen when parsing a protocol message
+    /// but whose field numbers or types are unrecognized. This most frequently
+    /// occurs when new fields are added to a message type and then messages containing
+    /// those fields are read by old software that was built before the new types were
+    /// added.
+    ///
+    /// Most users will never need to use this class directly.
+    /// </summary>
+    public sealed partial class UnknownFieldSet
+    {
+        private readonly IDictionary<int, UnknownField> fields;
+
+        /// <summary>
+        /// Creates a new UnknownFieldSet.
+        /// </summary>
+        internal UnknownFieldSet()
+        {
+            this.fields = new Dictionary<int, UnknownField>();
+        }
+
+        /// <summary>
+        /// Checks whether or not the given field number is present in the set.
+        /// </summary>
+        internal bool HasField(int field)
+        {
+            return fields.ContainsKey(field);
+        }
+
+        /// <summary>
+        /// Serializes the set and writes it to <paramref name="output"/>.
+        /// </summary>
+        public void WriteTo(CodedOutputStream output)
+        {
+            foreach (KeyValuePair<int, UnknownField> entry in fields)
+            {
+                entry.Value.WriteTo(entry.Key, output);
+            }
+        }
+
+        /// <summary>
+        /// Gets the number of bytes required to encode this set.
+        /// </summary>
+        public int CalculateSize()
+        {
+            int result = 0;
+            foreach (KeyValuePair<int, UnknownField> entry in fields)
+            {
+                result += entry.Value.GetSerializedSize(entry.Key);
+            }
+            return result;
+        }
+
+        /// <summary>
+        /// Checks if two unknown field sets are equal.
+        /// </summary>
+        public override bool Equals(object other)
+        {
+            if (ReferenceEquals(this, other))
+            {
+                return true;
+            }
+            UnknownFieldSet otherSet = other as UnknownFieldSet;
+            IDictionary<int, UnknownField> otherFields = otherSet.fields;
+            if (fields.Count  != otherFields.Count)
+            {
+                return false;
+            }
+            foreach (KeyValuePair<int, UnknownField> leftEntry in fields)
+            {
+                UnknownField rightValue;
+                if (!otherFields.TryGetValue(leftEntry.Key, out rightValue))
+                {
+                    return false;
+                }
+                if (!leftEntry.Value.Equals(rightValue))
+                {
+                    return false;
+                }
+            }
+            return true;
+        }
+
+        /// <summary>
+        /// Gets the unknown field set's hash code.
+        /// </summary>
+        public override int GetHashCode()
+        {
+            int ret = 1;
+            foreach (KeyValuePair<int, UnknownField> field in fields)
+            {
+                // Use ^ here to make the field order irrelevant.
+                int hash = field.Key.GetHashCode() ^ field.Value.GetHashCode();
+                ret ^= hash;
+            }
+            return ret;
+        }
+
+        // Optimization:  We keep around the last field that was
+        // modified so that we can efficiently add to it multiple times in a
+        // row (important when parsing an unknown repeated field).
+        private int lastFieldNumber;
+        private UnknownField lastField;
+
+        private UnknownField GetOrAddField(int number)
+        {
+            if (lastField != null && number == lastFieldNumber)
+            {
+                return lastField;
+            }
+            if (number == 0)
+            {
+                return null;
+            }
+
+            UnknownField existing;
+            if (fields.TryGetValue(number, out existing))
+            {
+                return existing;
+            }
+            lastField = new UnknownField();
+            AddOrReplaceField(number, lastField);
+            lastFieldNumber = number;
+            return lastField;
+        }
+
+        /// <summary>
+        /// Adds a field to the set. If a field with the same number already exists, it
+        /// is replaced.
+        /// </summary>
+        internal UnknownFieldSet AddOrReplaceField(int number, UnknownField field)
+        {
+            if (number == 0)
+            {
+                throw new ArgumentOutOfRangeException("number", "Zero is not a valid field number.");
+            }
+            fields[number] = field;
+            return this;
+        }
+
+        /// <summary>
+        /// Parse a single field from <paramref name="input"/> and merge it
+        /// into this set.
+        /// </summary>
+        /// <param name="input">The coded input stream containing the field</param>
+        /// <returns>false if the tag is an "end group" tag, true otherwise</returns>
+        private void MergeFieldFrom(CodedInputStream input)
+        {
+            uint tag = input.LastTag;
+            int number = WireFormat.GetTagFieldNumber(tag);
+            switch (WireFormat.GetTagWireType(tag))
+            {
+                case WireFormat.WireType.Varint:
+                    {
+                        ulong uint64 = input.ReadUInt64();
+                        GetOrAddField(number).AddVarint(uint64);
+                        return;
+                    }
+                case WireFormat.WireType.Fixed32:
+                    {
+                        uint uint32 = input.ReadFixed32();
+                        GetOrAddField(number).AddFixed32(uint32);
+                        return;
+                    }
+                case WireFormat.WireType.Fixed64:
+                    {
+                        ulong uint64 = input.ReadFixed64();
+                        GetOrAddField(number).AddFixed64(uint64);
+                        return;
+                    }
+                case WireFormat.WireType.LengthDelimited:
+                    {
+                        ByteString bytes = input.ReadBytes();
+                        GetOrAddField(number).AddLengthDelimited(bytes);
+                        return;
+                    }
+                case WireFormat.WireType.StartGroup:
+                    {
+                        input.SkipGroup(tag);
+                        return;
+                    }
+                case WireFormat.WireType.EndGroup:
+                    {
+                        throw new InvalidProtocolBufferException("Merge an unknown field of end-group tag, indicating that the corresponding start-group was missing.");
+                    }
+                default:
+                    throw new InvalidOperationException("Wire Type is invalid.");
+            }
+        }
+
+        /// <summary>
+        /// Create a new UnknownFieldSet if unknownFields is null.
+        /// Parse a single field from <paramref name="input"/> and merge it
+        /// into unknownFields.
+        /// </summary>
+        /// <param name="unknownFields">The UnknownFieldSet which need to be merged</param>
+        /// <param name="input">The coded input stream containing the field</param>
+        /// <returns>The merged UnknownFieldSet</returns>
+        public static UnknownFieldSet MergeFieldFrom(UnknownFieldSet unknownFields,
+                                                     CodedInputStream input)
+        {
+            if (unknownFields == null)
+            {
+                unknownFields = new UnknownFieldSet();
+            }
+            unknownFields.MergeFieldFrom(input);
+            return unknownFields;
+        }
+
+        /// <summary>
+        /// Merges the fields from <paramref name="other"/> into this set.
+        /// If a field number exists in both sets, the values in <paramref name="other"/>
+        /// will be appended to the values in this set.
+        /// </summary>
+        private UnknownFieldSet MergeFrom(UnknownFieldSet other)
+        {
+            if (other != null)
+            {
+                foreach (KeyValuePair<int, UnknownField> entry in other.fields)
+                {
+                    MergeField(entry.Key, entry.Value);
+                }
+            }
+            return this;
+        }
+
+        /// <summary>
+        /// Created a new UnknownFieldSet to <paramref name="unknownFields"/> if
+        /// needed and merges the fields from <paramref name="other"/> into the first set.
+        /// If a field number exists in both sets, the values in <paramref name="other"/>
+        /// will be appended to the values in this set.
+        /// </summary>
+        public static UnknownFieldSet MergeFrom(UnknownFieldSet unknownFields,
+                                                UnknownFieldSet other)
+        {
+            if (other == null)
+            {
+                return unknownFields;
+            }
+            if (unknownFields == null)
+            {
+                unknownFields = new UnknownFieldSet();
+            }
+            unknownFields.MergeFrom(other);
+            return unknownFields;
+        }
+
+
+        /// <summary>
+        /// Adds a field to the unknown field set. If a field with the same
+        /// number already exists, the two are merged.
+        /// </summary>
+        private UnknownFieldSet MergeField(int number, UnknownField field)
+        {
+            if (number == 0)
+            {
+                throw new ArgumentOutOfRangeException("number", "Zero is not a valid field number.");
+            }
+            if (HasField(number))
+            {
+                GetOrAddField(number).MergeFrom(field);
+            }
+            else
+            {
+                AddOrReplaceField(number, field);
+            }
+            return this;
+        }
+
+        /// <summary>
+        /// Clone an unknown field set from <paramref name="other"/>.
+        /// </summary>
+        public static UnknownFieldSet Clone(UnknownFieldSet other)
+        {
+            if (other == null)
+            {
+                return null;
+            }
+            UnknownFieldSet unknownFields = new UnknownFieldSet();
+            unknownFields.MergeFrom(other);
+            return unknownFields;
+        }
+    }
+}
+

+ 18 - 4
csharp/src/Google.Protobuf/WellKnownTypes/Any.cs

@@ -1,5 +1,7 @@
-// Generated by the protocol buffer compiler.  DO NOT EDIT!
-// source: google/protobuf/any.proto
+// <auto-generated>
+//     Generated by the protocol buffer compiler.  DO NOT EDIT!
+//     source: google/protobuf/any.proto
+// </auto-generated>
 #pragma warning disable 1591, 0612, 3021
 #pragma warning disable 1591, 0612, 3021
 #region Designer generated code
 #region Designer generated code
 
 
@@ -119,6 +121,7 @@ namespace Google.Protobuf.WellKnownTypes {
   /// </summary>
   /// </summary>
   public sealed partial class Any : pb::IMessage<Any> {
   public sealed partial class Any : pb::IMessage<Any> {
     private static readonly pb::MessageParser<Any> _parser = new pb::MessageParser<Any>(() => new Any());
     private static readonly pb::MessageParser<Any> _parser = new pb::MessageParser<Any>(() => new Any());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<Any> Parser { get { return _parser; } }
     public static pb::MessageParser<Any> Parser { get { return _parser; } }
 
 
@@ -143,6 +146,7 @@ namespace Google.Protobuf.WellKnownTypes {
     public Any(Any other) : this() {
     public Any(Any other) : this() {
       typeUrl_ = other.typeUrl_;
       typeUrl_ = other.typeUrl_;
       value_ = other.value_;
       value_ = other.value_;
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -218,7 +222,7 @@ namespace Google.Protobuf.WellKnownTypes {
       }
       }
       if (TypeUrl != other.TypeUrl) return false;
       if (TypeUrl != other.TypeUrl) return false;
       if (Value != other.Value) return false;
       if (Value != other.Value) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -226,6 +230,9 @@ namespace Google.Protobuf.WellKnownTypes {
       int hash = 1;
       int hash = 1;
       if (TypeUrl.Length != 0) hash ^= TypeUrl.GetHashCode();
       if (TypeUrl.Length != 0) hash ^= TypeUrl.GetHashCode();
       if (Value.Length != 0) hash ^= Value.GetHashCode();
       if (Value.Length != 0) hash ^= Value.GetHashCode();
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
       return hash;
     }
     }
 
 
@@ -244,6 +251,9 @@ namespace Google.Protobuf.WellKnownTypes {
         output.WriteRawTag(18);
         output.WriteRawTag(18);
         output.WriteBytes(Value);
         output.WriteBytes(Value);
       }
       }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -255,6 +265,9 @@ namespace Google.Protobuf.WellKnownTypes {
       if (Value.Length != 0) {
       if (Value.Length != 0) {
         size += 1 + pb::CodedOutputStream.ComputeBytesSize(Value);
         size += 1 + pb::CodedOutputStream.ComputeBytesSize(Value);
       }
       }
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
       return size;
     }
     }
 
 
@@ -269,6 +282,7 @@ namespace Google.Protobuf.WellKnownTypes {
       if (other.Value.Length != 0) {
       if (other.Value.Length != 0) {
         Value = other.Value;
         Value = other.Value;
       }
       }
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -277,7 +291,7 @@ namespace Google.Protobuf.WellKnownTypes {
       while ((tag = input.ReadTag()) != 0) {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
         switch(tag) {
           default:
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
             break;
           case 10: {
           case 10: {
             TypeUrl = input.ReadString();
             TypeUrl = input.ReadString();

+ 46 - 8
csharp/src/Google.Protobuf/WellKnownTypes/Api.cs

@@ -1,5 +1,7 @@
-// Generated by the protocol buffer compiler.  DO NOT EDIT!
-// source: google/protobuf/api.proto
+// <auto-generated>
+//     Generated by the protocol buffer compiler.  DO NOT EDIT!
+//     source: google/protobuf/api.proto
+// </auto-generated>
 #pragma warning disable 1591, 0612, 3021
 #pragma warning disable 1591, 0612, 3021
 #region Designer generated code
 #region Designer generated code
 
 
@@ -64,6 +66,7 @@ namespace Google.Protobuf.WellKnownTypes {
   /// </summary>
   /// </summary>
   public sealed partial class Api : pb::IMessage<Api> {
   public sealed partial class Api : pb::IMessage<Api> {
     private static readonly pb::MessageParser<Api> _parser = new pb::MessageParser<Api>(() => new Api());
     private static readonly pb::MessageParser<Api> _parser = new pb::MessageParser<Api>(() => new Api());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<Api> Parser { get { return _parser; } }
     public static pb::MessageParser<Api> Parser { get { return _parser; } }
 
 
@@ -93,6 +96,7 @@ namespace Google.Protobuf.WellKnownTypes {
       SourceContext = other.sourceContext_ != null ? other.SourceContext.Clone() : null;
       SourceContext = other.sourceContext_ != null ? other.SourceContext.Clone() : null;
       mixins_ = other.mixins_.Clone();
       mixins_ = other.mixins_.Clone();
       syntax_ = other.syntax_;
       syntax_ = other.syntax_;
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -235,7 +239,7 @@ namespace Google.Protobuf.WellKnownTypes {
       if (!object.Equals(SourceContext, other.SourceContext)) return false;
       if (!object.Equals(SourceContext, other.SourceContext)) return false;
       if(!mixins_.Equals(other.mixins_)) return false;
       if(!mixins_.Equals(other.mixins_)) return false;
       if (Syntax != other.Syntax) return false;
       if (Syntax != other.Syntax) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -248,6 +252,9 @@ namespace Google.Protobuf.WellKnownTypes {
       if (sourceContext_ != null) hash ^= SourceContext.GetHashCode();
       if (sourceContext_ != null) hash ^= SourceContext.GetHashCode();
       hash ^= mixins_.GetHashCode();
       hash ^= mixins_.GetHashCode();
       if (Syntax != 0) hash ^= Syntax.GetHashCode();
       if (Syntax != 0) hash ^= Syntax.GetHashCode();
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
       return hash;
     }
     }
 
 
@@ -277,6 +284,9 @@ namespace Google.Protobuf.WellKnownTypes {
         output.WriteRawTag(56);
         output.WriteRawTag(56);
         output.WriteEnum((int) Syntax);
         output.WriteEnum((int) Syntax);
       }
       }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -297,6 +307,9 @@ namespace Google.Protobuf.WellKnownTypes {
       if (Syntax != 0) {
       if (Syntax != 0) {
         size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Syntax);
         size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Syntax);
       }
       }
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
       return size;
     }
     }
 
 
@@ -323,6 +336,7 @@ namespace Google.Protobuf.WellKnownTypes {
       if (other.Syntax != 0) {
       if (other.Syntax != 0) {
         Syntax = other.Syntax;
         Syntax = other.Syntax;
       }
       }
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -331,7 +345,7 @@ namespace Google.Protobuf.WellKnownTypes {
       while ((tag = input.ReadTag()) != 0) {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
         switch(tag) {
           default:
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
             break;
           case 10: {
           case 10: {
             Name = input.ReadString();
             Name = input.ReadString();
@@ -375,6 +389,7 @@ namespace Google.Protobuf.WellKnownTypes {
   /// </summary>
   /// </summary>
   public sealed partial class Method : pb::IMessage<Method> {
   public sealed partial class Method : pb::IMessage<Method> {
     private static readonly pb::MessageParser<Method> _parser = new pb::MessageParser<Method>(() => new Method());
     private static readonly pb::MessageParser<Method> _parser = new pb::MessageParser<Method>(() => new Method());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<Method> Parser { get { return _parser; } }
     public static pb::MessageParser<Method> Parser { get { return _parser; } }
 
 
@@ -404,6 +419,7 @@ namespace Google.Protobuf.WellKnownTypes {
       responseStreaming_ = other.responseStreaming_;
       responseStreaming_ = other.responseStreaming_;
       options_ = other.options_.Clone();
       options_ = other.options_.Clone();
       syntax_ = other.syntax_;
       syntax_ = other.syntax_;
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -528,7 +544,7 @@ namespace Google.Protobuf.WellKnownTypes {
       if (ResponseStreaming != other.ResponseStreaming) return false;
       if (ResponseStreaming != other.ResponseStreaming) return false;
       if(!options_.Equals(other.options_)) return false;
       if(!options_.Equals(other.options_)) return false;
       if (Syntax != other.Syntax) return false;
       if (Syntax != other.Syntax) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -541,6 +557,9 @@ namespace Google.Protobuf.WellKnownTypes {
       if (ResponseStreaming != false) hash ^= ResponseStreaming.GetHashCode();
       if (ResponseStreaming != false) hash ^= ResponseStreaming.GetHashCode();
       hash ^= options_.GetHashCode();
       hash ^= options_.GetHashCode();
       if (Syntax != 0) hash ^= Syntax.GetHashCode();
       if (Syntax != 0) hash ^= Syntax.GetHashCode();
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
       return hash;
     }
     }
 
 
@@ -576,6 +595,9 @@ namespace Google.Protobuf.WellKnownTypes {
         output.WriteRawTag(56);
         output.WriteRawTag(56);
         output.WriteEnum((int) Syntax);
         output.WriteEnum((int) Syntax);
       }
       }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -600,6 +622,9 @@ namespace Google.Protobuf.WellKnownTypes {
       if (Syntax != 0) {
       if (Syntax != 0) {
         size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Syntax);
         size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Syntax);
       }
       }
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
       return size;
     }
     }
 
 
@@ -627,6 +652,7 @@ namespace Google.Protobuf.WellKnownTypes {
       if (other.Syntax != 0) {
       if (other.Syntax != 0) {
         Syntax = other.Syntax;
         Syntax = other.Syntax;
       }
       }
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -635,7 +661,7 @@ namespace Google.Protobuf.WellKnownTypes {
       while ((tag = input.ReadTag()) != 0) {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
         switch(tag) {
           default:
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
             break;
           case 10: {
           case 10: {
             Name = input.ReadString();
             Name = input.ReadString();
@@ -753,6 +779,7 @@ namespace Google.Protobuf.WellKnownTypes {
   /// </summary>
   /// </summary>
   public sealed partial class Mixin : pb::IMessage<Mixin> {
   public sealed partial class Mixin : pb::IMessage<Mixin> {
     private static readonly pb::MessageParser<Mixin> _parser = new pb::MessageParser<Mixin>(() => new Mixin());
     private static readonly pb::MessageParser<Mixin> _parser = new pb::MessageParser<Mixin>(() => new Mixin());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<Mixin> Parser { get { return _parser; } }
     public static pb::MessageParser<Mixin> Parser { get { return _parser; } }
 
 
@@ -777,6 +804,7 @@ namespace Google.Protobuf.WellKnownTypes {
     public Mixin(Mixin other) : this() {
     public Mixin(Mixin other) : this() {
       name_ = other.name_;
       name_ = other.name_;
       root_ = other.root_;
       root_ = other.root_;
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -828,7 +856,7 @@ namespace Google.Protobuf.WellKnownTypes {
       }
       }
       if (Name != other.Name) return false;
       if (Name != other.Name) return false;
       if (Root != other.Root) return false;
       if (Root != other.Root) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -836,6 +864,9 @@ namespace Google.Protobuf.WellKnownTypes {
       int hash = 1;
       int hash = 1;
       if (Name.Length != 0) hash ^= Name.GetHashCode();
       if (Name.Length != 0) hash ^= Name.GetHashCode();
       if (Root.Length != 0) hash ^= Root.GetHashCode();
       if (Root.Length != 0) hash ^= Root.GetHashCode();
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
       return hash;
     }
     }
 
 
@@ -854,6 +885,9 @@ namespace Google.Protobuf.WellKnownTypes {
         output.WriteRawTag(18);
         output.WriteRawTag(18);
         output.WriteString(Root);
         output.WriteString(Root);
       }
       }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -865,6 +899,9 @@ namespace Google.Protobuf.WellKnownTypes {
       if (Root.Length != 0) {
       if (Root.Length != 0) {
         size += 1 + pb::CodedOutputStream.ComputeStringSize(Root);
         size += 1 + pb::CodedOutputStream.ComputeStringSize(Root);
       }
       }
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
       return size;
     }
     }
 
 
@@ -879,6 +916,7 @@ namespace Google.Protobuf.WellKnownTypes {
       if (other.Root.Length != 0) {
       if (other.Root.Length != 0) {
         Root = other.Root;
         Root = other.Root;
       }
       }
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -887,7 +925,7 @@ namespace Google.Protobuf.WellKnownTypes {
       while ((tag = input.ReadTag()) != 0) {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
         switch(tag) {
           default:
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
             break;
           case 10: {
           case 10: {
             Name = input.ReadString();
             Name = input.ReadString();

+ 18 - 4
csharp/src/Google.Protobuf/WellKnownTypes/Duration.cs

@@ -1,5 +1,7 @@
-// Generated by the protocol buffer compiler.  DO NOT EDIT!
-// source: google/protobuf/duration.proto
+// <auto-generated>
+//     Generated by the protocol buffer compiler.  DO NOT EDIT!
+//     source: google/protobuf/duration.proto
+// </auto-generated>
 #pragma warning disable 1591, 0612, 3021
 #pragma warning disable 1591, 0612, 3021
 #region Designer generated code
 #region Designer generated code
 
 
@@ -100,6 +102,7 @@ namespace Google.Protobuf.WellKnownTypes {
   /// </summary>
   /// </summary>
   public sealed partial class Duration : pb::IMessage<Duration> {
   public sealed partial class Duration : pb::IMessage<Duration> {
     private static readonly pb::MessageParser<Duration> _parser = new pb::MessageParser<Duration>(() => new Duration());
     private static readonly pb::MessageParser<Duration> _parser = new pb::MessageParser<Duration>(() => new Duration());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<Duration> Parser { get { return _parser; } }
     public static pb::MessageParser<Duration> Parser { get { return _parser; } }
 
 
@@ -124,6 +127,7 @@ namespace Google.Protobuf.WellKnownTypes {
     public Duration(Duration other) : this() {
     public Duration(Duration other) : this() {
       seconds_ = other.seconds_;
       seconds_ = other.seconds_;
       nanos_ = other.nanos_;
       nanos_ = other.nanos_;
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -181,7 +185,7 @@ namespace Google.Protobuf.WellKnownTypes {
       }
       }
       if (Seconds != other.Seconds) return false;
       if (Seconds != other.Seconds) return false;
       if (Nanos != other.Nanos) return false;
       if (Nanos != other.Nanos) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -189,6 +193,9 @@ namespace Google.Protobuf.WellKnownTypes {
       int hash = 1;
       int hash = 1;
       if (Seconds != 0L) hash ^= Seconds.GetHashCode();
       if (Seconds != 0L) hash ^= Seconds.GetHashCode();
       if (Nanos != 0) hash ^= Nanos.GetHashCode();
       if (Nanos != 0) hash ^= Nanos.GetHashCode();
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
       return hash;
     }
     }
 
 
@@ -207,6 +214,9 @@ namespace Google.Protobuf.WellKnownTypes {
         output.WriteRawTag(16);
         output.WriteRawTag(16);
         output.WriteInt32(Nanos);
         output.WriteInt32(Nanos);
       }
       }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -218,6 +228,9 @@ namespace Google.Protobuf.WellKnownTypes {
       if (Nanos != 0) {
       if (Nanos != 0) {
         size += 1 + pb::CodedOutputStream.ComputeInt32Size(Nanos);
         size += 1 + pb::CodedOutputStream.ComputeInt32Size(Nanos);
       }
       }
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
       return size;
     }
     }
 
 
@@ -232,6 +245,7 @@ namespace Google.Protobuf.WellKnownTypes {
       if (other.Nanos != 0) {
       if (other.Nanos != 0) {
         Nanos = other.Nanos;
         Nanos = other.Nanos;
       }
       }
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -240,7 +254,7 @@ namespace Google.Protobuf.WellKnownTypes {
       while ((tag = input.ReadTag()) != 0) {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
         switch(tag) {
           default:
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
             break;
           case 8: {
           case 8: {
             Seconds = input.ReadInt64();
             Seconds = input.ReadInt64();

+ 18 - 4
csharp/src/Google.Protobuf/WellKnownTypes/Empty.cs

@@ -1,5 +1,7 @@
-// Generated by the protocol buffer compiler.  DO NOT EDIT!
-// source: google/protobuf/empty.proto
+// <auto-generated>
+//     Generated by the protocol buffer compiler.  DO NOT EDIT!
+//     source: google/protobuf/empty.proto
+// </auto-generated>
 #pragma warning disable 1591, 0612, 3021
 #pragma warning disable 1591, 0612, 3021
 #region Designer generated code
 #region Designer generated code
 
 
@@ -50,6 +52,7 @@ namespace Google.Protobuf.WellKnownTypes {
   /// </summary>
   /// </summary>
   public sealed partial class Empty : pb::IMessage<Empty> {
   public sealed partial class Empty : pb::IMessage<Empty> {
     private static readonly pb::MessageParser<Empty> _parser = new pb::MessageParser<Empty>(() => new Empty());
     private static readonly pb::MessageParser<Empty> _parser = new pb::MessageParser<Empty>(() => new Empty());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<Empty> Parser { get { return _parser; } }
     public static pb::MessageParser<Empty> Parser { get { return _parser; } }
 
 
@@ -72,6 +75,7 @@ namespace Google.Protobuf.WellKnownTypes {
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public Empty(Empty other) : this() {
     public Empty(Empty other) : this() {
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -92,12 +96,15 @@ namespace Google.Protobuf.WellKnownTypes {
       if (ReferenceEquals(other, this)) {
       if (ReferenceEquals(other, this)) {
         return true;
         return true;
       }
       }
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public override int GetHashCode() {
     public override int GetHashCode() {
       int hash = 1;
       int hash = 1;
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
       return hash;
     }
     }
 
 
@@ -108,11 +115,17 @@ namespace Google.Protobuf.WellKnownTypes {
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public void WriteTo(pb::CodedOutputStream output) {
     public void WriteTo(pb::CodedOutputStream output) {
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public int CalculateSize() {
     public int CalculateSize() {
       int size = 0;
       int size = 0;
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
       return size;
     }
     }
 
 
@@ -121,6 +134,7 @@ namespace Google.Protobuf.WellKnownTypes {
       if (other == null) {
       if (other == null) {
         return;
         return;
       }
       }
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -129,7 +143,7 @@ namespace Google.Protobuf.WellKnownTypes {
       while ((tag = input.ReadTag()) != 0) {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
         switch(tag) {
           default:
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
             break;
         }
         }
       }
       }

+ 18 - 4
csharp/src/Google.Protobuf/WellKnownTypes/FieldMask.cs

@@ -1,5 +1,7 @@
-// Generated by the protocol buffer compiler.  DO NOT EDIT!
-// source: google/protobuf/field_mask.proto
+// <auto-generated>
+//     Generated by the protocol buffer compiler.  DO NOT EDIT!
+//     source: google/protobuf/field_mask.proto
+// </auto-generated>
 #pragma warning disable 1591, 0612, 3021
 #pragma warning disable 1591, 0612, 3021
 #region Designer generated code
 #region Designer generated code
 
 
@@ -248,6 +250,7 @@ namespace Google.Protobuf.WellKnownTypes {
   /// </summary>
   /// </summary>
   public sealed partial class FieldMask : pb::IMessage<FieldMask> {
   public sealed partial class FieldMask : pb::IMessage<FieldMask> {
     private static readonly pb::MessageParser<FieldMask> _parser = new pb::MessageParser<FieldMask>(() => new FieldMask());
     private static readonly pb::MessageParser<FieldMask> _parser = new pb::MessageParser<FieldMask>(() => new FieldMask());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<FieldMask> Parser { get { return _parser; } }
     public static pb::MessageParser<FieldMask> Parser { get { return _parser; } }
 
 
@@ -271,6 +274,7 @@ namespace Google.Protobuf.WellKnownTypes {
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public FieldMask(FieldMask other) : this() {
     public FieldMask(FieldMask other) : this() {
       paths_ = other.paths_.Clone();
       paths_ = other.paths_.Clone();
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -305,13 +309,16 @@ namespace Google.Protobuf.WellKnownTypes {
         return true;
         return true;
       }
       }
       if(!paths_.Equals(other.paths_)) return false;
       if(!paths_.Equals(other.paths_)) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public override int GetHashCode() {
     public override int GetHashCode() {
       int hash = 1;
       int hash = 1;
       hash ^= paths_.GetHashCode();
       hash ^= paths_.GetHashCode();
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
       return hash;
     }
     }
 
 
@@ -323,12 +330,18 @@ namespace Google.Protobuf.WellKnownTypes {
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public void WriteTo(pb::CodedOutputStream output) {
     public void WriteTo(pb::CodedOutputStream output) {
       paths_.WriteTo(output, _repeated_paths_codec);
       paths_.WriteTo(output, _repeated_paths_codec);
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public int CalculateSize() {
     public int CalculateSize() {
       int size = 0;
       int size = 0;
       size += paths_.CalculateSize(_repeated_paths_codec);
       size += paths_.CalculateSize(_repeated_paths_codec);
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
       return size;
     }
     }
 
 
@@ -338,6 +351,7 @@ namespace Google.Protobuf.WellKnownTypes {
         return;
         return;
       }
       }
       paths_.Add(other.paths_);
       paths_.Add(other.paths_);
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -346,7 +360,7 @@ namespace Google.Protobuf.WellKnownTypes {
       while ((tag = input.ReadTag()) != 0) {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
         switch(tag) {
           default:
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
             break;
           case 10: {
           case 10: {
             paths_.AddEntriesFrom(input, _repeated_paths_codec);
             paths_.AddEntriesFrom(input, _repeated_paths_codec);

+ 18 - 4
csharp/src/Google.Protobuf/WellKnownTypes/SourceContext.cs

@@ -1,5 +1,7 @@
-// Generated by the protocol buffer compiler.  DO NOT EDIT!
-// source: google/protobuf/source_context.proto
+// <auto-generated>
+//     Generated by the protocol buffer compiler.  DO NOT EDIT!
+//     source: google/protobuf/source_context.proto
+// </auto-generated>
 #pragma warning disable 1591, 0612, 3021
 #pragma warning disable 1591, 0612, 3021
 #region Designer generated code
 #region Designer generated code
 
 
@@ -44,6 +46,7 @@ namespace Google.Protobuf.WellKnownTypes {
   /// </summary>
   /// </summary>
   public sealed partial class SourceContext : pb::IMessage<SourceContext> {
   public sealed partial class SourceContext : pb::IMessage<SourceContext> {
     private static readonly pb::MessageParser<SourceContext> _parser = new pb::MessageParser<SourceContext>(() => new SourceContext());
     private static readonly pb::MessageParser<SourceContext> _parser = new pb::MessageParser<SourceContext>(() => new SourceContext());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<SourceContext> Parser { get { return _parser; } }
     public static pb::MessageParser<SourceContext> Parser { get { return _parser; } }
 
 
@@ -67,6 +70,7 @@ namespace Google.Protobuf.WellKnownTypes {
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public SourceContext(SourceContext other) : this() {
     public SourceContext(SourceContext other) : this() {
       fileName_ = other.fileName_;
       fileName_ = other.fileName_;
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -103,13 +107,16 @@ namespace Google.Protobuf.WellKnownTypes {
         return true;
         return true;
       }
       }
       if (FileName != other.FileName) return false;
       if (FileName != other.FileName) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public override int GetHashCode() {
     public override int GetHashCode() {
       int hash = 1;
       int hash = 1;
       if (FileName.Length != 0) hash ^= FileName.GetHashCode();
       if (FileName.Length != 0) hash ^= FileName.GetHashCode();
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
       return hash;
     }
     }
 
 
@@ -124,6 +131,9 @@ namespace Google.Protobuf.WellKnownTypes {
         output.WriteRawTag(10);
         output.WriteRawTag(10);
         output.WriteString(FileName);
         output.WriteString(FileName);
       }
       }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -132,6 +142,9 @@ namespace Google.Protobuf.WellKnownTypes {
       if (FileName.Length != 0) {
       if (FileName.Length != 0) {
         size += 1 + pb::CodedOutputStream.ComputeStringSize(FileName);
         size += 1 + pb::CodedOutputStream.ComputeStringSize(FileName);
       }
       }
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
       return size;
     }
     }
 
 
@@ -143,6 +156,7 @@ namespace Google.Protobuf.WellKnownTypes {
       if (other.FileName.Length != 0) {
       if (other.FileName.Length != 0) {
         FileName = other.FileName;
         FileName = other.FileName;
       }
       }
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -151,7 +165,7 @@ namespace Google.Protobuf.WellKnownTypes {
       while ((tag = input.ReadTag()) != 0) {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
         switch(tag) {
           default:
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
             break;
           case 10: {
           case 10: {
             FileName = input.ReadString();
             FileName = input.ReadString();

+ 48 - 10
csharp/src/Google.Protobuf/WellKnownTypes/Struct.cs

@@ -1,5 +1,7 @@
-// Generated by the protocol buffer compiler.  DO NOT EDIT!
-// source: google/protobuf/struct.proto
+// <auto-generated>
+//     Generated by the protocol buffer compiler.  DO NOT EDIT!
+//     source: google/protobuf/struct.proto
+// </auto-generated>
 #pragma warning disable 1591, 0612, 3021
 #pragma warning disable 1591, 0612, 3021
 #region Designer generated code
 #region Designer generated code
 
 
@@ -77,6 +79,7 @@ namespace Google.Protobuf.WellKnownTypes {
   /// </summary>
   /// </summary>
   public sealed partial class Struct : pb::IMessage<Struct> {
   public sealed partial class Struct : pb::IMessage<Struct> {
     private static readonly pb::MessageParser<Struct> _parser = new pb::MessageParser<Struct>(() => new Struct());
     private static readonly pb::MessageParser<Struct> _parser = new pb::MessageParser<Struct>(() => new Struct());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<Struct> Parser { get { return _parser; } }
     public static pb::MessageParser<Struct> Parser { get { return _parser; } }
 
 
@@ -100,6 +103,7 @@ namespace Google.Protobuf.WellKnownTypes {
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public Struct(Struct other) : this() {
     public Struct(Struct other) : this() {
       fields_ = other.fields_.Clone();
       fields_ = other.fields_.Clone();
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -134,13 +138,16 @@ namespace Google.Protobuf.WellKnownTypes {
         return true;
         return true;
       }
       }
       if (!Fields.Equals(other.Fields)) return false;
       if (!Fields.Equals(other.Fields)) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public override int GetHashCode() {
     public override int GetHashCode() {
       int hash = 1;
       int hash = 1;
       hash ^= Fields.GetHashCode();
       hash ^= Fields.GetHashCode();
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
       return hash;
     }
     }
 
 
@@ -152,12 +159,18 @@ namespace Google.Protobuf.WellKnownTypes {
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public void WriteTo(pb::CodedOutputStream output) {
     public void WriteTo(pb::CodedOutputStream output) {
       fields_.WriteTo(output, _map_fields_codec);
       fields_.WriteTo(output, _map_fields_codec);
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public int CalculateSize() {
     public int CalculateSize() {
       int size = 0;
       int size = 0;
       size += fields_.CalculateSize(_map_fields_codec);
       size += fields_.CalculateSize(_map_fields_codec);
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
       return size;
     }
     }
 
 
@@ -167,6 +180,7 @@ namespace Google.Protobuf.WellKnownTypes {
         return;
         return;
       }
       }
       fields_.Add(other.fields_);
       fields_.Add(other.fields_);
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -175,7 +189,7 @@ namespace Google.Protobuf.WellKnownTypes {
       while ((tag = input.ReadTag()) != 0) {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
         switch(tag) {
           default:
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
             break;
           case 10: {
           case 10: {
             fields_.AddEntriesFrom(input, _map_fields_codec);
             fields_.AddEntriesFrom(input, _map_fields_codec);
@@ -197,6 +211,7 @@ namespace Google.Protobuf.WellKnownTypes {
   /// </summary>
   /// </summary>
   public sealed partial class Value : pb::IMessage<Value> {
   public sealed partial class Value : pb::IMessage<Value> {
     private static readonly pb::MessageParser<Value> _parser = new pb::MessageParser<Value>(() => new Value());
     private static readonly pb::MessageParser<Value> _parser = new pb::MessageParser<Value>(() => new Value());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<Value> Parser { get { return _parser; } }
     public static pb::MessageParser<Value> Parser { get { return _parser; } }
 
 
@@ -240,6 +255,7 @@ namespace Google.Protobuf.WellKnownTypes {
           break;
           break;
       }
       }
 
 
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -368,25 +384,28 @@ namespace Google.Protobuf.WellKnownTypes {
         return true;
         return true;
       }
       }
       if (NullValue != other.NullValue) return false;
       if (NullValue != other.NullValue) return false;
-      if (NumberValue != other.NumberValue) return false;
+      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(NumberValue, other.NumberValue)) return false;
       if (StringValue != other.StringValue) return false;
       if (StringValue != other.StringValue) return false;
       if (BoolValue != other.BoolValue) return false;
       if (BoolValue != other.BoolValue) return false;
       if (!object.Equals(StructValue, other.StructValue)) return false;
       if (!object.Equals(StructValue, other.StructValue)) return false;
       if (!object.Equals(ListValue, other.ListValue)) return false;
       if (!object.Equals(ListValue, other.ListValue)) return false;
       if (KindCase != other.KindCase) return false;
       if (KindCase != other.KindCase) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public override int GetHashCode() {
     public override int GetHashCode() {
       int hash = 1;
       int hash = 1;
       if (kindCase_ == KindOneofCase.NullValue) hash ^= NullValue.GetHashCode();
       if (kindCase_ == KindOneofCase.NullValue) hash ^= NullValue.GetHashCode();
-      if (kindCase_ == KindOneofCase.NumberValue) hash ^= NumberValue.GetHashCode();
+      if (kindCase_ == KindOneofCase.NumberValue) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(NumberValue);
       if (kindCase_ == KindOneofCase.StringValue) hash ^= StringValue.GetHashCode();
       if (kindCase_ == KindOneofCase.StringValue) hash ^= StringValue.GetHashCode();
       if (kindCase_ == KindOneofCase.BoolValue) hash ^= BoolValue.GetHashCode();
       if (kindCase_ == KindOneofCase.BoolValue) hash ^= BoolValue.GetHashCode();
       if (kindCase_ == KindOneofCase.StructValue) hash ^= StructValue.GetHashCode();
       if (kindCase_ == KindOneofCase.StructValue) hash ^= StructValue.GetHashCode();
       if (kindCase_ == KindOneofCase.ListValue) hash ^= ListValue.GetHashCode();
       if (kindCase_ == KindOneofCase.ListValue) hash ^= ListValue.GetHashCode();
       hash ^= (int) kindCase_;
       hash ^= (int) kindCase_;
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
       return hash;
     }
     }
 
 
@@ -421,6 +440,9 @@ namespace Google.Protobuf.WellKnownTypes {
         output.WriteRawTag(50);
         output.WriteRawTag(50);
         output.WriteMessage(ListValue);
         output.WriteMessage(ListValue);
       }
       }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -444,6 +466,9 @@ namespace Google.Protobuf.WellKnownTypes {
       if (kindCase_ == KindOneofCase.ListValue) {
       if (kindCase_ == KindOneofCase.ListValue) {
         size += 1 + pb::CodedOutputStream.ComputeMessageSize(ListValue);
         size += 1 + pb::CodedOutputStream.ComputeMessageSize(ListValue);
       }
       }
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
       return size;
     }
     }
 
 
@@ -479,6 +504,7 @@ namespace Google.Protobuf.WellKnownTypes {
           break;
           break;
       }
       }
 
 
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -487,7 +513,7 @@ namespace Google.Protobuf.WellKnownTypes {
       while ((tag = input.ReadTag()) != 0) {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
         switch(tag) {
           default:
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
             break;
           case 8: {
           case 8: {
             kind_ = input.ReadEnum();
             kind_ = input.ReadEnum();
@@ -537,6 +563,7 @@ namespace Google.Protobuf.WellKnownTypes {
   /// </summary>
   /// </summary>
   public sealed partial class ListValue : pb::IMessage<ListValue> {
   public sealed partial class ListValue : pb::IMessage<ListValue> {
     private static readonly pb::MessageParser<ListValue> _parser = new pb::MessageParser<ListValue>(() => new ListValue());
     private static readonly pb::MessageParser<ListValue> _parser = new pb::MessageParser<ListValue>(() => new ListValue());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<ListValue> Parser { get { return _parser; } }
     public static pb::MessageParser<ListValue> Parser { get { return _parser; } }
 
 
@@ -560,6 +587,7 @@ namespace Google.Protobuf.WellKnownTypes {
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public ListValue(ListValue other) : this() {
     public ListValue(ListValue other) : this() {
       values_ = other.values_.Clone();
       values_ = other.values_.Clone();
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -594,13 +622,16 @@ namespace Google.Protobuf.WellKnownTypes {
         return true;
         return true;
       }
       }
       if(!values_.Equals(other.values_)) return false;
       if(!values_.Equals(other.values_)) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public override int GetHashCode() {
     public override int GetHashCode() {
       int hash = 1;
       int hash = 1;
       hash ^= values_.GetHashCode();
       hash ^= values_.GetHashCode();
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
       return hash;
     }
     }
 
 
@@ -612,12 +643,18 @@ namespace Google.Protobuf.WellKnownTypes {
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public void WriteTo(pb::CodedOutputStream output) {
     public void WriteTo(pb::CodedOutputStream output) {
       values_.WriteTo(output, _repeated_values_codec);
       values_.WriteTo(output, _repeated_values_codec);
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public int CalculateSize() {
     public int CalculateSize() {
       int size = 0;
       int size = 0;
       size += values_.CalculateSize(_repeated_values_codec);
       size += values_.CalculateSize(_repeated_values_codec);
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
       return size;
     }
     }
 
 
@@ -627,6 +664,7 @@ namespace Google.Protobuf.WellKnownTypes {
         return;
         return;
       }
       }
       values_.Add(other.values_);
       values_.Add(other.values_);
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -635,7 +673,7 @@ namespace Google.Protobuf.WellKnownTypes {
       while ((tag = input.ReadTag()) != 0) {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
         switch(tag) {
           default:
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
             break;
           case 10: {
           case 10: {
             values_.AddEntriesFrom(input, _repeated_values_codec);
             values_.AddEntriesFrom(input, _repeated_values_codec);

+ 21 - 5
csharp/src/Google.Protobuf/WellKnownTypes/Timestamp.cs

@@ -1,5 +1,7 @@
-// Generated by the protocol buffer compiler.  DO NOT EDIT!
-// source: google/protobuf/timestamp.proto
+// <auto-generated>
+//     Generated by the protocol buffer compiler.  DO NOT EDIT!
+//     source: google/protobuf/timestamp.proto
+// </auto-generated>
 #pragma warning disable 1591, 0612, 3021
 #pragma warning disable 1591, 0612, 3021
 #region Designer generated code
 #region Designer generated code
 
 
@@ -101,7 +103,9 @@ namespace Google.Protobuf.WellKnownTypes {
   /// {hour}, {min}, and {sec} are zero-padded to two digits each. The fractional
   /// {hour}, {min}, and {sec} are zero-padded to two digits each. The fractional
   /// seconds, which can go up to 9 digits (i.e. up to 1 nanosecond resolution),
   /// seconds, which can go up to 9 digits (i.e. up to 1 nanosecond resolution),
   /// are optional. The "Z" suffix indicates the timezone ("UTC"); the timezone
   /// are optional. The "Z" suffix indicates the timezone ("UTC"); the timezone
-  /// is required, though only UTC (as indicated by "Z") is presently supported.
+  /// is required. A proto3 JSON serializer should always use UTC (as indicated by
+  /// "Z") when printing the Timestamp type and a proto3 JSON parser should be
+  /// able to accept both UTC and other timezones (as indicated by an offset).
   ///
   ///
   /// For example, "2017-01-15T01:30:15.01Z" encodes 15.01 seconds past
   /// For example, "2017-01-15T01:30:15.01Z" encodes 15.01 seconds past
   /// 01:30 UTC on January 15, 2017.
   /// 01:30 UTC on January 15, 2017.
@@ -117,6 +121,7 @@ namespace Google.Protobuf.WellKnownTypes {
   /// </summary>
   /// </summary>
   public sealed partial class Timestamp : pb::IMessage<Timestamp> {
   public sealed partial class Timestamp : pb::IMessage<Timestamp> {
     private static readonly pb::MessageParser<Timestamp> _parser = new pb::MessageParser<Timestamp>(() => new Timestamp());
     private static readonly pb::MessageParser<Timestamp> _parser = new pb::MessageParser<Timestamp>(() => new Timestamp());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<Timestamp> Parser { get { return _parser; } }
     public static pb::MessageParser<Timestamp> Parser { get { return _parser; } }
 
 
@@ -141,6 +146,7 @@ namespace Google.Protobuf.WellKnownTypes {
     public Timestamp(Timestamp other) : this() {
     public Timestamp(Timestamp other) : this() {
       seconds_ = other.seconds_;
       seconds_ = other.seconds_;
       nanos_ = other.nanos_;
       nanos_ = other.nanos_;
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -196,7 +202,7 @@ namespace Google.Protobuf.WellKnownTypes {
       }
       }
       if (Seconds != other.Seconds) return false;
       if (Seconds != other.Seconds) return false;
       if (Nanos != other.Nanos) return false;
       if (Nanos != other.Nanos) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -204,6 +210,9 @@ namespace Google.Protobuf.WellKnownTypes {
       int hash = 1;
       int hash = 1;
       if (Seconds != 0L) hash ^= Seconds.GetHashCode();
       if (Seconds != 0L) hash ^= Seconds.GetHashCode();
       if (Nanos != 0) hash ^= Nanos.GetHashCode();
       if (Nanos != 0) hash ^= Nanos.GetHashCode();
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
       return hash;
     }
     }
 
 
@@ -222,6 +231,9 @@ namespace Google.Protobuf.WellKnownTypes {
         output.WriteRawTag(16);
         output.WriteRawTag(16);
         output.WriteInt32(Nanos);
         output.WriteInt32(Nanos);
       }
       }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -233,6 +245,9 @@ namespace Google.Protobuf.WellKnownTypes {
       if (Nanos != 0) {
       if (Nanos != 0) {
         size += 1 + pb::CodedOutputStream.ComputeInt32Size(Nanos);
         size += 1 + pb::CodedOutputStream.ComputeInt32Size(Nanos);
       }
       }
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
       return size;
     }
     }
 
 
@@ -247,6 +262,7 @@ namespace Google.Protobuf.WellKnownTypes {
       if (other.Nanos != 0) {
       if (other.Nanos != 0) {
         Nanos = other.Nanos;
         Nanos = other.Nanos;
       }
       }
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -255,7 +271,7 @@ namespace Google.Protobuf.WellKnownTypes {
       while ((tag = input.ReadTag()) != 0) {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
         switch(tag) {
           default:
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
             break;
           case 8: {
           case 8: {
             Seconds = input.ReadInt64();
             Seconds = input.ReadInt64();

+ 74 - 12
csharp/src/Google.Protobuf/WellKnownTypes/Type.cs

@@ -1,5 +1,7 @@
-// Generated by the protocol buffer compiler.  DO NOT EDIT!
-// source: google/protobuf/type.proto
+// <auto-generated>
+//     Generated by the protocol buffer compiler.  DO NOT EDIT!
+//     source: google/protobuf/type.proto
+// </auto-generated>
 #pragma warning disable 1591, 0612, 3021
 #pragma warning disable 1591, 0612, 3021
 #region Designer generated code
 #region Designer generated code
 
 
@@ -94,6 +96,7 @@ namespace Google.Protobuf.WellKnownTypes {
   /// </summary>
   /// </summary>
   public sealed partial class Type : pb::IMessage<Type> {
   public sealed partial class Type : pb::IMessage<Type> {
     private static readonly pb::MessageParser<Type> _parser = new pb::MessageParser<Type>(() => new Type());
     private static readonly pb::MessageParser<Type> _parser = new pb::MessageParser<Type>(() => new Type());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<Type> Parser { get { return _parser; } }
     public static pb::MessageParser<Type> Parser { get { return _parser; } }
 
 
@@ -122,6 +125,7 @@ namespace Google.Protobuf.WellKnownTypes {
       options_ = other.options_.Clone();
       options_ = other.options_.Clone();
       SourceContext = other.sourceContext_ != null ? other.SourceContext.Clone() : null;
       SourceContext = other.sourceContext_ != null ? other.SourceContext.Clone() : null;
       syntax_ = other.syntax_;
       syntax_ = other.syntax_;
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -229,7 +233,7 @@ namespace Google.Protobuf.WellKnownTypes {
       if(!options_.Equals(other.options_)) return false;
       if(!options_.Equals(other.options_)) return false;
       if (!object.Equals(SourceContext, other.SourceContext)) return false;
       if (!object.Equals(SourceContext, other.SourceContext)) return false;
       if (Syntax != other.Syntax) return false;
       if (Syntax != other.Syntax) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -241,6 +245,9 @@ namespace Google.Protobuf.WellKnownTypes {
       hash ^= options_.GetHashCode();
       hash ^= options_.GetHashCode();
       if (sourceContext_ != null) hash ^= SourceContext.GetHashCode();
       if (sourceContext_ != null) hash ^= SourceContext.GetHashCode();
       if (Syntax != 0) hash ^= Syntax.GetHashCode();
       if (Syntax != 0) hash ^= Syntax.GetHashCode();
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
       return hash;
     }
     }
 
 
@@ -266,6 +273,9 @@ namespace Google.Protobuf.WellKnownTypes {
         output.WriteRawTag(48);
         output.WriteRawTag(48);
         output.WriteEnum((int) Syntax);
         output.WriteEnum((int) Syntax);
       }
       }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -283,6 +293,9 @@ namespace Google.Protobuf.WellKnownTypes {
       if (Syntax != 0) {
       if (Syntax != 0) {
         size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Syntax);
         size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Syntax);
       }
       }
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
       return size;
     }
     }
 
 
@@ -306,6 +319,7 @@ namespace Google.Protobuf.WellKnownTypes {
       if (other.Syntax != 0) {
       if (other.Syntax != 0) {
         Syntax = other.Syntax;
         Syntax = other.Syntax;
       }
       }
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -314,7 +328,7 @@ namespace Google.Protobuf.WellKnownTypes {
       while ((tag = input.ReadTag()) != 0) {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
         switch(tag) {
           default:
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
             break;
           case 10: {
           case 10: {
             Name = input.ReadString();
             Name = input.ReadString();
@@ -354,6 +368,7 @@ namespace Google.Protobuf.WellKnownTypes {
   /// </summary>
   /// </summary>
   public sealed partial class Field : pb::IMessage<Field> {
   public sealed partial class Field : pb::IMessage<Field> {
     private static readonly pb::MessageParser<Field> _parser = new pb::MessageParser<Field>(() => new Field());
     private static readonly pb::MessageParser<Field> _parser = new pb::MessageParser<Field>(() => new Field());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<Field> Parser { get { return _parser; } }
     public static pb::MessageParser<Field> Parser { get { return _parser; } }
 
 
@@ -386,6 +401,7 @@ namespace Google.Protobuf.WellKnownTypes {
       options_ = other.options_.Clone();
       options_ = other.options_.Clone();
       jsonName_ = other.jsonName_;
       jsonName_ = other.jsonName_;
       defaultValue_ = other.defaultValue_;
       defaultValue_ = other.defaultValue_;
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -557,7 +573,7 @@ namespace Google.Protobuf.WellKnownTypes {
       if(!options_.Equals(other.options_)) return false;
       if(!options_.Equals(other.options_)) return false;
       if (JsonName != other.JsonName) return false;
       if (JsonName != other.JsonName) return false;
       if (DefaultValue != other.DefaultValue) return false;
       if (DefaultValue != other.DefaultValue) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -573,6 +589,9 @@ namespace Google.Protobuf.WellKnownTypes {
       hash ^= options_.GetHashCode();
       hash ^= options_.GetHashCode();
       if (JsonName.Length != 0) hash ^= JsonName.GetHashCode();
       if (JsonName.Length != 0) hash ^= JsonName.GetHashCode();
       if (DefaultValue.Length != 0) hash ^= DefaultValue.GetHashCode();
       if (DefaultValue.Length != 0) hash ^= DefaultValue.GetHashCode();
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
       return hash;
     }
     }
 
 
@@ -620,6 +639,9 @@ namespace Google.Protobuf.WellKnownTypes {
         output.WriteRawTag(90);
         output.WriteRawTag(90);
         output.WriteString(DefaultValue);
         output.WriteString(DefaultValue);
       }
       }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -653,6 +675,9 @@ namespace Google.Protobuf.WellKnownTypes {
       if (DefaultValue.Length != 0) {
       if (DefaultValue.Length != 0) {
         size += 1 + pb::CodedOutputStream.ComputeStringSize(DefaultValue);
         size += 1 + pb::CodedOutputStream.ComputeStringSize(DefaultValue);
       }
       }
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
       return size;
     }
     }
 
 
@@ -689,6 +714,7 @@ namespace Google.Protobuf.WellKnownTypes {
       if (other.DefaultValue.Length != 0) {
       if (other.DefaultValue.Length != 0) {
         DefaultValue = other.DefaultValue;
         DefaultValue = other.DefaultValue;
       }
       }
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -697,7 +723,7 @@ namespace Google.Protobuf.WellKnownTypes {
       while ((tag = input.ReadTag()) != 0) {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
         switch(tag) {
           default:
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
             break;
           case 8: {
           case 8: {
             kind_ = (global::Google.Protobuf.WellKnownTypes.Field.Types.Kind) input.ReadEnum();
             kind_ = (global::Google.Protobuf.WellKnownTypes.Field.Types.Kind) input.ReadEnum();
@@ -861,6 +887,7 @@ namespace Google.Protobuf.WellKnownTypes {
   /// </summary>
   /// </summary>
   public sealed partial class Enum : pb::IMessage<Enum> {
   public sealed partial class Enum : pb::IMessage<Enum> {
     private static readonly pb::MessageParser<Enum> _parser = new pb::MessageParser<Enum>(() => new Enum());
     private static readonly pb::MessageParser<Enum> _parser = new pb::MessageParser<Enum>(() => new Enum());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<Enum> Parser { get { return _parser; } }
     public static pb::MessageParser<Enum> Parser { get { return _parser; } }
 
 
@@ -888,6 +915,7 @@ namespace Google.Protobuf.WellKnownTypes {
       options_ = other.options_.Clone();
       options_ = other.options_.Clone();
       SourceContext = other.sourceContext_ != null ? other.SourceContext.Clone() : null;
       SourceContext = other.sourceContext_ != null ? other.SourceContext.Clone() : null;
       syntax_ = other.syntax_;
       syntax_ = other.syntax_;
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -981,7 +1009,7 @@ namespace Google.Protobuf.WellKnownTypes {
       if(!options_.Equals(other.options_)) return false;
       if(!options_.Equals(other.options_)) return false;
       if (!object.Equals(SourceContext, other.SourceContext)) return false;
       if (!object.Equals(SourceContext, other.SourceContext)) return false;
       if (Syntax != other.Syntax) return false;
       if (Syntax != other.Syntax) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -992,6 +1020,9 @@ namespace Google.Protobuf.WellKnownTypes {
       hash ^= options_.GetHashCode();
       hash ^= options_.GetHashCode();
       if (sourceContext_ != null) hash ^= SourceContext.GetHashCode();
       if (sourceContext_ != null) hash ^= SourceContext.GetHashCode();
       if (Syntax != 0) hash ^= Syntax.GetHashCode();
       if (Syntax != 0) hash ^= Syntax.GetHashCode();
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
       return hash;
     }
     }
 
 
@@ -1016,6 +1047,9 @@ namespace Google.Protobuf.WellKnownTypes {
         output.WriteRawTag(40);
         output.WriteRawTag(40);
         output.WriteEnum((int) Syntax);
         output.WriteEnum((int) Syntax);
       }
       }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1032,6 +1066,9 @@ namespace Google.Protobuf.WellKnownTypes {
       if (Syntax != 0) {
       if (Syntax != 0) {
         size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Syntax);
         size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Syntax);
       }
       }
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
       return size;
     }
     }
 
 
@@ -1054,6 +1091,7 @@ namespace Google.Protobuf.WellKnownTypes {
       if (other.Syntax != 0) {
       if (other.Syntax != 0) {
         Syntax = other.Syntax;
         Syntax = other.Syntax;
       }
       }
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1062,7 +1100,7 @@ namespace Google.Protobuf.WellKnownTypes {
       while ((tag = input.ReadTag()) != 0) {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
         switch(tag) {
           default:
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
             break;
           case 10: {
           case 10: {
             Name = input.ReadString();
             Name = input.ReadString();
@@ -1098,6 +1136,7 @@ namespace Google.Protobuf.WellKnownTypes {
   /// </summary>
   /// </summary>
   public sealed partial class EnumValue : pb::IMessage<EnumValue> {
   public sealed partial class EnumValue : pb::IMessage<EnumValue> {
     private static readonly pb::MessageParser<EnumValue> _parser = new pb::MessageParser<EnumValue>(() => new EnumValue());
     private static readonly pb::MessageParser<EnumValue> _parser = new pb::MessageParser<EnumValue>(() => new EnumValue());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<EnumValue> Parser { get { return _parser; } }
     public static pb::MessageParser<EnumValue> Parser { get { return _parser; } }
 
 
@@ -1123,6 +1162,7 @@ namespace Google.Protobuf.WellKnownTypes {
       name_ = other.name_;
       name_ = other.name_;
       number_ = other.number_;
       number_ = other.number_;
       options_ = other.options_.Clone();
       options_ = other.options_.Clone();
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1187,7 +1227,7 @@ namespace Google.Protobuf.WellKnownTypes {
       if (Name != other.Name) return false;
       if (Name != other.Name) return false;
       if (Number != other.Number) return false;
       if (Number != other.Number) return false;
       if(!options_.Equals(other.options_)) return false;
       if(!options_.Equals(other.options_)) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1196,6 +1236,9 @@ namespace Google.Protobuf.WellKnownTypes {
       if (Name.Length != 0) hash ^= Name.GetHashCode();
       if (Name.Length != 0) hash ^= Name.GetHashCode();
       if (Number != 0) hash ^= Number.GetHashCode();
       if (Number != 0) hash ^= Number.GetHashCode();
       hash ^= options_.GetHashCode();
       hash ^= options_.GetHashCode();
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
       return hash;
     }
     }
 
 
@@ -1215,6 +1258,9 @@ namespace Google.Protobuf.WellKnownTypes {
         output.WriteInt32(Number);
         output.WriteInt32(Number);
       }
       }
       options_.WriteTo(output, _repeated_options_codec);
       options_.WriteTo(output, _repeated_options_codec);
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1227,6 +1273,9 @@ namespace Google.Protobuf.WellKnownTypes {
         size += 1 + pb::CodedOutputStream.ComputeInt32Size(Number);
         size += 1 + pb::CodedOutputStream.ComputeInt32Size(Number);
       }
       }
       size += options_.CalculateSize(_repeated_options_codec);
       size += options_.CalculateSize(_repeated_options_codec);
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
       return size;
     }
     }
 
 
@@ -1242,6 +1291,7 @@ namespace Google.Protobuf.WellKnownTypes {
         Number = other.Number;
         Number = other.Number;
       }
       }
       options_.Add(other.options_);
       options_.Add(other.options_);
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1250,7 +1300,7 @@ namespace Google.Protobuf.WellKnownTypes {
       while ((tag = input.ReadTag()) != 0) {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
         switch(tag) {
           default:
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
             break;
           case 10: {
           case 10: {
             Name = input.ReadString();
             Name = input.ReadString();
@@ -1276,6 +1326,7 @@ namespace Google.Protobuf.WellKnownTypes {
   /// </summary>
   /// </summary>
   public sealed partial class Option : pb::IMessage<Option> {
   public sealed partial class Option : pb::IMessage<Option> {
     private static readonly pb::MessageParser<Option> _parser = new pb::MessageParser<Option>(() => new Option());
     private static readonly pb::MessageParser<Option> _parser = new pb::MessageParser<Option>(() => new Option());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<Option> Parser { get { return _parser; } }
     public static pb::MessageParser<Option> Parser { get { return _parser; } }
 
 
@@ -1300,6 +1351,7 @@ namespace Google.Protobuf.WellKnownTypes {
     public Option(Option other) : this() {
     public Option(Option other) : this() {
       name_ = other.name_;
       name_ = other.name_;
       Value = other.value_ != null ? other.Value.Clone() : null;
       Value = other.value_ != null ? other.Value.Clone() : null;
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1356,7 +1408,7 @@ namespace Google.Protobuf.WellKnownTypes {
       }
       }
       if (Name != other.Name) return false;
       if (Name != other.Name) return false;
       if (!object.Equals(Value, other.Value)) return false;
       if (!object.Equals(Value, other.Value)) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1364,6 +1416,9 @@ namespace Google.Protobuf.WellKnownTypes {
       int hash = 1;
       int hash = 1;
       if (Name.Length != 0) hash ^= Name.GetHashCode();
       if (Name.Length != 0) hash ^= Name.GetHashCode();
       if (value_ != null) hash ^= Value.GetHashCode();
       if (value_ != null) hash ^= Value.GetHashCode();
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
       return hash;
     }
     }
 
 
@@ -1382,6 +1437,9 @@ namespace Google.Protobuf.WellKnownTypes {
         output.WriteRawTag(18);
         output.WriteRawTag(18);
         output.WriteMessage(Value);
         output.WriteMessage(Value);
       }
       }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1393,6 +1451,9 @@ namespace Google.Protobuf.WellKnownTypes {
       if (value_ != null) {
       if (value_ != null) {
         size += 1 + pb::CodedOutputStream.ComputeMessageSize(Value);
         size += 1 + pb::CodedOutputStream.ComputeMessageSize(Value);
       }
       }
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
       return size;
     }
     }
 
 
@@ -1410,6 +1471,7 @@ namespace Google.Protobuf.WellKnownTypes {
         }
         }
         Value.MergeFrom(other.Value);
         Value.MergeFrom(other.Value);
       }
       }
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1418,7 +1480,7 @@ namespace Google.Protobuf.WellKnownTypes {
       while ((tag = input.ReadTag()) != 0) {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
         switch(tag) {
           default:
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
             break;
           case 10: {
           case 10: {
             Name = input.ReadString();
             Name = input.ReadString();

+ 134 - 24
csharp/src/Google.Protobuf/WellKnownTypes/Wrappers.cs

@@ -1,5 +1,7 @@
-// Generated by the protocol buffer compiler.  DO NOT EDIT!
-// source: google/protobuf/wrappers.proto
+// <auto-generated>
+//     Generated by the protocol buffer compiler.  DO NOT EDIT!
+//     source: google/protobuf/wrappers.proto
+// </auto-generated>
 #pragma warning disable 1591, 0612, 3021
 #pragma warning disable 1591, 0612, 3021
 #region Designer generated code
 #region Designer generated code
 
 
@@ -57,6 +59,7 @@ namespace Google.Protobuf.WellKnownTypes {
   /// </summary>
   /// </summary>
   public sealed partial class DoubleValue : pb::IMessage<DoubleValue> {
   public sealed partial class DoubleValue : pb::IMessage<DoubleValue> {
     private static readonly pb::MessageParser<DoubleValue> _parser = new pb::MessageParser<DoubleValue>(() => new DoubleValue());
     private static readonly pb::MessageParser<DoubleValue> _parser = new pb::MessageParser<DoubleValue>(() => new DoubleValue());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<DoubleValue> Parser { get { return _parser; } }
     public static pb::MessageParser<DoubleValue> Parser { get { return _parser; } }
 
 
@@ -80,6 +83,7 @@ namespace Google.Protobuf.WellKnownTypes {
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public DoubleValue(DoubleValue other) : this() {
     public DoubleValue(DoubleValue other) : this() {
       value_ = other.value_;
       value_ = other.value_;
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -114,14 +118,17 @@ namespace Google.Protobuf.WellKnownTypes {
       if (ReferenceEquals(other, this)) {
       if (ReferenceEquals(other, this)) {
         return true;
         return true;
       }
       }
-      if (Value != other.Value) return false;
-      return true;
+      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(Value, other.Value)) return false;
+      return Equals(_unknownFields, other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public override int GetHashCode() {
     public override int GetHashCode() {
       int hash = 1;
       int hash = 1;
-      if (Value != 0D) hash ^= Value.GetHashCode();
+      if (Value != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(Value);
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
       return hash;
     }
     }
 
 
@@ -136,6 +143,9 @@ namespace Google.Protobuf.WellKnownTypes {
         output.WriteRawTag(9);
         output.WriteRawTag(9);
         output.WriteDouble(Value);
         output.WriteDouble(Value);
       }
       }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -144,6 +154,9 @@ namespace Google.Protobuf.WellKnownTypes {
       if (Value != 0D) {
       if (Value != 0D) {
         size += 1 + 8;
         size += 1 + 8;
       }
       }
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
       return size;
     }
     }
 
 
@@ -155,6 +168,7 @@ namespace Google.Protobuf.WellKnownTypes {
       if (other.Value != 0D) {
       if (other.Value != 0D) {
         Value = other.Value;
         Value = other.Value;
       }
       }
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -163,7 +177,7 @@ namespace Google.Protobuf.WellKnownTypes {
       while ((tag = input.ReadTag()) != 0) {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
         switch(tag) {
           default:
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
             break;
           case 9: {
           case 9: {
             Value = input.ReadDouble();
             Value = input.ReadDouble();
@@ -182,6 +196,7 @@ namespace Google.Protobuf.WellKnownTypes {
   /// </summary>
   /// </summary>
   public sealed partial class FloatValue : pb::IMessage<FloatValue> {
   public sealed partial class FloatValue : pb::IMessage<FloatValue> {
     private static readonly pb::MessageParser<FloatValue> _parser = new pb::MessageParser<FloatValue>(() => new FloatValue());
     private static readonly pb::MessageParser<FloatValue> _parser = new pb::MessageParser<FloatValue>(() => new FloatValue());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<FloatValue> Parser { get { return _parser; } }
     public static pb::MessageParser<FloatValue> Parser { get { return _parser; } }
 
 
@@ -205,6 +220,7 @@ namespace Google.Protobuf.WellKnownTypes {
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public FloatValue(FloatValue other) : this() {
     public FloatValue(FloatValue other) : this() {
       value_ = other.value_;
       value_ = other.value_;
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -239,14 +255,17 @@ namespace Google.Protobuf.WellKnownTypes {
       if (ReferenceEquals(other, this)) {
       if (ReferenceEquals(other, this)) {
         return true;
         return true;
       }
       }
-      if (Value != other.Value) return false;
-      return true;
+      if (!pbc::ProtobufEqualityComparers.BitwiseSingleEqualityComparer.Equals(Value, other.Value)) return false;
+      return Equals(_unknownFields, other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public override int GetHashCode() {
     public override int GetHashCode() {
       int hash = 1;
       int hash = 1;
-      if (Value != 0F) hash ^= Value.GetHashCode();
+      if (Value != 0F) hash ^= pbc::ProtobufEqualityComparers.BitwiseSingleEqualityComparer.GetHashCode(Value);
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
       return hash;
     }
     }
 
 
@@ -261,6 +280,9 @@ namespace Google.Protobuf.WellKnownTypes {
         output.WriteRawTag(13);
         output.WriteRawTag(13);
         output.WriteFloat(Value);
         output.WriteFloat(Value);
       }
       }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -269,6 +291,9 @@ namespace Google.Protobuf.WellKnownTypes {
       if (Value != 0F) {
       if (Value != 0F) {
         size += 1 + 4;
         size += 1 + 4;
       }
       }
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
       return size;
     }
     }
 
 
@@ -280,6 +305,7 @@ namespace Google.Protobuf.WellKnownTypes {
       if (other.Value != 0F) {
       if (other.Value != 0F) {
         Value = other.Value;
         Value = other.Value;
       }
       }
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -288,7 +314,7 @@ namespace Google.Protobuf.WellKnownTypes {
       while ((tag = input.ReadTag()) != 0) {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
         switch(tag) {
           default:
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
             break;
           case 13: {
           case 13: {
             Value = input.ReadFloat();
             Value = input.ReadFloat();
@@ -307,6 +333,7 @@ namespace Google.Protobuf.WellKnownTypes {
   /// </summary>
   /// </summary>
   public sealed partial class Int64Value : pb::IMessage<Int64Value> {
   public sealed partial class Int64Value : pb::IMessage<Int64Value> {
     private static readonly pb::MessageParser<Int64Value> _parser = new pb::MessageParser<Int64Value>(() => new Int64Value());
     private static readonly pb::MessageParser<Int64Value> _parser = new pb::MessageParser<Int64Value>(() => new Int64Value());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<Int64Value> Parser { get { return _parser; } }
     public static pb::MessageParser<Int64Value> Parser { get { return _parser; } }
 
 
@@ -330,6 +357,7 @@ namespace Google.Protobuf.WellKnownTypes {
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public Int64Value(Int64Value other) : this() {
     public Int64Value(Int64Value other) : this() {
       value_ = other.value_;
       value_ = other.value_;
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -365,13 +393,16 @@ namespace Google.Protobuf.WellKnownTypes {
         return true;
         return true;
       }
       }
       if (Value != other.Value) return false;
       if (Value != other.Value) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public override int GetHashCode() {
     public override int GetHashCode() {
       int hash = 1;
       int hash = 1;
       if (Value != 0L) hash ^= Value.GetHashCode();
       if (Value != 0L) hash ^= Value.GetHashCode();
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
       return hash;
     }
     }
 
 
@@ -386,6 +417,9 @@ namespace Google.Protobuf.WellKnownTypes {
         output.WriteRawTag(8);
         output.WriteRawTag(8);
         output.WriteInt64(Value);
         output.WriteInt64(Value);
       }
       }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -394,6 +428,9 @@ namespace Google.Protobuf.WellKnownTypes {
       if (Value != 0L) {
       if (Value != 0L) {
         size += 1 + pb::CodedOutputStream.ComputeInt64Size(Value);
         size += 1 + pb::CodedOutputStream.ComputeInt64Size(Value);
       }
       }
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
       return size;
     }
     }
 
 
@@ -405,6 +442,7 @@ namespace Google.Protobuf.WellKnownTypes {
       if (other.Value != 0L) {
       if (other.Value != 0L) {
         Value = other.Value;
         Value = other.Value;
       }
       }
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -413,7 +451,7 @@ namespace Google.Protobuf.WellKnownTypes {
       while ((tag = input.ReadTag()) != 0) {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
         switch(tag) {
           default:
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
             break;
           case 8: {
           case 8: {
             Value = input.ReadInt64();
             Value = input.ReadInt64();
@@ -432,6 +470,7 @@ namespace Google.Protobuf.WellKnownTypes {
   /// </summary>
   /// </summary>
   public sealed partial class UInt64Value : pb::IMessage<UInt64Value> {
   public sealed partial class UInt64Value : pb::IMessage<UInt64Value> {
     private static readonly pb::MessageParser<UInt64Value> _parser = new pb::MessageParser<UInt64Value>(() => new UInt64Value());
     private static readonly pb::MessageParser<UInt64Value> _parser = new pb::MessageParser<UInt64Value>(() => new UInt64Value());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<UInt64Value> Parser { get { return _parser; } }
     public static pb::MessageParser<UInt64Value> Parser { get { return _parser; } }
 
 
@@ -455,6 +494,7 @@ namespace Google.Protobuf.WellKnownTypes {
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public UInt64Value(UInt64Value other) : this() {
     public UInt64Value(UInt64Value other) : this() {
       value_ = other.value_;
       value_ = other.value_;
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -490,13 +530,16 @@ namespace Google.Protobuf.WellKnownTypes {
         return true;
         return true;
       }
       }
       if (Value != other.Value) return false;
       if (Value != other.Value) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public override int GetHashCode() {
     public override int GetHashCode() {
       int hash = 1;
       int hash = 1;
       if (Value != 0UL) hash ^= Value.GetHashCode();
       if (Value != 0UL) hash ^= Value.GetHashCode();
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
       return hash;
     }
     }
 
 
@@ -511,6 +554,9 @@ namespace Google.Protobuf.WellKnownTypes {
         output.WriteRawTag(8);
         output.WriteRawTag(8);
         output.WriteUInt64(Value);
         output.WriteUInt64(Value);
       }
       }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -519,6 +565,9 @@ namespace Google.Protobuf.WellKnownTypes {
       if (Value != 0UL) {
       if (Value != 0UL) {
         size += 1 + pb::CodedOutputStream.ComputeUInt64Size(Value);
         size += 1 + pb::CodedOutputStream.ComputeUInt64Size(Value);
       }
       }
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
       return size;
     }
     }
 
 
@@ -530,6 +579,7 @@ namespace Google.Protobuf.WellKnownTypes {
       if (other.Value != 0UL) {
       if (other.Value != 0UL) {
         Value = other.Value;
         Value = other.Value;
       }
       }
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -538,7 +588,7 @@ namespace Google.Protobuf.WellKnownTypes {
       while ((tag = input.ReadTag()) != 0) {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
         switch(tag) {
           default:
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
             break;
           case 8: {
           case 8: {
             Value = input.ReadUInt64();
             Value = input.ReadUInt64();
@@ -557,6 +607,7 @@ namespace Google.Protobuf.WellKnownTypes {
   /// </summary>
   /// </summary>
   public sealed partial class Int32Value : pb::IMessage<Int32Value> {
   public sealed partial class Int32Value : pb::IMessage<Int32Value> {
     private static readonly pb::MessageParser<Int32Value> _parser = new pb::MessageParser<Int32Value>(() => new Int32Value());
     private static readonly pb::MessageParser<Int32Value> _parser = new pb::MessageParser<Int32Value>(() => new Int32Value());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<Int32Value> Parser { get { return _parser; } }
     public static pb::MessageParser<Int32Value> Parser { get { return _parser; } }
 
 
@@ -580,6 +631,7 @@ namespace Google.Protobuf.WellKnownTypes {
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public Int32Value(Int32Value other) : this() {
     public Int32Value(Int32Value other) : this() {
       value_ = other.value_;
       value_ = other.value_;
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -615,13 +667,16 @@ namespace Google.Protobuf.WellKnownTypes {
         return true;
         return true;
       }
       }
       if (Value != other.Value) return false;
       if (Value != other.Value) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public override int GetHashCode() {
     public override int GetHashCode() {
       int hash = 1;
       int hash = 1;
       if (Value != 0) hash ^= Value.GetHashCode();
       if (Value != 0) hash ^= Value.GetHashCode();
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
       return hash;
     }
     }
 
 
@@ -636,6 +691,9 @@ namespace Google.Protobuf.WellKnownTypes {
         output.WriteRawTag(8);
         output.WriteRawTag(8);
         output.WriteInt32(Value);
         output.WriteInt32(Value);
       }
       }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -644,6 +702,9 @@ namespace Google.Protobuf.WellKnownTypes {
       if (Value != 0) {
       if (Value != 0) {
         size += 1 + pb::CodedOutputStream.ComputeInt32Size(Value);
         size += 1 + pb::CodedOutputStream.ComputeInt32Size(Value);
       }
       }
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
       return size;
     }
     }
 
 
@@ -655,6 +716,7 @@ namespace Google.Protobuf.WellKnownTypes {
       if (other.Value != 0) {
       if (other.Value != 0) {
         Value = other.Value;
         Value = other.Value;
       }
       }
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -663,7 +725,7 @@ namespace Google.Protobuf.WellKnownTypes {
       while ((tag = input.ReadTag()) != 0) {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
         switch(tag) {
           default:
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
             break;
           case 8: {
           case 8: {
             Value = input.ReadInt32();
             Value = input.ReadInt32();
@@ -682,6 +744,7 @@ namespace Google.Protobuf.WellKnownTypes {
   /// </summary>
   /// </summary>
   public sealed partial class UInt32Value : pb::IMessage<UInt32Value> {
   public sealed partial class UInt32Value : pb::IMessage<UInt32Value> {
     private static readonly pb::MessageParser<UInt32Value> _parser = new pb::MessageParser<UInt32Value>(() => new UInt32Value());
     private static readonly pb::MessageParser<UInt32Value> _parser = new pb::MessageParser<UInt32Value>(() => new UInt32Value());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<UInt32Value> Parser { get { return _parser; } }
     public static pb::MessageParser<UInt32Value> Parser { get { return _parser; } }
 
 
@@ -705,6 +768,7 @@ namespace Google.Protobuf.WellKnownTypes {
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public UInt32Value(UInt32Value other) : this() {
     public UInt32Value(UInt32Value other) : this() {
       value_ = other.value_;
       value_ = other.value_;
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -740,13 +804,16 @@ namespace Google.Protobuf.WellKnownTypes {
         return true;
         return true;
       }
       }
       if (Value != other.Value) return false;
       if (Value != other.Value) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public override int GetHashCode() {
     public override int GetHashCode() {
       int hash = 1;
       int hash = 1;
       if (Value != 0) hash ^= Value.GetHashCode();
       if (Value != 0) hash ^= Value.GetHashCode();
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
       return hash;
     }
     }
 
 
@@ -761,6 +828,9 @@ namespace Google.Protobuf.WellKnownTypes {
         output.WriteRawTag(8);
         output.WriteRawTag(8);
         output.WriteUInt32(Value);
         output.WriteUInt32(Value);
       }
       }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -769,6 +839,9 @@ namespace Google.Protobuf.WellKnownTypes {
       if (Value != 0) {
       if (Value != 0) {
         size += 1 + pb::CodedOutputStream.ComputeUInt32Size(Value);
         size += 1 + pb::CodedOutputStream.ComputeUInt32Size(Value);
       }
       }
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
       return size;
     }
     }
 
 
@@ -780,6 +853,7 @@ namespace Google.Protobuf.WellKnownTypes {
       if (other.Value != 0) {
       if (other.Value != 0) {
         Value = other.Value;
         Value = other.Value;
       }
       }
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -788,7 +862,7 @@ namespace Google.Protobuf.WellKnownTypes {
       while ((tag = input.ReadTag()) != 0) {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
         switch(tag) {
           default:
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
             break;
           case 8: {
           case 8: {
             Value = input.ReadUInt32();
             Value = input.ReadUInt32();
@@ -807,6 +881,7 @@ namespace Google.Protobuf.WellKnownTypes {
   /// </summary>
   /// </summary>
   public sealed partial class BoolValue : pb::IMessage<BoolValue> {
   public sealed partial class BoolValue : pb::IMessage<BoolValue> {
     private static readonly pb::MessageParser<BoolValue> _parser = new pb::MessageParser<BoolValue>(() => new BoolValue());
     private static readonly pb::MessageParser<BoolValue> _parser = new pb::MessageParser<BoolValue>(() => new BoolValue());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<BoolValue> Parser { get { return _parser; } }
     public static pb::MessageParser<BoolValue> Parser { get { return _parser; } }
 
 
@@ -830,6 +905,7 @@ namespace Google.Protobuf.WellKnownTypes {
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public BoolValue(BoolValue other) : this() {
     public BoolValue(BoolValue other) : this() {
       value_ = other.value_;
       value_ = other.value_;
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -865,13 +941,16 @@ namespace Google.Protobuf.WellKnownTypes {
         return true;
         return true;
       }
       }
       if (Value != other.Value) return false;
       if (Value != other.Value) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public override int GetHashCode() {
     public override int GetHashCode() {
       int hash = 1;
       int hash = 1;
       if (Value != false) hash ^= Value.GetHashCode();
       if (Value != false) hash ^= Value.GetHashCode();
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
       return hash;
     }
     }
 
 
@@ -886,6 +965,9 @@ namespace Google.Protobuf.WellKnownTypes {
         output.WriteRawTag(8);
         output.WriteRawTag(8);
         output.WriteBool(Value);
         output.WriteBool(Value);
       }
       }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -894,6 +976,9 @@ namespace Google.Protobuf.WellKnownTypes {
       if (Value != false) {
       if (Value != false) {
         size += 1 + 1;
         size += 1 + 1;
       }
       }
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
       return size;
     }
     }
 
 
@@ -905,6 +990,7 @@ namespace Google.Protobuf.WellKnownTypes {
       if (other.Value != false) {
       if (other.Value != false) {
         Value = other.Value;
         Value = other.Value;
       }
       }
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -913,7 +999,7 @@ namespace Google.Protobuf.WellKnownTypes {
       while ((tag = input.ReadTag()) != 0) {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
         switch(tag) {
           default:
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
             break;
           case 8: {
           case 8: {
             Value = input.ReadBool();
             Value = input.ReadBool();
@@ -932,6 +1018,7 @@ namespace Google.Protobuf.WellKnownTypes {
   /// </summary>
   /// </summary>
   public sealed partial class StringValue : pb::IMessage<StringValue> {
   public sealed partial class StringValue : pb::IMessage<StringValue> {
     private static readonly pb::MessageParser<StringValue> _parser = new pb::MessageParser<StringValue>(() => new StringValue());
     private static readonly pb::MessageParser<StringValue> _parser = new pb::MessageParser<StringValue>(() => new StringValue());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<StringValue> Parser { get { return _parser; } }
     public static pb::MessageParser<StringValue> Parser { get { return _parser; } }
 
 
@@ -955,6 +1042,7 @@ namespace Google.Protobuf.WellKnownTypes {
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public StringValue(StringValue other) : this() {
     public StringValue(StringValue other) : this() {
       value_ = other.value_;
       value_ = other.value_;
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -990,13 +1078,16 @@ namespace Google.Protobuf.WellKnownTypes {
         return true;
         return true;
       }
       }
       if (Value != other.Value) return false;
       if (Value != other.Value) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public override int GetHashCode() {
     public override int GetHashCode() {
       int hash = 1;
       int hash = 1;
       if (Value.Length != 0) hash ^= Value.GetHashCode();
       if (Value.Length != 0) hash ^= Value.GetHashCode();
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
       return hash;
     }
     }
 
 
@@ -1011,6 +1102,9 @@ namespace Google.Protobuf.WellKnownTypes {
         output.WriteRawTag(10);
         output.WriteRawTag(10);
         output.WriteString(Value);
         output.WriteString(Value);
       }
       }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1019,6 +1113,9 @@ namespace Google.Protobuf.WellKnownTypes {
       if (Value.Length != 0) {
       if (Value.Length != 0) {
         size += 1 + pb::CodedOutputStream.ComputeStringSize(Value);
         size += 1 + pb::CodedOutputStream.ComputeStringSize(Value);
       }
       }
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
       return size;
     }
     }
 
 
@@ -1030,6 +1127,7 @@ namespace Google.Protobuf.WellKnownTypes {
       if (other.Value.Length != 0) {
       if (other.Value.Length != 0) {
         Value = other.Value;
         Value = other.Value;
       }
       }
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1038,7 +1136,7 @@ namespace Google.Protobuf.WellKnownTypes {
       while ((tag = input.ReadTag()) != 0) {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
         switch(tag) {
           default:
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
             break;
           case 10: {
           case 10: {
             Value = input.ReadString();
             Value = input.ReadString();
@@ -1057,6 +1155,7 @@ namespace Google.Protobuf.WellKnownTypes {
   /// </summary>
   /// </summary>
   public sealed partial class BytesValue : pb::IMessage<BytesValue> {
   public sealed partial class BytesValue : pb::IMessage<BytesValue> {
     private static readonly pb::MessageParser<BytesValue> _parser = new pb::MessageParser<BytesValue>(() => new BytesValue());
     private static readonly pb::MessageParser<BytesValue> _parser = new pb::MessageParser<BytesValue>(() => new BytesValue());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<BytesValue> Parser { get { return _parser; } }
     public static pb::MessageParser<BytesValue> Parser { get { return _parser; } }
 
 
@@ -1080,6 +1179,7 @@ namespace Google.Protobuf.WellKnownTypes {
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public BytesValue(BytesValue other) : this() {
     public BytesValue(BytesValue other) : this() {
       value_ = other.value_;
       value_ = other.value_;
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1115,13 +1215,16 @@ namespace Google.Protobuf.WellKnownTypes {
         return true;
         return true;
       }
       }
       if (Value != other.Value) return false;
       if (Value != other.Value) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public override int GetHashCode() {
     public override int GetHashCode() {
       int hash = 1;
       int hash = 1;
       if (Value.Length != 0) hash ^= Value.GetHashCode();
       if (Value.Length != 0) hash ^= Value.GetHashCode();
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
       return hash;
     }
     }
 
 
@@ -1136,6 +1239,9 @@ namespace Google.Protobuf.WellKnownTypes {
         output.WriteRawTag(10);
         output.WriteRawTag(10);
         output.WriteBytes(Value);
         output.WriteBytes(Value);
       }
       }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1144,6 +1250,9 @@ namespace Google.Protobuf.WellKnownTypes {
       if (Value.Length != 0) {
       if (Value.Length != 0) {
         size += 1 + pb::CodedOutputStream.ComputeBytesSize(Value);
         size += 1 + pb::CodedOutputStream.ComputeBytesSize(Value);
       }
       }
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
       return size;
     }
     }
 
 
@@ -1155,6 +1264,7 @@ namespace Google.Protobuf.WellKnownTypes {
       if (other.Value.Length != 0) {
       if (other.Value.Length != 0) {
         Value = other.Value;
         Value = other.Value;
       }
       }
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
     }
 
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1163,7 +1273,7 @@ namespace Google.Protobuf.WellKnownTypes {
       while ((tag = input.ReadTag()) != 0) {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
         switch(tag) {
           default:
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
             break;
           case 10: {
           case 10: {
             Value = input.ReadBytes();
             Value = input.ReadBytes();

+ 3 - 1
objectivec/google/protobuf/Timestamp.pbobjc.h

@@ -115,7 +115,9 @@ typedef GPB_ENUM(GPBTimestamp_FieldNumber) {
  * {hour}, {min}, and {sec} are zero-padded to two digits each. The fractional
  * {hour}, {min}, and {sec} are zero-padded to two digits each. The fractional
  * seconds, which can go up to 9 digits (i.e. up to 1 nanosecond resolution),
  * seconds, which can go up to 9 digits (i.e. up to 1 nanosecond resolution),
  * are optional. The "Z" suffix indicates the timezone ("UTC"); the timezone
  * are optional. The "Z" suffix indicates the timezone ("UTC"); the timezone
- * is required, though only UTC (as indicated by "Z") is presently supported.
+ * is required. A proto3 JSON serializer should always use UTC (as indicated by
+ * "Z") when printing the Timestamp type and a proto3 JSON parser should be
+ * able to accept both UTC and other timezones (as indicated by an offset).
  *
  *
  * For example, "2017-01-15T01:30:15.01Z" encodes 15.01 seconds past
  * For example, "2017-01-15T01:30:15.01Z" encodes 15.01 seconds past
  * 01:30 UTC on January 15, 2017.
  * 01:30 UTC on January 15, 2017.

+ 0 - 4
ruby/README.md

@@ -16,10 +16,6 @@ install it as you would any other gem:
 
 
     $ gem install [--prerelease] google-protobuf
     $ gem install [--prerelease] google-protobuf
 
 
-The `--pre` flag is necessary if we have not yet made a non-alpha/beta release
-of the Ruby extension; it allows `gem` to consider these "pre-release"
-alpha/beta versions.
-
 Once the gem is installed, you may or may not need `protoc`. If you write your
 Once the gem is installed, you may or may not need `protoc`. If you write your
 message type descriptions directly in the Ruby DSL, you do not need it.
 message type descriptions directly in the Ruby DSL, you do not need it.
 However, if you wish to generate the Ruby DSL from a `.proto` file, you will
 However, if you wish to generate the Ruby DSL from a `.proto` file, you will

+ 3 - 3
src/google/protobuf/any.pb.h

@@ -1,8 +1,8 @@
 // Generated by the protocol buffer compiler.  DO NOT EDIT!
 // Generated by the protocol buffer compiler.  DO NOT EDIT!
 // source: google/protobuf/any.proto
 // source: google/protobuf/any.proto
 
 
-#ifndef PROTOBUF_google_2fprotobuf_2fany_2eproto__INCLUDED
-#define PROTOBUF_google_2fprotobuf_2fany_2eproto__INCLUDED
+#ifndef PROTOBUF_google_2fprotobuf_2fany_2eproto_INCLUDED
+#define PROTOBUF_google_2fprotobuf_2fany_2eproto_INCLUDED
 
 
 #include <string>
 #include <string>
 
 
@@ -329,4 +329,4 @@ inline void Any::set_allocated_value(::std::string* value) {
 
 
 // @@protoc_insertion_point(global_scope)
 // @@protoc_insertion_point(global_scope)
 
 
-#endif  // PROTOBUF_google_2fprotobuf_2fany_2eproto__INCLUDED
+#endif  // PROTOBUF_google_2fprotobuf_2fany_2eproto_INCLUDED

+ 3 - 3
src/google/protobuf/api.pb.h

@@ -1,8 +1,8 @@
 // Generated by the protocol buffer compiler.  DO NOT EDIT!
 // Generated by the protocol buffer compiler.  DO NOT EDIT!
 // source: google/protobuf/api.proto
 // source: google/protobuf/api.proto
 
 
-#ifndef PROTOBUF_google_2fprotobuf_2fapi_2eproto__INCLUDED
-#define PROTOBUF_google_2fprotobuf_2fapi_2eproto__INCLUDED
+#ifndef PROTOBUF_google_2fprotobuf_2fapi_2eproto_INCLUDED
+#define PROTOBUF_google_2fprotobuf_2fapi_2eproto_INCLUDED
 
 
 #include <string>
 #include <string>
 
 
@@ -1182,4 +1182,4 @@ inline void Mixin::set_allocated_root(::std::string* root) {
 
 
 // @@protoc_insertion_point(global_scope)
 // @@protoc_insertion_point(global_scope)
 
 
-#endif  // PROTOBUF_google_2fprotobuf_2fapi_2eproto__INCLUDED
+#endif  // PROTOBUF_google_2fprotobuf_2fapi_2eproto_INCLUDED

+ 3 - 3
src/google/protobuf/compiler/cpp/cpp_file.cc

@@ -1145,8 +1145,8 @@ void FileGenerator::GenerateTopHeaderGuard(io::Printer* printer,
       "// Generated by the protocol buffer compiler.  DO NOT EDIT!\n"
       "// Generated by the protocol buffer compiler.  DO NOT EDIT!\n"
       "// source: $filename$\n"
       "// source: $filename$\n"
       "\n"
       "\n"
-      "#ifndef PROTOBUF_$filename_identifier$__INCLUDED\n"
-      "#define PROTOBUF_$filename_identifier$__INCLUDED\n"
+      "#ifndef PROTOBUF_$filename_identifier$_INCLUDED\n"
+      "#define PROTOBUF_$filename_identifier$_INCLUDED\n"
       "\n"
       "\n"
       "#include <string>\n",
       "#include <string>\n",
       "filename", file_->name(), "filename_identifier", filename_identifier);
       "filename", file_->name(), "filename_identifier", filename_identifier);
@@ -1156,7 +1156,7 @@ void FileGenerator::GenerateTopHeaderGuard(io::Printer* printer,
 void FileGenerator::GenerateBottomHeaderGuard(
 void FileGenerator::GenerateBottomHeaderGuard(
     io::Printer* printer, const string& filename_identifier) {
     io::Printer* printer, const string& filename_identifier) {
   printer->Print(
   printer->Print(
-    "#endif  // PROTOBUF_$filename_identifier$__INCLUDED\n",
+    "#endif  // PROTOBUF_$filename_identifier$_INCLUDED\n",
     "filename_identifier", filename_identifier);
     "filename_identifier", filename_identifier);
 }
 }
 
 

+ 65 - 37
src/google/protobuf/compiler/csharp/csharp_message.cc

@@ -111,7 +111,7 @@ void MessageGenerator::Generate(io::Printer* printer) {
 
 
   WriteMessageDocComment(printer, descriptor_);
   WriteMessageDocComment(printer, descriptor_);
   AddDeprecatedFlag(printer);
   AddDeprecatedFlag(printer);
-  
+
   printer->Print(
   printer->Print(
     vars,
     vars,
     "$access_level$ sealed partial class $class_name$ : pb::IMessage<$class_name$> {\n");
     "$access_level$ sealed partial class $class_name$ : pb::IMessage<$class_name$> {\n");
@@ -119,14 +119,17 @@ void MessageGenerator::Generate(io::Printer* printer) {
 
 
   // All static fields and properties
   // All static fields and properties
   printer->Print(
   printer->Print(
-	  vars,
-	  "private static readonly pb::MessageParser<$class_name$> _parser = new pb::MessageParser<$class_name$>(() => new $class_name$());\n");
+      vars,
+      "private static readonly pb::MessageParser<$class_name$> _parser = new pb::MessageParser<$class_name$>(() => new $class_name$());\n");
+
+  printer->Print(
+      "private pb::UnknownFieldSet _unknownFields;\n");
 
 
   WriteGeneratedCodeAttributes(printer);
   WriteGeneratedCodeAttributes(printer);
 
 
   printer->Print(
   printer->Print(
-	  vars,
-	  "public static pb::MessageParser<$class_name$> Parser { get { return _parser; } }\n\n");
+      vars,
+      "public static pb::MessageParser<$class_name$> Parser { get { return _parser; } }\n\n");
 
 
   // Access the message descriptor via the relevant file descriptor or containing message descriptor.
   // Access the message descriptor via the relevant file descriptor or containing message descriptor.
   if (!descriptor_->containing_type()) {
   if (!descriptor_->containing_type()) {
@@ -139,14 +142,14 @@ void MessageGenerator::Generate(io::Printer* printer) {
 
 
   WriteGeneratedCodeAttributes(printer);
   WriteGeneratedCodeAttributes(printer);
   printer->Print(
   printer->Print(
-	vars,
-	"public static pbr::MessageDescriptor Descriptor {\n"
-	"  get { return $descriptor_accessor$; }\n"
-	"}\n"
-	"\n");
+    vars,
+    "public static pbr::MessageDescriptor Descriptor {\n"
+    "  get { return $descriptor_accessor$; }\n"
+    "}\n"
+    "\n");
   WriteGeneratedCodeAttributes(printer);
   WriteGeneratedCodeAttributes(printer);
   printer->Print(
   printer->Print(
-	vars,
+    vars,
     "pbr::MessageDescriptor pb::IMessage.Descriptor {\n"
     "pbr::MessageDescriptor pb::IMessage.Descriptor {\n"
     "  get { return Descriptor; }\n"
     "  get { return Descriptor; }\n"
     "}\n"
     "}\n"
@@ -209,18 +212,18 @@ void MessageGenerator::Generate(io::Printer* printer) {
     printer->Print("}\n");
     printer->Print("}\n");
     // TODO: Should we put the oneof .proto comments here?
     // TODO: Should we put the oneof .proto comments here?
     // It's unclear exactly where they should go.
     // It's unclear exactly where they should go.
-	printer->Print(
-	  vars,
-	  "private $property_name$OneofCase $name$Case_ = $property_name$OneofCase.None;\n");
-	WriteGeneratedCodeAttributes(printer);
-	printer->Print(
-	  vars,
-	  "public $property_name$OneofCase $property_name$Case {\n"
-	  "  get { return $name$Case_; }\n"
-	  "}\n\n");
-	WriteGeneratedCodeAttributes(printer);
-	printer->Print(
-	  vars,
+    printer->Print(
+      vars,
+      "private $property_name$OneofCase $name$Case_ = $property_name$OneofCase.None;\n");
+    WriteGeneratedCodeAttributes(printer);
+    printer->Print(
+      vars,
+      "public $property_name$OneofCase $property_name$Case {\n"
+      "  get { return $name$Case_; }\n"
+      "}\n\n");
+    WriteGeneratedCodeAttributes(printer);
+    printer->Print(
+      vars,
       "public void Clear$property_name$() {\n"
       "public void Clear$property_name$() {\n"
       "  $name$Case_ = $property_name$OneofCase.None;\n"
       "  $name$Case_ = $property_name$OneofCase.None;\n"
       "  $name$_ = null;\n"
       "  $name$_ = null;\n"
@@ -317,6 +320,9 @@ void MessageGenerator::GenerateCloningCode(io::Printer* printer) {
     printer->Outdent();
     printer->Outdent();
     printer->Print("}\n\n");
     printer->Print("}\n\n");
   }
   }
+  // Clone unknown fields
+  printer->Print(
+      "_unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);\n");
 
 
   printer->Outdent();
   printer->Outdent();
   printer->Print("}\n\n");
   printer->Print("}\n\n");
@@ -337,15 +343,15 @@ void MessageGenerator::GenerateFrameworkMethods(io::Printer* printer) {
     vars["class_name"] = class_name();
     vars["class_name"] = class_name();
 
 
     // Equality
     // Equality
-	WriteGeneratedCodeAttributes(printer);
+    WriteGeneratedCodeAttributes(printer);
     printer->Print(
     printer->Print(
         vars,
         vars,
         "public override bool Equals(object other) {\n"
         "public override bool Equals(object other) {\n"
         "  return Equals(other as $class_name$);\n"
         "  return Equals(other as $class_name$);\n"
         "}\n\n");
         "}\n\n");
-	WriteGeneratedCodeAttributes(printer);
-	printer->Print(
-	    vars,
+    WriteGeneratedCodeAttributes(printer);
+    printer->Print(
+        vars,
         "public bool Equals($class_name$ other) {\n"
         "public bool Equals($class_name$ other) {\n"
         "  if (ReferenceEquals(other, null)) {\n"
         "  if (ReferenceEquals(other, null)) {\n"
         "    return false;\n"
         "    return false;\n"
@@ -365,13 +371,13 @@ void MessageGenerator::GenerateFrameworkMethods(io::Printer* printer) {
     }
     }
     printer->Outdent();
     printer->Outdent();
     printer->Print(
     printer->Print(
-        "  return true;\n"
+        "  return Equals(_unknownFields, other._unknownFields);\n"
         "}\n\n");
         "}\n\n");
 
 
     // GetHashCode
     // GetHashCode
     // Start with a non-zero value to easily distinguish between null and "empty" messages.
     // Start with a non-zero value to easily distinguish between null and "empty" messages.
-	WriteGeneratedCodeAttributes(printer);
-	printer->Print(
+    WriteGeneratedCodeAttributes(printer);
+    printer->Print(
         "public override int GetHashCode() {\n"
         "public override int GetHashCode() {\n"
         "  int hash = 1;\n");
         "  int hash = 1;\n");
     printer->Indent();
     printer->Indent();
@@ -384,12 +390,16 @@ void MessageGenerator::GenerateFrameworkMethods(io::Printer* printer) {
         printer->Print("hash ^= (int) $name$Case_;\n",
         printer->Print("hash ^= (int) $name$Case_;\n",
             "name", UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), false));
             "name", UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), false));
     }
     }
-    printer->Print("return hash;\n");
+    printer->Print(
+        "if (_unknownFields != null) {\n"
+        "  hash ^= _unknownFields.GetHashCode();\n"
+        "}\n"
+        "return hash;\n");
     printer->Outdent();
     printer->Outdent();
     printer->Print("}\n\n");
     printer->Print("}\n\n");
 
 
-	WriteGeneratedCodeAttributes(printer);
-	printer->Print(
+    WriteGeneratedCodeAttributes(printer);
+    printer->Print(
         "public override string ToString() {\n"
         "public override string ToString() {\n"
         "  return pb::JsonFormatter.ToDiagnosticString(this);\n"
         "  return pb::JsonFormatter.ToDiagnosticString(this);\n"
         "}\n\n");
         "}\n\n");
@@ -408,11 +418,17 @@ void MessageGenerator::GenerateMessageSerializationMethods(io::Printer* printer)
     generator->GenerateSerializationCode(printer);
     generator->GenerateSerializationCode(printer);
   }
   }
 
 
+  // Serialize unknown fields
+  printer->Print(
+    "if (_unknownFields != null) {\n"
+    "  _unknownFields.WriteTo(output);\n"
+    "}\n");
+
   // TODO(jonskeet): Memoize size of frozen messages?
   // TODO(jonskeet): Memoize size of frozen messages?
   printer->Outdent();
   printer->Outdent();
   printer->Print(
   printer->Print(
-	"}\n"
-	"\n");
+    "}\n"
+    "\n");
   WriteGeneratedCodeAttributes(printer);
   WriteGeneratedCodeAttributes(printer);
   printer->Print(
   printer->Print(
     "public int CalculateSize() {\n");
     "public int CalculateSize() {\n");
@@ -423,6 +439,12 @@ void MessageGenerator::GenerateMessageSerializationMethods(io::Printer* printer)
         CreateFieldGeneratorInternal(descriptor_->field(i)));
         CreateFieldGeneratorInternal(descriptor_->field(i)));
     generator->GenerateSerializedSizeCode(printer);
     generator->GenerateSerializedSizeCode(printer);
   }
   }
+
+  printer->Print(
+    "if (_unknownFields != null) {\n"
+    "  size += _unknownFields.CalculateSize();\n"
+    "}\n");
+
   printer->Print("return size;\n");
   printer->Print("return size;\n");
   printer->Outdent();
   printer->Outdent();
   printer->Print("}\n\n");
   printer->Print("}\n\n");
@@ -473,8 +495,14 @@ void MessageGenerator::GenerateMergingMethods(io::Printer* printer) {
     printer->Outdent();
     printer->Outdent();
     printer->Print("}\n\n");
     printer->Print("}\n\n");
   }
   }
+  // Merge unknown fields.
+  printer->Print(
+      "_unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);\n");
+
   printer->Outdent();
   printer->Outdent();
   printer->Print("}\n\n");
   printer->Print("}\n\n");
+
+
   WriteGeneratedCodeAttributes(printer);
   WriteGeneratedCodeAttributes(printer);
   printer->Print("public void MergeFrom(pb::CodedInputStream input) {\n");
   printer->Print("public void MergeFrom(pb::CodedInputStream input) {\n");
   printer->Indent();
   printer->Indent();
@@ -486,14 +514,14 @@ void MessageGenerator::GenerateMergingMethods(io::Printer* printer) {
   printer->Indent();
   printer->Indent();
   // Option messages need to store unknown fields so that options can be parsed later.
   // Option messages need to store unknown fields so that options can be parsed later.
   if (IsDescriptorOptionMessage(descriptor_)) {
   if (IsDescriptorOptionMessage(descriptor_)) {
-	printer->Print(
+    printer->Print(
       "default:\n"
       "default:\n"
       "  CustomOptions = CustomOptions.ReadOrSkipUnknownField(input);\n"
       "  CustomOptions = CustomOptions.ReadOrSkipUnknownField(input);\n"
       "  break;\n");
       "  break;\n");
   } else {
   } else {
     printer->Print(
     printer->Print(
       "default:\n"
       "default:\n"
-      "  input.SkipLastField();\n" // We're not storing the data, but we still need to consume it.
+      "  _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);\n"
       "  break;\n");
       "  break;\n");
   }
   }
   for (int i = 0; i < fields_by_number().size(); i++) {
   for (int i = 0; i < fields_by_number().size(); i++) {

+ 14 - 6
src/google/protobuf/compiler/csharp/csharp_primitive_field.cc

@@ -137,14 +137,22 @@ void PrimitiveFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) {
 }
 }
 
 
 void PrimitiveFieldGenerator::WriteHash(io::Printer* printer) {
 void PrimitiveFieldGenerator::WriteHash(io::Printer* printer) {
-  printer->Print(
-    variables_,
-    "if ($has_property_check$) hash ^= $property_name$.GetHashCode();\n");
+  const char *text = "if ($has_property_check$) hash ^= $property_name$.GetHashCode();\n";
+  if (descriptor_->type() == FieldDescriptor::TYPE_FLOAT) {
+    text = "if ($has_property_check$) hash ^= pbc::ProtobufEqualityComparers.BitwiseSingleEqualityComparer.GetHashCode($property_name$);\n";
+  } else if (descriptor_->type() == FieldDescriptor::TYPE_DOUBLE) {
+    text = "if ($has_property_check$) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode($property_name$);\n";
+  }
+	printer->Print(variables_, text);
 }
 }
 void PrimitiveFieldGenerator::WriteEquals(io::Printer* printer) {
 void PrimitiveFieldGenerator::WriteEquals(io::Printer* printer) {
-  printer->Print(
-    variables_,
-    "if ($property_name$ != other.$property_name$) return false;\n");
+  const char *text = "if ($property_name$ != other.$property_name$) return false;\n";
+  if (descriptor_->type() == FieldDescriptor::TYPE_FLOAT) {
+    text = "if (!pbc::ProtobufEqualityComparers.BitwiseSingleEqualityComparer.Equals($property_name$, other.$property_name$)) return false;\n";
+  } else if (descriptor_->type() == FieldDescriptor::TYPE_DOUBLE) {
+    text = "if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals($property_name$, other.$property_name$)) return false;\n";
+  }
+  printer->Print(variables_, text);
 }
 }
 void PrimitiveFieldGenerator::WriteToString(io::Printer* printer) {
 void PrimitiveFieldGenerator::WriteToString(io::Printer* printer) {
   printer->Print(
   printer->Print(

+ 4 - 2
src/google/protobuf/compiler/csharp/csharp_reflection_class.cc

@@ -104,8 +104,10 @@ void ReflectionClassGenerator::Generate(io::Printer* printer) {
 
 
 void ReflectionClassGenerator::WriteIntroduction(io::Printer* printer) {
 void ReflectionClassGenerator::WriteIntroduction(io::Printer* printer) {
   printer->Print(
   printer->Print(
-    "// Generated by the protocol buffer compiler.  DO NOT EDIT!\n"
-    "// source: $file_name$\n"
+    "// <auto-generated>\n"
+    "//     Generated by the protocol buffer compiler.  DO NOT EDIT!\n"
+    "//     source: $file_name$\n"
+    "// </auto-generated>\n"
     "#pragma warning disable 1591, 0612, 3021\n"
     "#pragma warning disable 1591, 0612, 3021\n"
     "#region Designer generated code\n"
     "#region Designer generated code\n"
     "\n"
     "\n"

+ 16 - 6
src/google/protobuf/compiler/csharp/csharp_wrapper_field.cc

@@ -120,15 +120,25 @@ void WrapperFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) {
 }
 }
 
 
 void WrapperFieldGenerator::WriteHash(io::Printer* printer) {
 void WrapperFieldGenerator::WriteHash(io::Printer* printer) {
-  printer->Print(
-    variables_,
-    "if ($has_property_check$) hash ^= $property_name$.GetHashCode();\n");
+  const char *text = "if ($has_property_check$) hash ^= $property_name$.GetHashCode();\n";
+  if (descriptor_->message_type()->field(0)->type() == FieldDescriptor::TYPE_FLOAT) {
+    text = "if ($has_property_check$) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableSingleEqualityComparer.GetHashCode($property_name$);\n";
+  }
+  else if (descriptor_->message_type()->field(0)->type() == FieldDescriptor::TYPE_DOUBLE) {
+    text = "if ($has_property_check$) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode($property_name$);\n";
+  }
+  printer->Print(variables_, text);
 }
 }
 
 
 void WrapperFieldGenerator::WriteEquals(io::Printer* printer) {
 void WrapperFieldGenerator::WriteEquals(io::Printer* printer) {
-  printer->Print(
-    variables_,
-    "if ($property_name$ != other.$property_name$) return false;\n");
+  const char *text = "if ($property_name$ != other.$property_name$) return false;\n";
+  if (descriptor_->message_type()->field(0)->type() == FieldDescriptor::TYPE_FLOAT) {
+    text = "if (!pbc::ProtobufEqualityComparers.BitwiseNullableSingleEqualityComparer.Equals($property_name$, other.$property_name$)) return false;\n";
+  }
+  else if (descriptor_->message_type()->field(0)->type() == FieldDescriptor::TYPE_DOUBLE) {
+    text = "if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals($property_name$, other.$property_name$)) return false;\n";
+  }
+  printer->Print(variables_, text);
 }
 }
 
 
 void WrapperFieldGenerator::WriteToString(io::Printer* printer) {
 void WrapperFieldGenerator::WriteToString(io::Printer* printer) {

+ 3 - 3
src/google/protobuf/compiler/plugin.pb.h

@@ -1,8 +1,8 @@
 // Generated by the protocol buffer compiler.  DO NOT EDIT!
 // Generated by the protocol buffer compiler.  DO NOT EDIT!
 // source: google/protobuf/compiler/plugin.proto
 // source: google/protobuf/compiler/plugin.proto
 
 
-#ifndef PROTOBUF_google_2fprotobuf_2fcompiler_2fplugin_2eproto__INCLUDED
-#define PROTOBUF_google_2fprotobuf_2fcompiler_2fplugin_2eproto__INCLUDED
+#ifndef PROTOBUF_google_2fprotobuf_2fcompiler_2fplugin_2eproto_INCLUDED
+#define PROTOBUF_google_2fprotobuf_2fcompiler_2fplugin_2eproto_INCLUDED
 
 
 #include <string>
 #include <string>
 
 
@@ -1383,4 +1383,4 @@ CodeGeneratorResponse::file() const {
 
 
 // @@protoc_insertion_point(global_scope)
 // @@protoc_insertion_point(global_scope)
 
 
-#endif  // PROTOBUF_google_2fprotobuf_2fcompiler_2fplugin_2eproto__INCLUDED
+#endif  // PROTOBUF_google_2fprotobuf_2fcompiler_2fplugin_2eproto_INCLUDED

+ 3 - 3
src/google/protobuf/descriptor.pb.h

@@ -1,8 +1,8 @@
 // Generated by the protocol buffer compiler.  DO NOT EDIT!
 // Generated by the protocol buffer compiler.  DO NOT EDIT!
 // source: google/protobuf/descriptor.proto
 // source: google/protobuf/descriptor.proto
 
 
-#ifndef PROTOBUF_google_2fprotobuf_2fdescriptor_2eproto__INCLUDED
-#define PROTOBUF_google_2fprotobuf_2fdescriptor_2eproto__INCLUDED
+#ifndef PROTOBUF_google_2fprotobuf_2fdescriptor_2eproto_INCLUDED
+#define PROTOBUF_google_2fprotobuf_2fdescriptor_2eproto_INCLUDED
 
 
 #include <string>
 #include <string>
 
 
@@ -11613,4 +11613,4 @@ inline const EnumDescriptor* GetEnumDescriptor< ::google::protobuf::MethodOption
 
 
 // @@protoc_insertion_point(global_scope)
 // @@protoc_insertion_point(global_scope)
 
 
-#endif  // PROTOBUF_google_2fprotobuf_2fdescriptor_2eproto__INCLUDED
+#endif  // PROTOBUF_google_2fprotobuf_2fdescriptor_2eproto_INCLUDED

+ 3 - 3
src/google/protobuf/duration.pb.h

@@ -1,8 +1,8 @@
 // Generated by the protocol buffer compiler.  DO NOT EDIT!
 // Generated by the protocol buffer compiler.  DO NOT EDIT!
 // source: google/protobuf/duration.proto
 // source: google/protobuf/duration.proto
 
 
-#ifndef PROTOBUF_google_2fprotobuf_2fduration_2eproto__INCLUDED
-#define PROTOBUF_google_2fprotobuf_2fduration_2eproto__INCLUDED
+#ifndef PROTOBUF_google_2fprotobuf_2fduration_2eproto_INCLUDED
+#define PROTOBUF_google_2fprotobuf_2fduration_2eproto_INCLUDED
 
 
 #include <string>
 #include <string>
 
 
@@ -238,4 +238,4 @@ inline void Duration::set_nanos(::google::protobuf::int32 value) {
 
 
 // @@protoc_insertion_point(global_scope)
 // @@protoc_insertion_point(global_scope)
 
 
-#endif  // PROTOBUF_google_2fprotobuf_2fduration_2eproto__INCLUDED
+#endif  // PROTOBUF_google_2fprotobuf_2fduration_2eproto_INCLUDED

+ 3 - 3
src/google/protobuf/empty.pb.h

@@ -1,8 +1,8 @@
 // Generated by the protocol buffer compiler.  DO NOT EDIT!
 // Generated by the protocol buffer compiler.  DO NOT EDIT!
 // source: google/protobuf/empty.proto
 // source: google/protobuf/empty.proto
 
 
-#ifndef PROTOBUF_google_2fprotobuf_2fempty_2eproto__INCLUDED
-#define PROTOBUF_google_2fprotobuf_2fempty_2eproto__INCLUDED
+#ifndef PROTOBUF_google_2fprotobuf_2fempty_2eproto_INCLUDED
+#define PROTOBUF_google_2fprotobuf_2fempty_2eproto_INCLUDED
 
 
 #include <string>
 #include <string>
 
 
@@ -196,4 +196,4 @@ class LIBPROTOBUF_EXPORT Empty : public ::google::protobuf::Message /* @@protoc_
 
 
 // @@protoc_insertion_point(global_scope)
 // @@protoc_insertion_point(global_scope)
 
 
-#endif  // PROTOBUF_google_2fprotobuf_2fempty_2eproto__INCLUDED
+#endif  // PROTOBUF_google_2fprotobuf_2fempty_2eproto_INCLUDED

+ 3 - 3
src/google/protobuf/field_mask.pb.h

@@ -1,8 +1,8 @@
 // Generated by the protocol buffer compiler.  DO NOT EDIT!
 // Generated by the protocol buffer compiler.  DO NOT EDIT!
 // source: google/protobuf/field_mask.proto
 // source: google/protobuf/field_mask.proto
 
 
-#ifndef PROTOBUF_google_2fprotobuf_2ffield_5fmask_2eproto__INCLUDED
-#define PROTOBUF_google_2fprotobuf_2ffield_5fmask_2eproto__INCLUDED
+#ifndef PROTOBUF_google_2fprotobuf_2ffield_5fmask_2eproto_INCLUDED
+#define PROTOBUF_google_2fprotobuf_2ffield_5fmask_2eproto_INCLUDED
 
 
 #include <string>
 #include <string>
 
 
@@ -273,4 +273,4 @@ FieldMask::mutable_paths() {
 
 
 // @@protoc_insertion_point(global_scope)
 // @@protoc_insertion_point(global_scope)
 
 
-#endif  // PROTOBUF_google_2fprotobuf_2ffield_5fmask_2eproto__INCLUDED
+#endif  // PROTOBUF_google_2fprotobuf_2ffield_5fmask_2eproto_INCLUDED

+ 3 - 3
src/google/protobuf/source_context.pb.h

@@ -1,8 +1,8 @@
 // Generated by the protocol buffer compiler.  DO NOT EDIT!
 // Generated by the protocol buffer compiler.  DO NOT EDIT!
 // source: google/protobuf/source_context.proto
 // source: google/protobuf/source_context.proto
 
 
-#ifndef PROTOBUF_google_2fprotobuf_2fsource_5fcontext_2eproto__INCLUDED
-#define PROTOBUF_google_2fprotobuf_2fsource_5fcontext_2eproto__INCLUDED
+#ifndef PROTOBUF_google_2fprotobuf_2fsource_5fcontext_2eproto_INCLUDED
+#define PROTOBUF_google_2fprotobuf_2fsource_5fcontext_2eproto_INCLUDED
 
 
 #include <string>
 #include <string>
 
 
@@ -249,4 +249,4 @@ inline void SourceContext::set_allocated_file_name(::std::string* file_name) {
 
 
 // @@protoc_insertion_point(global_scope)
 // @@protoc_insertion_point(global_scope)
 
 
-#endif  // PROTOBUF_google_2fprotobuf_2fsource_5fcontext_2eproto__INCLUDED
+#endif  // PROTOBUF_google_2fprotobuf_2fsource_5fcontext_2eproto_INCLUDED

+ 3 - 3
src/google/protobuf/struct.pb.h

@@ -1,8 +1,8 @@
 // Generated by the protocol buffer compiler.  DO NOT EDIT!
 // Generated by the protocol buffer compiler.  DO NOT EDIT!
 // source: google/protobuf/struct.proto
 // source: google/protobuf/struct.proto
 
 
-#ifndef PROTOBUF_google_2fprotobuf_2fstruct_2eproto__INCLUDED
-#define PROTOBUF_google_2fprotobuf_2fstruct_2eproto__INCLUDED
+#ifndef PROTOBUF_google_2fprotobuf_2fstruct_2eproto_INCLUDED
+#define PROTOBUF_google_2fprotobuf_2fstruct_2eproto_INCLUDED
 
 
 #include <string>
 #include <string>
 
 
@@ -1039,4 +1039,4 @@ inline const EnumDescriptor* GetEnumDescriptor< ::google::protobuf::NullValue>()
 
 
 // @@protoc_insertion_point(global_scope)
 // @@protoc_insertion_point(global_scope)
 
 
-#endif  // PROTOBUF_google_2fprotobuf_2fstruct_2eproto__INCLUDED
+#endif  // PROTOBUF_google_2fprotobuf_2fstruct_2eproto_INCLUDED

+ 5 - 4
src/google/protobuf/stubs/io_win32.cc

@@ -155,12 +155,13 @@ string normalize(string path) {
 
 
   static const string dot(".");
   static const string dot(".");
   static const string dotdot("..");
   static const string dotdot("..");
+  const char *p = path.c_str();
 
 
   std::vector<string> segments;
   std::vector<string> segments;
   int segment_start = -1;
   int segment_start = -1;
   // Find the path segments in `path` (separated by "/").
   // Find the path segments in `path` (separated by "/").
   for (int i = 0;; ++i) {
   for (int i = 0;; ++i) {
-    if (!is_separator(path[i]) && path[i] != '\0') {
+    if (!is_separator(p[i]) && p[i] != '\0') {
       // The current character does not end a segment, so start one unless it's
       // The current character does not end a segment, so start one unless it's
       // already started.
       // already started.
       if (segment_start < 0) {
       if (segment_start < 0) {
@@ -169,7 +170,7 @@ string normalize(string path) {
     } else if (segment_start >= 0 && i > segment_start) {
     } else if (segment_start >= 0 && i > segment_start) {
       // The current character is "/" or "\0", so this ends a segment.
       // The current character is "/" or "\0", so this ends a segment.
       // Add that to `segments` if there's anything to add; handle "." and "..".
       // Add that to `segments` if there's anything to add; handle "." and "..".
-      string segment(path, segment_start, i - segment_start);
+      string segment(p, segment_start, i - segment_start);
       segment_start = -1;
       segment_start = -1;
       if (segment == dotdot) {
       if (segment == dotdot) {
         if (!segments.empty() &&
         if (!segments.empty() &&
@@ -180,7 +181,7 @@ string normalize(string path) {
         segments.push_back(segment);
         segments.push_back(segment);
       }
       }
     }
     }
-    if (path[i] == '\0') {
+    if (p[i] == '\0') {
       break;
       break;
     }
     }
   }
   }
@@ -203,7 +204,7 @@ string normalize(string path) {
     result << segments[i];
     result << segments[i];
   }
   }
   // Preserve trailing separator if the input contained it.
   // Preserve trailing separator if the input contained it.
-  if (!path.empty() && is_separator(path[path.size() - 1])) {
+  if (!path.empty() && is_separator(p[path.size() - 1])) {
     result << '\\';
     result << '\\';
   }
   }
   return result.str();
   return result.str();

+ 12 - 4
src/google/protobuf/stubs/port.h

@@ -348,6 +348,13 @@ inline void GOOGLE_UNALIGNED_STORE64(void *p, uint64 v) {
 }
 }
 #endif
 #endif
 
 
+#if defined(GOOGLE_PROTOBUF_OS_NACL) \
+    || (defined(__ANDROID__) && defined(__clang__) \
+        && (__clang_major__ == 3 && __clang_minor__ == 8) \
+        && (__clang_patchlevel__ < 275480))
+# define GOOGLE_PROTOBUF_USE_PORTABLE_LOG2
+#endif
+
 #if defined(_MSC_VER)
 #if defined(_MSC_VER)
 #define GOOGLE_THREAD_LOCAL __declspec(thread)
 #define GOOGLE_THREAD_LOCAL __declspec(thread)
 #else
 #else
@@ -413,12 +420,13 @@ class Bits {
   }
   }
 
 
   static uint32 Log2FloorNonZero64(uint64 n) {
   static uint32 Log2FloorNonZero64(uint64 n) {
-    // arm-nacl-clang runs into an instruction-selection failure when it
-    // encounters __builtin_clzll:
+    // Older versions of clang run into an instruction-selection failure when
+    // it encounters __builtin_clzll:
     // https://bugs.chromium.org/p/nativeclient/issues/detail?id=4395
     // https://bugs.chromium.org/p/nativeclient/issues/detail?id=4395
-    // To work around this, when we build for NaCl we use the portable
+    // This includes arm-nacl-clang and clang in older Android NDK versions.
+    // To work around this, when we build with those we use the portable
     // implementation instead.
     // implementation instead.
-#if defined(__GNUC__) && !defined(GOOGLE_PROTOBUF_OS_NACL)
+#if defined(__GNUC__) && !defined(GOOGLE_PROTOBUF_USE_PORTABLE_LOG2)
   return 63 ^ static_cast<uint32>(__builtin_clzll(n));
   return 63 ^ static_cast<uint32>(__builtin_clzll(n));
 #else
 #else
   return Log2FloorNonZero64_Portable(n);
   return Log2FloorNonZero64_Portable(n);

+ 30 - 1
src/google/protobuf/stubs/structurally_valid.cc

@@ -1,4 +1,33 @@
-// Copyright 2005-2008 Google Inc. All Rights Reserved.
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 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.
+
 // Author: jrm@google.com (Jim Meehan)
 // Author: jrm@google.com (Jim Meehan)
 
 
 #include <google/protobuf/stubs/common.h>
 #include <google/protobuf/stubs/common.h>

+ 30 - 0
src/google/protobuf/stubs/structurally_valid_unittest.cc

@@ -1,3 +1,33 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 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.
+
 // Copyright 2008 Google Inc. All Rights Reserved.
 // Copyright 2008 Google Inc. All Rights Reserved.
 // Author: xpeng@google.com (Peter Peng)
 // Author: xpeng@google.com (Peter Peng)
 
 

+ 3 - 3
src/google/protobuf/timestamp.pb.h

@@ -1,8 +1,8 @@
 // Generated by the protocol buffer compiler.  DO NOT EDIT!
 // Generated by the protocol buffer compiler.  DO NOT EDIT!
 // source: google/protobuf/timestamp.proto
 // source: google/protobuf/timestamp.proto
 
 
-#ifndef PROTOBUF_google_2fprotobuf_2ftimestamp_2eproto__INCLUDED
-#define PROTOBUF_google_2fprotobuf_2ftimestamp_2eproto__INCLUDED
+#ifndef PROTOBUF_google_2fprotobuf_2ftimestamp_2eproto_INCLUDED
+#define PROTOBUF_google_2fprotobuf_2ftimestamp_2eproto_INCLUDED
 
 
 #include <string>
 #include <string>
 
 
@@ -238,4 +238,4 @@ inline void Timestamp::set_nanos(::google::protobuf::int32 value) {
 
 
 // @@protoc_insertion_point(global_scope)
 // @@protoc_insertion_point(global_scope)
 
 
-#endif  // PROTOBUF_google_2fprotobuf_2ftimestamp_2eproto__INCLUDED
+#endif  // PROTOBUF_google_2fprotobuf_2ftimestamp_2eproto_INCLUDED

+ 3 - 1
src/google/protobuf/timestamp.proto

@@ -103,7 +103,9 @@ option objc_class_prefix = "GPB";
 // {hour}, {min}, and {sec} are zero-padded to two digits each. The fractional
 // {hour}, {min}, and {sec} are zero-padded to two digits each. The fractional
 // seconds, which can go up to 9 digits (i.e. up to 1 nanosecond resolution),
 // seconds, which can go up to 9 digits (i.e. up to 1 nanosecond resolution),
 // are optional. The "Z" suffix indicates the timezone ("UTC"); the timezone
 // are optional. The "Z" suffix indicates the timezone ("UTC"); the timezone
-// is required, though only UTC (as indicated by "Z") is presently supported.
+// is required. A proto3 JSON serializer should always use UTC (as indicated by
+// "Z") when printing the Timestamp type and a proto3 JSON parser should be
+// able to accept both UTC and other timezones (as indicated by an offset).
 //
 //
 // For example, "2017-01-15T01:30:15.01Z" encodes 15.01 seconds past
 // For example, "2017-01-15T01:30:15.01Z" encodes 15.01 seconds past
 // 01:30 UTC on January 15, 2017.
 // 01:30 UTC on January 15, 2017.

+ 3 - 3
src/google/protobuf/type.pb.h

@@ -1,8 +1,8 @@
 // Generated by the protocol buffer compiler.  DO NOT EDIT!
 // Generated by the protocol buffer compiler.  DO NOT EDIT!
 // source: google/protobuf/type.proto
 // source: google/protobuf/type.proto
 
 
-#ifndef PROTOBUF_google_2fprotobuf_2ftype_2eproto__INCLUDED
-#define PROTOBUF_google_2fprotobuf_2ftype_2eproto__INCLUDED
+#ifndef PROTOBUF_google_2fprotobuf_2ftype_2eproto_INCLUDED
+#define PROTOBUF_google_2fprotobuf_2ftype_2eproto_INCLUDED
 
 
 #include <string>
 #include <string>
 
 
@@ -2403,4 +2403,4 @@ inline const EnumDescriptor* GetEnumDescriptor< ::google::protobuf::Syntax>() {
 
 
 // @@protoc_insertion_point(global_scope)
 // @@protoc_insertion_point(global_scope)
 
 
-#endif  // PROTOBUF_google_2fprotobuf_2ftype_2eproto__INCLUDED
+#endif  // PROTOBUF_google_2fprotobuf_2ftype_2eproto_INCLUDED

+ 4 - 4
src/google/protobuf/util/json_util.h

@@ -56,10 +56,10 @@ struct JsonPrintOptions {
   // Whether to add spaces, line breaks and indentation to make the JSON output
   // Whether to add spaces, line breaks and indentation to make the JSON output
   // easy to read.
   // easy to read.
   bool add_whitespace;
   bool add_whitespace;
-  // Whether to always print primitive fields. By default primitive fields with
-  // default values will be omitted in JSON joutput. For example, an int32 field
-  // set to 0 will be omitted. Set this flag to true will override the default
-  // behavior and print primitive fields regardless of their values.
+  // Whether to always print primitive fields. By default proto3 primitive
+  // fields with default values will be omitted in JSON output. For example, an
+  // int32 field set to 0 will be omitted. Set this flag to true will override
+  // the default behavior and print primitive fields regardless of their values.
   bool always_print_primitive_fields;
   bool always_print_primitive_fields;
   // Whether to always print enums as ints. By default they are rendered as
   // Whether to always print enums as ints. By default they are rendered as
   // strings.
   // strings.

+ 2 - 2
src/google/protobuf/wire_format_lite.h

@@ -860,7 +860,7 @@ inline uint32 WireFormatLite::ZigZagEncode32(int32 n) {
 
 
 inline int32 WireFormatLite::ZigZagDecode32(uint32 n) {
 inline int32 WireFormatLite::ZigZagDecode32(uint32 n) {
   // Note:  Using unsigned types prevent undefined behavior
   // Note:  Using unsigned types prevent undefined behavior
-  return static_cast<int32>((n >> 1) ^ -(n & 1));
+  return static_cast<int32>((n >> 1) ^ (~(n & 1) + 1));
 }
 }
 
 
 inline uint64 WireFormatLite::ZigZagEncode64(int64 n) {
 inline uint64 WireFormatLite::ZigZagEncode64(int64 n) {
@@ -871,7 +871,7 @@ inline uint64 WireFormatLite::ZigZagEncode64(int64 n) {
 
 
 inline int64 WireFormatLite::ZigZagDecode64(uint64 n) {
 inline int64 WireFormatLite::ZigZagDecode64(uint64 n) {
   // Note:  Using unsigned types prevent undefined behavior
   // Note:  Using unsigned types prevent undefined behavior
-  return static_cast<int64>((n >> 1) ^ -(n & 1));
+  return static_cast<int64>((n >> 1) ^ (~(n & 1) + 1));
 }
 }
 
 
 // String is for UTF-8 text only, but, even so, ReadString() can simply
 // String is for UTF-8 text only, but, even so, ReadString() can simply

+ 3 - 3
src/google/protobuf/wrappers.pb.h

@@ -1,8 +1,8 @@
 // Generated by the protocol buffer compiler.  DO NOT EDIT!
 // Generated by the protocol buffer compiler.  DO NOT EDIT!
 // source: google/protobuf/wrappers.proto
 // source: google/protobuf/wrappers.proto
 
 
-#ifndef PROTOBUF_google_2fprotobuf_2fwrappers_2eproto__INCLUDED
-#define PROTOBUF_google_2fprotobuf_2fwrappers_2eproto__INCLUDED
+#ifndef PROTOBUF_google_2fprotobuf_2fwrappers_2eproto_INCLUDED
+#define PROTOBUF_google_2fprotobuf_2fwrappers_2eproto_INCLUDED
 
 
 #include <string>
 #include <string>
 
 
@@ -1533,4 +1533,4 @@ inline void BytesValue::unsafe_arena_set_allocated_value(
 
 
 // @@protoc_insertion_point(global_scope)
 // @@protoc_insertion_point(global_scope)
 
 
-#endif  // PROTOBUF_google_2fprotobuf_2fwrappers_2eproto__INCLUDED
+#endif  // PROTOBUF_google_2fprotobuf_2fwrappers_2eproto_INCLUDED

Some files were not shown because too many files changed in this diff