Skip to content

Commit a3888f5

Browse files
Clean up TextFormat parser (#10673)
* Fix TextFormat parser
1 parent 3b5301c commit a3888f5

File tree

2 files changed

+59
-12
lines changed

2 files changed

+59
-12
lines changed

CHANGES.txt

+5-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,11 @@
77
* Change the Lite runtime to prefer merging from the wireformat into mutable
88
messages rather than building up a new immutable object before merging. This
99
way results in fewer allocations and copy operations.
10-
* Make message-type extensions merge from wire-format instead of building up instances and merging afterwards. This has much better performance.
10+
* Make message-type extensions merge from wire-format instead of building up
11+
instances and merging afterwards. This has much better performance.
12+
* Fix TextFormat parser to build up recurring (but supposedly not repeated)
13+
sub-messages directly from text rather than building a new sub-message and
14+
merging the fully formed message into the existing field.
1115

1216
2022-09-13 version 21.6 (C++/Java/Python/PHP/Objective-C/C#/Ruby)
1317

java/core/src/main/java/com/google/protobuf/MessageReflection.java

+54-11
Original file line numberDiff line numberDiff line change
@@ -378,6 +378,7 @@ MergeTarget newEmptyTargetForField(
378378
static class BuilderAdapter implements MergeTarget {
379379

380380
private final Message.Builder builder;
381+
private boolean hasNestedBuilders = true;
381382

382383
@Override
383384
public Descriptors.Descriptor getDescriptorForType() {
@@ -393,13 +394,30 @@ public Object getField(Descriptors.FieldDescriptor field) {
393394
return builder.getField(field);
394395
}
395396

397+
private Message.Builder getFieldBuilder(Descriptors.FieldDescriptor field) {
398+
if (hasNestedBuilders) {
399+
try {
400+
return builder.getFieldBuilder(field);
401+
} catch (UnsupportedOperationException e) {
402+
hasNestedBuilders = false;
403+
}
404+
}
405+
return null;
406+
}
407+
396408
@Override
397409
public boolean hasField(Descriptors.FieldDescriptor field) {
398410
return builder.hasField(field);
399411
}
400412

401413
@Override
402414
public MergeTarget setField(Descriptors.FieldDescriptor field, Object value) {
415+
if (!field.isRepeated() && value instanceof MessageLite.Builder) {
416+
if (value != getFieldBuilder(field)) {
417+
builder.setField(field, ((MessageLite.Builder) value).buildPartial());
418+
}
419+
return this;
420+
}
403421
builder.setField(field, value);
404422
return this;
405423
}
@@ -413,12 +431,18 @@ public MergeTarget clearField(Descriptors.FieldDescriptor field) {
413431
@Override
414432
public MergeTarget setRepeatedField(
415433
Descriptors.FieldDescriptor field, int index, Object value) {
434+
if (value instanceof MessageLite.Builder) {
435+
value = ((MessageLite.Builder) value).buildPartial();
436+
}
416437
builder.setRepeatedField(field, index, value);
417438
return this;
418439
}
419440

420441
@Override
421442
public MergeTarget addRepeatedField(Descriptors.FieldDescriptor field, Object value) {
443+
if (value instanceof MessageLite.Builder) {
444+
value = ((MessageLite.Builder) value).buildPartial();
445+
}
422446
builder.addRepeatedField(field, value);
423447
return this;
424448
}
@@ -536,11 +560,19 @@ public void mergeGroup(
536560
Message defaultInstance)
537561
throws IOException {
538562
if (!field.isRepeated()) {
563+
Message.Builder subBuilder;
539564
if (hasField(field)) {
540-
input.readGroup(field.getNumber(), builder.getFieldBuilder(field), extensionRegistry);
541-
return;
565+
subBuilder = getFieldBuilder(field);
566+
if (subBuilder != null) {
567+
input.readGroup(field.getNumber(), subBuilder, extensionRegistry);
568+
return;
569+
} else {
570+
subBuilder = newMessageFieldInstance(field, defaultInstance);
571+
subBuilder.mergeFrom((Message) getField(field));
572+
}
573+
} else {
574+
subBuilder = newMessageFieldInstance(field, defaultInstance);
542575
}
543-
Message.Builder subBuilder = newMessageFieldInstance(field, defaultInstance);
544576
input.readGroup(field.getNumber(), subBuilder, extensionRegistry);
545577
Object unused = setField(field, subBuilder.buildPartial());
546578
} else {
@@ -558,11 +590,19 @@ public void mergeMessage(
558590
Message defaultInstance)
559591
throws IOException {
560592
if (!field.isRepeated()) {
593+
Message.Builder subBuilder;
561594
if (hasField(field)) {
562-
input.readMessage(builder.getFieldBuilder(field), extensionRegistry);
563-
return;
595+
subBuilder = getFieldBuilder(field);
596+
if (subBuilder != null) {
597+
input.readMessage(subBuilder, extensionRegistry);
598+
return;
599+
} else {
600+
subBuilder = newMessageFieldInstance(field, defaultInstance);
601+
subBuilder.mergeFrom((Message) getField(field));
602+
}
603+
} else {
604+
subBuilder = newMessageFieldInstance(field, defaultInstance);
564605
}
565-
Message.Builder subBuilder = newMessageFieldInstance(field, defaultInstance);
566606
input.readMessage(subBuilder, extensionRegistry);
567607
Object unused = setField(field, subBuilder.buildPartial());
568608
} else {
@@ -586,11 +626,14 @@ private Message.Builder newMessageFieldInstance(
586626
public MergeTarget newMergeTargetForField(
587627
Descriptors.FieldDescriptor field, Message defaultInstance) {
588628
Message.Builder subBuilder;
589-
if (defaultInstance != null) {
590-
subBuilder = defaultInstance.newBuilderForType();
591-
} else {
592-
subBuilder = builder.newBuilderForField(field);
629+
if (!field.isRepeated() && hasField(field)) {
630+
subBuilder = getFieldBuilder(field);
631+
if (subBuilder != null) {
632+
return new BuilderAdapter(subBuilder);
633+
}
593634
}
635+
636+
subBuilder = newMessageFieldInstance(field, defaultInstance);
594637
if (!field.isRepeated()) {
595638
Message originalMessage = (Message) getField(field);
596639
if (originalMessage != null) {
@@ -626,7 +669,7 @@ public WireFormat.Utf8Validation getUtf8Validation(Descriptors.FieldDescriptor d
626669

627670
@Override
628671
public Object finish() {
629-
return builder.buildPartial();
672+
return builder;
630673
}
631674
}
632675

0 commit comments

Comments
 (0)