@@ -768,14 +768,16 @@ class _FieldSet {
768
768
/// in this message. Repeated fields are appended. Singular sub-messages are
769
769
/// recursively merged.
770
770
void _mergeFromMessage (_FieldSet other) {
771
- // TODO(https://github.com/google/protobuf.dart/issues/60): Recognize
772
- // when `this` and [other] are the same protobuf (e.g. from cloning). In
773
- // this case, we can merge the non-extension fields without field lookups or
774
- // validation checks.
775
-
771
+ final sameMessage = identical (_meta, other._meta);
776
772
for (var fi in other._infosSortedByTag) {
777
773
var value = other._values[fi.index! ];
778
- if (value != null ) _mergeField (fi, value, isExtension: false );
774
+ if (value != null ) {
775
+ if (sameMessage) {
776
+ _mergeNonExtensionFieldUnchecked (fi, value);
777
+ } else {
778
+ _mergeField (fi, value, isExtension: false );
779
+ }
780
+ }
779
781
}
780
782
if (other._hasExtensions) {
781
783
var others = other._extensions! ;
@@ -791,14 +793,55 @@ class _FieldSet {
791
793
}
792
794
}
793
795
794
- void _mergeField (FieldInfo otherFi, fieldValue, {bool ? isExtension}) {
796
+ void _mergeNonExtensionFieldUnchecked (FieldInfo fi, dynamic fieldValue) {
797
+ if (fi.isMapField) {
798
+ final mapInfo = fi as MapFieldInfo <dynamic , dynamic >;
799
+ final map =
800
+ mapInfo._ensureMapField (_meta, this ) as PbMap <dynamic , dynamic >;
801
+ if (_isGroupOrMessage (mapInfo.valueFieldType)) {
802
+ for (MapEntry entry in fieldValue.entries) {
803
+ map[entry.key] = (entry.value as GeneratedMessage ).deepCopy ();
804
+ }
805
+ } else {
806
+ map.addAll (fieldValue);
807
+ }
808
+ return ;
809
+ }
810
+
811
+ if (fi.isRepeated) {
812
+ if (_isGroupOrMessage (fi.type)) {
813
+ PbListBase <GeneratedMessage > pbList = fieldValue;
814
+ var repeatedFields = fi._ensureRepeatedField (_meta, this );
815
+ for (var i = 0 ; i < pbList.length; ++ i) {
816
+ repeatedFields.add (pbList[i].deepCopy ());
817
+ }
818
+ } else {
819
+ PbListBase pbList = fieldValue;
820
+ fi._ensureRepeatedField (_meta, this ).addAll (pbList);
821
+ }
822
+ return ;
823
+ }
824
+
825
+ if (fi.isGroupOrMessage) {
826
+ final currentFieldValue = _values[fi.index! ];
827
+ if (currentFieldValue == null ) {
828
+ fieldValue = (fieldValue as GeneratedMessage ).deepCopy ();
829
+ } else {
830
+ fieldValue = currentFieldValue..mergeFromMessage (fieldValue);
831
+ }
832
+ }
833
+
834
+ _setNonExtensionFieldUnchecked (_meta, fi, fieldValue);
835
+ }
836
+
837
+ void _mergeField (FieldInfo otherFi, fieldValue, {required bool isExtension}) {
795
838
final tagNumber = otherFi.tagNumber;
796
839
797
840
// Determine the FieldInfo to use.
798
841
// Don't allow regular fields to be overwritten by extensions.
799
842
final meta = _meta;
800
843
var fi = _nonExtensionInfo (meta, tagNumber);
801
- if (fi == null && isExtension! ) {
844
+ if (fi == null && isExtension) {
802
845
// This will overwrite any existing extension field info.
803
846
fi = otherFi;
804
847
}
@@ -836,7 +879,7 @@ class _FieldSet {
836
879
}
837
880
838
881
if (otherFi.isGroupOrMessage) {
839
- final currentFi = isExtension!
882
+ final currentFi = isExtension
840
883
? _ensureExtensions ()._getFieldOrNull (fi as Extension <dynamic >)
841
884
: _values[fi.index! ];
842
885
@@ -847,7 +890,7 @@ class _FieldSet {
847
890
}
848
891
}
849
892
850
- if (isExtension! ) {
893
+ if (isExtension) {
851
894
_ensureExtensions ()
852
895
._setFieldAndInfo (fi as Extension <dynamic >, fieldValue);
853
896
} else {
0 commit comments