Unverified Commit d106399d authored by Jisi Liu's avatar Jisi Liu Committed by GitHub

Merge pull request #4072 from google/jieluo

Cherrypick for csharp, including:
parents 6c3c7f6d b308580b
...@@ -61,8 +61,13 @@ csharp_EXTRA_DIST= \ ...@@ -61,8 +61,13 @@ csharp_EXTRA_DIST= \
csharp/keys/Google.Protobuf.public.snk \ csharp/keys/Google.Protobuf.public.snk \
csharp/keys/Google.Protobuf.snk \ csharp/keys/Google.Protobuf.snk \
csharp/keys/README.md \ csharp/keys/README.md \
csharp/protos/README.md \
csharp/protos/map_unittest_proto3.proto \
csharp/protos/unittest_custom_options_proto3.proto \ csharp/protos/unittest_custom_options_proto3.proto \
csharp/protos/unittest_import_public_proto3.proto \
csharp/protos/unittest_import_proto3.proto \
csharp/protos/unittest_issues.proto \ csharp/protos/unittest_issues.proto \
csharp/protos/unittest_proto3.proto \
csharp/src/AddressBook/AddPerson.cs \ csharp/src/AddressBook/AddPerson.cs \
csharp/src/AddressBook/Addressbook.cs \ csharp/src/AddressBook/Addressbook.cs \
csharp/src/AddressBook/AddressBook.csproj \ csharp/src/AddressBook/AddressBook.csproj \
...@@ -79,6 +84,7 @@ csharp_EXTRA_DIST= \ ...@@ -79,6 +84,7 @@ csharp_EXTRA_DIST= \
csharp/src/Google.Protobuf.Test/CodedInputStreamTest.cs \ csharp/src/Google.Protobuf.Test/CodedInputStreamTest.cs \
csharp/src/Google.Protobuf.Test/CodedOutputStreamTest.cs \ csharp/src/Google.Protobuf.Test/CodedOutputStreamTest.cs \
csharp/src/Google.Protobuf.Test/Collections/MapFieldTest.cs \ csharp/src/Google.Protobuf.Test/Collections/MapFieldTest.cs \
csharp/src/Google.Protobuf.Test/Collections/ProtobufEqualityComparersTest.cs \
csharp/src/Google.Protobuf.Test/Collections/RepeatedFieldTest.cs \ csharp/src/Google.Protobuf.Test/Collections/RepeatedFieldTest.cs \
csharp/src/Google.Protobuf.Test/Compatibility/PropertyInfoExtensionsTest.cs \ csharp/src/Google.Protobuf.Test/Compatibility/PropertyInfoExtensionsTest.cs \
csharp/src/Google.Protobuf.Test/Compatibility/StreamExtensionsTest.cs \ csharp/src/Google.Protobuf.Test/Compatibility/StreamExtensionsTest.cs \
...@@ -99,6 +105,7 @@ csharp_EXTRA_DIST= \ ...@@ -99,6 +105,7 @@ csharp_EXTRA_DIST= \
csharp/src/Google.Protobuf.Test/Reflection/TypeRegistryTest.cs \ csharp/src/Google.Protobuf.Test/Reflection/TypeRegistryTest.cs \
csharp/src/Google.Protobuf.Test/SampleEnum.cs \ csharp/src/Google.Protobuf.Test/SampleEnum.cs \
csharp/src/Google.Protobuf.Test/SampleMessages.cs \ csharp/src/Google.Protobuf.Test/SampleMessages.cs \
csharp/src/Google.Protobuf.Test/SampleNaNs.cs \
csharp/src/Google.Protobuf.Test/TestCornerCases.cs \ csharp/src/Google.Protobuf.Test/TestCornerCases.cs \
csharp/src/Google.Protobuf.Test/TestProtos/ForeignMessagePartial.cs \ csharp/src/Google.Protobuf.Test/TestProtos/ForeignMessagePartial.cs \
csharp/src/Google.Protobuf.Test/TestProtos/MapUnittestProto3.cs \ csharp/src/Google.Protobuf.Test/TestProtos/MapUnittestProto3.cs \
...@@ -114,13 +121,16 @@ csharp_EXTRA_DIST= \ ...@@ -114,13 +121,16 @@ csharp_EXTRA_DIST= \
csharp/src/Google.Protobuf.Test/WellKnownTypes/FieldMaskTest.cs \ csharp/src/Google.Protobuf.Test/WellKnownTypes/FieldMaskTest.cs \
csharp/src/Google.Protobuf.Test/WellKnownTypes/TimestampTest.cs \ csharp/src/Google.Protobuf.Test/WellKnownTypes/TimestampTest.cs \
csharp/src/Google.Protobuf.Test/WellKnownTypes/WrappersTest.cs \ csharp/src/Google.Protobuf.Test/WellKnownTypes/WrappersTest.cs \
csharp/src/Google.Protobuf.Test/UnknownFieldSetTest.cs \
csharp/src/Google.Protobuf.sln \ csharp/src/Google.Protobuf.sln \
csharp/src/Google.Protobuf/ByteArray.cs \ csharp/src/Google.Protobuf/ByteArray.cs \
csharp/src/Google.Protobuf/ByteString.cs \ csharp/src/Google.Protobuf/ByteString.cs \
csharp/src/Google.Protobuf/CodedInputStream.cs \ csharp/src/Google.Protobuf/CodedInputStream.cs \
csharp/src/Google.Protobuf/CodedOutputStream.ComputeSize.cs \ csharp/src/Google.Protobuf/CodedOutputStream.ComputeSize.cs \
csharp/src/Google.Protobuf/CodedOutputStream.cs \ csharp/src/Google.Protobuf/CodedOutputStream.cs \
csharp/src/Google.Protobuf/Collections/Lists.cs \
csharp/src/Google.Protobuf/Collections/MapField.cs \ csharp/src/Google.Protobuf/Collections/MapField.cs \
csharp/src/Google.Protobuf/Collections/ProtobufEqualityComparers.cs \
csharp/src/Google.Protobuf/Collections/ReadOnlyDictionary.cs \ csharp/src/Google.Protobuf/Collections/ReadOnlyDictionary.cs \
csharp/src/Google.Protobuf/Collections/RepeatedField.cs \ csharp/src/Google.Protobuf/Collections/RepeatedField.cs \
csharp/src/Google.Protobuf/Compatibility/PropertyInfoExtensions.cs \ csharp/src/Google.Protobuf/Compatibility/PropertyInfoExtensions.cs \
...@@ -188,7 +198,9 @@ csharp_EXTRA_DIST= \ ...@@ -188,7 +198,9 @@ csharp_EXTRA_DIST= \
csharp/src/Google.Protobuf/WellKnownTypes/ValuePartial.cs \ csharp/src/Google.Protobuf/WellKnownTypes/ValuePartial.cs \
csharp/src/Google.Protobuf/WellKnownTypes/Wrappers.cs \ csharp/src/Google.Protobuf/WellKnownTypes/Wrappers.cs \
csharp/src/Google.Protobuf/WellKnownTypes/WrappersPartial.cs \ csharp/src/Google.Protobuf/WellKnownTypes/WrappersPartial.cs \
csharp/src/Google.Protobuf/WireFormat.cs csharp/src/Google.Protobuf/WireFormat.cs \
csharp/src/Google.Protobuf/UnknownField.cs \
csharp/src/Google.Protobuf/UnknownFieldSet.cs
java_EXTRA_DIST= \ java_EXTRA_DIST= \
java/README.md \ java/README.md \
......
Recommended.Proto3.JsonInput.BytesFieldBase64Url.JsonOutput Recommended.Proto3.JsonInput.BytesFieldBase64Url.JsonOutput
Recommended.Proto3.JsonInput.BytesFieldBase64Url.ProtobufOutput Recommended.Proto3.JsonInput.BytesFieldBase64Url.ProtobufOutput
Required.Proto3.ProtobufInput.UnknownVarint.ProtobufOutput
...@@ -638,7 +638,7 @@ namespace Google.Protobuf ...@@ -638,7 +638,7 @@ namespace Google.Protobuf
} }
[Test] [Test]
public void IgnoreUnknownFields_RealDataStillRead() public void DiscardUnknownFields_RealDataStillRead()
{ {
var message = SampleMessages.CreateFullTestAllTypes(); var message = SampleMessages.CreateFullTestAllTypes();
var stream = new MemoryStream(); var stream = new MemoryStream();
...@@ -652,16 +652,18 @@ namespace Google.Protobuf ...@@ -652,16 +652,18 @@ namespace Google.Protobuf
stream.Position = 0; stream.Position = 0;
var parsed = TestAllTypes.Parser.ParseFrom(stream); var parsed = TestAllTypes.Parser.ParseFrom(stream);
Assert.AreEqual(message, parsed); // TODO(jieluo): Add test back after DiscardUnknownFields is supported
// Assert.AreEqual(message, parsed);
} }
[Test] [Test]
public void IgnoreUnknownFields_AllTypes() public void DiscardUnknownFields_AllTypes()
{ {
// Simple way of ensuring we can skip all kinds of fields. // Simple way of ensuring we can skip all kinds of fields.
var data = SampleMessages.CreateFullTestAllTypes().ToByteArray(); var data = SampleMessages.CreateFullTestAllTypes().ToByteArray();
var empty = Empty.Parser.ParseFrom(data); var empty = Empty.Parser.ParseFrom(data);
Assert.AreEqual(new Empty(), empty); // TODO(jieluo): Add test back after DiscardUnknownField is supported.
// Assert.AreEqual(new Empty(), empty);
} }
// This was originally seen as a conformance test failure. // This was originally seen as a conformance test failure.
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
# You first need to make sure protoc has been built (see instructions on # You first need to make sure protoc has been built (see instructions on
# building protoc in root of this repository) # building protoc in root of this repository)
set -ex set -e
# cd to repository root # cd to repository root
pushd $(dirname $0)/.. pushd $(dirname $0)/..
...@@ -40,28 +40,20 @@ $PROTOC -Isrc --csharp_out=csharp/src/Google.Protobuf \ ...@@ -40,28 +40,20 @@ $PROTOC -Isrc --csharp_out=csharp/src/Google.Protobuf \
src/google/protobuf/type.proto \ src/google/protobuf/type.proto \
src/google/protobuf/wrappers.proto src/google/protobuf/wrappers.proto
# Test protos where the namespace matches the target location # Test protos
$PROTOC -Isrc --csharp_out=csharp/src/Google.Protobuf.Test \ $PROTOC -Isrc -Icsharp/protos \
--csharp_opt=base_namespace=Google.Protobuf \ --csharp_out=csharp/src/Google.Protobuf.Test/TestProtos \
src/google/protobuf/map_unittest_proto3.proto \ csharp/protos/map_unittest_proto3.proto \
src/google/protobuf/unittest_proto3.proto \
src/google/protobuf/unittest_import_proto3.proto \
src/google/protobuf/unittest_import_public_proto3.proto \
src/google/protobuf/unittest_well_known_types.proto
# Different base namespace to the protos above
$PROTOC -Isrc -Icsharp/protos --csharp_out=csharp/src/Google.Protobuf.Test \
--csharp_opt=base_namespace=UnitTest.Issues \
csharp/protos/unittest_issues.proto \ csharp/protos/unittest_issues.proto \
csharp/protos/unittest_custom_options_proto3.proto csharp/protos/unittest_custom_options_proto3.proto \
csharp/protos/unittest_proto3.proto \
# Don't specify a base namespace at all; we just want to make sure the csharp/protos/unittest_import_proto3.proto \
# results end up in TestProtos. csharp/protos/unittest_import_public_proto3.proto \
$PROTOC -Isrc --csharp_out=csharp/src/Google.Protobuf.Test/TestProtos \ src/google/protobuf/unittest_well_known_types.proto \
src/google/protobuf/test_messages_proto3.proto src/google/protobuf/test_messages_proto3.proto
# AddressBook sample protos # AddressBook sample protos
$PROTOC -Iexamples --csharp_out=csharp/src/AddressBook \ $PROTOC -Iexamples -Isrc --csharp_out=csharp/src/AddressBook \
examples/addressbook.proto examples/addressbook.proto
$PROTOC -Iconformance -Isrc --csharp_out=csharp/src/Google.Protobuf.Conformance \ $PROTOC -Iconformance -Isrc --csharp_out=csharp/src/Google.Protobuf.Conformance \
......
This directory contains unit test protos adapted from those in
src/google/protobuf, and C#-specific test protos for regression
tests against bugs found in the C# codegen or library.
// 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.
// This file is mostly equivalent to map_unittest.proto, but imports
// unittest_proto3.proto instead of unittest.proto, so that it only
// uses proto3 messages. This makes it suitable for testing
// implementations which only support proto3.
// The TestRequiredMessageMap message has been removed as there are no
// required fields in proto3.
syntax = "proto3";
option csharp_namespace = "Google.Protobuf.TestProtos";
import "unittest_proto3.proto";
package protobuf_unittest3;
// Tests maps.
message TestMap {
map<int32 , int32 > map_int32_int32 = 1;
map<int64 , int64 > map_int64_int64 = 2;
map<uint32 , uint32 > map_uint32_uint32 = 3;
map<uint64 , uint64 > map_uint64_uint64 = 4;
map<sint32 , sint32 > map_sint32_sint32 = 5;
map<sint64 , sint64 > map_sint64_sint64 = 6;
map<fixed32 , fixed32 > map_fixed32_fixed32 = 7;
map<fixed64 , fixed64 > map_fixed64_fixed64 = 8;
map<sfixed32, sfixed32> map_sfixed32_sfixed32 = 9;
map<sfixed64, sfixed64> map_sfixed64_sfixed64 = 10;
map<int32 , float > map_int32_float = 11;
map<int32 , double > map_int32_double = 12;
map<bool , bool > map_bool_bool = 13;
map<string , string > map_string_string = 14;
map<int32 , bytes > map_int32_bytes = 15;
map<int32 , MapEnum > map_int32_enum = 16;
map<int32 , ForeignMessage> map_int32_foreign_message = 17;
}
message TestMapSubmessage {
TestMap test_map = 1;
}
message TestMessageMap {
map<int32, TestAllTypes> map_int32_message = 1;
}
// Two map fields share the same entry default instance.
message TestSameTypeMap {
map<int32, int32> map1 = 1;
map<int32, int32> map2 = 2;
}
enum MapEnum {
MAP_ENUM_FOO = 0;
MAP_ENUM_BAR = 1;
MAP_ENUM_BAZ = 2;
}
message TestArenaMap {
map<int32 , int32 > map_int32_int32 = 1;
map<int64 , int64 > map_int64_int64 = 2;
map<uint32 , uint32 > map_uint32_uint32 = 3;
map<uint64 , uint64 > map_uint64_uint64 = 4;
map<sint32 , sint32 > map_sint32_sint32 = 5;
map<sint64 , sint64 > map_sint64_sint64 = 6;
map<fixed32 , fixed32 > map_fixed32_fixed32 = 7;
map<fixed64 , fixed64 > map_fixed64_fixed64 = 8;
map<sfixed32, sfixed32> map_sfixed32_sfixed32 = 9;
map<sfixed64, sfixed64> map_sfixed64_sfixed64 = 10;
map<int32 , float > map_int32_float = 11;
map<int32 , double > map_int32_double = 12;
map<bool , bool > map_bool_bool = 13;
map<int32 , MapEnum > map_int32_enum = 14;
map<int32 , ForeignMessage> map_int32_foreign_message = 15;
}
// Previously, message containing enum called Type cannot be used as value of
// map field.
message MessageContainingEnumCalledType {
enum Type {
TYPE_FOO = 0;
}
map<int32, MessageContainingEnumCalledType> type = 1;
}
// Previously, message cannot contain map field called "entry".
message MessageContainingMapCalledEntry {
map<int32, int32> entry = 1;
}
// 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: kenton@google.com (Kenton Varda)
// Based on original Protocol Buffers design by
// Sanjay Ghemawat, Jeff Dean, and others.
//
// A proto file which is imported by unittest_proto3.proto to test importing.
syntax = "proto3";
package protobuf_unittest_import;
option csharp_namespace = "Google.Protobuf.TestProtos";
// Test public import
import public "unittest_import_public_proto3.proto";
message ImportMessage {
int32 d = 1;
}
enum ImportEnum {
IMPORT_ENUM_UNSPECIFIED = 0;
IMPORT_FOO = 7;
IMPORT_BAR = 8;
IMPORT_BAZ = 9;
}
// 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: liujisi@google.com (Pherl Liu)
syntax = "proto3";
package protobuf_unittest_import;
option csharp_namespace = "Google.Protobuf.TestProtos";
message PublicImportMessage {
int32 e = 1;
}
...@@ -7,7 +7,6 @@ syntax = "proto3"; ...@@ -7,7 +7,6 @@ syntax = "proto3";
option csharp_namespace = "UnitTest.Issues.TestProtos"; option csharp_namespace = "UnitTest.Issues.TestProtos";
package unittest_issues; package unittest_issues;
option optimize_for = SPEED;
// Issue 307: when generating doubly-nested types, any references // Issue 307: when generating doubly-nested types, any references
// should be of the form A.Types.B.Types.C. // should be of the form A.Types.B.Types.C.
......
This diff is collapsed.
// <auto-generated>
// Generated by the protocol buffer compiler. DO NOT EDIT! // Generated by the protocol buffer compiler. DO NOT EDIT!
// source: addressbook.proto // source: addressbook.proto
// </auto-generated>
#pragma warning disable 1591, 0612, 3021 #pragma warning disable 1591, 0612, 3021
#region Designer generated code #region Designer generated code
...@@ -49,6 +51,7 @@ namespace Google.Protobuf.Examples.AddressBook { ...@@ -49,6 +51,7 @@ namespace Google.Protobuf.Examples.AddressBook {
/// </summary> /// </summary>
public sealed partial class Person : pb::IMessage<Person> { public sealed partial class Person : pb::IMessage<Person> {
private static readonly pb::MessageParser<Person> _parser = new pb::MessageParser<Person>(() => new Person()); private static readonly pb::MessageParser<Person> _parser = new pb::MessageParser<Person>(() => new Person());
private pb::UnknownFieldSet _unknownFields;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pb::MessageParser<Person> Parser { get { return _parser; } } public static pb::MessageParser<Person> Parser { get { return _parser; } }
...@@ -76,6 +79,7 @@ namespace Google.Protobuf.Examples.AddressBook { ...@@ -76,6 +79,7 @@ namespace Google.Protobuf.Examples.AddressBook {
email_ = other.email_; email_ = other.email_;
phones_ = other.phones_.Clone(); phones_ = other.phones_.Clone();
LastUpdated = other.lastUpdated_ != null ? other.LastUpdated.Clone() : null; LastUpdated = other.lastUpdated_ != null ? other.LastUpdated.Clone() : null;
_unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
} }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
...@@ -158,7 +162,7 @@ namespace Google.Protobuf.Examples.AddressBook { ...@@ -158,7 +162,7 @@ namespace Google.Protobuf.Examples.AddressBook {
if (Email != other.Email) return false; if (Email != other.Email) return false;
if(!phones_.Equals(other.phones_)) return false; if(!phones_.Equals(other.phones_)) return false;
if (!object.Equals(LastUpdated, other.LastUpdated)) return false; if (!object.Equals(LastUpdated, other.LastUpdated)) return false;
return true; return Equals(_unknownFields, other._unknownFields);
} }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
...@@ -169,6 +173,9 @@ namespace Google.Protobuf.Examples.AddressBook { ...@@ -169,6 +173,9 @@ namespace Google.Protobuf.Examples.AddressBook {
if (Email.Length != 0) hash ^= Email.GetHashCode(); if (Email.Length != 0) hash ^= Email.GetHashCode();
hash ^= phones_.GetHashCode(); hash ^= phones_.GetHashCode();
if (lastUpdated_ != null) hash ^= LastUpdated.GetHashCode(); if (lastUpdated_ != null) hash ^= LastUpdated.GetHashCode();
if (_unknownFields != null) {
hash ^= _unknownFields.GetHashCode();
}
return hash; return hash;
} }
...@@ -196,6 +203,9 @@ namespace Google.Protobuf.Examples.AddressBook { ...@@ -196,6 +203,9 @@ namespace Google.Protobuf.Examples.AddressBook {
output.WriteRawTag(42); output.WriteRawTag(42);
output.WriteMessage(LastUpdated); output.WriteMessage(LastUpdated);
} }
if (_unknownFields != null) {
_unknownFields.WriteTo(output);
}
} }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
...@@ -214,6 +224,9 @@ namespace Google.Protobuf.Examples.AddressBook { ...@@ -214,6 +224,9 @@ namespace Google.Protobuf.Examples.AddressBook {
if (lastUpdated_ != null) { if (lastUpdated_ != null) {
size += 1 + pb::CodedOutputStream.ComputeMessageSize(LastUpdated); size += 1 + pb::CodedOutputStream.ComputeMessageSize(LastUpdated);
} }
if (_unknownFields != null) {
size += _unknownFields.CalculateSize();
}
return size; return size;
} }
...@@ -238,6 +251,7 @@ namespace Google.Protobuf.Examples.AddressBook { ...@@ -238,6 +251,7 @@ namespace Google.Protobuf.Examples.AddressBook {
} }
LastUpdated.MergeFrom(other.LastUpdated); LastUpdated.MergeFrom(other.LastUpdated);
} }
_unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
} }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
...@@ -246,7 +260,7 @@ namespace Google.Protobuf.Examples.AddressBook { ...@@ -246,7 +260,7 @@ namespace Google.Protobuf.Examples.AddressBook {
while ((tag = input.ReadTag()) != 0) { while ((tag = input.ReadTag()) != 0) {
switch(tag) { switch(tag) {
default: default:
input.SkipLastField(); _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
break; break;
case 10: { case 10: {
Name = input.ReadString(); Name = input.ReadString();
...@@ -287,6 +301,7 @@ namespace Google.Protobuf.Examples.AddressBook { ...@@ -287,6 +301,7 @@ namespace Google.Protobuf.Examples.AddressBook {
public sealed partial class PhoneNumber : pb::IMessage<PhoneNumber> { public sealed partial class PhoneNumber : pb::IMessage<PhoneNumber> {
private static readonly pb::MessageParser<PhoneNumber> _parser = new pb::MessageParser<PhoneNumber>(() => new PhoneNumber()); private static readonly pb::MessageParser<PhoneNumber> _parser = new pb::MessageParser<PhoneNumber>(() => new PhoneNumber());
private pb::UnknownFieldSet _unknownFields;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pb::MessageParser<PhoneNumber> Parser { get { return _parser; } } public static pb::MessageParser<PhoneNumber> Parser { get { return _parser; } }
...@@ -311,6 +326,7 @@ namespace Google.Protobuf.Examples.AddressBook { ...@@ -311,6 +326,7 @@ namespace Google.Protobuf.Examples.AddressBook {
public PhoneNumber(PhoneNumber other) : this() { public PhoneNumber(PhoneNumber other) : this() {
number_ = other.number_; number_ = other.number_;
type_ = other.type_; type_ = other.type_;
_unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
} }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
...@@ -355,7 +371,7 @@ namespace Google.Protobuf.Examples.AddressBook { ...@@ -355,7 +371,7 @@ namespace Google.Protobuf.Examples.AddressBook {
} }
if (Number != other.Number) return false; if (Number != other.Number) return false;
if (Type != other.Type) return false; if (Type != other.Type) return false;
return true; return Equals(_unknownFields, other._unknownFields);
} }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
...@@ -363,6 +379,9 @@ namespace Google.Protobuf.Examples.AddressBook { ...@@ -363,6 +379,9 @@ namespace Google.Protobuf.Examples.AddressBook {
int hash = 1; int hash = 1;
if (Number.Length != 0) hash ^= Number.GetHashCode(); if (Number.Length != 0) hash ^= Number.GetHashCode();
if (Type != 0) hash ^= Type.GetHashCode(); if (Type != 0) hash ^= Type.GetHashCode();
if (_unknownFields != null) {
hash ^= _unknownFields.GetHashCode();
}
return hash; return hash;
} }
...@@ -381,6 +400,9 @@ namespace Google.Protobuf.Examples.AddressBook { ...@@ -381,6 +400,9 @@ namespace Google.Protobuf.Examples.AddressBook {
output.WriteRawTag(16); output.WriteRawTag(16);
output.WriteEnum((int) Type); output.WriteEnum((int) Type);
} }
if (_unknownFields != null) {
_unknownFields.WriteTo(output);
}
} }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
...@@ -392,6 +414,9 @@ namespace Google.Protobuf.Examples.AddressBook { ...@@ -392,6 +414,9 @@ namespace Google.Protobuf.Examples.AddressBook {
if (Type != 0) { if (Type != 0) {
size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Type); size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Type);
} }
if (_unknownFields != null) {
size += _unknownFields.CalculateSize();
}
return size; return size;
} }
...@@ -406,6 +431,7 @@ namespace Google.Protobuf.Examples.AddressBook { ...@@ -406,6 +431,7 @@ namespace Google.Protobuf.Examples.AddressBook {
if (other.Type != 0) { if (other.Type != 0) {
Type = other.Type; Type = other.Type;
} }
_unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
} }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
...@@ -414,7 +440,7 @@ namespace Google.Protobuf.Examples.AddressBook { ...@@ -414,7 +440,7 @@ namespace Google.Protobuf.Examples.AddressBook {
while ((tag = input.ReadTag()) != 0) { while ((tag = input.ReadTag()) != 0) {
switch(tag) { switch(tag) {
default: default:
input.SkipLastField(); _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
break; break;
case 10: { case 10: {
Number = input.ReadString(); Number = input.ReadString();
...@@ -440,6 +466,7 @@ namespace Google.Protobuf.Examples.AddressBook { ...@@ -440,6 +466,7 @@ namespace Google.Protobuf.Examples.AddressBook {
/// </summary> /// </summary>
public sealed partial class AddressBook : pb::IMessage<AddressBook> { public sealed partial class AddressBook : pb::IMessage<AddressBook> {
private static readonly pb::MessageParser<AddressBook> _parser = new pb::MessageParser<AddressBook>(() => new AddressBook()); private static readonly pb::MessageParser<AddressBook> _parser = new pb::MessageParser<AddressBook>(() => new AddressBook());
private pb::UnknownFieldSet _unknownFields;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pb::MessageParser<AddressBook> Parser { get { return _parser; } } public static pb::MessageParser<AddressBook> Parser { get { return _parser; } }
...@@ -463,6 +490,7 @@ namespace Google.Protobuf.Examples.AddressBook { ...@@ -463,6 +490,7 @@ namespace Google.Protobuf.Examples.AddressBook {
[global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public AddressBook(AddressBook other) : this() { public AddressBook(AddressBook other) : this() {
people_ = other.people_.Clone(); people_ = other.people_.Clone();
_unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
} }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
...@@ -494,13 +522,16 @@ namespace Google.Protobuf.Examples.AddressBook { ...@@ -494,13 +522,16 @@ namespace Google.Protobuf.Examples.AddressBook {
return true; return true;
} }
if(!people_.Equals(other.people_)) return false; if(!people_.Equals(other.people_)) return false;
return true; return Equals(_unknownFields, other._unknownFields);
} }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public override int GetHashCode() { public override int GetHashCode() {
int hash = 1; int hash = 1;
hash ^= people_.GetHashCode(); hash ^= people_.GetHashCode();
if (_unknownFields != null) {
hash ^= _unknownFields.GetHashCode();
}
return hash; return hash;
} }
...@@ -512,12 +543,18 @@ namespace Google.Protobuf.Examples.AddressBook { ...@@ -512,12 +543,18 @@ namespace Google.Protobuf.Examples.AddressBook {
[global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public void WriteTo(pb::CodedOutputStream output) { public void WriteTo(pb::CodedOutputStream output) {
people_.WriteTo(output, _repeated_people_codec); people_.WriteTo(output, _repeated_people_codec);
if (_unknownFields != null) {
_unknownFields.WriteTo(output);
}
} }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public int CalculateSize() { public int CalculateSize() {
int size = 0; int size = 0;
size += people_.CalculateSize(_repeated_people_codec); size += people_.CalculateSize(_repeated_people_codec);
if (_unknownFields != null) {
size += _unknownFields.CalculateSize();
}
return size; return size;
} }
...@@ -527,6 +564,7 @@ namespace Google.Protobuf.Examples.AddressBook { ...@@ -527,6 +564,7 @@ namespace Google.Protobuf.Examples.AddressBook {
return; return;
} }
people_.Add(other.people_); people_.Add(other.people_);
_unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
} }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
...@@ -535,7 +573,7 @@ namespace Google.Protobuf.Examples.AddressBook { ...@@ -535,7 +573,7 @@ namespace Google.Protobuf.Examples.AddressBook {
while ((tag = input.ReadTag()) != 0) { while ((tag = input.ReadTag()) != 0) {
switch(tag) { switch(tag) {
default: default:
input.SkipLastField(); _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
break; break;
case 10: { case 10: {
people_.AddEntriesFrom(input, _repeated_people_codec); people_.AddEntriesFrom(input, _repeated_people_codec);
......
// <auto-generated>
// Generated by the protocol buffer compiler. DO NOT EDIT! // Generated by the protocol buffer compiler. DO NOT EDIT!
// source: conformance.proto // source: conformance.proto
// </auto-generated>
#pragma warning disable 1591, 0612, 3021 #pragma warning disable 1591, 0612, 3021
#region Designer generated code #region Designer generated code
...@@ -62,6 +64,7 @@ namespace Conformance { ...@@ -62,6 +64,7 @@ namespace Conformance {
/// </summary> /// </summary>
public sealed partial class ConformanceRequest : pb::IMessage<ConformanceRequest> { public sealed partial class ConformanceRequest : pb::IMessage<ConformanceRequest> {
private static readonly pb::MessageParser<ConformanceRequest> _parser = new pb::MessageParser<ConformanceRequest>(() => new ConformanceRequest()); private static readonly pb::MessageParser<ConformanceRequest> _parser = new pb::MessageParser<ConformanceRequest>(() => new ConformanceRequest());
private pb::UnknownFieldSet _unknownFields;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pb::MessageParser<ConformanceRequest> Parser { get { return _parser; } } public static pb::MessageParser<ConformanceRequest> Parser { get { return _parser; } }
...@@ -95,6 +98,7 @@ namespace Conformance { ...@@ -95,6 +98,7 @@ namespace Conformance {
break; break;
} }
_unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
} }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
...@@ -191,7 +195,7 @@ namespace Conformance { ...@@ -191,7 +195,7 @@ namespace Conformance {
if (RequestedOutputFormat != other.RequestedOutputFormat) return false; if (RequestedOutputFormat != other.RequestedOutputFormat) return false;
if (MessageType != other.MessageType) return false; if (MessageType != other.MessageType) return false;
if (PayloadCase != other.PayloadCase) return false; if (PayloadCase != other.PayloadCase) return false;
return true; return Equals(_unknownFields, other._unknownFields);
} }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
...@@ -202,6 +206,9 @@ namespace Conformance { ...@@ -202,6 +206,9 @@ namespace Conformance {
if (RequestedOutputFormat != 0) hash ^= RequestedOutputFormat.GetHashCode(); if (RequestedOutputFormat != 0) hash ^= RequestedOutputFormat.GetHashCode();
if (MessageType.Length != 0) hash ^= MessageType.GetHashCode(); if (MessageType.Length != 0) hash ^= MessageType.GetHashCode();
hash ^= (int) payloadCase_; hash ^= (int) payloadCase_;
if (_unknownFields != null) {
hash ^= _unknownFields.GetHashCode();
}
return hash; return hash;
} }
...@@ -228,6 +235,9 @@ namespace Conformance { ...@@ -228,6 +235,9 @@ namespace Conformance {
output.WriteRawTag(34); output.WriteRawTag(34);
output.WriteString(MessageType); output.WriteString(MessageType);
} }
if (_unknownFields != null) {
_unknownFields.WriteTo(output);
}
} }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
...@@ -245,6 +255,9 @@ namespace Conformance { ...@@ -245,6 +255,9 @@ namespace Conformance {
if (MessageType.Length != 0) { if (MessageType.Length != 0) {
size += 1 + pb::CodedOutputStream.ComputeStringSize(MessageType); size += 1 + pb::CodedOutputStream.ComputeStringSize(MessageType);
} }
if (_unknownFields != null) {
size += _unknownFields.CalculateSize();
}
return size; return size;
} }
...@@ -268,6 +281,7 @@ namespace Conformance { ...@@ -268,6 +281,7 @@ namespace Conformance {
break; break;
} }
_unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
} }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
...@@ -276,7 +290,7 @@ namespace Conformance { ...@@ -276,7 +290,7 @@ namespace Conformance {
while ((tag = input.ReadTag()) != 0) { while ((tag = input.ReadTag()) != 0) {
switch(tag) { switch(tag) {
default: default:
input.SkipLastField(); _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
break; break;
case 10: { case 10: {
ProtobufPayload = input.ReadBytes(); ProtobufPayload = input.ReadBytes();
...@@ -305,6 +319,7 @@ namespace Conformance { ...@@ -305,6 +319,7 @@ namespace Conformance {
/// </summary> /// </summary>
public sealed partial class ConformanceResponse : pb::IMessage<ConformanceResponse> { public sealed partial class ConformanceResponse : pb::IMessage<ConformanceResponse> {
private static readonly pb::MessageParser<ConformanceResponse> _parser = new pb::MessageParser<ConformanceResponse>(() => new ConformanceResponse()); private static readonly pb::MessageParser<ConformanceResponse> _parser = new pb::MessageParser<ConformanceResponse>(() => new ConformanceResponse());
private pb::UnknownFieldSet _unknownFields;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pb::MessageParser<ConformanceResponse> Parser { get { return _parser; } } public static pb::MessageParser<ConformanceResponse> Parser { get { return _parser; } }
...@@ -348,6 +363,7 @@ namespace Conformance { ...@@ -348,6 +363,7 @@ namespace Conformance {
break; break;
} }
_unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
} }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
...@@ -493,7 +509,7 @@ namespace Conformance { ...@@ -493,7 +509,7 @@ namespace Conformance {
if (JsonPayload != other.JsonPayload) return false; if (JsonPayload != other.JsonPayload) return false;
if (Skipped != other.Skipped) return false; if (Skipped != other.Skipped) return false;
if (ResultCase != other.ResultCase) return false; if (ResultCase != other.ResultCase) return false;
return true; return Equals(_unknownFields, other._unknownFields);
} }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
...@@ -506,6 +522,9 @@ namespace Conformance { ...@@ -506,6 +522,9 @@ namespace Conformance {
if (resultCase_ == ResultOneofCase.JsonPayload) hash ^= JsonPayload.GetHashCode(); if (resultCase_ == ResultOneofCase.JsonPayload) hash ^= JsonPayload.GetHashCode();
if (resultCase_ == ResultOneofCase.Skipped) hash ^= Skipped.GetHashCode(); if (resultCase_ == ResultOneofCase.Skipped) hash ^= Skipped.GetHashCode();
hash ^= (int) resultCase_; hash ^= (int) resultCase_;
if (_unknownFields != null) {
hash ^= _unknownFields.GetHashCode();
}
return hash; return hash;
} }
...@@ -540,6 +559,9 @@ namespace Conformance { ...@@ -540,6 +559,9 @@ namespace Conformance {
output.WriteRawTag(50); output.WriteRawTag(50);
output.WriteString(SerializeError); output.WriteString(SerializeError);
} }
if (_unknownFields != null) {
_unknownFields.WriteTo(output);
}
} }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
...@@ -563,6 +585,9 @@ namespace Conformance { ...@@ -563,6 +585,9 @@ namespace Conformance {
if (resultCase_ == ResultOneofCase.Skipped) { if (resultCase_ == ResultOneofCase.Skipped) {
size += 1 + pb::CodedOutputStream.ComputeStringSize(Skipped); size += 1 + pb::CodedOutputStream.ComputeStringSize(Skipped);
} }
if (_unknownFields != null) {
size += _unknownFields.CalculateSize();
}
return size; return size;
} }
...@@ -592,6 +617,7 @@ namespace Conformance { ...@@ -592,6 +617,7 @@ namespace Conformance {
break; break;
} }
_unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
} }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
...@@ -600,7 +626,7 @@ namespace Conformance { ...@@ -600,7 +626,7 @@ namespace Conformance {
while ((tag = input.ReadTag()) != 0) { while ((tag = input.ReadTag()) != 0) {
switch(tag) { switch(tag) {
default: default:
input.SkipLastField(); _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
break; break;
case 10: { case 10: {
ParseError = input.ReadString(); ParseError = input.ReadString();
......
...@@ -540,6 +540,49 @@ namespace Google.Protobuf.Collections ...@@ -540,6 +540,49 @@ namespace Google.Protobuf.Collections
Assert.Throws<ArgumentException>(() => map.ToString()); Assert.Throws<ArgumentException>(() => map.ToString());
} }
[Test]
public void NaNValuesComparedBitwise()
{
var map1 = new MapField<string, double>
{
{ "x", SampleNaNs.Regular },
{ "y", SampleNaNs.SignallingFlipped }
};
var map2 = new MapField<string, double>
{
{ "x", SampleNaNs.Regular },
{ "y", SampleNaNs.PayloadFlipped }
};
var map3 = new MapField<string, double>
{
{ "x", SampleNaNs.Regular },
{ "y", SampleNaNs.SignallingFlipped }
};
EqualityTester.AssertInequality(map1, map2);
EqualityTester.AssertEquality(map1, map3);
Assert.True(map1.Values.Contains(SampleNaNs.SignallingFlipped));
Assert.False(map2.Values.Contains(SampleNaNs.SignallingFlipped));
}
// This wouldn't usually happen, as protos can't use doubles as map keys,
// but let's be consistent.
[Test]
public void NaNKeysComparedBitwise()
{
var map = new MapField<double, string>
{
{ SampleNaNs.Regular, "x" },
{ SampleNaNs.SignallingFlipped, "y" }
};
Assert.AreEqual("x", map[SampleNaNs.Regular]);
Assert.AreEqual("y", map[SampleNaNs.SignallingFlipped]);
string ignored;
Assert.False(map.TryGetValue(SampleNaNs.PayloadFlipped, out ignored));
}
#if !NET35 #if !NET35
[Test] [Test]
public void IDictionaryKeys_Equals_IReadOnlyDictionaryKeys() public void IDictionaryKeys_Equals_IReadOnlyDictionaryKeys()
......
#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]);
}
}
}
}
}
}
...@@ -742,5 +742,18 @@ namespace Google.Protobuf.Collections ...@@ -742,5 +742,18 @@ namespace Google.Protobuf.Collections
var text = list.ToString(); var text = list.ToString();
Assert.AreEqual(text, "[ { \"foo\": 20 } ]", message.ToString()); Assert.AreEqual(text, "[ { \"foo\": 20 } ]", message.ToString());
} }
[Test]
public void NaNValuesComparedBitwise()
{
var list1 = new RepeatedField<double> { SampleNaNs.Regular, SampleNaNs.SignallingFlipped };
var list2 = new RepeatedField<double> { SampleNaNs.Regular, SampleNaNs.PayloadFlipped };
var list3 = new RepeatedField<double> { SampleNaNs.Regular, SampleNaNs.SignallingFlipped };
EqualityTester.AssertInequality(list1, list2);
EqualityTester.AssertEquality(list1, list3);
Assert.True(list1.Contains(SampleNaNs.SignallingFlipped));
Assert.False(list2.Contains(SampleNaNs.SignallingFlipped));
}
} }
} }
...@@ -638,7 +638,7 @@ namespace Google.Protobuf ...@@ -638,7 +638,7 @@ namespace Google.Protobuf
} }
[Test] [Test]
public void IgnoreUnknownFields_RealDataStillRead() public void DiscardUnknownFields_RealDataStillRead()
{ {
var message = SampleMessages.CreateFullTestAllTypes(); var message = SampleMessages.CreateFullTestAllTypes();
var stream = new MemoryStream(); var stream = new MemoryStream();
...@@ -652,16 +652,18 @@ namespace Google.Protobuf ...@@ -652,16 +652,18 @@ namespace Google.Protobuf
stream.Position = 0; stream.Position = 0;
var parsed = TestAllTypes.Parser.ParseFrom(stream); var parsed = TestAllTypes.Parser.ParseFrom(stream);
Assert.AreEqual(message, parsed); // TODO(jieluo): Add test back when DiscardUnknownFields API is supported.
// Assert.AreEqual(message, parsed);
} }
[Test] [Test]
public void IgnoreUnknownFields_AllTypes() public void DiscardUnknownFields_AllTypes()
{ {
// Simple way of ensuring we can skip all kinds of fields. // Simple way of ensuring we can skip all kinds of fields.
var data = SampleMessages.CreateFullTestAllTypes().ToByteArray(); var data = SampleMessages.CreateFullTestAllTypes().ToByteArray();
var empty = Empty.Parser.ParseFrom(data); var empty = Empty.Parser.ParseFrom(data);
Assert.AreEqual(new Empty(), empty); // TODO(jieluo): Add test back when DiscardUnknownFields API is supported.
// Assert.AreNotEqual(new Empty(), empty);
} }
// This was originally seen as a conformance test failure. // This was originally seen as a conformance test failure.
...@@ -719,5 +721,16 @@ namespace Google.Protobuf ...@@ -719,5 +721,16 @@ namespace Google.Protobuf
JsonFormatter.Default.Format(message, writer); JsonFormatter.Default.Format(message, writer);
Assert.AreEqual("{ \"c\": 31 }", writer.ToString()); Assert.AreEqual("{ \"c\": 31 }", writer.ToString());
} }
[Test]
public void NaNComparisons()
{
var message1 = new TestAllTypes { SingleDouble = SampleNaNs.Regular };
var message2 = new TestAllTypes { SingleDouble = SampleNaNs.PayloadFlipped };
var message3 = new TestAllTypes { SingleDouble = SampleNaNs.Regular };
EqualityTester.AssertInequality(message1, message2);
EqualityTester.AssertEquality(message1, message3);
}
} }
} }
\ No newline at end of file
...@@ -514,7 +514,7 @@ namespace Google.Protobuf ...@@ -514,7 +514,7 @@ namespace Google.Protobuf
var formatter = new JsonFormatter(JsonFormatter.Settings.Default.WithTypeRegistry(TypeRegistry.FromMessages(TestAllTypes.Descriptor))); var formatter = new JsonFormatter(JsonFormatter.Settings.Default.WithTypeRegistry(TypeRegistry.FromMessages(TestAllTypes.Descriptor)));
var message = new TestAllTypes { SingleInt32 = 10, SingleNestedMessage = new TestAllTypes.Types.NestedMessage { Bb = 20 } }; var message = new TestAllTypes { SingleInt32 = 10, SingleNestedMessage = new TestAllTypes.Types.NestedMessage { Bb = 20 } };
var any = Any.Pack(message); var any = Any.Pack(message);
AssertJson("{ '@type': 'type.googleapis.com/protobuf_unittest.TestAllTypes', 'singleInt32': 10, 'singleNestedMessage': { 'bb': 20 } }", formatter.Format(any)); AssertJson("{ '@type': 'type.googleapis.com/protobuf_unittest3.TestAllTypes', 'singleInt32': 10, 'singleNestedMessage': { 'bb': 20 } }", formatter.Format(any));
} }
[Test] [Test]
...@@ -523,7 +523,7 @@ namespace Google.Protobuf ...@@ -523,7 +523,7 @@ namespace Google.Protobuf
var formatter = new JsonFormatter(JsonFormatter.Settings.Default.WithTypeRegistry(TypeRegistry.FromMessages(TestAllTypes.Descriptor))); var formatter = new JsonFormatter(JsonFormatter.Settings.Default.WithTypeRegistry(TypeRegistry.FromMessages(TestAllTypes.Descriptor)));
var message = new TestAllTypes { SingleInt32 = 10 }; var message = new TestAllTypes { SingleInt32 = 10 };
var any = Any.Pack(message, "foo.bar/baz"); var any = Any.Pack(message, "foo.bar/baz");
AssertJson("{ '@type': 'foo.bar/baz/protobuf_unittest.TestAllTypes', 'singleInt32': 10 }", formatter.Format(any)); AssertJson("{ '@type': 'foo.bar/baz/protobuf_unittest3.TestAllTypes', 'singleInt32': 10 }", formatter.Format(any));
} }
[Test] [Test]
...@@ -536,7 +536,7 @@ namespace Google.Protobuf ...@@ -536,7 +536,7 @@ namespace Google.Protobuf
var doubleNestedMessage = new TestAllTypes { SingleInt32 = 20 }; var doubleNestedMessage = new TestAllTypes { SingleInt32 = 20 };
var nestedMessage = Any.Pack(doubleNestedMessage); var nestedMessage = Any.Pack(doubleNestedMessage);
var message = new TestWellKnownTypes { AnyField = Any.Pack(nestedMessage) }; var message = new TestWellKnownTypes { AnyField = Any.Pack(nestedMessage) };
AssertJson("{ 'anyField': { '@type': 'type.googleapis.com/google.protobuf.Any', 'value': { '@type': 'type.googleapis.com/protobuf_unittest.TestAllTypes', 'singleInt32': 20 } } }", AssertJson("{ 'anyField': { '@type': 'type.googleapis.com/google.protobuf.Any', 'value': { '@type': 'type.googleapis.com/protobuf_unittest3.TestAllTypes', 'singleInt32': 20 } } }",
formatter.Format(message)); formatter.Format(message));
} }
......
...@@ -809,7 +809,7 @@ namespace Google.Protobuf ...@@ -809,7 +809,7 @@ namespace Google.Protobuf
var json = formatter.Format(original); // This is tested in JsonFormatterTest var json = formatter.Format(original); // This is tested in JsonFormatterTest
var parser = new JsonParser(new JsonParser.Settings(10, registry)); var parser = new JsonParser(new JsonParser.Settings(10, registry));
Assert.AreEqual(original, parser.Parse<Any>(json)); Assert.AreEqual(original, parser.Parse<Any>(json));
string valueFirstJson = "{ \"singleInt32\": 10, \"singleNestedMessage\": { \"bb\": 20 }, \"@type\": \"type.googleapis.com/protobuf_unittest.TestAllTypes\" }"; string valueFirstJson = "{ \"singleInt32\": 10, \"singleNestedMessage\": { \"bb\": 20 }, \"@type\": \"type.googleapis.com/protobuf_unittest3.TestAllTypes\" }";
Assert.AreEqual(original, parser.Parse<Any>(valueFirstJson)); Assert.AreEqual(original, parser.Parse<Any>(valueFirstJson));
} }
...@@ -820,7 +820,7 @@ namespace Google.Protobuf ...@@ -820,7 +820,7 @@ namespace Google.Protobuf
var message = new TestAllTypes { SingleInt32 = 10 }; var message = new TestAllTypes { SingleInt32 = 10 };
var original = Any.Pack(message, "custom.prefix/middle-part"); var original = Any.Pack(message, "custom.prefix/middle-part");
var parser = new JsonParser(new JsonParser.Settings(10, registry)); var parser = new JsonParser(new JsonParser.Settings(10, registry));
string json = "{ \"@type\": \"custom.prefix/middle-part/protobuf_unittest.TestAllTypes\", \"singleInt32\": 10 }"; string json = "{ \"@type\": \"custom.prefix/middle-part/protobuf_unittest3.TestAllTypes\", \"singleInt32\": 10 }";
Assert.AreEqual(original, parser.Parse<Any>(json)); Assert.AreEqual(original, parser.Parse<Any>(json));
} }
......
...@@ -48,13 +48,13 @@ namespace Google.Protobuf.Reflection ...@@ -48,13 +48,13 @@ namespace Google.Protobuf.Reflection
{ {
FileDescriptor file = UnittestProto3Reflection.Descriptor; FileDescriptor file = UnittestProto3Reflection.Descriptor;
Assert.AreEqual("google/protobuf/unittest_proto3.proto", file.Name); Assert.AreEqual("unittest_proto3.proto", file.Name);
Assert.AreEqual("protobuf_unittest", file.Package); Assert.AreEqual("protobuf_unittest3", file.Package);
Assert.AreEqual("UnittestProto", file.Proto.Options.JavaOuterClassname); Assert.AreEqual("UnittestProto", file.Proto.Options.JavaOuterClassname);
Assert.AreEqual("google/protobuf/unittest_proto3.proto", file.Proto.Name); Assert.AreEqual("unittest_proto3.proto", file.Proto.Name);
// unittest.proto doesn't have any public imports, but unittest_import.proto does. // unittest_proto3.proto doesn't have any public imports, but unittest_import_proto3.proto does.
Assert.AreEqual(0, file.PublicDependencies.Count); Assert.AreEqual(0, file.PublicDependencies.Count);
Assert.AreEqual(1, UnittestImportProto3Reflection.Descriptor.PublicDependencies.Count); Assert.AreEqual(1, UnittestImportProto3Reflection.Descriptor.PublicDependencies.Count);
Assert.AreEqual(UnittestImportPublicProto3Reflection.Descriptor, UnittestImportProto3Reflection.Descriptor.PublicDependencies[0]); Assert.AreEqual(UnittestImportPublicProto3Reflection.Descriptor, UnittestImportProto3Reflection.Descriptor.PublicDependencies[0]);
...@@ -68,7 +68,7 @@ namespace Google.Protobuf.Reflection ...@@ -68,7 +68,7 @@ namespace Google.Protobuf.Reflection
Assert.AreEqual(messageType, file.MessageTypes[0]); Assert.AreEqual(messageType, file.MessageTypes[0]);
Assert.AreEqual(messageType, file.FindTypeByName<MessageDescriptor>("TestAllTypes")); Assert.AreEqual(messageType, file.FindTypeByName<MessageDescriptor>("TestAllTypes"));
Assert.Null(file.FindTypeByName<MessageDescriptor>("NoSuchType")); Assert.Null(file.FindTypeByName<MessageDescriptor>("NoSuchType"));
Assert.Null(file.FindTypeByName<MessageDescriptor>("protobuf_unittest.TestAllTypes")); Assert.Null(file.FindTypeByName<MessageDescriptor>("protobuf_unittest3.TestAllTypes"));
for (int i = 0; i < file.MessageTypes.Count; i++) for (int i = 0; i < file.MessageTypes.Count; i++)
{ {
Assert.AreEqual(i, file.MessageTypes[i].Index); Assert.AreEqual(i, file.MessageTypes[i].Index);
...@@ -76,7 +76,7 @@ namespace Google.Protobuf.Reflection ...@@ -76,7 +76,7 @@ namespace Google.Protobuf.Reflection
Assert.AreEqual(file.EnumTypes[0], file.FindTypeByName<EnumDescriptor>("ForeignEnum")); Assert.AreEqual(file.EnumTypes[0], file.FindTypeByName<EnumDescriptor>("ForeignEnum"));
Assert.Null(file.FindTypeByName<EnumDescriptor>("NoSuchType")); Assert.Null(file.FindTypeByName<EnumDescriptor>("NoSuchType"));
Assert.Null(file.FindTypeByName<EnumDescriptor>("protobuf_unittest.ForeignEnum")); Assert.Null(file.FindTypeByName<EnumDescriptor>("protobuf_unittest3.ForeignEnum"));
Assert.AreEqual(1, UnittestImportProto3Reflection.Descriptor.EnumTypes.Count); Assert.AreEqual(1, UnittestImportProto3Reflection.Descriptor.EnumTypes.Count);
Assert.AreEqual("ImportEnum", UnittestImportProto3Reflection.Descriptor.EnumTypes[0].Name); Assert.AreEqual("ImportEnum", UnittestImportProto3Reflection.Descriptor.EnumTypes[0].Name);
for (int i = 0; i < file.EnumTypes.Count; i++) for (int i = 0; i < file.EnumTypes.Count; i++)
...@@ -87,6 +87,16 @@ namespace Google.Protobuf.Reflection ...@@ -87,6 +87,16 @@ namespace Google.Protobuf.Reflection
Assert.AreEqual(10, file.SerializedData[0]); Assert.AreEqual(10, file.SerializedData[0]);
} }
[Test]
public void FileDescriptor_NonRootPath()
{
// unittest_proto3.proto used to be in google/protobuf. Now it's in the C#-specific location,
// let's test something that's still in a directory.
FileDescriptor file = UnittestWellKnownTypesReflection.Descriptor;
Assert.AreEqual("google/protobuf/unittest_well_known_types.proto", file.Name);
Assert.AreEqual("protobuf_unittest", file.Package);
}
[Test] [Test]
public void MessageDescriptor() public void MessageDescriptor()
{ {
...@@ -94,7 +104,7 @@ namespace Google.Protobuf.Reflection ...@@ -94,7 +104,7 @@ namespace Google.Protobuf.Reflection
MessageDescriptor nestedType = TestAllTypes.Types.NestedMessage.Descriptor; MessageDescriptor nestedType = TestAllTypes.Types.NestedMessage.Descriptor;
Assert.AreEqual("TestAllTypes", messageType.Name); Assert.AreEqual("TestAllTypes", messageType.Name);
Assert.AreEqual("protobuf_unittest.TestAllTypes", messageType.FullName); Assert.AreEqual("protobuf_unittest3.TestAllTypes", messageType.FullName);
Assert.AreEqual(UnittestProto3Reflection.Descriptor, messageType.File); Assert.AreEqual(UnittestProto3Reflection.Descriptor, messageType.File);
Assert.IsNull(messageType.ContainingType); Assert.IsNull(messageType.ContainingType);
Assert.IsNull(messageType.Proto.Options); Assert.IsNull(messageType.Proto.Options);
...@@ -102,7 +112,7 @@ namespace Google.Protobuf.Reflection ...@@ -102,7 +112,7 @@ namespace Google.Protobuf.Reflection
Assert.AreEqual("TestAllTypes", messageType.Name); Assert.AreEqual("TestAllTypes", messageType.Name);
Assert.AreEqual("NestedMessage", nestedType.Name); Assert.AreEqual("NestedMessage", nestedType.Name);
Assert.AreEqual("protobuf_unittest.TestAllTypes.NestedMessage", nestedType.FullName); Assert.AreEqual("protobuf_unittest3.TestAllTypes.NestedMessage", nestedType.FullName);
Assert.AreEqual(UnittestProto3Reflection.Descriptor, nestedType.File); Assert.AreEqual(UnittestProto3Reflection.Descriptor, nestedType.File);
Assert.AreEqual(messageType, nestedType.ContainingType); Assert.AreEqual(messageType, nestedType.ContainingType);
...@@ -143,7 +153,7 @@ namespace Google.Protobuf.Reflection ...@@ -143,7 +153,7 @@ namespace Google.Protobuf.Reflection
FieldDescriptor messageField = messageType.FindDescriptor<FieldDescriptor>("single_foreign_message"); FieldDescriptor messageField = messageType.FindDescriptor<FieldDescriptor>("single_foreign_message");
Assert.AreEqual("single_int32", primitiveField.Name); Assert.AreEqual("single_int32", primitiveField.Name);
Assert.AreEqual("protobuf_unittest.TestAllTypes.single_int32", Assert.AreEqual("protobuf_unittest3.TestAllTypes.single_int32",
primitiveField.FullName); primitiveField.FullName);
Assert.AreEqual(1, primitiveField.FieldNumber); Assert.AreEqual(1, primitiveField.FieldNumber);
Assert.AreEqual(messageType, primitiveField.ContainingType); Assert.AreEqual(messageType, primitiveField.ContainingType);
...@@ -180,13 +190,13 @@ namespace Google.Protobuf.Reflection ...@@ -180,13 +190,13 @@ namespace Google.Protobuf.Reflection
EnumDescriptor nestedType = TestAllTypes.Descriptor.FindDescriptor<EnumDescriptor>("NestedEnum"); EnumDescriptor nestedType = TestAllTypes.Descriptor.FindDescriptor<EnumDescriptor>("NestedEnum");
Assert.AreEqual("ForeignEnum", enumType.Name); Assert.AreEqual("ForeignEnum", enumType.Name);
Assert.AreEqual("protobuf_unittest.ForeignEnum", enumType.FullName); Assert.AreEqual("protobuf_unittest3.ForeignEnum", enumType.FullName);
Assert.AreEqual(UnittestProto3Reflection.Descriptor, enumType.File); Assert.AreEqual(UnittestProto3Reflection.Descriptor, enumType.File);
Assert.Null(enumType.ContainingType); Assert.Null(enumType.ContainingType);
Assert.Null(enumType.Proto.Options); Assert.Null(enumType.Proto.Options);
Assert.AreEqual("NestedEnum", nestedType.Name); Assert.AreEqual("NestedEnum", nestedType.Name);
Assert.AreEqual("protobuf_unittest.TestAllTypes.NestedEnum", Assert.AreEqual("protobuf_unittest3.TestAllTypes.NestedEnum",
nestedType.FullName); nestedType.FullName);
Assert.AreEqual(UnittestProto3Reflection.Descriptor, nestedType.File); Assert.AreEqual(UnittestProto3Reflection.Descriptor, nestedType.File);
Assert.AreEqual(TestAllTypes.Descriptor, nestedType.ContainingType); Assert.AreEqual(TestAllTypes.Descriptor, nestedType.ContainingType);
...@@ -209,7 +219,7 @@ namespace Google.Protobuf.Reflection ...@@ -209,7 +219,7 @@ namespace Google.Protobuf.Reflection
{ {
OneofDescriptor descriptor = TestAllTypes.Descriptor.FindDescriptor<OneofDescriptor>("oneof_field"); OneofDescriptor descriptor = TestAllTypes.Descriptor.FindDescriptor<OneofDescriptor>("oneof_field");
Assert.AreEqual("oneof_field", descriptor.Name); Assert.AreEqual("oneof_field", descriptor.Name);
Assert.AreEqual("protobuf_unittest.TestAllTypes.oneof_field", descriptor.FullName); Assert.AreEqual("protobuf_unittest3.TestAllTypes.oneof_field", descriptor.FullName);
var expectedFields = new[] { var expectedFields = new[] {
TestAllTypes.OneofBytesFieldNumber, TestAllTypes.OneofBytesFieldNumber,
......
#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);
}
}
// <auto-generated>
// Generated by the protocol buffer compiler. DO NOT EDIT! // Generated by the protocol buffer compiler. DO NOT EDIT!
// source: google/protobuf/unittest_import_proto3.proto // source: unittest_import_proto3.proto
// </auto-generated>
#pragma warning disable 1591, 0612, 3021 #pragma warning disable 1591, 0612, 3021
#region Designer generated code #region Designer generated code
...@@ -9,11 +11,11 @@ using pbr = global::Google.Protobuf.Reflection; ...@@ -9,11 +11,11 @@ using pbr = global::Google.Protobuf.Reflection;
using scg = global::System.Collections.Generic; using scg = global::System.Collections.Generic;
namespace Google.Protobuf.TestProtos { namespace Google.Protobuf.TestProtos {
/// <summary>Holder for reflection information generated from google/protobuf/unittest_import_proto3.proto</summary> /// <summary>Holder for reflection information generated from unittest_import_proto3.proto</summary>
public static partial class UnittestImportProto3Reflection { public static partial class UnittestImportProto3Reflection {
#region Descriptor #region Descriptor
/// <summary>File descriptor for google/protobuf/unittest_import_proto3.proto</summary> /// <summary>File descriptor for unittest_import_proto3.proto</summary>
public static pbr::FileDescriptor Descriptor { public static pbr::FileDescriptor Descriptor {
get { return descriptor; } get { return descriptor; }
} }
...@@ -22,14 +24,12 @@ namespace Google.Protobuf.TestProtos { ...@@ -22,14 +24,12 @@ namespace Google.Protobuf.TestProtos {
static UnittestImportProto3Reflection() { static UnittestImportProto3Reflection() {
byte[] descriptorData = global::System.Convert.FromBase64String( byte[] descriptorData = global::System.Convert.FromBase64String(
string.Concat( string.Concat(
"Cixnb29nbGUvcHJvdG9idWYvdW5pdHRlc3RfaW1wb3J0X3Byb3RvMy5wcm90", "Chx1bml0dGVzdF9pbXBvcnRfcHJvdG8zLnByb3RvEhhwcm90b2J1Zl91bml0",
"bxIYcHJvdG9idWZfdW5pdHRlc3RfaW1wb3J0GjNnb29nbGUvcHJvdG9idWYv", "dGVzdF9pbXBvcnQaI3VuaXR0ZXN0X2ltcG9ydF9wdWJsaWNfcHJvdG8zLnBy",
"dW5pdHRlc3RfaW1wb3J0X3B1YmxpY19wcm90bzMucHJvdG8iGgoNSW1wb3J0", "b3RvIhoKDUltcG9ydE1lc3NhZ2USCQoBZBgBIAEoBSpZCgpJbXBvcnRFbnVt",
"TWVzc2FnZRIJCgFkGAEgASgFKlkKCkltcG9ydEVudW0SGwoXSU1QT1JUX0VO", "EhsKF0lNUE9SVF9FTlVNX1VOU1BFQ0lGSUVEEAASDgoKSU1QT1JUX0ZPTxAH",
"VU1fVU5TUEVDSUZJRUQQABIOCgpJTVBPUlRfRk9PEAcSDgoKSU1QT1JUX0JB", "Eg4KCklNUE9SVF9CQVIQCBIOCgpJTVBPUlRfQkFaEAlCHaoCGkdvb2dsZS5Q",
"UhAIEg4KCklNUE9SVF9CQVoQCUI8Chhjb20uZ29vZ2xlLnByb3RvYnVmLnRl", "cm90b2J1Zi5UZXN0UHJvdG9zUABiBnByb3RvMw=="));
"c3RIAfgBAaoCGkdvb2dsZS5Qcm90b2J1Zi5UZXN0UHJvdG9zUABiBnByb3Rv",
"Mw=="));
descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
new pbr::FileDescriptor[] { global::Google.Protobuf.TestProtos.UnittestImportPublicProto3Reflection.Descriptor, }, new pbr::FileDescriptor[] { global::Google.Protobuf.TestProtos.UnittestImportPublicProto3Reflection.Descriptor, },
new pbr::GeneratedClrTypeInfo(new[] {typeof(global::Google.Protobuf.TestProtos.ImportEnum), }, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(new[] {typeof(global::Google.Protobuf.TestProtos.ImportEnum), }, new pbr::GeneratedClrTypeInfo[] {
...@@ -52,6 +52,7 @@ namespace Google.Protobuf.TestProtos { ...@@ -52,6 +52,7 @@ namespace Google.Protobuf.TestProtos {
#region Messages #region Messages
public sealed partial class ImportMessage : pb::IMessage<ImportMessage> { public sealed partial class ImportMessage : pb::IMessage<ImportMessage> {
private static readonly pb::MessageParser<ImportMessage> _parser = new pb::MessageParser<ImportMessage>(() => new ImportMessage()); private static readonly pb::MessageParser<ImportMessage> _parser = new pb::MessageParser<ImportMessage>(() => new ImportMessage());
private pb::UnknownFieldSet _unknownFields;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pb::MessageParser<ImportMessage> Parser { get { return _parser; } } public static pb::MessageParser<ImportMessage> Parser { get { return _parser; } }
...@@ -75,6 +76,7 @@ namespace Google.Protobuf.TestProtos { ...@@ -75,6 +76,7 @@ namespace Google.Protobuf.TestProtos {
[global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public ImportMessage(ImportMessage other) : this() { public ImportMessage(ImportMessage other) : this() {
d_ = other.d_; d_ = other.d_;
_unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
} }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
...@@ -107,13 +109,16 @@ namespace Google.Protobuf.TestProtos { ...@@ -107,13 +109,16 @@ namespace Google.Protobuf.TestProtos {
return true; return true;
} }
if (D != other.D) return false; if (D != other.D) return false;
return true; return Equals(_unknownFields, other._unknownFields);
} }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public override int GetHashCode() { public override int GetHashCode() {
int hash = 1; int hash = 1;
if (D != 0) hash ^= D.GetHashCode(); if (D != 0) hash ^= D.GetHashCode();
if (_unknownFields != null) {
hash ^= _unknownFields.GetHashCode();
}
return hash; return hash;
} }
...@@ -128,6 +133,9 @@ namespace Google.Protobuf.TestProtos { ...@@ -128,6 +133,9 @@ namespace Google.Protobuf.TestProtos {
output.WriteRawTag(8); output.WriteRawTag(8);
output.WriteInt32(D); output.WriteInt32(D);
} }
if (_unknownFields != null) {
_unknownFields.WriteTo(output);
}
} }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
...@@ -136,6 +144,9 @@ namespace Google.Protobuf.TestProtos { ...@@ -136,6 +144,9 @@ namespace Google.Protobuf.TestProtos {
if (D != 0) { if (D != 0) {
size += 1 + pb::CodedOutputStream.ComputeInt32Size(D); size += 1 + pb::CodedOutputStream.ComputeInt32Size(D);
} }
if (_unknownFields != null) {
size += _unknownFields.CalculateSize();
}
return size; return size;
} }
...@@ -147,6 +158,7 @@ namespace Google.Protobuf.TestProtos { ...@@ -147,6 +158,7 @@ namespace Google.Protobuf.TestProtos {
if (other.D != 0) { if (other.D != 0) {
D = other.D; D = other.D;
} }
_unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
} }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
...@@ -155,7 +167,7 @@ namespace Google.Protobuf.TestProtos { ...@@ -155,7 +167,7 @@ namespace Google.Protobuf.TestProtos {
while ((tag = input.ReadTag()) != 0) { while ((tag = input.ReadTag()) != 0) {
switch(tag) { switch(tag) {
default: default:
input.SkipLastField(); _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
break; break;
case 8: { case 8: {
D = input.ReadInt32(); D = input.ReadInt32();
......
// <auto-generated>
// Generated by the protocol buffer compiler. DO NOT EDIT! // Generated by the protocol buffer compiler. DO NOT EDIT!
// source: google/protobuf/unittest_import_public_proto3.proto // source: unittest_import_public_proto3.proto
// </auto-generated>
#pragma warning disable 1591, 0612, 3021 #pragma warning disable 1591, 0612, 3021
#region Designer generated code #region Designer generated code
...@@ -9,11 +11,11 @@ using pbr = global::Google.Protobuf.Reflection; ...@@ -9,11 +11,11 @@ using pbr = global::Google.Protobuf.Reflection;
using scg = global::System.Collections.Generic; using scg = global::System.Collections.Generic;
namespace Google.Protobuf.TestProtos { namespace Google.Protobuf.TestProtos {
/// <summary>Holder for reflection information generated from google/protobuf/unittest_import_public_proto3.proto</summary> /// <summary>Holder for reflection information generated from unittest_import_public_proto3.proto</summary>
public static partial class UnittestImportPublicProto3Reflection { public static partial class UnittestImportPublicProto3Reflection {
#region Descriptor #region Descriptor
/// <summary>File descriptor for google/protobuf/unittest_import_public_proto3.proto</summary> /// <summary>File descriptor for unittest_import_public_proto3.proto</summary>
public static pbr::FileDescriptor Descriptor { public static pbr::FileDescriptor Descriptor {
get { return descriptor; } get { return descriptor; }
} }
...@@ -22,10 +24,10 @@ namespace Google.Protobuf.TestProtos { ...@@ -22,10 +24,10 @@ namespace Google.Protobuf.TestProtos {
static UnittestImportPublicProto3Reflection() { static UnittestImportPublicProto3Reflection() {
byte[] descriptorData = global::System.Convert.FromBase64String( byte[] descriptorData = global::System.Convert.FromBase64String(
string.Concat( string.Concat(
"CjNnb29nbGUvcHJvdG9idWYvdW5pdHRlc3RfaW1wb3J0X3B1YmxpY19wcm90", "CiN1bml0dGVzdF9pbXBvcnRfcHVibGljX3Byb3RvMy5wcm90bxIYcHJvdG9i",
"bzMucHJvdG8SGHByb3RvYnVmX3VuaXR0ZXN0X2ltcG9ydCIgChNQdWJsaWNJ", "dWZfdW5pdHRlc3RfaW1wb3J0IiAKE1B1YmxpY0ltcG9ydE1lc3NhZ2USCQoB",
"bXBvcnRNZXNzYWdlEgkKAWUYASABKAVCNwoYY29tLmdvb2dsZS5wcm90b2J1", "ZRgBIAEoBUIdqgIaR29vZ2xlLlByb3RvYnVmLlRlc3RQcm90b3NiBnByb3Rv",
"Zi50ZXN0qgIaR29vZ2xlLlByb3RvYnVmLlRlc3RQcm90b3NiBnByb3RvMw==")); "Mw=="));
descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
new pbr::FileDescriptor[] { }, new pbr::FileDescriptor[] { },
new pbr::GeneratedClrTypeInfo(null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(null, new pbr::GeneratedClrTypeInfo[] {
...@@ -38,6 +40,7 @@ namespace Google.Protobuf.TestProtos { ...@@ -38,6 +40,7 @@ namespace Google.Protobuf.TestProtos {
#region Messages #region Messages
public sealed partial class PublicImportMessage : pb::IMessage<PublicImportMessage> { public sealed partial class PublicImportMessage : pb::IMessage<PublicImportMessage> {
private static readonly pb::MessageParser<PublicImportMessage> _parser = new pb::MessageParser<PublicImportMessage>(() => new PublicImportMessage()); private static readonly pb::MessageParser<PublicImportMessage> _parser = new pb::MessageParser<PublicImportMessage>(() => new PublicImportMessage());
private pb::UnknownFieldSet _unknownFields;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pb::MessageParser<PublicImportMessage> Parser { get { return _parser; } } public static pb::MessageParser<PublicImportMessage> Parser { get { return _parser; } }
...@@ -61,6 +64,7 @@ namespace Google.Protobuf.TestProtos { ...@@ -61,6 +64,7 @@ namespace Google.Protobuf.TestProtos {
[global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public PublicImportMessage(PublicImportMessage other) : this() { public PublicImportMessage(PublicImportMessage other) : this() {
e_ = other.e_; e_ = other.e_;
_unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
} }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
...@@ -93,13 +97,16 @@ namespace Google.Protobuf.TestProtos { ...@@ -93,13 +97,16 @@ namespace Google.Protobuf.TestProtos {
return true; return true;
} }
if (E != other.E) return false; if (E != other.E) return false;
return true; return Equals(_unknownFields, other._unknownFields);
} }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public override int GetHashCode() { public override int GetHashCode() {
int hash = 1; int hash = 1;
if (E != 0) hash ^= E.GetHashCode(); if (E != 0) hash ^= E.GetHashCode();
if (_unknownFields != null) {
hash ^= _unknownFields.GetHashCode();
}
return hash; return hash;
} }
...@@ -114,6 +121,9 @@ namespace Google.Protobuf.TestProtos { ...@@ -114,6 +121,9 @@ namespace Google.Protobuf.TestProtos {
output.WriteRawTag(8); output.WriteRawTag(8);
output.WriteInt32(E); output.WriteInt32(E);
} }
if (_unknownFields != null) {
_unknownFields.WriteTo(output);
}
} }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
...@@ -122,6 +132,9 @@ namespace Google.Protobuf.TestProtos { ...@@ -122,6 +132,9 @@ namespace Google.Protobuf.TestProtos {
if (E != 0) { if (E != 0) {
size += 1 + pb::CodedOutputStream.ComputeInt32Size(E); size += 1 + pb::CodedOutputStream.ComputeInt32Size(E);
} }
if (_unknownFields != null) {
size += _unknownFields.CalculateSize();
}
return size; return size;
} }
...@@ -133,6 +146,7 @@ namespace Google.Protobuf.TestProtos { ...@@ -133,6 +146,7 @@ namespace Google.Protobuf.TestProtos {
if (other.E != 0) { if (other.E != 0) {
E = other.E; E = other.E;
} }
_unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
} }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
...@@ -141,7 +155,7 @@ namespace Google.Protobuf.TestProtos { ...@@ -141,7 +155,7 @@ namespace Google.Protobuf.TestProtos {
while ((tag = input.ReadTag()) != 0) { while ((tag = input.ReadTag()) != 0) {
switch(tag) { switch(tag) {
default: default:
input.SkipLastField(); _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
break; break;
case 8: { case 8: {
E = input.ReadInt32(); E = input.ReadInt32();
......
This diff is collapsed.
...@@ -42,7 +42,7 @@ namespace Google.Protobuf.WellKnownTypes ...@@ -42,7 +42,7 @@ namespace Google.Protobuf.WellKnownTypes
{ {
var message = SampleMessages.CreateFullTestAllTypes(); var message = SampleMessages.CreateFullTestAllTypes();
var any = Any.Pack(message); var any = Any.Pack(message);
Assert.AreEqual("type.googleapis.com/protobuf_unittest.TestAllTypes", any.TypeUrl); Assert.AreEqual("type.googleapis.com/protobuf_unittest3.TestAllTypes", any.TypeUrl);
Assert.AreEqual(message.CalculateSize(), any.Value.Length); Assert.AreEqual(message.CalculateSize(), any.Value.Length);
} }
...@@ -51,7 +51,7 @@ namespace Google.Protobuf.WellKnownTypes ...@@ -51,7 +51,7 @@ namespace Google.Protobuf.WellKnownTypes
{ {
var message = SampleMessages.CreateFullTestAllTypes(); var message = SampleMessages.CreateFullTestAllTypes();
var any = Any.Pack(message, "foo.bar/baz"); var any = Any.Pack(message, "foo.bar/baz");
Assert.AreEqual("foo.bar/baz/protobuf_unittest.TestAllTypes", any.TypeUrl); Assert.AreEqual("foo.bar/baz/protobuf_unittest3.TestAllTypes", any.TypeUrl);
Assert.AreEqual(message.CalculateSize(), any.Value.Length); Assert.AreEqual(message.CalculateSize(), any.Value.Length);
} }
...@@ -60,7 +60,7 @@ namespace Google.Protobuf.WellKnownTypes ...@@ -60,7 +60,7 @@ namespace Google.Protobuf.WellKnownTypes
{ {
var message = SampleMessages.CreateFullTestAllTypes(); var message = SampleMessages.CreateFullTestAllTypes();
var any = Any.Pack(message, "foo.bar/baz/"); var any = Any.Pack(message, "foo.bar/baz/");
Assert.AreEqual("foo.bar/baz/protobuf_unittest.TestAllTypes", any.TypeUrl); Assert.AreEqual("foo.bar/baz/protobuf_unittest3.TestAllTypes", any.TypeUrl);
Assert.AreEqual(message.CalculateSize(), any.Value.Length); Assert.AreEqual(message.CalculateSize(), any.Value.Length);
} }
......
...@@ -417,5 +417,16 @@ namespace Google.Protobuf.WellKnownTypes ...@@ -417,5 +417,16 @@ namespace Google.Protobuf.WellKnownTypes
TestWellKnownTypes.Descriptor.Fields[TestWellKnownTypes.StringFieldFieldNumber].Accessor.Clear(message); TestWellKnownTypes.Descriptor.Fields[TestWellKnownTypes.StringFieldFieldNumber].Accessor.Clear(message);
Assert.IsNull(message.StringField); Assert.IsNull(message.StringField);
} }
[Test]
public void NaNComparisons()
{
var message1 = new TestWellKnownTypes { DoubleField = SampleNaNs.Regular };
var message2 = new TestWellKnownTypes { DoubleField = SampleNaNs.PayloadFlipped };
var message3 = new TestWellKnownTypes { DoubleField = SampleNaNs.Regular };
EqualityTester.AssertInequality(message1, message2);
EqualityTester.AssertEquality(message1, message3);
}
} }
} }
...@@ -424,7 +424,10 @@ namespace Google.Protobuf ...@@ -424,7 +424,10 @@ namespace Google.Protobuf
} }
} }
private void SkipGroup(uint startGroupTag) /// <summary>
/// Skip a group.
/// </summary>
internal void SkipGroup(uint startGroupTag)
{ {
// Note: Currently we expect this to be the way that groups are read. We could put the recursion // Note: Currently we expect this to be the way that groups are read. We could put the recursion
// depth changes into the ReadTag method instead, potentially... // depth changes into the ReadTag method instead, potentially...
...@@ -1270,7 +1273,6 @@ namespace Google.Protobuf ...@@ -1270,7 +1273,6 @@ namespace Google.Protobuf
} }
} }
} }
#endregion #endregion
} }
} }
\ No newline at end of file
This diff is collapsed.
...@@ -71,9 +71,12 @@ namespace Google.Protobuf.Collections ...@@ -71,9 +71,12 @@ namespace Google.Protobuf.Collections
, IReadOnlyDictionary<TKey, TValue> , IReadOnlyDictionary<TKey, TValue>
#endif #endif
{ {
private static readonly EqualityComparer<TValue> ValueEqualityComparer = ProtobufEqualityComparers.GetEqualityComparer<TValue>();
private static readonly EqualityComparer<TKey> KeyEqualityComparer = ProtobufEqualityComparers.GetEqualityComparer<TKey>();
// TODO: Don't create the map/list until we have an entry. (Assume many maps will be empty.) // TODO: Don't create the map/list until we have an entry. (Assume many maps will be empty.)
private readonly Dictionary<TKey, LinkedListNode<KeyValuePair<TKey, TValue>>> map = private readonly Dictionary<TKey, LinkedListNode<KeyValuePair<TKey, TValue>>> map =
new Dictionary<TKey, LinkedListNode<KeyValuePair<TKey, TValue>>>(); new Dictionary<TKey, LinkedListNode<KeyValuePair<TKey, TValue>>>(KeyEqualityComparer);
private readonly LinkedList<KeyValuePair<TKey, TValue>> list = new LinkedList<KeyValuePair<TKey, TValue>>(); private readonly LinkedList<KeyValuePair<TKey, TValue>> list = new LinkedList<KeyValuePair<TKey, TValue>>();
/// <summary> /// <summary>
...@@ -131,11 +134,8 @@ namespace Google.Protobuf.Collections ...@@ -131,11 +134,8 @@ namespace Google.Protobuf.Collections
return map.ContainsKey(key); return map.ContainsKey(key);
} }
private bool ContainsValue(TValue value) private bool ContainsValue(TValue value) =>
{ list.Any(pair => ValueEqualityComparer.Equals(pair.Value, value));
var comparer = EqualityComparer<TValue>.Default;
return list.Any(pair => comparer.Equals(pair.Value, value));
}
/// <summary> /// <summary>
/// Removes the entry identified by the given key from the map. /// Removes the entry identified by the given key from the map.
...@@ -293,8 +293,7 @@ namespace Google.Protobuf.Collections ...@@ -293,8 +293,7 @@ namespace Google.Protobuf.Collections
bool ICollection<KeyValuePair<TKey, TValue>>.Contains(KeyValuePair<TKey, TValue> item) bool ICollection<KeyValuePair<TKey, TValue>>.Contains(KeyValuePair<TKey, TValue> item)
{ {
TValue value; TValue value;
return TryGetValue(item.Key, out value) return TryGetValue(item.Key, out value) && ValueEqualityComparer.Equals(item.Value, value);
&& EqualityComparer<TValue>.Default.Equals(item.Value, value);
} }
/// <summary> /// <summary>
...@@ -363,11 +362,12 @@ namespace Google.Protobuf.Collections ...@@ -363,11 +362,12 @@ namespace Google.Protobuf.Collections
/// </returns> /// </returns>
public override int GetHashCode() public override int GetHashCode()
{ {
var valueComparer = EqualityComparer<TValue>.Default; var keyComparer = KeyEqualityComparer;
var valueComparer = ValueEqualityComparer;
int hash = 0; int hash = 0;
foreach (var pair in list) foreach (var pair in list)
{ {
hash ^= pair.Key.GetHashCode() * 31 + valueComparer.GetHashCode(pair.Value); hash ^= keyComparer.GetHashCode(pair.Key) * 31 + valueComparer.GetHashCode(pair.Value);
} }
return hash; return hash;
} }
...@@ -394,7 +394,7 @@ namespace Google.Protobuf.Collections ...@@ -394,7 +394,7 @@ namespace Google.Protobuf.Collections
{ {
return false; return false;
} }
var valueComparer = EqualityComparer<TValue>.Default; var valueComparer = ValueEqualityComparer;
foreach (var pair in this) foreach (var pair in this)
{ {
TValue value; TValue value;
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment