فهرست منبع

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

Yilun Chong 7 سال پیش
والد
کامیت
cd32aae377
68فایلهای تغییر یافته به همراه3014 افزوده شده و 428 حذف شده
  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/generated_message_table_driven_lite.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/zero_copy_stream.cc",
         "src/google/protobuf/io/zero_copy_stream_impl_lite.cc",
@@ -734,6 +735,7 @@ py_proto_library(
         ":python_srcs",
         "//external:six",
     ],
+    py_extra_srcs = glob(["python/**/__init__.py"]),
     srcs_version = "PY2AND3",
     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/CodedOutputStreamTest.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/Compatibility/PropertyInfoExtensionsTest.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/SampleEnum.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/TestProtos/ForeignMessagePartial.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/TimestampTest.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/ByteArray.cs                                    \
   csharp/src/Google.Protobuf/ByteString.cs                                   \
   csharp/src/Google.Protobuf/CodedInputStream.cs                             \
   csharp/src/Google.Protobuf/CodedOutputStream.ComputeSize.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/ProtobufEqualityComparers.cs        \
   csharp/src/Google.Protobuf/Collections/ReadOnlyDictionary.cs               \
   csharp/src/Google.Protobuf/Collections/RepeatedField.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/Wrappers.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/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_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\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\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

+ 0 - 1
conformance/failure_list_csharp.txt

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

+ 1 - 0
csharp/protos/unittest_proto3.proto

