Merge pull request #10339 from jskeet/merge-maps

Implement correct map merging behavior for C#
pull/10340/head
Matt Fowles Kulukundis 2 years ago committed by GitHub
commit 7b3e6cb3f2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 74
      csharp/src/Google.Protobuf.Test.TestProtos/MapUnittestProto3.cs
  2. 38
      csharp/src/Google.Protobuf.Test.TestProtos/TestMessagesProto2.cs
  3. 38
      csharp/src/Google.Protobuf.Test.TestProtos/TestMessagesProto3.cs
  4. 4
      csharp/src/Google.Protobuf.Test.TestProtos/Unittest.cs
  5. 36
      csharp/src/Google.Protobuf.Test.TestProtos/UnittestWellKnownTypes.cs
  6. 40
      csharp/src/Google.Protobuf.Test/GeneratedMessageTest.cs
  7. 15
      csharp/src/Google.Protobuf/Collections/MapField.cs
  8. 2
      csharp/src/Google.Protobuf/WellKnownTypes/Struct.cs
  9. 2
      src/google/protobuf/compiler/csharp/csharp_map_field.cc

@ -580,23 +580,23 @@ namespace Google.Protobuf.TestProtos {
if (other == null) {
return;
}
mapInt32Int32_.Add(other.mapInt32Int32_);
mapInt64Int64_.Add(other.mapInt64Int64_);
mapUint32Uint32_.Add(other.mapUint32Uint32_);
mapUint64Uint64_.Add(other.mapUint64Uint64_);
mapSint32Sint32_.Add(other.mapSint32Sint32_);
mapSint64Sint64_.Add(other.mapSint64Sint64_);
mapFixed32Fixed32_.Add(other.mapFixed32Fixed32_);
mapFixed64Fixed64_.Add(other.mapFixed64Fixed64_);
mapSfixed32Sfixed32_.Add(other.mapSfixed32Sfixed32_);
mapSfixed64Sfixed64_.Add(other.mapSfixed64Sfixed64_);
mapInt32Float_.Add(other.mapInt32Float_);
mapInt32Double_.Add(other.mapInt32Double_);
mapBoolBool_.Add(other.mapBoolBool_);
mapStringString_.Add(other.mapStringString_);
mapInt32Bytes_.Add(other.mapInt32Bytes_);
mapInt32Enum_.Add(other.mapInt32Enum_);
mapInt32ForeignMessage_.Add(other.mapInt32ForeignMessage_);
mapInt32Int32_.MergeFrom(other.mapInt32Int32_);
mapInt64Int64_.MergeFrom(other.mapInt64Int64_);
mapUint32Uint32_.MergeFrom(other.mapUint32Uint32_);
mapUint64Uint64_.MergeFrom(other.mapUint64Uint64_);
mapSint32Sint32_.MergeFrom(other.mapSint32Sint32_);
mapSint64Sint64_.MergeFrom(other.mapSint64Sint64_);
mapFixed32Fixed32_.MergeFrom(other.mapFixed32Fixed32_);
mapFixed64Fixed64_.MergeFrom(other.mapFixed64Fixed64_);
mapSfixed32Sfixed32_.MergeFrom(other.mapSfixed32Sfixed32_);
mapSfixed64Sfixed64_.MergeFrom(other.mapSfixed64Sfixed64_);
mapInt32Float_.MergeFrom(other.mapInt32Float_);
mapInt32Double_.MergeFrom(other.mapInt32Double_);
mapBoolBool_.MergeFrom(other.mapBoolBool_);
mapStringString_.MergeFrom(other.mapStringString_);
mapInt32Bytes_.MergeFrom(other.mapInt32Bytes_);
mapInt32Enum_.MergeFrom(other.mapInt32Enum_);
mapInt32ForeignMessage_.MergeFrom(other.mapInt32ForeignMessage_);
_unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
}
@ -1100,7 +1100,7 @@ namespace Google.Protobuf.TestProtos {
if (other == null) {
return;
}
mapInt32Message_.Add(other.mapInt32Message_);
mapInt32Message_.MergeFrom(other.mapInt32Message_);
_unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
}
@ -1298,8 +1298,8 @@ namespace Google.Protobuf.TestProtos {
if (other == null) {
return;
}
map1_.Add(other.map1_);
map2_.Add(other.map2_);
map1_.MergeFrom(other.map1_);
map2_.MergeFrom(other.map2_);
_unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
}
@ -1723,21 +1723,21 @@ namespace Google.Protobuf.TestProtos {
if (other == null) {
return;
}
mapInt32Int32_.Add(other.mapInt32Int32_);
mapInt64Int64_.Add(other.mapInt64Int64_);
mapUint32Uint32_.Add(other.mapUint32Uint32_);
mapUint64Uint64_.Add(other.mapUint64Uint64_);
mapSint32Sint32_.Add(other.mapSint32Sint32_);
mapSint64Sint64_.Add(other.mapSint64Sint64_);
mapFixed32Fixed32_.Add(other.mapFixed32Fixed32_);
mapFixed64Fixed64_.Add(other.mapFixed64Fixed64_);
mapSfixed32Sfixed32_.Add(other.mapSfixed32Sfixed32_);
mapSfixed64Sfixed64_.Add(other.mapSfixed64Sfixed64_);
mapInt32Float_.Add(other.mapInt32Float_);
mapInt32Double_.Add(other.mapInt32Double_);
mapBoolBool_.Add(other.mapBoolBool_);
mapInt32Enum_.Add(other.mapInt32Enum_);
mapInt32ForeignMessage_.Add(other.mapInt32ForeignMessage_);
mapInt32Int32_.MergeFrom(other.mapInt32Int32_);
mapInt64Int64_.MergeFrom(other.mapInt64Int64_);
mapUint32Uint32_.MergeFrom(other.mapUint32Uint32_);
mapUint64Uint64_.MergeFrom(other.mapUint64Uint64_);
mapSint32Sint32_.MergeFrom(other.mapSint32Sint32_);
mapSint64Sint64_.MergeFrom(other.mapSint64Sint64_);
mapFixed32Fixed32_.MergeFrom(other.mapFixed32Fixed32_);
mapFixed64Fixed64_.MergeFrom(other.mapFixed64Fixed64_);
mapSfixed32Sfixed32_.MergeFrom(other.mapSfixed32Sfixed32_);
mapSfixed64Sfixed64_.MergeFrom(other.mapSfixed64Sfixed64_);
mapInt32Float_.MergeFrom(other.mapInt32Float_);
mapInt32Double_.MergeFrom(other.mapInt32Double_);
mapBoolBool_.MergeFrom(other.mapBoolBool_);
mapInt32Enum_.MergeFrom(other.mapInt32Enum_);
mapInt32ForeignMessage_.MergeFrom(other.mapInt32ForeignMessage_);
_unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
}
@ -2031,7 +2031,7 @@ namespace Google.Protobuf.TestProtos {
if (other == null) {
return;
}
type_.Add(other.type_);
type_.MergeFrom(other.type_);
_unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
}
@ -2224,7 +2224,7 @@ namespace Google.Protobuf.TestProtos {
if (other == null) {
return;
}
entry_.Add(other.entry_);
entry_.MergeFrom(other.entry_);
_unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
}

