Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ private Object mergeOrReadMessageField(
if (existingValue instanceof RawProtoMessageLiteValue) {
bytes = ((RawProtoMessageLiteValue) existingValue).toByteString().concat(bytes);
}
return RawProtoMessageLiteValue.create(bytes, fieldProtoTypeName, this);
return RawProtoMessageLiteValue.create(bytes, fieldProtoTypeName, this, /* isView= */ true);
}
WellKnownProto wellKnownProto = WellKnownProto.getByTypeName(fieldProtoTypeName).orElse(null);
if (isStructLike(wellKnownProto)) {
Expand Down Expand Up @@ -356,6 +356,8 @@ private Map.Entry<Object, Object> readSingleMapEntry(
@Nullable FieldLiteDescriptor keyDescriptor,
@Nullable FieldLiteDescriptor valueDescriptor) {
CodedInputStream inputStream = bytes.newCodedInput();
// Submessages alias bytes; unwrapping parses or copies them, so no view outlives evaluation.
inputStream.enableAliasing(true);
int targetFieldNumber = fieldDescriptor.getFieldNumber();
Object fieldValue = null;
try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,14 +50,23 @@ abstract class RawProtoMessageLiteValue extends StructValue<String, WireMessageL

abstract ProtoLiteCelValueConverter protoLiteCelValueConverter();

// Set when toByteString() may alias a parent message's buffer.
abstract boolean isView();

@Override
public String protoTypeName() {
return celType().name();
}

@Override
public WireMessageLite value() {
return this;
// A view escaping evaluation would pin the parent's whole buffer, so it leaves as a copy.
return isView()
? create(
ByteString.copyFrom(toByteString().asReadOnlyByteBuffer()),
protoTypeName(),
protoLiteCelValueConverter())
: this;
}

@Override
Expand Down Expand Up @@ -136,14 +145,23 @@ static RawProtoMessageLiteValue create(
ByteString rawWireBytes,
String protoTypeName,
ProtoLiteCelValueConverter protoLiteCelValueConverter) {
return create(rawWireBytes, protoTypeName, protoLiteCelValueConverter, /* isView= */ false);
}

static RawProtoMessageLiteValue create(
ByteString rawWireBytes,
String protoTypeName,
ProtoLiteCelValueConverter protoLiteCelValueConverter,
boolean isView) {
checkNotNull(rawWireBytes);
checkNotNull(protoTypeName);
checkNotNull(protoLiteCelValueConverter);
return new AutoValue_RawProtoMessageLiteValue(
rawWireBytes,
StructTypeReference.create(
protoTypeName.isEmpty() ? UNKNOWN_MESSAGE_TYPE_NAME : protoTypeName),
protoLiteCelValueConverter);
protoLiteCelValueConverter,
isView);
}

RawProtoMessageLiteValue() {}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,22 @@ public void create_accessorsAndType() {
assertThat(value.celType().name()).isEqualTo("custom.Message");
}

@Test
public void value_selectedSubmessage_returnsCopy() throws Exception {
ByteString submessage = encode(out -> out.writeInt32(1, 42));
RawProtoMessageLiteValue raw =
RawProtoMessageLiteValue.create(
encode(out -> out.writeBytes(21, submessage)), EMPTY_CONVERTER);
SelectField field =
SelectField.create(21L, "single_nested_message", SelectField.MESSAGE_TYPE_CODE);
RawProtoMessageLiteValue selected = (RawProtoMessageLiteValue) raw.selectByFieldNumber(field);

WireMessageLite value = selected.value();

assertThat(value).isNotSameInstanceAs(selected);
assertThat(value.toByteString()).isEqualTo(submessage);
}

@Test
public void create_defaultsUnknownMessageTypeName() {
ByteString bytes = ByteString.copyFromUtf8("test");
Expand Down
Loading