@@ -377,3 +377,4 @@ service TestService {
 message BarRequest  {}
 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
 #region Designer generated code
 
@@ -49,6 +51,7 @@ namespace Google.Protobuf.Examples.AddressBook {
   /// </summary>
   public sealed partial class Person : pb::IMessage<Person> {
     private static readonly pb::MessageParser<Person> _parser = new pb::MessageParser<Person>(() => new Person());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<Person> Parser { get { return _parser; } }
 
@@ -76,6 +79,7 @@ namespace Google.Protobuf.Examples.AddressBook {
       email_ = other.email_;
       phones_ = other.phones_.Clone();
       LastUpdated = other.lastUpdated_ != null ? other.LastUpdated.Clone() : null;
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -158,7 +162,7 @@ namespace Google.Protobuf.Examples.AddressBook {
       if (Email != other.Email) return false;
       if(!phones_.Equals(other.phones_)) return false;
       if (!object.Equals(LastUpdated, other.LastUpdated)) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -169,6 +173,9 @@ namespace Google.Protobuf.Examples.AddressBook {
       if (Email.Length != 0) hash ^= Email.GetHashCode();
       hash ^= phones_.GetHashCode();
       if (lastUpdated_ != null) hash ^= LastUpdated.GetHashCode();
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
     }
 
@@ -196,6 +203,9 @@ namespace Google.Protobuf.Examples.AddressBook {
         output.WriteRawTag(42);
         output.WriteMessage(LastUpdated);
       }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -214,6 +224,9 @@ namespace Google.Protobuf.Examples.AddressBook {
       if (lastUpdated_ != null) {
         size += 1 + pb::CodedOutputStream.ComputeMessageSize(LastUpdated);
       }
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
     }
 
@@ -238,6 +251,7 @@ namespace Google.Protobuf.Examples.AddressBook {
         }
         LastUpdated.MergeFrom(other.LastUpdated);
       }
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -246,7 +260,7 @@ namespace Google.Protobuf.Examples.AddressBook {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
           case 10: {
             Name = input.ReadString();
@@ -287,6 +301,7 @@ namespace Google.Protobuf.Examples.AddressBook {
 
       public sealed partial class PhoneNumber : pb::IMessage<PhoneNumber> {
         private static readonly pb::MessageParser<PhoneNumber> _parser = new pb::MessageParser<PhoneNumber>(() => new PhoneNumber());
+        private pb::UnknownFieldSet _unknownFields;
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
         public static pb::MessageParser<PhoneNumber> Parser { get { return _parser; } }
 
@@ -311,6 +326,7 @@ namespace Google.Protobuf.Examples.AddressBook {
         public PhoneNumber(PhoneNumber other) : this() {
           number_ = other.number_;
           type_ = other.type_;
+          _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -355,7 +371,7 @@ namespace Google.Protobuf.Examples.AddressBook {
           }
           if (Number != other.Number) return false;
           if (Type != other.Type) return false;
-          return true;
+          return Equals(_unknownFields, other._unknownFields);
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -363,6 +379,9 @@ namespace Google.Protobuf.Examples.AddressBook {
           int hash = 1;
           if (Number.Length != 0) hash ^= Number.GetHashCode();
           if (Type != 0) hash ^= Type.GetHashCode();
+          if (_unknownFields != null) {
+            hash ^= _unknownFields.GetHashCode();
+          }
           return hash;
         }
 
@@ -381,6 +400,9 @@ namespace Google.Protobuf.Examples.AddressBook {
             output.WriteRawTag(16);
             output.WriteEnum((int) Type);
           }
+          if (_unknownFields != null) {
+            _unknownFields.WriteTo(output);
+          }
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -392,6 +414,9 @@ namespace Google.Protobuf.Examples.AddressBook {
           if (Type != 0) {
             size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Type);
           }
+          if (_unknownFields != null) {
+            size += _unknownFields.CalculateSize();
+          }
           return size;
         }
 
@@ -406,6 +431,7 @@ namespace Google.Protobuf.Examples.AddressBook {
           if (other.Type != 0) {
             Type = other.Type;
           }
+          _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -414,7 +440,7 @@ namespace Google.Protobuf.Examples.AddressBook {
           while ((tag = input.ReadTag()) != 0) {
             switch(tag) {
               default:
-                input.SkipLastField();
+                _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
                 break;
               case 10: {
                 Number = input.ReadString();
@@ -440,6 +466,7 @@ namespace Google.Protobuf.Examples.AddressBook {
   /// </summary>
   public sealed partial class AddressBook : pb::IMessage<AddressBook> {
     private static readonly pb::MessageParser<AddressBook> _parser = new pb::MessageParser<AddressBook>(() => new AddressBook());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<AddressBook> Parser { get { return _parser; } }
 
@@ -463,6 +490,7 @@ namespace Google.Protobuf.Examples.AddressBook {
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public AddressBook(AddressBook other) : this() {
       people_ = other.people_.Clone();
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -494,13 +522,16 @@ namespace Google.Protobuf.Examples.AddressBook {
         return true;
       }
       if(!people_.Equals(other.people_)) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public override int GetHashCode() {
       int hash = 1;
       hash ^= people_.GetHashCode();
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
     }
 
@@ -512,12 +543,18 @@ namespace Google.Protobuf.Examples.AddressBook {
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public void WriteTo(pb::CodedOutputStream output) {
       people_.WriteTo(output, _repeated_people_codec);
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public int CalculateSize() {
       int size = 0;
       size += people_.CalculateSize(_repeated_people_codec);
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
     }
 
@@ -527,6 +564,7 @@ namespace Google.Protobuf.Examples.AddressBook {
         return;
       }
       people_.Add(other.people_);
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -535,7 +573,7 @@ namespace Google.Protobuf.Examples.AddressBook {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
           case 10: {
             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
 #region Designer generated code
 
@@ -62,6 +64,7 @@ namespace Conformance {
   /// </summary>
   public sealed partial class ConformanceRequest : pb::IMessage<ConformanceRequest> {
     private static readonly pb::MessageParser<ConformanceRequest> _parser = new pb::MessageParser<ConformanceRequest>(() => new ConformanceRequest());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<ConformanceRequest> Parser { get { return _parser; } }
 
@@ -95,6 +98,7 @@ namespace Conformance {
           break;
       }
 
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -191,7 +195,7 @@ namespace Conformance {
       if (RequestedOutputFormat != other.RequestedOutputFormat) return false;
       if (MessageType != other.MessageType) return false;
       if (PayloadCase != other.PayloadCase) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -202,6 +206,9 @@ namespace Conformance {
       if (RequestedOutputFormat != 0) hash ^= RequestedOutputFormat.GetHashCode();
       if (MessageType.Length != 0) hash ^= MessageType.GetHashCode();
       hash ^= (int) payloadCase_;
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
     }
 
@@ -228,6 +235,9 @@ namespace Conformance {
         output.WriteRawTag(34);
         output.WriteString(MessageType);
       }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -245,6 +255,9 @@ namespace Conformance {
       if (MessageType.Length != 0) {
         size += 1 + pb::CodedOutputStream.ComputeStringSize(MessageType);
       }
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
     }
 
@@ -268,6 +281,7 @@ namespace Conformance {
           break;
       }
 
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -276,7 +290,7 @@ namespace Conformance {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
           case 10: {
             ProtobufPayload = input.ReadBytes();
@@ -305,6 +319,7 @@ namespace Conformance {
   /// </summary>
   public sealed partial class ConformanceResponse : pb::IMessage<ConformanceResponse> {
     private static readonly pb::MessageParser<ConformanceResponse> _parser = new pb::MessageParser<ConformanceResponse>(() => new ConformanceResponse());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<ConformanceResponse> Parser { get { return _parser; } }
 
@@ -348,6 +363,7 @@ namespace Conformance {
           break;
       }
 
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -493,7 +509,7 @@ namespace Conformance {
       if (JsonPayload != other.JsonPayload) return false;
       if (Skipped != other.Skipped) return false;
       if (ResultCase != other.ResultCase) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -506,6 +522,9 @@ namespace Conformance {
       if (resultCase_ == ResultOneofCase.JsonPayload) hash ^= JsonPayload.GetHashCode();
       if (resultCase_ == ResultOneofCase.Skipped) hash ^= Skipped.GetHashCode();
       hash ^= (int) resultCase_;
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
     }
 
@@ -540,6 +559,9 @@ namespace Conformance {
         output.WriteRawTag(50);
         output.WriteString(SerializeError);
       }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -563,6 +585,9 @@ namespace Conformance {
       if (resultCase_ == ResultOneofCase.Skipped) {
         size += 1 + pb::CodedOutputStream.ComputeStringSize(Skipped);
       }
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
     }
 
@@ -592,6 +617,7 @@ namespace Conformance {
           break;
       }
 
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -600,7 +626,7 @@ namespace Conformance {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
           case 10: {
             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());
         }
 
+        [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
         [Test]
         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();
             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]
-        public void IgnoreUnknownFields_RealDataStillRead()
+        public void DiscardUnknownFields_RealDataStillRead()
         {
             var message = SampleMessages.CreateFullTestAllTypes();
             var stream = new MemoryStream();
@@ -652,16 +652,18 @@ namespace Google.Protobuf
 
             stream.Position = 0;
             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]
-        public void IgnoreUnknownFields_AllTypes()
+        public void DiscardUnknownFields_AllTypes()
         {
             // Simple way of ensuring we can skip all kinds of fields.
             var data = SampleMessages.CreateFullTestAllTypes().ToByteArray();
             var empty = Empty.Parser.ParseFrom(data);
-            Assert.AreEqual(new Empty(), empty);
+            // TODO(jieluo): Add test back when DiscardUnknownFields API is supported.
+            // Assert.AreNotEqual(new Empty(), empty);
         }
 
         // This was originally seen as a conformance test failure.
@@ -719,5 +721,16 @@ namespace Google.Protobuf
             JsonFormatter.Default.Format(message, writer);
             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
 #region Designer generated code
 
@@ -176,6 +178,7 @@ namespace Google.Protobuf.TestProtos {
   /// </summary>
   public sealed partial class TestMap : pb::IMessage<TestMap> {
     private static readonly pb::MessageParser<TestMap> _parser = new pb::MessageParser<TestMap>(() => new TestMap());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<TestMap> Parser { get { return _parser; } }
 
@@ -215,6 +218,7 @@ namespace Google.Protobuf.TestProtos {
       mapInt32Bytes_ = other.mapInt32Bytes_.Clone();
       mapInt32Enum_ = other.mapInt32Enum_.Clone();
       mapInt32ForeignMessage_ = other.mapInt32ForeignMessage_.Clone();
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -422,7 +426,7 @@ namespace Google.Protobuf.TestProtos {
       if (!MapInt32Bytes.Equals(other.MapInt32Bytes)) return false;
       if (!MapInt32Enum.Equals(other.MapInt32Enum)) return false;
       if (!MapInt32ForeignMessage.Equals(other.MapInt32ForeignMessage)) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -445,6 +449,9 @@ namespace Google.Protobuf.TestProtos {
       hash ^= MapInt32Bytes.GetHashCode();
       hash ^= MapInt32Enum.GetHashCode();
       hash ^= MapInt32ForeignMessage.GetHashCode();
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
     }
 
@@ -472,6 +479,9 @@ namespace Google.Protobuf.TestProtos {
       mapInt32Bytes_.WriteTo(output, _map_mapInt32Bytes_codec);
       mapInt32Enum_.WriteTo(output, _map_mapInt32Enum_codec);
       mapInt32ForeignMessage_.WriteTo(output, _map_mapInt32ForeignMessage_codec);
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -494,6 +504,9 @@ namespace Google.Protobuf.TestProtos {
       size += mapInt32Bytes_.CalculateSize(_map_mapInt32Bytes_codec);
       size += mapInt32Enum_.CalculateSize(_map_mapInt32Enum_codec);
       size += mapInt32ForeignMessage_.CalculateSize(_map_mapInt32ForeignMessage_codec);
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
     }
 
@@ -519,6 +532,7 @@ namespace Google.Protobuf.TestProtos {
       mapInt32Bytes_.Add(other.mapInt32Bytes_);
       mapInt32Enum_.Add(other.mapInt32Enum_);
       mapInt32ForeignMessage_.Add(other.mapInt32ForeignMessage_);
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -527,7 +541,7 @@ namespace Google.Protobuf.TestProtos {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
           case 10: {
             mapInt32Int32_.AddEntriesFrom(input, _map_mapInt32Int32_codec);
@@ -605,6 +619,7 @@ namespace Google.Protobuf.TestProtos {
 
   public sealed partial class TestMapSubmessage : pb::IMessage<TestMapSubmessage> {
     private static readonly pb::MessageParser<TestMapSubmessage> _parser = new pb::MessageParser<TestMapSubmessage>(() => new TestMapSubmessage());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<TestMapSubmessage> Parser { get { return _parser; } }
 
@@ -628,6 +643,7 @@ namespace Google.Protobuf.TestProtos {
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public TestMapSubmessage(TestMapSubmessage other) : this() {
       TestMap = other.testMap_ != null ? other.TestMap.Clone() : null;
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -660,13 +676,16 @@ namespace Google.Protobuf.TestProtos {
         return true;
       }
       if (!object.Equals(TestMap, other.TestMap)) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public override int GetHashCode() {
       int hash = 1;
       if (testMap_ != null) hash ^= TestMap.GetHashCode();
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
     }
 
@@ -681,6 +700,9 @@ namespace Google.Protobuf.TestProtos {
         output.WriteRawTag(10);
         output.WriteMessage(TestMap);
       }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -689,6 +711,9 @@ namespace Google.Protobuf.TestProtos {
       if (testMap_ != null) {
         size += 1 + pb::CodedOutputStream.ComputeMessageSize(TestMap);
       }
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
     }
 
@@ -703,6 +728,7 @@ namespace Google.Protobuf.TestProtos {
         }
         TestMap.MergeFrom(other.TestMap);
       }
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -711,7 +737,7 @@ namespace Google.Protobuf.TestProtos {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
           case 10: {
             if (testMap_ == null) {
@@ -728,6 +754,7 @@ namespace Google.Protobuf.TestProtos {
 
   public sealed partial class TestMessageMap : pb::IMessage<TestMessageMap> {
     private static readonly pb::MessageParser<TestMessageMap> _parser = new pb::MessageParser<TestMessageMap>(() => new TestMessageMap());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<TestMessageMap> Parser { get { return _parser; } }
 
@@ -751,6 +778,7 @@ namespace Google.Protobuf.TestProtos {
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public TestMessageMap(TestMessageMap other) : this() {
       mapInt32Message_ = other.mapInt32Message_.Clone();
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -782,13 +810,16 @@ namespace Google.Protobuf.TestProtos {
         return true;
       }
       if (!MapInt32Message.Equals(other.MapInt32Message)) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public override int GetHashCode() {
       int hash = 1;
       hash ^= MapInt32Message.GetHashCode();
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
     }
 
@@ -800,12 +831,18 @@ namespace Google.Protobuf.TestProtos {
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public void WriteTo(pb::CodedOutputStream output) {
       mapInt32Message_.WriteTo(output, _map_mapInt32Message_codec);
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public int CalculateSize() {
       int size = 0;
       size += mapInt32Message_.CalculateSize(_map_mapInt32Message_codec);
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
     }
 
@@ -815,6 +852,7 @@ namespace Google.Protobuf.TestProtos {
         return;
       }
       mapInt32Message_.Add(other.mapInt32Message_);
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -823,7 +861,7 @@ namespace Google.Protobuf.TestProtos {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
           case 10: {
             mapInt32Message_.AddEntriesFrom(input, _map_mapInt32Message_codec);
@@ -840,6 +878,7 @@ namespace Google.Protobuf.TestProtos {
   /// </summary>
   public sealed partial class TestSameTypeMap : pb::IMessage<TestSameTypeMap> {
     private static readonly pb::MessageParser<TestSameTypeMap> _parser = new pb::MessageParser<TestSameTypeMap>(() => new TestSameTypeMap());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<TestSameTypeMap> Parser { get { return _parser; } }
 
@@ -864,6 +903,7 @@ namespace Google.Protobuf.TestProtos {
     public TestSameTypeMap(TestSameTypeMap other) : this() {
       map1_ = other.map1_.Clone();
       map2_ = other.map2_.Clone();
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -906,7 +946,7 @@ namespace Google.Protobuf.TestProtos {
       }
       if (!Map1.Equals(other.Map1)) return false;
       if (!Map2.Equals(other.Map2)) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -914,6 +954,9 @@ namespace Google.Protobuf.TestProtos {
       int hash = 1;
       hash ^= Map1.GetHashCode();
       hash ^= Map2.GetHashCode();
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
     }
 
@@ -926,6 +969,9 @@ namespace Google.Protobuf.TestProtos {
     public void WriteTo(pb::CodedOutputStream output) {
       map1_.WriteTo(output, _map_map1_codec);
       map2_.WriteTo(output, _map_map2_codec);
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -933,6 +979,9 @@ namespace Google.Protobuf.TestProtos {
       int size = 0;
       size += map1_.CalculateSize(_map_map1_codec);
       size += map2_.CalculateSize(_map_map2_codec);
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
     }
 
@@ -943,6 +992,7 @@ namespace Google.Protobuf.TestProtos {
       }
       map1_.Add(other.map1_);
       map2_.Add(other.map2_);
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -951,7 +1001,7 @@ namespace Google.Protobuf.TestProtos {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
           case 10: {
             map1_.AddEntriesFrom(input, _map_map1_codec);
@@ -969,6 +1019,7 @@ namespace Google.Protobuf.TestProtos {
 
   public sealed partial class TestArenaMap : pb::IMessage<TestArenaMap> {
     private static readonly pb::MessageParser<TestArenaMap> _parser = new pb::MessageParser<TestArenaMap>(() => new TestArenaMap());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<TestArenaMap> Parser { get { return _parser; } }
 
@@ -1006,6 +1057,7 @@ namespace Google.Protobuf.TestProtos {
       mapBoolBool_ = other.mapBoolBool_.Clone();
       mapInt32Enum_ = other.mapInt32Enum_.Clone();
       mapInt32ForeignMessage_ = other.mapInt32ForeignMessage_.Clone();
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1191,7 +1243,7 @@ namespace Google.Protobuf.TestProtos {
       if (!MapBoolBool.Equals(other.MapBoolBool)) return false;
       if (!MapInt32Enum.Equals(other.MapInt32Enum)) return false;
       if (!MapInt32ForeignMessage.Equals(other.MapInt32ForeignMessage)) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1212,6 +1264,9 @@ namespace Google.Protobuf.TestProtos {
       hash ^= MapBoolBool.GetHashCode();
       hash ^= MapInt32Enum.GetHashCode();
       hash ^= MapInt32ForeignMessage.GetHashCode();
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
     }
 
@@ -1237,6 +1292,9 @@ namespace Google.Protobuf.TestProtos {
       mapBoolBool_.WriteTo(output, _map_mapBoolBool_codec);
       mapInt32Enum_.WriteTo(output, _map_mapInt32Enum_codec);
       mapInt32ForeignMessage_.WriteTo(output, _map_mapInt32ForeignMessage_codec);
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1257,6 +1315,9 @@ namespace Google.Protobuf.TestProtos {
       size += mapBoolBool_.CalculateSize(_map_mapBoolBool_codec);
       size += mapInt32Enum_.CalculateSize(_map_mapInt32Enum_codec);
       size += mapInt32ForeignMessage_.CalculateSize(_map_mapInt32ForeignMessage_codec);
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
     }
 
@@ -1280,6 +1341,7 @@ namespace Google.Protobuf.TestProtos {
       mapBoolBool_.Add(other.mapBoolBool_);
       mapInt32Enum_.Add(other.mapInt32Enum_);
       mapInt32ForeignMessage_.Add(other.mapInt32ForeignMessage_);
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1288,7 +1350,7 @@ namespace Google.Protobuf.TestProtos {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
           case 10: {
             mapInt32Int32_.AddEntriesFrom(input, _map_mapInt32Int32_codec);
@@ -1362,6 +1424,7 @@ namespace Google.Protobuf.TestProtos {
   /// </summary>
   public sealed partial class MessageContainingEnumCalledType : pb::IMessage<MessageContainingEnumCalledType> {
     private static readonly pb::MessageParser<MessageContainingEnumCalledType> _parser = new pb::MessageParser<MessageContainingEnumCalledType>(() => new MessageContainingEnumCalledType());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<MessageContainingEnumCalledType> Parser { get { return _parser; } }
 
@@ -1385,6 +1448,7 @@ namespace Google.Protobuf.TestProtos {
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public MessageContainingEnumCalledType(MessageContainingEnumCalledType other) : this() {
       type_ = other.type_.Clone();
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1416,13 +1480,16 @@ namespace Google.Protobuf.TestProtos {
         return true;
       }
       if (!Type.Equals(other.Type)) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public override int GetHashCode() {
       int hash = 1;
       hash ^= Type.GetHashCode();
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
     }
 
@@ -1434,12 +1501,18 @@ namespace Google.Protobuf.TestProtos {
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public void WriteTo(pb::CodedOutputStream output) {
       type_.WriteTo(output, _map_type_codec);
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public int CalculateSize() {
       int size = 0;
       size += type_.CalculateSize(_map_type_codec);
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
     }
 
@@ -1449,6 +1522,7 @@ namespace Google.Protobuf.TestProtos {
         return;
       }
       type_.Add(other.type_);
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1457,7 +1531,7 @@ namespace Google.Protobuf.TestProtos {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
           case 10: {
             type_.AddEntriesFrom(input, _map_type_codec);
@@ -1485,6 +1559,7 @@ namespace Google.Protobuf.TestProtos {
   /// </summary>
   public sealed partial class MessageContainingMapCalledEntry : pb::IMessage<MessageContainingMapCalledEntry> {
     private static readonly pb::MessageParser<MessageContainingMapCalledEntry> _parser = new pb::MessageParser<MessageContainingMapCalledEntry>(() => new MessageContainingMapCalledEntry());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<MessageContainingMapCalledEntry> Parser { get { return _parser; } }
 
@@ -1508,6 +1583,7 @@ namespace Google.Protobuf.TestProtos {
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public MessageContainingMapCalledEntry(MessageContainingMapCalledEntry other) : this() {
       entry_ = other.entry_.Clone();
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1539,13 +1615,16 @@ namespace Google.Protobuf.TestProtos {
         return true;
       }
       if (!Entry.Equals(other.Entry)) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public override int GetHashCode() {
       int hash = 1;
       hash ^= Entry.GetHashCode();
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
     }
 
@@ -1557,12 +1636,18 @@ namespace Google.Protobuf.TestProtos {
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public void WriteTo(pb::CodedOutputStream output) {
       entry_.WriteTo(output, _map_entry_codec);
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public int CalculateSize() {
       int size = 0;
       size += entry_.CalculateSize(_map_entry_codec);
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
     }
 
@@ -1572,6 +1657,7 @@ namespace Google.Protobuf.TestProtos {
         return;
       }
       entry_.Add(other.entry_);
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1580,7 +1666,7 @@ namespace Google.Protobuf.TestProtos {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
           case 10: {
             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
 #region Designer generated code
 
@@ -233,6 +235,7 @@ namespace ProtobufTestMessages.Proto3 {
   /// </summary>
   public sealed partial class TestAllTypesProto3 : pb::IMessage<TestAllTypesProto3> {
     private static readonly pb::MessageParser<TestAllTypesProto3> _parser = new pb::MessageParser<TestAllTypesProto3>(() => new TestAllTypesProto3());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<TestAllTypesProto3> Parser { get { return _parser; } }
 
@@ -395,6 +398,7 @@ namespace ProtobufTestMessages.Proto3 {
           break;
       }
 
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1730,8 +1734,8 @@ namespace ProtobufTestMessages.Proto3 {
       if (OptionalFixed64 != other.OptionalFixed64) return false;
       if (OptionalSfixed32 != other.OptionalSfixed32) return false;
       if (OptionalSfixed64 != other.OptionalSfixed64) return false;
-      if (OptionalFloat != other.OptionalFloat) return false;
-      if (OptionalDouble != other.OptionalDouble) return false;
+      if (!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 (OptionalString != other.OptionalString) return false;
       if (OptionalBytes != other.OptionalBytes) return false;
@@ -1788,16 +1792,16 @@ namespace ProtobufTestMessages.Proto3 {
       if (OneofBytes != other.OneofBytes) return false;
       if (OneofBool != other.OneofBool) 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 (OptionalBoolWrapper != other.OptionalBoolWrapper) return false;
       if (OptionalInt32Wrapper != other.OptionalInt32Wrapper) return false;
       if (OptionalInt64Wrapper != other.OptionalInt64Wrapper) return false;
       if (OptionalUint32Wrapper != other.OptionalUint32Wrapper) return false;
       if (OptionalUint64Wrapper != other.OptionalUint64Wrapper) return false;
-      if (OptionalFloatWrapper != other.OptionalFloatWrapper) return false;
-      if (OptionalDoubleWrapper != other.OptionalDoubleWrapper) return false;
+      if (!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 (OptionalBytesWrapper != other.OptionalBytesWrapper) return false;
       if(!repeatedBoolWrapper_.Equals(other.repeatedBoolWrapper_)) return false;
@@ -1840,7 +1844,7 @@ namespace ProtobufTestMessages.Proto3 {
       if (FieldName17 != other.FieldName17) return false;
       if (FieldName18 != other.FieldName18) return false;
       if (OneofFieldCase != other.OneofFieldCase) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1856,8 +1860,8 @@ namespace ProtobufTestMessages.Proto3 {
       if (OptionalFixed64 != 0UL) hash ^= OptionalFixed64.GetHashCode();
       if (OptionalSfixed32 != 0) hash ^= OptionalSfixed32.GetHashCode();
       if (OptionalSfixed64 != 0L) hash ^= OptionalSfixed64.GetHashCode();
-      if (OptionalFloat != 0F) hash ^= OptionalFloat.GetHashCode();
-      if (OptionalDouble != 0D) hash ^= OptionalDouble.GetHashCode();
+      if (OptionalFloat != 0F) hash ^= pbc::ProtobufEqualityComparers.BitwiseSingleEqualityComparer.GetHashCode(OptionalFloat);
+      if (OptionalDouble != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(OptionalDouble);
       if (OptionalBool != false) hash ^= OptionalBool.GetHashCode();
       if (OptionalString.Length != 0) hash ^= OptionalString.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.OneofBool) hash ^= OneofBool.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 (optionalBoolWrapper_ != null) hash ^= OptionalBoolWrapper.GetHashCode();
       if (optionalInt32Wrapper_ != null) hash ^= OptionalInt32Wrapper.GetHashCode();
       if (optionalInt64Wrapper_ != null) hash ^= OptionalInt64Wrapper.GetHashCode();
       if (optionalUint32Wrapper_ != null) hash ^= OptionalUint32Wrapper.GetHashCode();
       if (optionalUint64Wrapper_ != null) hash ^= OptionalUint64Wrapper.GetHashCode();
-      if (optionalFloatWrapper_ != null) hash ^= OptionalFloatWrapper.GetHashCode();
-      if (optionalDoubleWrapper_ != null) hash ^= OptionalDoubleWrapper.GetHashCode();
+      if (optionalFloatWrapper_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableSingleEqualityComparer.GetHashCode(OptionalFloatWrapper);
+      if (optionalDoubleWrapper_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(OptionalDoubleWrapper);
       if (optionalStringWrapper_ != null) hash ^= OptionalStringWrapper.GetHashCode();
       if (optionalBytesWrapper_ != null) hash ^= OptionalBytesWrapper.GetHashCode();
       hash ^= repeatedBoolWrapper_.GetHashCode();
@@ -1966,6 +1970,9 @@ namespace ProtobufTestMessages.Proto3 {
       if (FieldName17 != 0) hash ^= FieldName17.GetHashCode();
       if (FieldName18 != 0) hash ^= FieldName18.GetHashCode();
       hash ^= (int) oneofFieldCase_;
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
     }
 
@@ -2278,6 +2285,9 @@ namespace ProtobufTestMessages.Proto3 {
         output.WriteRawTag(144, 26);
         output.WriteInt32(FieldName18);
       }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -2530,6 +2540,9 @@ namespace ProtobufTestMessages.Proto3 {
       if (FieldName18 != 0) {
         size += 2 + pb::CodedOutputStream.ComputeInt32Size(FieldName18);
       }
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
     }
 
@@ -2836,6 +2849,7 @@ namespace ProtobufTestMessages.Proto3 {
           break;
       }
 
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -2844,7 +2858,7 @@ namespace ProtobufTestMessages.Proto3 {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
           case 8: {
             OptionalInt32 = input.ReadInt32();
@@ -3417,6 +3431,7 @@ namespace ProtobufTestMessages.Proto3 {
 
       public sealed partial class NestedMessage : pb::IMessage<NestedMessage> {
         private static readonly pb::MessageParser<NestedMessage> _parser = new pb::MessageParser<NestedMessage>(() => new NestedMessage());
+        private pb::UnknownFieldSet _unknownFields;
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
         public static pb::MessageParser<NestedMessage> Parser { get { return _parser; } }
 
@@ -3441,6 +3456,7 @@ namespace ProtobufTestMessages.Proto3 {
         public NestedMessage(NestedMessage other) : this() {
           a_ = other.a_;
           Corecursive = other.corecursive_ != null ? other.Corecursive.Clone() : null;
+          _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -3485,7 +3501,7 @@ namespace ProtobufTestMessages.Proto3 {
           }
           if (A != other.A) return false;
           if (!object.Equals(Corecursive, other.Corecursive)) return false;
-          return true;
+          return Equals(_unknownFields, other._unknownFields);
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -3493,6 +3509,9 @@ namespace ProtobufTestMessages.Proto3 {
           int hash = 1;
           if (A != 0) hash ^= A.GetHashCode();
           if (corecursive_ != null) hash ^= Corecursive.GetHashCode();
+          if (_unknownFields != null) {
+            hash ^= _unknownFields.GetHashCode();
+          }
           return hash;
         }
 
@@ -3511,6 +3530,9 @@ namespace ProtobufTestMessages.Proto3 {
             output.WriteRawTag(18);
             output.WriteMessage(Corecursive);
           }
+          if (_unknownFields != null) {
+            _unknownFields.WriteTo(output);
+          }
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -3522,6 +3544,9 @@ namespace ProtobufTestMessages.Proto3 {
           if (corecursive_ != null) {
             size += 1 + pb::CodedOutputStream.ComputeMessageSize(Corecursive);
           }
+          if (_unknownFields != null) {
+            size += _unknownFields.CalculateSize();
+          }
           return size;
         }
 
@@ -3539,6 +3564,7 @@ namespace ProtobufTestMessages.Proto3 {
             }
             Corecursive.MergeFrom(other.Corecursive);
           }
+          _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -3547,7 +3573,7 @@ namespace ProtobufTestMessages.Proto3 {
           while ((tag = input.ReadTag()) != 0) {
             switch(tag) {
               default:
-                input.SkipLastField();
+                _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
                 break;
               case 8: {
                 A = input.ReadInt32();
@@ -3573,6 +3599,7 @@ namespace ProtobufTestMessages.Proto3 {
 
   public sealed partial class ForeignMessage : pb::IMessage<ForeignMessage> {
     private static readonly pb::MessageParser<ForeignMessage> _parser = new pb::MessageParser<ForeignMessage>(() => new ForeignMessage());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<ForeignMessage> Parser { get { return _parser; } }
 
@@ -3596,6 +3623,7 @@ namespace ProtobufTestMessages.Proto3 {
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public ForeignMessage(ForeignMessage other) : this() {
       c_ = other.c_;
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -3628,13 +3656,16 @@ namespace ProtobufTestMessages.Proto3 {
         return true;
       }
       if (C != other.C) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public override int GetHashCode() {
       int hash = 1;
       if (C != 0) hash ^= C.GetHashCode();
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
     }
 
@@ -3649,6 +3680,9 @@ namespace ProtobufTestMessages.Proto3 {
         output.WriteRawTag(8);
         output.WriteInt32(C);
       }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -3657,6 +3691,9 @@ namespace ProtobufTestMessages.Proto3 {
       if (C != 0) {
         size += 1 + pb::CodedOutputStream.ComputeInt32Size(C);
       }
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
     }
 
@@ -3668,6 +3705,7 @@ namespace ProtobufTestMessages.Proto3 {
       if (other.C != 0) {
         C = other.C;
       }
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -3676,7 +3714,7 @@ namespace ProtobufTestMessages.Proto3 {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
           case 8: {
             C = input.ReadInt32();

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

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 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
 #region Designer generated code
 
@@ -179,6 +181,7 @@ namespace Google.Protobuf.TestProtos {
   /// </summary>
   public sealed partial class TestWellKnownTypes : pb::IMessage<TestWellKnownTypes> {
     private static readonly pb::MessageParser<TestWellKnownTypes> _parser = new pb::MessageParser<TestWellKnownTypes>(() => new TestWellKnownTypes());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<TestWellKnownTypes> Parser { get { return _parser; } }
 
@@ -220,6 +223,7 @@ namespace Google.Protobuf.TestProtos {
       StringField = other.StringField;
       BytesField = other.BytesField;
       ValueField = other.valueField_ != null ? other.ValueField.Clone() : null;
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -470,8 +474,8 @@ namespace Google.Protobuf.TestProtos {
       if (!object.Equals(StructField, other.StructField)) return false;
       if (!object.Equals(TimestampField, other.TimestampField)) 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 (Uint64Field != other.Uint64Field) return false;
       if (Int32Field != other.Int32Field) return false;
@@ -480,7 +484,7 @@ namespace Google.Protobuf.TestProtos {
       if (StringField != other.StringField) return false;
       if (BytesField != other.BytesField) return false;
       if (!object.Equals(ValueField, other.ValueField)) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -495,8 +499,8 @@ namespace Google.Protobuf.TestProtos {
       if (structField_ != null) hash ^= StructField.GetHashCode();
       if (timestampField_ != null) hash ^= TimestampField.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 (uint64Field_ != null) hash ^= Uint64Field.GetHashCode();
       if (int32Field_ != null) hash ^= Int32Field.GetHashCode();
@@ -505,6 +509,9 @@ namespace Google.Protobuf.TestProtos {
       if (stringField_ != null) hash ^= StringField.GetHashCode();
       if (bytesField_ != null) hash ^= BytesField.GetHashCode();
       if (valueField_ != null) hash ^= ValueField.GetHashCode();
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
     }
 
@@ -582,6 +589,9 @@ namespace Google.Protobuf.TestProtos {
         output.WriteRawTag(154, 1);
         output.WriteMessage(ValueField);
       }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -644,6 +654,9 @@ namespace Google.Protobuf.TestProtos {
       if (valueField_ != null) {
         size += 2 + pb::CodedOutputStream.ComputeMessageSize(ValueField);
       }
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
     }
 
@@ -757,6 +770,7 @@ namespace Google.Protobuf.TestProtos {
         }
         ValueField.MergeFrom(other.ValueField);
       }
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -765,7 +779,7 @@ namespace Google.Protobuf.TestProtos {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
           case 10: {
             if (anyField_ == null) {
@@ -911,6 +925,7 @@ namespace Google.Protobuf.TestProtos {
   /// </summary>
   public sealed partial class RepeatedWellKnownTypes : pb::IMessage<RepeatedWellKnownTypes> {
     private static readonly pb::MessageParser<RepeatedWellKnownTypes> _parser = new pb::MessageParser<RepeatedWellKnownTypes>(() => new RepeatedWellKnownTypes());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<RepeatedWellKnownTypes> Parser { get { return _parser; } }
 
@@ -951,6 +966,7 @@ namespace Google.Protobuf.TestProtos {
       boolField_ = other.boolField_.Clone();
       stringField_ = other.stringField_.Clone();
       bytesField_ = other.bytesField_.Clone();
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1172,7 +1188,7 @@ namespace Google.Protobuf.TestProtos {
       if(!boolField_.Equals(other.boolField_)) return false;
       if(!stringField_.Equals(other.stringField_)) return false;
       if(!bytesField_.Equals(other.bytesField_)) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1196,6 +1212,9 @@ namespace Google.Protobuf.TestProtos {
       hash ^= boolField_.GetHashCode();
       hash ^= stringField_.GetHashCode();
       hash ^= bytesField_.GetHashCode();
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
     }
 
@@ -1224,6 +1243,9 @@ namespace Google.Protobuf.TestProtos {
       boolField_.WriteTo(output, _repeated_boolField_codec);
       stringField_.WriteTo(output, _repeated_stringField_codec);
       bytesField_.WriteTo(output, _repeated_bytesField_codec);
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1247,6 +1269,9 @@ namespace Google.Protobuf.TestProtos {
       size += boolField_.CalculateSize(_repeated_boolField_codec);
       size += stringField_.CalculateSize(_repeated_stringField_codec);
       size += bytesField_.CalculateSize(_repeated_bytesField_codec);
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
     }
 
@@ -1273,6 +1298,7 @@ namespace Google.Protobuf.TestProtos {
       boolField_.Add(other.boolField_);
       stringField_.Add(other.stringField_);
       bytesField_.Add(other.bytesField_);
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1281,7 +1307,7 @@ namespace Google.Protobuf.TestProtos {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
           case 10: {
             anyField_.AddEntriesFrom(input, _repeated_anyField_codec);
@@ -1363,6 +1389,7 @@ namespace Google.Protobuf.TestProtos {
 
   public sealed partial class OneofWellKnownTypes : pb::IMessage<OneofWellKnownTypes> {
     private static readonly pb::MessageParser<OneofWellKnownTypes> _parser = new pb::MessageParser<OneofWellKnownTypes>(() => new OneofWellKnownTypes());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<OneofWellKnownTypes> Parser { get { return _parser; } }
 
@@ -1442,6 +1469,7 @@ namespace Google.Protobuf.TestProtos {
           break;
       }
 
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1713,8 +1741,8 @@ namespace Google.Protobuf.TestProtos {
       if (!object.Equals(StructField, other.StructField)) return false;
       if (!object.Equals(TimestampField, other.TimestampField)) 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 (Uint64Field != other.Uint64Field) return false;
       if (Int32Field != other.Int32Field) return false;
@@ -1723,7 +1751,7 @@ namespace Google.Protobuf.TestProtos {
       if (StringField != other.StringField) return false;
       if (BytesField != other.BytesField) return false;
       if (OneofFieldCase != other.OneofFieldCase) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1738,8 +1766,8 @@ namespace Google.Protobuf.TestProtos {
       if (oneofFieldCase_ == OneofFieldOneofCase.StructField) hash ^= StructField.GetHashCode();
       if (oneofFieldCase_ == OneofFieldOneofCase.TimestampField) hash ^= TimestampField.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.Uint64Field) hash ^= Uint64Field.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.BytesField) hash ^= BytesField.GetHashCode();
       hash ^= (int) oneofFieldCase_;
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
     }
 
@@ -1821,6 +1852,9 @@ namespace Google.Protobuf.TestProtos {
       if (oneofFieldCase_ == OneofFieldOneofCase.BytesField) {
         _oneof_bytesField_codec.WriteTagAndValue(output, (pb::ByteString) oneofField_);
       }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1880,6 +1914,9 @@ namespace Google.Protobuf.TestProtos {
       if (oneofFieldCase_ == OneofFieldOneofCase.BytesField) {
         size += _oneof_bytesField_codec.CalculateSizeWithTag(BytesField);
       }
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
     }
 
@@ -1972,6 +2009,7 @@ namespace Google.Protobuf.TestProtos {
           break;
       }
 
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1980,7 +2018,7 @@ namespace Google.Protobuf.TestProtos {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
           case 10: {
             global::Google.Protobuf.WellKnownTypes.Any subBuilder = new global::Google.Protobuf.WellKnownTypes.Any();
@@ -2112,6 +2150,7 @@ namespace Google.Protobuf.TestProtos {
   /// </summary>
   public sealed partial class MapWellKnownTypes : pb::IMessage<MapWellKnownTypes> {
     private static readonly pb::MessageParser<MapWellKnownTypes> _parser = new pb::MessageParser<MapWellKnownTypes>(() => new MapWellKnownTypes());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<MapWellKnownTypes> Parser { get { return _parser; } }
 
@@ -2152,6 +2191,7 @@ namespace Google.Protobuf.TestProtos {
       boolField_ = other.boolField_.Clone();
       stringField_ = other.stringField_.Clone();
       bytesField_ = other.bytesField_.Clone();
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -2370,7 +2410,7 @@ namespace Google.Protobuf.TestProtos {
       if (!BoolField.Equals(other.BoolField)) return false;
       if (!StringField.Equals(other.StringField)) return false;
       if (!BytesField.Equals(other.BytesField)) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -2394,6 +2434,9 @@ namespace Google.Protobuf.TestProtos {
       hash ^= BoolField.GetHashCode();
       hash ^= StringField.GetHashCode();
       hash ^= BytesField.GetHashCode();
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
     }
 
@@ -2422,6 +2465,9 @@ namespace Google.Protobuf.TestProtos {
       boolField_.WriteTo(output, _map_boolField_codec);
       stringField_.WriteTo(output, _map_stringField_codec);
       bytesField_.WriteTo(output, _map_bytesField_codec);
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -2445,6 +2491,9 @@ namespace Google.Protobuf.TestProtos {
       size += boolField_.CalculateSize(_map_boolField_codec);
       size += stringField_.CalculateSize(_map_stringField_codec);
       size += bytesField_.CalculateSize(_map_bytesField_codec);
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
     }
 
@@ -2471,6 +2520,7 @@ namespace Google.Protobuf.TestProtos {
       boolField_.Add(other.boolField_);
       stringField_.Add(other.stringField_);
       bytesField_.Add(other.bytesField_);
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -2479,7 +2529,7 @@ namespace Google.Protobuf.TestProtos {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
           case 10: {
             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);
             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
             // depth changes into the ReadTag method instead, potentially...
@@ -1270,7 +1273,6 @@ namespace Google.Protobuf
                 }
             }
         }
-
         #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>
 #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.)
         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>>();
 
         /// <summary>
@@ -131,11 +134,8 @@ namespace Google.Protobuf.Collections
             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>
         /// 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)
         {
             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>
@@ -363,11 +362,12 @@ namespace Google.Protobuf.Collections
         /// </returns>
         public override int GetHashCode()
         {
-            var valueComparer = EqualityComparer<TValue>.Default;
+            var keyComparer = KeyEqualityComparer;
+            var valueComparer = ValueEqualityComparer;
             int hash = 0;
             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;
         }
@@ -394,7 +394,7 @@ namespace Google.Protobuf.Collections
             {
                 return false;
             }
-            var valueComparer = EqualityComparer<TValue>.Default;
+            var valueComparer = ValueEqualityComparer;
             foreach (var pair in this)
             {
                 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>
 #endif
     {
+        private static readonly EqualityComparer<T> EqualityComparer = ProtobufEqualityComparers.GetEqualityComparer<T>();
         private static readonly T[] EmptyArray = new T[0];
         private const int MinArraySize = 8;
 
@@ -434,7 +435,7 @@ namespace Google.Protobuf.Collections
             {
                 return false;
             }
-            EqualityComparer<T> comparer = EqualityComparer<T>.Default;
+            EqualityComparer<T> comparer = EqualityComparer;
             for (int i = 0; i < count; i++)
             {
                 if (!comparer.Equals(array[i], other.array[i]))
@@ -454,7 +455,7 @@ namespace Google.Protobuf.Collections
         public int IndexOf(T item)
         {
             ProtoPreconditions.CheckNotNullUnconstrained(item, nameof(item));
-            EqualityComparer<T> comparer = EqualityComparer<T>.Default;
+            EqualityComparer<T> comparer = EqualityComparer;
             for (int i = 0; i < count; i++)
             {
                 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.
 #endregion
 
+using Google.Protobuf.Collections;
 using Google.Protobuf.Compatibility;
 using Google.Protobuf.WellKnownTypes;
 using System;
@@ -346,6 +347,7 @@ namespace Google.Protobuf
     /// </remarks>
     public sealed class FieldCodec<T>
     {
+        private static readonly EqualityComparer<T> EqualityComparer = ProtobufEqualityComparers.GetEqualityComparer<T>();
         private static readonly T DefaultDefault;
         // Only non-nullable value types support packing. This is the simplest way of detecting that.
         private static readonly bool TypeSupportsPacking = default(T) != null;
@@ -469,6 +471,6 @@ namespace Google.Protobuf
         /// </summary>
         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);
     }
 }

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 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
 #region Designer generated code
 
@@ -119,6 +121,7 @@ namespace Google.Protobuf.WellKnownTypes {
   /// </summary>
   public sealed partial class Any : pb::IMessage<Any> {
     private static readonly pb::MessageParser<Any> _parser = new pb::MessageParser<Any>(() => new Any());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<Any> Parser { get { return _parser; } }
 
@@ -143,6 +146,7 @@ namespace Google.Protobuf.WellKnownTypes {
     public Any(Any other) : this() {
       typeUrl_ = other.typeUrl_;
       value_ = other.value_;
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -218,7 +222,7 @@ namespace Google.Protobuf.WellKnownTypes {
       }
       if (TypeUrl != other.TypeUrl) return false;
       if (Value != other.Value) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -226,6 +230,9 @@ namespace Google.Protobuf.WellKnownTypes {
       int hash = 1;
       if (TypeUrl.Length != 0) hash ^= TypeUrl.GetHashCode();
       if (Value.Length != 0) hash ^= Value.GetHashCode();
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
     }
 
@@ -244,6 +251,9 @@ namespace Google.Protobuf.WellKnownTypes {
         output.WriteRawTag(18);
         output.WriteBytes(Value);
       }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -255,6 +265,9 @@ namespace Google.Protobuf.WellKnownTypes {
       if (Value.Length != 0) {
         size += 1 + pb::CodedOutputStream.ComputeBytesSize(Value);
       }
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
     }
 
@@ -269,6 +282,7 @@ namespace Google.Protobuf.WellKnownTypes {
       if (other.Value.Length != 0) {
         Value = other.Value;
       }
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -277,7 +291,7 @@ namespace Google.Protobuf.WellKnownTypes {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
           case 10: {
             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
 #region Designer generated code
 
@@ -64,6 +66,7 @@ namespace Google.Protobuf.WellKnownTypes {
   /// </summary>
   public sealed partial class Api : pb::IMessage<Api> {
     private static readonly pb::MessageParser<Api> _parser = new pb::MessageParser<Api>(() => new Api());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     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;
       mixins_ = other.mixins_.Clone();
       syntax_ = other.syntax_;
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -235,7 +239,7 @@ namespace Google.Protobuf.WellKnownTypes {
       if (!object.Equals(SourceContext, other.SourceContext)) return false;
       if(!mixins_.Equals(other.mixins_)) return false;
       if (Syntax != other.Syntax) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -248,6 +252,9 @@ namespace Google.Protobuf.WellKnownTypes {
       if (sourceContext_ != null) hash ^= SourceContext.GetHashCode();
       hash ^= mixins_.GetHashCode();
       if (Syntax != 0) hash ^= Syntax.GetHashCode();
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
     }
 
@@ -277,6 +284,9 @@ namespace Google.Protobuf.WellKnownTypes {
         output.WriteRawTag(56);
         output.WriteEnum((int) Syntax);
       }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -297,6 +307,9 @@ namespace Google.Protobuf.WellKnownTypes {
       if (Syntax != 0) {
         size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Syntax);
       }
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
     }
 
@@ -323,6 +336,7 @@ namespace Google.Protobuf.WellKnownTypes {
       if (other.Syntax != 0) {
         Syntax = other.Syntax;
       }
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -331,7 +345,7 @@ namespace Google.Protobuf.WellKnownTypes {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
           case 10: {
             Name = input.ReadString();
@@ -375,6 +389,7 @@ namespace Google.Protobuf.WellKnownTypes {
   /// </summary>
   public sealed partial class Method : pb::IMessage<Method> {
     private static readonly pb::MessageParser<Method> _parser = new pb::MessageParser<Method>(() => new Method());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<Method> Parser { get { return _parser; } }
 
@@ -404,6 +419,7 @@ namespace Google.Protobuf.WellKnownTypes {
       responseStreaming_ = other.responseStreaming_;
       options_ = other.options_.Clone();
       syntax_ = other.syntax_;
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -528,7 +544,7 @@ namespace Google.Protobuf.WellKnownTypes {
       if (ResponseStreaming != other.ResponseStreaming) return false;
       if(!options_.Equals(other.options_)) return false;
       if (Syntax != other.Syntax) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -541,6 +557,9 @@ namespace Google.Protobuf.WellKnownTypes {
       if (ResponseStreaming != false) hash ^= ResponseStreaming.GetHashCode();
       hash ^= options_.GetHashCode();
       if (Syntax != 0) hash ^= Syntax.GetHashCode();
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
     }
 
@@ -576,6 +595,9 @@ namespace Google.Protobuf.WellKnownTypes {
         output.WriteRawTag(56);
         output.WriteEnum((int) Syntax);
       }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -600,6 +622,9 @@ namespace Google.Protobuf.WellKnownTypes {
       if (Syntax != 0) {
         size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Syntax);
       }
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
     }
 
@@ -627,6 +652,7 @@ namespace Google.Protobuf.WellKnownTypes {
       if (other.Syntax != 0) {
         Syntax = other.Syntax;
       }
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -635,7 +661,7 @@ namespace Google.Protobuf.WellKnownTypes {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
           case 10: {
             Name = input.ReadString();
@@ -753,6 +779,7 @@ namespace Google.Protobuf.WellKnownTypes {
   /// </summary>
   public sealed partial class Mixin : pb::IMessage<Mixin> {
     private static readonly pb::MessageParser<Mixin> _parser = new pb::MessageParser<Mixin>(() => new Mixin());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<Mixin> Parser { get { return _parser; } }
 
@@ -777,6 +804,7 @@ namespace Google.Protobuf.WellKnownTypes {
     public Mixin(Mixin other) : this() {
       name_ = other.name_;
       root_ = other.root_;
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -828,7 +856,7 @@ namespace Google.Protobuf.WellKnownTypes {
       }
       if (Name != other.Name) return false;
       if (Root != other.Root) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -836,6 +864,9 @@ namespace Google.Protobuf.WellKnownTypes {
       int hash = 1;
       if (Name.Length != 0) hash ^= Name.GetHashCode();
       if (Root.Length != 0) hash ^= Root.GetHashCode();
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
     }
 
@@ -854,6 +885,9 @@ namespace Google.Protobuf.WellKnownTypes {
         output.WriteRawTag(18);
         output.WriteString(Root);
       }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -865,6 +899,9 @@ namespace Google.Protobuf.WellKnownTypes {
       if (Root.Length != 0) {
         size += 1 + pb::CodedOutputStream.ComputeStringSize(Root);
       }
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
     }
 
@@ -879,6 +916,7 @@ namespace Google.Protobuf.WellKnownTypes {
       if (other.Root.Length != 0) {
         Root = other.Root;
       }
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -887,7 +925,7 @@ namespace Google.Protobuf.WellKnownTypes {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
           case 10: {
             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
 #region Designer generated code
 
@@ -100,6 +102,7 @@ namespace Google.Protobuf.WellKnownTypes {
   /// </summary>
   public sealed partial class Duration : pb::IMessage<Duration> {
     private static readonly pb::MessageParser<Duration> _parser = new pb::MessageParser<Duration>(() => new Duration());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<Duration> Parser { get { return _parser; } }
 
@@ -124,6 +127,7 @@ namespace Google.Protobuf.WellKnownTypes {
     public Duration(Duration other) : this() {
       seconds_ = other.seconds_;
       nanos_ = other.nanos_;
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -181,7 +185,7 @@ namespace Google.Protobuf.WellKnownTypes {
       }
       if (Seconds != other.Seconds) return false;
       if (Nanos != other.Nanos) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -189,6 +193,9 @@ namespace Google.Protobuf.WellKnownTypes {
       int hash = 1;
       if (Seconds != 0L) hash ^= Seconds.GetHashCode();
       if (Nanos != 0) hash ^= Nanos.GetHashCode();
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
     }
 
@@ -207,6 +214,9 @@ namespace Google.Protobuf.WellKnownTypes {
         output.WriteRawTag(16);
         output.WriteInt32(Nanos);
       }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -218,6 +228,9 @@ namespace Google.Protobuf.WellKnownTypes {
       if (Nanos != 0) {
         size += 1 + pb::CodedOutputStream.ComputeInt32Size(Nanos);
       }
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
     }
 
@@ -232,6 +245,7 @@ namespace Google.Protobuf.WellKnownTypes {
       if (other.Nanos != 0) {
         Nanos = other.Nanos;
       }
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -240,7 +254,7 @@ namespace Google.Protobuf.WellKnownTypes {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
           case 8: {
             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
 #region Designer generated code
 
@@ -50,6 +52,7 @@ namespace Google.Protobuf.WellKnownTypes {
   /// </summary>
   public sealed partial class Empty : pb::IMessage<Empty> {
     private static readonly pb::MessageParser<Empty> _parser = new pb::MessageParser<Empty>(() => new Empty());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<Empty> Parser { get { return _parser; } }
 
@@ -72,6 +75,7 @@ namespace Google.Protobuf.WellKnownTypes {
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public Empty(Empty other) : this() {
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -92,12 +96,15 @@ namespace Google.Protobuf.WellKnownTypes {
       if (ReferenceEquals(other, this)) {
         return true;
       }
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public override int GetHashCode() {
       int hash = 1;
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
     }
 
@@ -108,11 +115,17 @@ namespace Google.Protobuf.WellKnownTypes {
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public void WriteTo(pb::CodedOutputStream output) {
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public int CalculateSize() {
       int size = 0;
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
     }
 
@@ -121,6 +134,7 @@ namespace Google.Protobuf.WellKnownTypes {
       if (other == null) {
         return;
       }
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -129,7 +143,7 @@ namespace Google.Protobuf.WellKnownTypes {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             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
 #region Designer generated code
 
@@ -248,6 +250,7 @@ namespace Google.Protobuf.WellKnownTypes {
   /// </summary>
   public sealed partial class FieldMask : pb::IMessage<FieldMask> {
     private static readonly pb::MessageParser<FieldMask> _parser = new pb::MessageParser<FieldMask>(() => new FieldMask());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<FieldMask> Parser { get { return _parser; } }
 
@@ -271,6 +274,7 @@ namespace Google.Protobuf.WellKnownTypes {
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public FieldMask(FieldMask other) : this() {
       paths_ = other.paths_.Clone();
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -305,13 +309,16 @@ namespace Google.Protobuf.WellKnownTypes {
         return true;
       }
       if(!paths_.Equals(other.paths_)) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public override int GetHashCode() {
       int hash = 1;
       hash ^= paths_.GetHashCode();
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
     }
 
@@ -323,12 +330,18 @@ namespace Google.Protobuf.WellKnownTypes {
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public void WriteTo(pb::CodedOutputStream output) {
       paths_.WriteTo(output, _repeated_paths_codec);
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public int CalculateSize() {
       int size = 0;
       size += paths_.CalculateSize(_repeated_paths_codec);
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
     }
 
@@ -338,6 +351,7 @@ namespace Google.Protobuf.WellKnownTypes {
         return;
       }
       paths_.Add(other.paths_);
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -346,7 +360,7 @@ namespace Google.Protobuf.WellKnownTypes {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
           case 10: {
             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
 #region Designer generated code
 
@@ -44,6 +46,7 @@ namespace Google.Protobuf.WellKnownTypes {
   /// </summary>
   public sealed partial class SourceContext : pb::IMessage<SourceContext> {
     private static readonly pb::MessageParser<SourceContext> _parser = new pb::MessageParser<SourceContext>(() => new SourceContext());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<SourceContext> Parser { get { return _parser; } }
 
@@ -67,6 +70,7 @@ namespace Google.Protobuf.WellKnownTypes {
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public SourceContext(SourceContext other) : this() {
       fileName_ = other.fileName_;
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -103,13 +107,16 @@ namespace Google.Protobuf.WellKnownTypes {
         return true;
       }
       if (FileName != other.FileName) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public override int GetHashCode() {
       int hash = 1;
       if (FileName.Length != 0) hash ^= FileName.GetHashCode();
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
     }
 
@@ -124,6 +131,9 @@ namespace Google.Protobuf.WellKnownTypes {
         output.WriteRawTag(10);
         output.WriteString(FileName);
       }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -132,6 +142,9 @@ namespace Google.Protobuf.WellKnownTypes {
       if (FileName.Length != 0) {
         size += 1 + pb::CodedOutputStream.ComputeStringSize(FileName);
       }
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
     }
 
@@ -143,6 +156,7 @@ namespace Google.Protobuf.WellKnownTypes {
       if (other.FileName.Length != 0) {
         FileName = other.FileName;
       }
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -151,7 +165,7 @@ namespace Google.Protobuf.WellKnownTypes {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
           case 10: {
             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
 #region Designer generated code
 
@@ -77,6 +79,7 @@ namespace Google.Protobuf.WellKnownTypes {
   /// </summary>
   public sealed partial class Struct : pb::IMessage<Struct> {
     private static readonly pb::MessageParser<Struct> _parser = new pb::MessageParser<Struct>(() => new Struct());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<Struct> Parser { get { return _parser; } }
 
@@ -100,6 +103,7 @@ namespace Google.Protobuf.WellKnownTypes {
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public Struct(Struct other) : this() {
       fields_ = other.fields_.Clone();
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -134,13 +138,16 @@ namespace Google.Protobuf.WellKnownTypes {
         return true;
       }
       if (!Fields.Equals(other.Fields)) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public override int GetHashCode() {
       int hash = 1;
       hash ^= Fields.GetHashCode();
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
     }
 
@@ -152,12 +159,18 @@ namespace Google.Protobuf.WellKnownTypes {
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public void WriteTo(pb::CodedOutputStream output) {
       fields_.WriteTo(output, _map_fields_codec);
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public int CalculateSize() {
       int size = 0;
       size += fields_.CalculateSize(_map_fields_codec);
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
     }
 
@@ -167,6 +180,7 @@ namespace Google.Protobuf.WellKnownTypes {
         return;
       }
       fields_.Add(other.fields_);
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -175,7 +189,7 @@ namespace Google.Protobuf.WellKnownTypes {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
           case 10: {
             fields_.AddEntriesFrom(input, _map_fields_codec);
@@ -197,6 +211,7 @@ namespace Google.Protobuf.WellKnownTypes {
   /// </summary>
   public sealed partial class Value : pb::IMessage<Value> {
     private static readonly pb::MessageParser<Value> _parser = new pb::MessageParser<Value>(() => new Value());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<Value> Parser { get { return _parser; } }
 
@@ -240,6 +255,7 @@ namespace Google.Protobuf.WellKnownTypes {
           break;
       }
 
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -368,25 +384,28 @@ namespace Google.Protobuf.WellKnownTypes {
         return true;
       }
       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 (BoolValue != other.BoolValue) return false;
       if (!object.Equals(StructValue, other.StructValue)) return false;
       if (!object.Equals(ListValue, other.ListValue)) return false;
       if (KindCase != other.KindCase) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public override int GetHashCode() {
       int hash = 1;
       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.BoolValue) hash ^= BoolValue.GetHashCode();
       if (kindCase_ == KindOneofCase.StructValue) hash ^= StructValue.GetHashCode();
       if (kindCase_ == KindOneofCase.ListValue) hash ^= ListValue.GetHashCode();
       hash ^= (int) kindCase_;
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
     }
 
@@ -421,6 +440,9 @@ namespace Google.Protobuf.WellKnownTypes {
         output.WriteRawTag(50);
         output.WriteMessage(ListValue);
       }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -444,6 +466,9 @@ namespace Google.Protobuf.WellKnownTypes {
       if (kindCase_ == KindOneofCase.ListValue) {
         size += 1 + pb::CodedOutputStream.ComputeMessageSize(ListValue);
       }
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
     }
 
@@ -479,6 +504,7 @@ namespace Google.Protobuf.WellKnownTypes {
           break;
       }
 
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -487,7 +513,7 @@ namespace Google.Protobuf.WellKnownTypes {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
           case 8: {
             kind_ = input.ReadEnum();
@@ -537,6 +563,7 @@ namespace Google.Protobuf.WellKnownTypes {
   /// </summary>
   public sealed partial class ListValue : pb::IMessage<ListValue> {
     private static readonly pb::MessageParser<ListValue> _parser = new pb::MessageParser<ListValue>(() => new ListValue());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<ListValue> Parser { get { return _parser; } }
 
@@ -560,6 +587,7 @@ namespace Google.Protobuf.WellKnownTypes {
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public ListValue(ListValue other) : this() {
       values_ = other.values_.Clone();
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -594,13 +622,16 @@ namespace Google.Protobuf.WellKnownTypes {
         return true;
       }
       if(!values_.Equals(other.values_)) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public override int GetHashCode() {
       int hash = 1;
       hash ^= values_.GetHashCode();
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
     }
 
@@ -612,12 +643,18 @@ namespace Google.Protobuf.WellKnownTypes {
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public void WriteTo(pb::CodedOutputStream output) {
       values_.WriteTo(output, _repeated_values_codec);
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public int CalculateSize() {
       int size = 0;
       size += values_.CalculateSize(_repeated_values_codec);
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
     }
 
@@ -627,6 +664,7 @@ namespace Google.Protobuf.WellKnownTypes {
         return;
       }
       values_.Add(other.values_);
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -635,7 +673,7 @@ namespace Google.Protobuf.WellKnownTypes {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
           case 10: {
             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
 #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
   /// 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
-  /// 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
   /// 01:30 UTC on January 15, 2017.
@@ -117,6 +121,7 @@ namespace Google.Protobuf.WellKnownTypes {
   /// </summary>
   public sealed partial class Timestamp : pb::IMessage<Timestamp> {
     private static readonly pb::MessageParser<Timestamp> _parser = new pb::MessageParser<Timestamp>(() => new Timestamp());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<Timestamp> Parser { get { return _parser; } }
 
@@ -141,6 +146,7 @@ namespace Google.Protobuf.WellKnownTypes {
     public Timestamp(Timestamp other) : this() {
       seconds_ = other.seconds_;
       nanos_ = other.nanos_;
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -196,7 +202,7 @@ namespace Google.Protobuf.WellKnownTypes {
       }
       if (Seconds != other.Seconds) return false;
       if (Nanos != other.Nanos) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -204,6 +210,9 @@ namespace Google.Protobuf.WellKnownTypes {
       int hash = 1;
       if (Seconds != 0L) hash ^= Seconds.GetHashCode();
       if (Nanos != 0) hash ^= Nanos.GetHashCode();
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
     }
 
@@ -222,6 +231,9 @@ namespace Google.Protobuf.WellKnownTypes {
         output.WriteRawTag(16);
         output.WriteInt32(Nanos);
       }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -233,6 +245,9 @@ namespace Google.Protobuf.WellKnownTypes {
       if (Nanos != 0) {
         size += 1 + pb::CodedOutputStream.ComputeInt32Size(Nanos);
       }
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
     }
 
@@ -247,6 +262,7 @@ namespace Google.Protobuf.WellKnownTypes {
       if (other.Nanos != 0) {
         Nanos = other.Nanos;
       }
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -255,7 +271,7 @@ namespace Google.Protobuf.WellKnownTypes {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
           case 8: {
             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
 #region Designer generated code
 
@@ -94,6 +96,7 @@ namespace Google.Protobuf.WellKnownTypes {
   /// </summary>
   public sealed partial class Type : pb::IMessage<Type> {
     private static readonly pb::MessageParser<Type> _parser = new pb::MessageParser<Type>(() => new Type());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<Type> Parser { get { return _parser; } }
 
@@ -122,6 +125,7 @@ namespace Google.Protobuf.WellKnownTypes {
       options_ = other.options_.Clone();
       SourceContext = other.sourceContext_ != null ? other.SourceContext.Clone() : null;
       syntax_ = other.syntax_;
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -229,7 +233,7 @@ namespace Google.Protobuf.WellKnownTypes {
       if(!options_.Equals(other.options_)) return false;
       if (!object.Equals(SourceContext, other.SourceContext)) return false;
       if (Syntax != other.Syntax) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -241,6 +245,9 @@ namespace Google.Protobuf.WellKnownTypes {
       hash ^= options_.GetHashCode();
       if (sourceContext_ != null) hash ^= SourceContext.GetHashCode();
       if (Syntax != 0) hash ^= Syntax.GetHashCode();
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
     }
 
@@ -266,6 +273,9 @@ namespace Google.Protobuf.WellKnownTypes {
         output.WriteRawTag(48);
         output.WriteEnum((int) Syntax);
       }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -283,6 +293,9 @@ namespace Google.Protobuf.WellKnownTypes {
       if (Syntax != 0) {
         size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Syntax);
       }
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
     }
 
@@ -306,6 +319,7 @@ namespace Google.Protobuf.WellKnownTypes {
       if (other.Syntax != 0) {
         Syntax = other.Syntax;
       }
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -314,7 +328,7 @@ namespace Google.Protobuf.WellKnownTypes {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
           case 10: {
             Name = input.ReadString();
@@ -354,6 +368,7 @@ namespace Google.Protobuf.WellKnownTypes {
   /// </summary>
   public sealed partial class Field : pb::IMessage<Field> {
     private static readonly pb::MessageParser<Field> _parser = new pb::MessageParser<Field>(() => new Field());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<Field> Parser { get { return _parser; } }
 
@@ -386,6 +401,7 @@ namespace Google.Protobuf.WellKnownTypes {
       options_ = other.options_.Clone();
       jsonName_ = other.jsonName_;
       defaultValue_ = other.defaultValue_;
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -557,7 +573,7 @@ namespace Google.Protobuf.WellKnownTypes {
       if(!options_.Equals(other.options_)) return false;
       if (JsonName != other.JsonName) return false;
       if (DefaultValue != other.DefaultValue) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -573,6 +589,9 @@ namespace Google.Protobuf.WellKnownTypes {
       hash ^= options_.GetHashCode();
       if (JsonName.Length != 0) hash ^= JsonName.GetHashCode();
       if (DefaultValue.Length != 0) hash ^= DefaultValue.GetHashCode();
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
     }
 
@@ -620,6 +639,9 @@ namespace Google.Protobuf.WellKnownTypes {
         output.WriteRawTag(90);
         output.WriteString(DefaultValue);
       }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -653,6 +675,9 @@ namespace Google.Protobuf.WellKnownTypes {
       if (DefaultValue.Length != 0) {
         size += 1 + pb::CodedOutputStream.ComputeStringSize(DefaultValue);
       }
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
     }
 
@@ -689,6 +714,7 @@ namespace Google.Protobuf.WellKnownTypes {
       if (other.DefaultValue.Length != 0) {
         DefaultValue = other.DefaultValue;
       }
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -697,7 +723,7 @@ namespace Google.Protobuf.WellKnownTypes {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
           case 8: {
             kind_ = (global::Google.Protobuf.WellKnownTypes.Field.Types.Kind) input.ReadEnum();
@@ -861,6 +887,7 @@ namespace Google.Protobuf.WellKnownTypes {
   /// </summary>
   public sealed partial class Enum : pb::IMessage<Enum> {
     private static readonly pb::MessageParser<Enum> _parser = new pb::MessageParser<Enum>(() => new Enum());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<Enum> Parser { get { return _parser; } }
 
@@ -888,6 +915,7 @@ namespace Google.Protobuf.WellKnownTypes {
       options_ = other.options_.Clone();
       SourceContext = other.sourceContext_ != null ? other.SourceContext.Clone() : null;
       syntax_ = other.syntax_;
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -981,7 +1009,7 @@ namespace Google.Protobuf.WellKnownTypes {
       if(!options_.Equals(other.options_)) return false;
       if (!object.Equals(SourceContext, other.SourceContext)) return false;
       if (Syntax != other.Syntax) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -992,6 +1020,9 @@ namespace Google.Protobuf.WellKnownTypes {
       hash ^= options_.GetHashCode();
       if (sourceContext_ != null) hash ^= SourceContext.GetHashCode();
       if (Syntax != 0) hash ^= Syntax.GetHashCode();
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
     }
 
@@ -1016,6 +1047,9 @@ namespace Google.Protobuf.WellKnownTypes {
         output.WriteRawTag(40);
         output.WriteEnum((int) Syntax);
       }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1032,6 +1066,9 @@ namespace Google.Protobuf.WellKnownTypes {
       if (Syntax != 0) {
         size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Syntax);
       }
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
     }
 
@@ -1054,6 +1091,7 @@ namespace Google.Protobuf.WellKnownTypes {
       if (other.Syntax != 0) {
         Syntax = other.Syntax;
       }
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1062,7 +1100,7 @@ namespace Google.Protobuf.WellKnownTypes {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
           case 10: {
             Name = input.ReadString();
@@ -1098,6 +1136,7 @@ namespace Google.Protobuf.WellKnownTypes {
   /// </summary>
   public sealed partial class EnumValue : pb::IMessage<EnumValue> {
     private static readonly pb::MessageParser<EnumValue> _parser = new pb::MessageParser<EnumValue>(() => new EnumValue());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<EnumValue> Parser { get { return _parser; } }
 
@@ -1123,6 +1162,7 @@ namespace Google.Protobuf.WellKnownTypes {
       name_ = other.name_;
       number_ = other.number_;
       options_ = other.options_.Clone();
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1187,7 +1227,7 @@ namespace Google.Protobuf.WellKnownTypes {
       if (Name != other.Name) return false;
       if (Number != other.Number) return false;
       if(!options_.Equals(other.options_)) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1196,6 +1236,9 @@ namespace Google.Protobuf.WellKnownTypes {
       if (Name.Length != 0) hash ^= Name.GetHashCode();
       if (Number != 0) hash ^= Number.GetHashCode();
       hash ^= options_.GetHashCode();
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
     }
 
@@ -1215,6 +1258,9 @@ namespace Google.Protobuf.WellKnownTypes {
         output.WriteInt32(Number);
       }
       options_.WriteTo(output, _repeated_options_codec);
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1227,6 +1273,9 @@ namespace Google.Protobuf.WellKnownTypes {
         size += 1 + pb::CodedOutputStream.ComputeInt32Size(Number);
       }
       size += options_.CalculateSize(_repeated_options_codec);
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
     }
 
@@ -1242,6 +1291,7 @@ namespace Google.Protobuf.WellKnownTypes {
         Number = other.Number;
       }
       options_.Add(other.options_);
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1250,7 +1300,7 @@ namespace Google.Protobuf.WellKnownTypes {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
           case 10: {
             Name = input.ReadString();
@@ -1276,6 +1326,7 @@ namespace Google.Protobuf.WellKnownTypes {
   /// </summary>
   public sealed partial class Option : pb::IMessage<Option> {
     private static readonly pb::MessageParser<Option> _parser = new pb::MessageParser<Option>(() => new Option());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<Option> Parser { get { return _parser; } }
 
@@ -1300,6 +1351,7 @@ namespace Google.Protobuf.WellKnownTypes {
     public Option(Option other) : this() {
       name_ = other.name_;
       Value = other.value_ != null ? other.Value.Clone() : null;
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1356,7 +1408,7 @@ namespace Google.Protobuf.WellKnownTypes {
       }
       if (Name != other.Name) return false;
       if (!object.Equals(Value, other.Value)) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1364,6 +1416,9 @@ namespace Google.Protobuf.WellKnownTypes {
       int hash = 1;
       if (Name.Length != 0) hash ^= Name.GetHashCode();
       if (value_ != null) hash ^= Value.GetHashCode();
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
     }
 
@@ -1382,6 +1437,9 @@ namespace Google.Protobuf.WellKnownTypes {
         output.WriteRawTag(18);
         output.WriteMessage(Value);
       }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1393,6 +1451,9 @@ namespace Google.Protobuf.WellKnownTypes {
       if (value_ != null) {
         size += 1 + pb::CodedOutputStream.ComputeMessageSize(Value);
       }
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
     }
 
@@ -1410,6 +1471,7 @@ namespace Google.Protobuf.WellKnownTypes {
         }
         Value.MergeFrom(other.Value);
       }
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1418,7 +1480,7 @@ namespace Google.Protobuf.WellKnownTypes {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
           case 10: {
             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
 #region Designer generated code
 
@@ -57,6 +59,7 @@ namespace Google.Protobuf.WellKnownTypes {
   /// </summary>
   public sealed partial class DoubleValue : pb::IMessage<DoubleValue> {
     private static readonly pb::MessageParser<DoubleValue> _parser = new pb::MessageParser<DoubleValue>(() => new DoubleValue());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<DoubleValue> Parser { get { return _parser; } }
 
@@ -80,6 +83,7 @@ namespace Google.Protobuf.WellKnownTypes {
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public DoubleValue(DoubleValue other) : this() {
       value_ = other.value_;
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -114,14 +118,17 @@ namespace Google.Protobuf.WellKnownTypes {
       if (ReferenceEquals(other, this)) {
         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]
     public override int GetHashCode() {
       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;
     }
 
@@ -136,6 +143,9 @@ namespace Google.Protobuf.WellKnownTypes {
         output.WriteRawTag(9);
         output.WriteDouble(Value);
       }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -144,6 +154,9 @@ namespace Google.Protobuf.WellKnownTypes {
       if (Value != 0D) {
         size += 1 + 8;
       }
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
     }
 
@@ -155,6 +168,7 @@ namespace Google.Protobuf.WellKnownTypes {
       if (other.Value != 0D) {
         Value = other.Value;
       }
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -163,7 +177,7 @@ namespace Google.Protobuf.WellKnownTypes {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
           case 9: {
             Value = input.ReadDouble();
@@ -182,6 +196,7 @@ namespace Google.Protobuf.WellKnownTypes {
   /// </summary>
   public sealed partial class FloatValue : pb::IMessage<FloatValue> {
     private static readonly pb::MessageParser<FloatValue> _parser = new pb::MessageParser<FloatValue>(() => new FloatValue());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<FloatValue> Parser { get { return _parser; } }
 
@@ -205,6 +220,7 @@ namespace Google.Protobuf.WellKnownTypes {
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public FloatValue(FloatValue other) : this() {
       value_ = other.value_;
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -239,14 +255,17 @@ namespace Google.Protobuf.WellKnownTypes {
       if (ReferenceEquals(other, this)) {
         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]
     public override int GetHashCode() {
       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;
     }
 
@@ -261,6 +280,9 @@ namespace Google.Protobuf.WellKnownTypes {
         output.WriteRawTag(13);
         output.WriteFloat(Value);
       }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -269,6 +291,9 @@ namespace Google.Protobuf.WellKnownTypes {
       if (Value != 0F) {
         size += 1 + 4;
       }
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
     }
 
@@ -280,6 +305,7 @@ namespace Google.Protobuf.WellKnownTypes {
       if (other.Value != 0F) {
         Value = other.Value;
       }
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -288,7 +314,7 @@ namespace Google.Protobuf.WellKnownTypes {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
           case 13: {
             Value = input.ReadFloat();
@@ -307,6 +333,7 @@ namespace Google.Protobuf.WellKnownTypes {
   /// </summary>
   public sealed partial class Int64Value : pb::IMessage<Int64Value> {
     private static readonly pb::MessageParser<Int64Value> _parser = new pb::MessageParser<Int64Value>(() => new Int64Value());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<Int64Value> Parser { get { return _parser; } }
 
@@ -330,6 +357,7 @@ namespace Google.Protobuf.WellKnownTypes {
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public Int64Value(Int64Value other) : this() {
       value_ = other.value_;
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -365,13 +393,16 @@ namespace Google.Protobuf.WellKnownTypes {
         return true;
       }
       if (Value != other.Value) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public override int GetHashCode() {
       int hash = 1;
       if (Value != 0L) hash ^= Value.GetHashCode();
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
     }
 
@@ -386,6 +417,9 @@ namespace Google.Protobuf.WellKnownTypes {
         output.WriteRawTag(8);
         output.WriteInt64(Value);
       }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -394,6 +428,9 @@ namespace Google.Protobuf.WellKnownTypes {
       if (Value != 0L) {
         size += 1 + pb::CodedOutputStream.ComputeInt64Size(Value);
       }
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
     }
 
@@ -405,6 +442,7 @@ namespace Google.Protobuf.WellKnownTypes {
       if (other.Value != 0L) {
         Value = other.Value;
       }
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -413,7 +451,7 @@ namespace Google.Protobuf.WellKnownTypes {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
           case 8: {
             Value = input.ReadInt64();
@@ -432,6 +470,7 @@ namespace Google.Protobuf.WellKnownTypes {
   /// </summary>
   public sealed partial class UInt64Value : pb::IMessage<UInt64Value> {
     private static readonly pb::MessageParser<UInt64Value> _parser = new pb::MessageParser<UInt64Value>(() => new UInt64Value());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<UInt64Value> Parser { get { return _parser; } }
 
@@ -455,6 +494,7 @@ namespace Google.Protobuf.WellKnownTypes {
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public UInt64Value(UInt64Value other) : this() {
       value_ = other.value_;
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -490,13 +530,16 @@ namespace Google.Protobuf.WellKnownTypes {
         return true;
       }
       if (Value != other.Value) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public override int GetHashCode() {
       int hash = 1;
       if (Value != 0UL) hash ^= Value.GetHashCode();
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
     }
 
@@ -511,6 +554,9 @@ namespace Google.Protobuf.WellKnownTypes {
         output.WriteRawTag(8);
         output.WriteUInt64(Value);
       }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -519,6 +565,9 @@ namespace Google.Protobuf.WellKnownTypes {
       if (Value != 0UL) {
         size += 1 + pb::CodedOutputStream.ComputeUInt64Size(Value);
       }
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
     }
 
@@ -530,6 +579,7 @@ namespace Google.Protobuf.WellKnownTypes {
       if (other.Value != 0UL) {
         Value = other.Value;
       }
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -538,7 +588,7 @@ namespace Google.Protobuf.WellKnownTypes {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
           case 8: {
             Value = input.ReadUInt64();
@@ -557,6 +607,7 @@ namespace Google.Protobuf.WellKnownTypes {
   /// </summary>
   public sealed partial class Int32Value : pb::IMessage<Int32Value> {
     private static readonly pb::MessageParser<Int32Value> _parser = new pb::MessageParser<Int32Value>(() => new Int32Value());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<Int32Value> Parser { get { return _parser; } }
 
@@ -580,6 +631,7 @@ namespace Google.Protobuf.WellKnownTypes {
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public Int32Value(Int32Value other) : this() {
       value_ = other.value_;
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -615,13 +667,16 @@ namespace Google.Protobuf.WellKnownTypes {
         return true;
       }
       if (Value != other.Value) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public override int GetHashCode() {
       int hash = 1;
       if (Value != 0) hash ^= Value.GetHashCode();
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
     }
 
@@ -636,6 +691,9 @@ namespace Google.Protobuf.WellKnownTypes {
         output.WriteRawTag(8);
         output.WriteInt32(Value);
       }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -644,6 +702,9 @@ namespace Google.Protobuf.WellKnownTypes {
       if (Value != 0) {
         size += 1 + pb::CodedOutputStream.ComputeInt32Size(Value);
       }
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
     }
 
@@ -655,6 +716,7 @@ namespace Google.Protobuf.WellKnownTypes {
       if (other.Value != 0) {
         Value = other.Value;
       }
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -663,7 +725,7 @@ namespace Google.Protobuf.WellKnownTypes {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
           case 8: {
             Value = input.ReadInt32();
@@ -682,6 +744,7 @@ namespace Google.Protobuf.WellKnownTypes {
   /// </summary>
   public sealed partial class UInt32Value : pb::IMessage<UInt32Value> {
     private static readonly pb::MessageParser<UInt32Value> _parser = new pb::MessageParser<UInt32Value>(() => new UInt32Value());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<UInt32Value> Parser { get { return _parser; } }
 
@@ -705,6 +768,7 @@ namespace Google.Protobuf.WellKnownTypes {
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public UInt32Value(UInt32Value other) : this() {
       value_ = other.value_;
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -740,13 +804,16 @@ namespace Google.Protobuf.WellKnownTypes {
         return true;
       }
       if (Value != other.Value) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public override int GetHashCode() {
       int hash = 1;
       if (Value != 0) hash ^= Value.GetHashCode();
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
     }
 
@@ -761,6 +828,9 @@ namespace Google.Protobuf.WellKnownTypes {
         output.WriteRawTag(8);
         output.WriteUInt32(Value);
       }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -769,6 +839,9 @@ namespace Google.Protobuf.WellKnownTypes {
       if (Value != 0) {
         size += 1 + pb::CodedOutputStream.ComputeUInt32Size(Value);
       }
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
     }
 
@@ -780,6 +853,7 @@ namespace Google.Protobuf.WellKnownTypes {
       if (other.Value != 0) {
         Value = other.Value;
       }
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -788,7 +862,7 @@ namespace Google.Protobuf.WellKnownTypes {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
           case 8: {
             Value = input.ReadUInt32();
@@ -807,6 +881,7 @@ namespace Google.Protobuf.WellKnownTypes {
   /// </summary>
   public sealed partial class BoolValue : pb::IMessage<BoolValue> {
     private static readonly pb::MessageParser<BoolValue> _parser = new pb::MessageParser<BoolValue>(() => new BoolValue());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<BoolValue> Parser { get { return _parser; } }
 
@@ -830,6 +905,7 @@ namespace Google.Protobuf.WellKnownTypes {
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public BoolValue(BoolValue other) : this() {
       value_ = other.value_;
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -865,13 +941,16 @@ namespace Google.Protobuf.WellKnownTypes {
         return true;
       }
       if (Value != other.Value) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public override int GetHashCode() {
       int hash = 1;
       if (Value != false) hash ^= Value.GetHashCode();
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
     }
 
@@ -886,6 +965,9 @@ namespace Google.Protobuf.WellKnownTypes {
         output.WriteRawTag(8);
         output.WriteBool(Value);
       }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -894,6 +976,9 @@ namespace Google.Protobuf.WellKnownTypes {
       if (Value != false) {
         size += 1 + 1;
       }
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
     }
 
@@ -905,6 +990,7 @@ namespace Google.Protobuf.WellKnownTypes {
       if (other.Value != false) {
         Value = other.Value;
       }
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -913,7 +999,7 @@ namespace Google.Protobuf.WellKnownTypes {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
           case 8: {
             Value = input.ReadBool();
@@ -932,6 +1018,7 @@ namespace Google.Protobuf.WellKnownTypes {
   /// </summary>
   public sealed partial class StringValue : pb::IMessage<StringValue> {
     private static readonly pb::MessageParser<StringValue> _parser = new pb::MessageParser<StringValue>(() => new StringValue());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<StringValue> Parser { get { return _parser; } }
 
@@ -955,6 +1042,7 @@ namespace Google.Protobuf.WellKnownTypes {
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public StringValue(StringValue other) : this() {
       value_ = other.value_;
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -990,13 +1078,16 @@ namespace Google.Protobuf.WellKnownTypes {
         return true;
       }
       if (Value != other.Value) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public override int GetHashCode() {
       int hash = 1;
       if (Value.Length != 0) hash ^= Value.GetHashCode();
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
     }
 
@@ -1011,6 +1102,9 @@ namespace Google.Protobuf.WellKnownTypes {
         output.WriteRawTag(10);
         output.WriteString(Value);
       }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1019,6 +1113,9 @@ namespace Google.Protobuf.WellKnownTypes {
       if (Value.Length != 0) {
         size += 1 + pb::CodedOutputStream.ComputeStringSize(Value);
       }
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
     }
 
@@ -1030,6 +1127,7 @@ namespace Google.Protobuf.WellKnownTypes {
       if (other.Value.Length != 0) {
         Value = other.Value;
       }
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1038,7 +1136,7 @@ namespace Google.Protobuf.WellKnownTypes {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
           case 10: {
             Value = input.ReadString();
@@ -1057,6 +1155,7 @@ namespace Google.Protobuf.WellKnownTypes {
   /// </summary>
   public sealed partial class BytesValue : pb::IMessage<BytesValue> {
     private static readonly pb::MessageParser<BytesValue> _parser = new pb::MessageParser<BytesValue>(() => new BytesValue());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<BytesValue> Parser { get { return _parser; } }
 
@@ -1080,6 +1179,7 @@ namespace Google.Protobuf.WellKnownTypes {
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public BytesValue(BytesValue other) : this() {
       value_ = other.value_;
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1115,13 +1215,16 @@ namespace Google.Protobuf.WellKnownTypes {
         return true;
       }
       if (Value != other.Value) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public override int GetHashCode() {
       int hash = 1;
       if (Value.Length != 0) hash ^= Value.GetHashCode();
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
     }
 
@@ -1136,6 +1239,9 @@ namespace Google.Protobuf.WellKnownTypes {
         output.WriteRawTag(10);
         output.WriteBytes(Value);
       }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1144,6 +1250,9 @@ namespace Google.Protobuf.WellKnownTypes {
       if (Value.Length != 0) {
         size += 1 + pb::CodedOutputStream.ComputeBytesSize(Value);
       }
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
     }
 
@@ -1155,6 +1264,7 @@ namespace Google.Protobuf.WellKnownTypes {
       if (other.Value.Length != 0) {
         Value = other.Value;
       }
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1163,7 +1273,7 @@ namespace Google.Protobuf.WellKnownTypes {
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
           case 10: {
             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
  * 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
- * 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
  * 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
 
-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
 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

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

@@ -1,8 +1,8 @@
 // Generated by the protocol buffer compiler.  DO NOT EDIT!
 // 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>
 
@@ -329,4 +329,4 @@ inline void Any::set_allocated_value(::std::string* value) {
 
 // @@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!
 // 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>
 
@@ -1182,4 +1182,4 @@ inline void Mixin::set_allocated_root(::std::string* root) {
 
 // @@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"
       "// source: $filename$\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"
       "#include <string>\n",
       "filename", file_->name(), "filename_identifier", filename_identifier);
@@ -1156,7 +1156,7 @@ void FileGenerator::GenerateTopHeaderGuard(io::Printer* printer,
 void FileGenerator::GenerateBottomHeaderGuard(
     io::Printer* printer, const string& filename_identifier) {
   printer->Print(
-    "#endif  // PROTOBUF_$filename_identifier$__INCLUDED\n",
+    "#endif  // PROTOBUF_$filename_identifier$_INCLUDED\n",
     "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_);
   AddDeprecatedFlag(printer);
-  
+
   printer->Print(
     vars,
     "$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
   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);
 
   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.
   if (!descriptor_->containing_type()) {
@@ -139,14 +142,14 @@ void MessageGenerator::Generate(io::Printer* printer) {
 
   WriteGeneratedCodeAttributes(printer);
   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);
   printer->Print(
-	vars,
+    vars,
     "pbr::MessageDescriptor pb::IMessage.Descriptor {\n"
     "  get { return Descriptor; }\n"
     "}\n"
@@ -209,18 +212,18 @@ void MessageGenerator::Generate(io::Printer* printer) {
     printer->Print("}\n");
     // TODO: Should we put the oneof .proto comments here?
     // 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"
       "  $name$Case_ = $property_name$OneofCase.None;\n"
       "  $name$_ = null;\n"
@@ -317,6 +320,9 @@ void MessageGenerator::GenerateCloningCode(io::Printer* printer) {
     printer->Outdent();
     printer->Print("}\n\n");
   }
+  // Clone unknown fields
+  printer->Print(
+      "_unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);\n");
 
   printer->Outdent();
   printer->Print("}\n\n");
@@ -337,15 +343,15 @@ void MessageGenerator::GenerateFrameworkMethods(io::Printer* printer) {
     vars["class_name"] = class_name();
 
     // Equality
-	WriteGeneratedCodeAttributes(printer);
+    WriteGeneratedCodeAttributes(printer);
     printer->Print(
         vars,
         "public override bool Equals(object other) {\n"
         "  return Equals(other as $class_name$);\n"
         "}\n\n");
-	WriteGeneratedCodeAttributes(printer);
-	printer->Print(
-	    vars,
+    WriteGeneratedCodeAttributes(printer);
+    printer->Print(
+        vars,
         "public bool Equals($class_name$ other) {\n"
         "  if (ReferenceEquals(other, null)) {\n"
         "    return false;\n"
@@ -365,13 +371,13 @@ void MessageGenerator::GenerateFrameworkMethods(io::Printer* printer) {
     }
     printer->Outdent();
     printer->Print(
-        "  return true;\n"
+        "  return Equals(_unknownFields, other._unknownFields);\n"
         "}\n\n");
 
     // GetHashCode
     // 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"
         "  int hash = 1;\n");
     printer->Indent();
@@ -384,12 +390,16 @@ void MessageGenerator::GenerateFrameworkMethods(io::Printer* printer) {
         printer->Print("hash ^= (int) $name$Case_;\n",
             "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->Print("}\n\n");
 
-	WriteGeneratedCodeAttributes(printer);
-	printer->Print(
+    WriteGeneratedCodeAttributes(printer);
+    printer->Print(
         "public override string ToString() {\n"
         "  return pb::JsonFormatter.ToDiagnosticString(this);\n"
         "}\n\n");
@@ -408,11 +418,17 @@ void MessageGenerator::GenerateMessageSerializationMethods(io::Printer* 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?
   printer->Outdent();
   printer->Print(
-	"}\n"
-	"\n");
+    "}\n"
+    "\n");
   WriteGeneratedCodeAttributes(printer);
   printer->Print(
     "public int CalculateSize() {\n");
@@ -423,6 +439,12 @@ void MessageGenerator::GenerateMessageSerializationMethods(io::Printer* printer)
         CreateFieldGeneratorInternal(descriptor_->field(i)));
     generator->GenerateSerializedSizeCode(printer);
   }
+
+  printer->Print(
+    "if (_unknownFields != null) {\n"
+    "  size += _unknownFields.CalculateSize();\n"
+    "}\n");
+
   printer->Print("return size;\n");
   printer->Outdent();
   printer->Print("}\n\n");
@@ -473,8 +495,14 @@ void MessageGenerator::GenerateMergingMethods(io::Printer* printer) {
     printer->Outdent();
     printer->Print("}\n\n");
   }
+  // Merge unknown fields.
+  printer->Print(
+      "_unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);\n");
+
   printer->Outdent();
   printer->Print("}\n\n");
+
+
   WriteGeneratedCodeAttributes(printer);
   printer->Print("public void MergeFrom(pb::CodedInputStream input) {\n");
   printer->Indent();
@@ -486,14 +514,14 @@ void MessageGenerator::GenerateMergingMethods(io::Printer* printer) {
   printer->Indent();
   // Option messages need to store unknown fields so that options can be parsed later.
   if (IsDescriptorOptionMessage(descriptor_)) {
-	printer->Print(
+    printer->Print(
       "default:\n"
       "  CustomOptions = CustomOptions.ReadOrSkipUnknownField(input);\n"
       "  break;\n");
   } else {
     printer->Print(
       "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");
   }
   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) {
-  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) {
-  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) {
   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) {
   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"
     "#region Designer generated code\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) {
-  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) {
-  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) {

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

@@ -1,8 +1,8 @@
 // Generated by the protocol buffer compiler.  DO NOT EDIT!
 // 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>
 
@@ -1383,4 +1383,4 @@ CodeGeneratorResponse::file() const {
 
 // @@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!
 // 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>
 
@@ -11613,4 +11613,4 @@ inline const EnumDescriptor* GetEnumDescriptor< ::google::protobuf::MethodOption
 
 // @@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!
 // 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>
 
@@ -238,4 +238,4 @@ inline void Duration::set_nanos(::google::protobuf::int32 value) {
 
 // @@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!
 // 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>
 
@@ -196,4 +196,4 @@ class LIBPROTOBUF_EXPORT Empty : public ::google::protobuf::Message /* @@protoc_
 
 // @@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!
 // 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>
 
@@ -273,4 +273,4 @@ FieldMask::mutable_paths() {
 
 // @@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!
 // 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>
 
@@ -249,4 +249,4 @@ inline void SourceContext::set_allocated_file_name(::std::string* file_name) {
 
 // @@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!
 // 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>
 
@@ -1039,4 +1039,4 @@ inline const EnumDescriptor* GetEnumDescriptor< ::google::protobuf::NullValue>()
 
 // @@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 dotdot("..");
+  const char *p = path.c_str();
 
   std::vector<string> segments;
   int segment_start = -1;
   // Find the path segments in `path` (separated by "/").
   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
       // already started.
       if (segment_start < 0) {
@@ -169,7 +170,7 @@ string normalize(string path) {
     } else if (segment_start >= 0 && i > segment_start) {
       // The current character is "/" or "\0", so this ends a segment.
       // 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;
       if (segment == dotdot) {
         if (!segments.empty() &&
@@ -180,7 +181,7 @@ string normalize(string path) {
         segments.push_back(segment);
       }
     }
-    if (path[i] == '\0') {
+    if (p[i] == '\0') {
       break;
     }
   }
@@ -203,7 +204,7 @@ string normalize(string path) {
     result << segments[i];
   }
   // 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 << '\\';
   }
   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
 
+#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)
 #define GOOGLE_THREAD_LOCAL __declspec(thread)
 #else
@@ -413,12 +420,13 @@ class Bits {
   }
 
   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
-    // 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.
-#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));
 #else
   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)
 
 #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.
 // 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!
 // 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>
 
@@ -238,4 +238,4 @@ inline void Timestamp::set_nanos(::google::protobuf::int32 value) {
 
 // @@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
 // 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
-// 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
 // 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!
 // 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>
 
@@ -2403,4 +2403,4 @@ inline const EnumDescriptor* GetEnumDescriptor< ::google::protobuf::Syntax>() {
 
 // @@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
   // easy to read.
   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;
   // Whether to always print enums as ints. By default they are rendered as
   // 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) {
   // 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) {
@@ -871,7 +871,7 @@ inline uint64 WireFormatLite::ZigZagEncode64(int64 n) {
 
 inline int64 WireFormatLite::ZigZagDecode64(uint64 n) {
   // 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

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

@@ -1,8 +1,8 @@
 // Generated by the protocol buffer compiler.  DO NOT EDIT!
 // 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>
 
@@ -1533,4 +1533,4 @@ inline void BytesValue::unsafe_arena_set_allocated_value(
 
 // @@protoc_insertion_point(global_scope)
 
-#endif  // PROTOBUF_google_2fprotobuf_2fwrappers_2eproto__INCLUDED
+#endif  // PROTOBUF_google_2fprotobuf_2fwrappers_2eproto_INCLUDED

برخی فایل ها در این مقایسه diff نمایش داده نمی شوند زیرا تعداد فایل ها بسیار زیاد است