@ -4344,25 +4344,25 @@ namespace ProtobufTestMessages.Proto2 {
unpackedDouble_.Add(other.unpackedDouble_);
unpackedBool_.Add(other.unpackedBool_);
unpackedNestedEnum_.Add(other.unpackedNestedEnum_);
mapInt32Int32_.Add(other.mapInt32Int32_);
mapInt64Int64_.Add(other.mapInt64Int64_);
mapUint32Uint32_.Add(other.mapUint32Uint32_);
mapUint64Uint64_.Add(other.mapUint64Uint64_);
mapSint32Sint32_.Add(other.mapSint32Sint32_);
mapSint64Sint64_.Add(other.mapSint64Sint64_);
mapFixed32Fixed32_.Add(other.mapFixed32Fixed32_);
mapFixed64Fixed64_.Add(other.mapFixed64Fixed64_);
mapSfixed32Sfixed32_.Add(other.mapSfixed32Sfixed32_);
mapSfixed64Sfixed64_.Add(other.mapSfixed64Sfixed64_);
mapInt32Float_.Add(other.mapInt32Float_);
mapInt32Double_.Add(other.mapInt32Double_);
mapBoolBool_.Add(other.mapBoolBool_);
mapStringString_.Add(other.mapStringString_);
mapStringBytes_.Add(other.mapStringBytes_);
mapStringNestedMessage_.Add(other.mapStringNestedMessage_);
mapStringForeignMessage_.Add(other.mapStringForeignMessage_);
mapStringNestedEnum_.Add(other.mapStringNestedEnum_);
mapStringForeignEnum_.Add(other.mapStringForeignEnum_);
mapInt32Int32_.MergeFrom(other.mapInt32Int32_);
mapInt64Int64_.MergeFrom(other.mapInt64Int64_);
mapUint32Uint32_.MergeFrom(other.mapUint32Uint32_);
mapUint64Uint64_.MergeFrom(other.mapUint64Uint64_);
mapSint32Sint32_.MergeFrom(other.mapSint32Sint32_);
mapSint64Sint64_.MergeFrom(other.mapSint64Sint64_);
mapFixed32Fixed32_.MergeFrom(other.mapFixed32Fixed32_);
mapFixed64Fixed64_.MergeFrom(other.mapFixed64Fixed64_);
mapSfixed32Sfixed32_.MergeFrom(other.mapSfixed32Sfixed32_);
mapSfixed64Sfixed64_.MergeFrom(other.mapSfixed64Sfixed64_);
mapInt32Float_.MergeFrom(other.mapInt32Float_);
mapInt32Double_.MergeFrom(other.mapInt32Double_);
mapBoolBool_.MergeFrom(other.mapBoolBool_);
mapStringString_.MergeFrom(other.mapStringString_);
mapStringBytes_.MergeFrom(other.mapStringBytes_);
mapStringNestedMessage_.MergeFrom(other.mapStringNestedMessage_);
mapStringForeignMessage_.MergeFrom(other.mapStringForeignMessage_);
mapStringNestedEnum_.MergeFrom(other.mapStringNestedEnum_);
mapStringForeignEnum_.MergeFrom(other.mapStringForeignEnum_);
if (other.HasData) {
if (!HasData) {
Data = new global::ProtobufTestMessages.Proto2.TestAllTypesProto2.Types.Data();

@ -3753,25 +3753,25 @@ namespace ProtobufTestMessages.Proto3 {
unpackedDouble_.Add(other.unpackedDouble_);
unpackedBool_.Add(other.unpackedBool_);
unpackedNestedEnum_.Add(other.unpackedNestedEnum_);
mapInt32Int32_.Add(other.mapInt32Int32_);
mapInt64Int64_.Add(other.mapInt64Int64_);
mapUint32Uint32_.Add(other.mapUint32Uint32_);
mapUint64Uint64_.Add(other.mapUint64Uint64_);
mapSint32Sint32_.Add(other.mapSint32Sint32_);
mapSint64Sint64_.Add(other.mapSint64Sint64_);
mapFixed32Fixed32_.Add(other.mapFixed32Fixed32_);
mapFixed64Fixed64_.Add(other.mapFixed64Fixed64_);
mapSfixed32Sfixed32_.Add(other.mapSfixed32Sfixed32_);
mapSfixed64Sfixed64_.Add(other.mapSfixed64Sfixed64_);
mapInt32Float_.Add(other.mapInt32Float_);
mapInt32Double_.Add(other.mapInt32Double_);
mapBoolBool_.Add(other.mapBoolBool_);
mapStringString_.Add(other.mapStringString_);
mapStringBytes_.Add(other.mapStringBytes_);
mapStringNestedMessage_.Add(other.mapStringNestedMessage_);
mapStringForeignMessage_.Add(other.mapStringForeignMessage_);
mapStringNestedEnum_.Add(other.mapStringNestedEnum_);
mapStringForeignEnum_.Add(other.mapStringForeignEnum_);
mapInt32Int32_.MergeFrom(other.mapInt32Int32_);
mapInt64Int64_.MergeFrom(other.mapInt64Int64_);
mapUint32Uint32_.MergeFrom(other.mapUint32Uint32_);
mapUint64Uint64_.MergeFrom(other.mapUint64Uint64_);
mapSint32Sint32_.MergeFrom(other.mapSint32Sint32_);
mapSint64Sint64_.MergeFrom(other.mapSint64Sint64_);
mapFixed32Fixed32_.MergeFrom(other.mapFixed32Fixed32_);
mapFixed64Fixed64_.MergeFrom(other.mapFixed64Fixed64_);
mapSfixed32Sfixed32_.MergeFrom(other.mapSfixed32Sfixed32_);
mapSfixed64Sfixed64_.MergeFrom(other.mapSfixed64Sfixed64_);
mapInt32Float_.MergeFrom(other.mapInt32Float_);
mapInt32Double_.MergeFrom(other.mapInt32Double_);
mapBoolBool_.MergeFrom(other.mapBoolBool_);
mapStringString_.MergeFrom(other.mapStringString_);
mapStringBytes_.MergeFrom(other.mapStringBytes_);
mapStringNestedMessage_.MergeFrom(other.mapStringNestedMessage_);
mapStringForeignMessage_.MergeFrom(other.mapStringForeignMessage_);
mapStringNestedEnum_.MergeFrom(other.mapStringNestedEnum_);
mapStringForeignEnum_.MergeFrom(other.mapStringForeignEnum_);
if (other.optionalBoolWrapper_ != null) {
if (optionalBoolWrapper_ == null || other.OptionalBoolWrapper != false) {
OptionalBoolWrapper = other.OptionalBoolWrapper;

@ -24112,7 +24112,7 @@ namespace Google.Protobuf.TestProtos.Proto2 {
if (other == null) {
return;
}
foo_.Add(other.foo_);
foo_.MergeFrom(other.foo_);
_unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
}
@ -30708,7 +30708,7 @@ namespace Google.Protobuf.TestProtos.Proto2 {
}
OptionalGroup.MergeFrom(other.OptionalGroup);
}
stringStringMap_.Add(other.stringStringMap_);
stringStringMap_.MergeFrom(other.stringStringMap_);
switch (other.OneofFieldCase) {
case OneofFieldOneofCase.OneofUint32:
OneofUint32 = other.OneofUint32;

@ -3258,24 +3258,24 @@ namespace Google.Protobuf.TestProtos {
if (other == null) {
return;
}
anyField_.Add(other.anyField_);
apiField_.Add(other.apiField_);
durationField_.Add(other.durationField_);
emptyField_.Add(other.emptyField_);
fieldMaskField_.Add(other.fieldMaskField_);
sourceContextField_.Add(other.sourceContextField_);
structField_.Add(other.structField_);
timestampField_.Add(other.timestampField_);
typeField_.Add(other.typeField_);
doubleField_.Add(other.doubleField_);
floatField_.Add(other.floatField_);
int64Field_.Add(other.int64Field_);
uint64Field_.Add(other.uint64Field_);
int32Field_.Add(other.int32Field_);
uint32Field_.Add(other.uint32Field_);
boolField_.Add(other.boolField_);
stringField_.Add(other.stringField_);
bytesField_.Add(other.bytesField_);
anyField_.MergeFrom(other.anyField_);
apiField_.MergeFrom(other.apiField_);
durationField_.MergeFrom(other.durationField_);
emptyField_.MergeFrom(other.emptyField_);
fieldMaskField_.MergeFrom(other.fieldMaskField_);
sourceContextField_.MergeFrom(other.sourceContextField_);
structField_.MergeFrom(other.structField_);
timestampField_.MergeFrom(other.timestampField_);
typeField_.MergeFrom(other.typeField_);
doubleField_.MergeFrom(other.doubleField_);
floatField_.MergeFrom(other.floatField_);
int64Field_.MergeFrom(other.int64Field_);
uint64Field_.MergeFrom(other.uint64Field_);
int32Field_.MergeFrom(other.int32Field_);
uint32Field_.MergeFrom(other.uint32Field_);
boolField_.MergeFrom(other.boolField_);
stringField_.MergeFrom(other.stringField_);
bytesField_.MergeFrom(other.bytesField_);
_unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
}

@ -36,6 +36,7 @@ using Google.Protobuf.TestProtos;
using NUnit.Framework;
using System.Linq;
using Google.Protobuf.WellKnownTypes;
using Google.Protobuf.Collections;
namespace Google.Protobuf
{
@ -795,5 +796,44 @@ namespace Google.Protobuf
EqualityTester.AssertInequality(message1, message2);
EqualityTester.AssertEquality(message1, message3);
}
[Test]
[TestCase(false)]
[TestCase(true)]
public void MapFieldMerging(bool direct)
{
var message1 = new TestMap
{
MapStringString =
{
{ "x1", "y1" },
{ "common", "message1" }
}
};
var message2 = new TestMap
{
MapStringString =
{
{ "x2", "y2" },
{ "common", "message2" }
}
};
if (direct)
{
message1.MergeFrom(message2);
}
else
{
message1.MergeFrom(message2.ToByteArray());
}
var expected = new MapField<string, string>
{
{ "x1", "y1" },
{ "x2", "y2" },
{ "common", "message2" }
};
Assert.AreEqual(expected, message1.MapStringString);
}
}
}

@ -237,6 +237,21 @@ namespace Google.Protobuf.Collections
}
}
/// <summary>
/// Adds the specified entries to the map, replacing any existing entries with the same keys.
/// The keys and values are not automatically cloned.
/// </summary>
/// <remarks>This method primarily exists to be called from MergeFrom methods in generated classes for messages.</remarks>
/// <param name="entries">The entries to add to the map.</param>
public void MergeFrom(IDictionary<TKey, TValue> entries)
{
ProtoPreconditions.CheckNotNull(entries, nameof(entries));
foreach (var pair in entries)
{
this[pair.Key] = pair.Value;
}
}
/// <summary>
/// Returns an enumerator that iterates through the collection.
/// </summary>

@ -212,7 +212,7 @@ namespace Google.Protobuf.WellKnownTypes {
if (other == null) {
return;
}
fields_.Add(other.fields_);
fields_.MergeFrom(other.fields_);
_unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
}

@ -90,7 +90,7 @@ void MapFieldGenerator::GenerateMembers(io::Printer* printer) {
void MapFieldGenerator::GenerateMergingCode(io::Printer* printer) {
printer->Print(
variables_,
"$name$_.Add(other.$name$_);\n");
"$name$_.MergeFrom(other.$name$_);\n");
}
void MapFieldGenerator::GenerateParsingCode(io::Printer* printer) {

Loading…
Cancel
Save