|
|
|
@ -42,7 +42,6 @@ import static com.google.protobuf.ArrayDecoders.decodeFixed64; |
|
|
|
|
import static com.google.protobuf.ArrayDecoders.decodeFixed64List; |
|
|
|
|
import static com.google.protobuf.ArrayDecoders.decodeFloat; |
|
|
|
|
import static com.google.protobuf.ArrayDecoders.decodeFloatList; |
|
|
|
|
import static com.google.protobuf.ArrayDecoders.decodeGroupField; |
|
|
|
|
import static com.google.protobuf.ArrayDecoders.decodeGroupList; |
|
|
|
|
import static com.google.protobuf.ArrayDecoders.decodeMessageField; |
|
|
|
|
import static com.google.protobuf.ArrayDecoders.decodeMessageList; |
|
|
|
@ -66,6 +65,8 @@ import static com.google.protobuf.ArrayDecoders.decodeVarint32; |
|
|
|
|
import static com.google.protobuf.ArrayDecoders.decodeVarint32List; |
|
|
|
|
import static com.google.protobuf.ArrayDecoders.decodeVarint64; |
|
|
|
|
import static com.google.protobuf.ArrayDecoders.decodeVarint64List; |
|
|
|
|
import static com.google.protobuf.ArrayDecoders.mergeGroupField; |
|
|
|
|
import static com.google.protobuf.ArrayDecoders.mergeMessageField; |
|
|
|
|
import static com.google.protobuf.ArrayDecoders.skipField; |
|
|
|
|
|
|
|
|
|
import com.google.protobuf.ArrayDecoders.Registers; |
|
|
|
@ -1177,6 +1178,7 @@ final class MessageSchema<T> implements Schema<T> { |
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
|
public void mergeFrom(T message, T other) { |
|
|
|
|
checkMutable(message); |
|
|
|
|
if (other == null) { |
|
|
|
|
throw new NullPointerException(); |
|
|
|
|
} |
|
|
|
@ -1375,47 +1377,83 @@ final class MessageSchema<T> implements Schema<T> { |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private void mergeMessage(T message, T other, int pos) { |
|
|
|
|
private void mergeMessage(T targetParent, T sourceParent, int pos) { |
|
|
|
|
if (!isFieldPresent(sourceParent, pos)) { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
final int typeAndOffset = typeAndOffsetAt(pos); |
|
|
|
|
final long offset = offset(typeAndOffset); |
|
|
|
|
|
|
|
|
|
if (!isFieldPresent(other, pos)) { |
|
|
|
|
final Object source = UNSAFE.getObject(sourceParent, offset); |
|
|
|
|
if (source == null) { |
|
|
|
|
throw new IllegalStateException( |
|
|
|
|
"Source subfield " + numberAt(pos) + " is present but null: " + sourceParent); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
final Schema fieldSchema = getMessageFieldSchema(pos); |
|
|
|
|
if (!isFieldPresent(targetParent, pos)) { |
|
|
|
|
if (!isMutable(source)) { |
|
|
|
|
// Can safely share source if it is immutable
|
|
|
|
|
UNSAFE.putObject(targetParent, offset, source); |
|
|
|
|
} else { |
|
|
|
|
// Make a safetey copy of source
|
|
|
|
|
final Object copyOfSource = fieldSchema.newInstance(); |
|
|
|
|
fieldSchema.mergeFrom(copyOfSource, source); |
|
|
|
|
UNSAFE.putObject(targetParent, offset, copyOfSource); |
|
|
|
|
} |
|
|
|
|
setFieldPresent(targetParent, pos); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
Object mine = UnsafeUtil.getObject(message, offset); |
|
|
|
|
Object theirs = UnsafeUtil.getObject(other, offset); |
|
|
|
|
if (mine != null && theirs != null) { |
|
|
|
|
Object merged = Internal.mergeMessage(mine, theirs); |
|
|
|
|
UnsafeUtil.putObject(message, offset, merged); |
|
|
|
|
setFieldPresent(message, pos); |
|
|
|
|
} else if (theirs != null) { |
|
|
|
|
UnsafeUtil.putObject(message, offset, theirs); |
|
|
|
|
setFieldPresent(message, pos); |
|
|
|
|
// Sub-message is present, merge from source
|
|
|
|
|
Object target = UNSAFE.getObject(targetParent, offset); |
|
|
|
|
if (!isMutable(target)) { |
|
|
|
|
Object newInstance = fieldSchema.newInstance(); |
|
|
|
|
fieldSchema.mergeFrom(newInstance, target); |
|
|
|
|
UNSAFE.putObject(targetParent, offset, newInstance); |
|
|
|
|
target = newInstance; |
|
|
|
|
} |
|
|
|
|
fieldSchema.mergeFrom(target, source); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private void mergeOneofMessage(T message, T other, int pos) { |
|
|
|
|
int typeAndOffset = typeAndOffsetAt(pos); |
|
|
|
|
private void mergeOneofMessage(T targetParent, T sourceParent, int pos) { |
|
|
|
|
int number = numberAt(pos); |
|
|
|
|
long offset = offset(typeAndOffset); |
|
|
|
|
|
|
|
|
|
if (!isOneofPresent(other, number, pos)) { |
|
|
|
|
if (!isOneofPresent(sourceParent, number, pos)) { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
Object mine = null; |
|
|
|
|
if (isOneofPresent(message, number, pos)) { |
|
|
|
|
mine = UnsafeUtil.getObject(message, offset); |
|
|
|
|
|
|
|
|
|
long offset = offset(typeAndOffsetAt(pos)); |
|
|
|
|
final Object source = UNSAFE.getObject(sourceParent, offset); |
|
|
|
|
if (source == null) { |
|
|
|
|
throw new IllegalStateException( |
|
|
|
|
"Source subfield " + numberAt(pos) + " is present but null: " + sourceParent); |
|
|
|
|
} |
|
|
|
|
Object theirs = UnsafeUtil.getObject(other, offset); |
|
|
|
|
if (mine != null && theirs != null) { |
|
|
|
|
Object merged = Internal.mergeMessage(mine, theirs); |
|
|
|
|
UnsafeUtil.putObject(message, offset, merged); |
|
|
|
|
setOneofPresent(message, number, pos); |
|
|
|
|
} else if (theirs != null) { |
|
|
|
|
UnsafeUtil.putObject(message, offset, theirs); |
|
|
|
|
setOneofPresent(message, number, pos); |
|
|
|
|
|
|
|
|
|
final Schema fieldSchema = getMessageFieldSchema(pos); |
|
|
|
|
if (!isOneofPresent(targetParent, number, pos)) { |
|
|
|
|
if (!isMutable(source)) { |
|
|
|
|
// Can safely share source if it is immutable
|
|
|
|
|
UNSAFE.putObject(targetParent, offset, source); |
|
|
|
|
} else { |
|
|
|
|
// Make a safety copy of theirs
|
|
|
|
|
final Object copyOfSource = fieldSchema.newInstance(); |
|
|
|
|
fieldSchema.mergeFrom(copyOfSource, source); |
|
|
|
|
UNSAFE.putObject(targetParent, offset, copyOfSource); |
|
|
|
|
} |
|
|
|
|
setOneofPresent(targetParent, number, pos); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Sub-message is present, merge from source
|
|
|
|
|
Object target = UNSAFE.getObject(targetParent, offset); |
|
|
|
|
if (!isMutable(target)) { |
|
|
|
|
Object newInstance = fieldSchema.newInstance(); |
|
|
|
|
fieldSchema.mergeFrom(newInstance, target); |
|
|
|
|
UNSAFE.putObject(targetParent, offset, newInstance); |
|
|
|
|
target = newInstance; |
|
|
|
|
} |
|
|
|
|
fieldSchema.mergeFrom(target, source); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
@ -3853,6 +3891,7 @@ final class MessageSchema<T> implements Schema<T> { |
|
|
|
|
if (extensionRegistry == null) { |
|
|
|
|
throw new NullPointerException(); |
|
|
|
|
} |
|
|
|
|
checkMutable(message); |
|
|
|
|
mergeFromHelper(unknownFieldSchema, extensionSchema, message, reader, extensionRegistry); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -3889,6 +3928,7 @@ final class MessageSchema<T> implements Schema<T> { |
|
|
|
|
} |
|
|
|
|
unknownFields = |
|
|
|
|
extensionSchema.parseExtension( |
|
|
|
|
message, |
|
|
|
|
reader, |
|
|
|
|
extension, |
|
|
|
|
extensionRegistry, |
|
|
|
@ -3955,21 +3995,10 @@ final class MessageSchema<T> implements Schema<T> { |
|
|
|
|
break; |
|
|
|
|
case 9: |
|
|
|
|
{ // MESSAGE:
|
|
|
|
|
if (isFieldPresent(message, pos)) { |
|
|
|
|
Object mergedResult = |
|
|
|
|
Internal.mergeMessage( |
|
|
|
|
UnsafeUtil.getObject(message, offset(typeAndOffset)), |
|
|
|
|
reader.readMessageBySchemaWithCheck( |
|
|
|
|
(Schema<T>) getMessageFieldSchema(pos), extensionRegistry)); |
|
|
|
|
UnsafeUtil.putObject(message, offset(typeAndOffset), mergedResult); |
|
|
|
|
} else { |
|
|
|
|
UnsafeUtil.putObject( |
|
|
|
|
message, |
|
|
|
|
offset(typeAndOffset), |
|
|
|
|
reader.readMessageBySchemaWithCheck( |
|
|
|
|
(Schema<T>) getMessageFieldSchema(pos), extensionRegistry)); |
|
|
|
|
setFieldPresent(message, pos); |
|
|
|
|
} |
|
|
|
|
final MessageLite current = (MessageLite) mutableMessageFieldForMerge(message, pos); |
|
|
|
|
reader.mergeMessageField( |
|
|
|
|
current, (Schema<MessageLite>) getMessageFieldSchema(pos), extensionRegistry); |
|
|
|
|
storeMessageField(message, pos, current); |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
case 10: // BYTES:
|
|
|
|
@ -3990,7 +4019,7 @@ final class MessageSchema<T> implements Schema<T> { |
|
|
|
|
} else { |
|
|
|
|
unknownFields = |
|
|
|
|
SchemaUtil.storeUnknownEnum( |
|
|
|
|
number, enumValue, unknownFields, unknownFieldSchema); |
|
|
|
|
message, number, enumValue, unknownFields, unknownFieldSchema); |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
@ -4012,21 +4041,10 @@ final class MessageSchema<T> implements Schema<T> { |
|
|
|
|
break; |
|
|
|
|
case 17: |
|
|
|
|
{ // GROUP:
|
|
|
|
|
if (isFieldPresent(message, pos)) { |
|
|
|
|
Object mergedResult = |
|
|
|
|
Internal.mergeMessage( |
|
|
|
|
UnsafeUtil.getObject(message, offset(typeAndOffset)), |
|
|
|
|
reader.readGroupBySchemaWithCheck( |
|
|
|
|
(Schema<T>) getMessageFieldSchema(pos), extensionRegistry)); |
|
|
|
|
UnsafeUtil.putObject(message, offset(typeAndOffset), mergedResult); |
|
|
|
|
} else { |
|
|
|
|
UnsafeUtil.putObject( |
|
|
|
|
message, |
|
|
|
|
offset(typeAndOffset), |
|
|
|
|
reader.readGroupBySchemaWithCheck( |
|
|
|
|
(Schema<T>) getMessageFieldSchema(pos), extensionRegistry)); |
|
|
|
|
setFieldPresent(message, pos); |
|
|
|
|
} |
|
|
|
|
final MessageLite current = (MessageLite) mutableMessageFieldForMerge(message, pos); |
|
|
|
|
reader.mergeGroupField( |
|
|
|
|
current, (Schema<MessageLite>) getMessageFieldSchema(pos), extensionRegistry); |
|
|
|
|
storeMessageField(message, pos, current); |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
case 18: // DOUBLE_LIST:
|
|
|
|
@ -4089,6 +4107,7 @@ final class MessageSchema<T> implements Schema<T> { |
|
|
|
|
reader.readEnumList(enumList); |
|
|
|
|
unknownFields = |
|
|
|
|
SchemaUtil.filterUnknownEnumList( |
|
|
|
|
message, |
|
|
|
|
number, |
|
|
|
|
enumList, |
|
|
|
|
getEnumFieldVerifier(pos), |
|
|
|
@ -4155,6 +4174,7 @@ final class MessageSchema<T> implements Schema<T> { |
|
|
|
|
reader.readEnumList(enumList); |
|
|
|
|
unknownFields = |
|
|
|
|
SchemaUtil.filterUnknownEnumList( |
|
|
|
|
message, |
|
|
|
|
number, |
|
|
|
|
enumList, |
|
|
|
|
getEnumFieldVerifier(pos), |
|
|
|
@ -4235,24 +4255,15 @@ final class MessageSchema<T> implements Schema<T> { |
|
|
|
|
readString(message, typeAndOffset, reader); |
|
|
|
|
setOneofPresent(message, number, pos); |
|
|
|
|
break; |
|
|
|
|
case 60: // ONEOF_MESSAGE:
|
|
|
|
|
if (isOneofPresent(message, number, pos)) { |
|
|
|
|
Object mergedResult = |
|
|
|
|
Internal.mergeMessage( |
|
|
|
|
UnsafeUtil.getObject(message, offset(typeAndOffset)), |
|
|
|
|
reader.readMessageBySchemaWithCheck( |
|
|
|
|
getMessageFieldSchema(pos), extensionRegistry)); |
|
|
|
|
UnsafeUtil.putObject(message, offset(typeAndOffset), mergedResult); |
|
|
|
|
} else { |
|
|
|
|
UnsafeUtil.putObject( |
|
|
|
|
message, |
|
|
|
|
offset(typeAndOffset), |
|
|
|
|
reader.readMessageBySchemaWithCheck( |
|
|
|
|
getMessageFieldSchema(pos), extensionRegistry)); |
|
|
|
|
setFieldPresent(message, pos); |
|
|
|
|
case 60: |
|
|
|
|
{ // ONEOF_MESSAGE:
|
|
|
|
|
final MessageLite current = |
|
|
|
|
(MessageLite) mutableOneofMessageFieldForMerge(message, number, pos); |
|
|
|
|
reader.mergeMessageField( |
|
|
|
|
current, (Schema<MessageLite>) getMessageFieldSchema(pos), extensionRegistry); |
|
|
|
|
storeOneofMessageField(message, number, pos, current); |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
setOneofPresent(message, number, pos); |
|
|
|
|
break; |
|
|
|
|
case 61: // ONEOF_BYTES:
|
|
|
|
|
UnsafeUtil.putObject(message, offset(typeAndOffset), reader.readBytes()); |
|
|
|
|
setOneofPresent(message, number, pos); |
|
|
|
@ -4272,7 +4283,7 @@ final class MessageSchema<T> implements Schema<T> { |
|
|
|
|
} else { |
|
|
|
|
unknownFields = |
|
|
|
|
SchemaUtil.storeUnknownEnum( |
|
|
|
|
number, enumValue, unknownFields, unknownFieldSchema); |
|
|
|
|
message, number, enumValue, unknownFields, unknownFieldSchema); |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
@ -4296,17 +4307,19 @@ final class MessageSchema<T> implements Schema<T> { |
|
|
|
|
message, offset(typeAndOffset), Long.valueOf(reader.readSInt64())); |
|
|
|
|
setOneofPresent(message, number, pos); |
|
|
|
|
break; |
|
|
|
|
case 68: // ONEOF_GROUP:
|
|
|
|
|
UnsafeUtil.putObject( |
|
|
|
|
message, |
|
|
|
|
offset(typeAndOffset), |
|
|
|
|
reader.readGroupBySchemaWithCheck(getMessageFieldSchema(pos), extensionRegistry)); |
|
|
|
|
setOneofPresent(message, number, pos); |
|
|
|
|
break; |
|
|
|
|
case 68: |
|
|
|
|
{ // ONEOF_GROUP:
|
|
|
|
|
final MessageLite current = |
|
|
|
|
(MessageLite) mutableOneofMessageFieldForMerge(message, number, pos); |
|
|
|
|
reader.mergeGroupField( |
|
|
|
|
current, (Schema<MessageLite>) getMessageFieldSchema(pos), extensionRegistry); |
|
|
|
|
storeOneofMessageField(message, number, pos, current); |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
default: |
|
|
|
|
// Assume we've landed on an empty entry. Treat it as an unknown field.
|
|
|
|
|
if (unknownFields == null) { |
|
|
|
|
unknownFields = unknownFieldSchema.newBuilder(); |
|
|
|
|
unknownFields = unknownFieldSchema.getBuilderFromMessage(message); |
|
|
|
|
} |
|
|
|
|
if (!unknownFieldSchema.mergeOneFieldFrom(unknownFields, reader)) { |
|
|
|
|
return; |
|
|
|
@ -4333,7 +4346,8 @@ final class MessageSchema<T> implements Schema<T> { |
|
|
|
|
} finally { |
|
|
|
|
for (int i = checkInitializedCount; i < repeatedFieldOffsetStart; i++) { |
|
|
|
|
unknownFields = |
|
|
|
|
filterMapUnknownEnumValues(message, intArray[i], unknownFields, unknownFieldSchema); |
|
|
|
|
filterMapUnknownEnumValues( |
|
|
|
|
message, intArray[i], unknownFields, unknownFieldSchema, message); |
|
|
|
|
} |
|
|
|
|
if (unknownFields != null) { |
|
|
|
|
unknownFieldSchema.setBuilderToMessage(message, unknownFields); |
|
|
|
@ -4343,6 +4357,8 @@ final class MessageSchema<T> implements Schema<T> { |
|
|
|
|
|
|
|
|
|
@SuppressWarnings("ReferenceEquality") |
|
|
|
|
static UnknownFieldSetLite getMutableUnknownFields(Object message) { |
|
|
|
|
// TODO(b/248560713) decide if we're keeping support for Full in schema classes and handle this
|
|
|
|
|
// better.
|
|
|
|
|
UnknownFieldSetLite unknownFields = ((GeneratedMessageLite) message).unknownFields; |
|
|
|
|
if (unknownFields == UnknownFieldSetLite.getDefaultInstance()) { |
|
|
|
|
unknownFields = UnknownFieldSetLite.newInstance(); |
|
|
|
@ -4603,24 +4619,13 @@ final class MessageSchema<T> implements Schema<T> { |
|
|
|
|
} else { |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
UnknownFieldSetLite unknownFields = ((GeneratedMessageLite) message).unknownFields; |
|
|
|
|
if (unknownFields == UnknownFieldSetLite.getDefaultInstance()) { |
|
|
|
|
// filterUnknownEnumList() expects the unknownFields parameter to be mutable or null.
|
|
|
|
|
// Since we don't know yet whether there exist unknown enum values, we'd better pass
|
|
|
|
|
// null to it instead of allocating a mutable instance. This is also needed to be
|
|
|
|
|
// consistent with the behavior of generated parser/builder.
|
|
|
|
|
unknownFields = null; |
|
|
|
|
} |
|
|
|
|
unknownFields = |
|
|
|
|
SchemaUtil.filterUnknownEnumList( |
|
|
|
|
number, |
|
|
|
|
(ProtobufList<Integer>) list, |
|
|
|
|
getEnumFieldVerifier(bufferPosition), |
|
|
|
|
unknownFields, |
|
|
|
|
(UnknownFieldSchema<UnknownFieldSetLite, UnknownFieldSetLite>) unknownFieldSchema); |
|
|
|
|
if (unknownFields != null) { |
|
|
|
|
((GeneratedMessageLite) message).unknownFields = unknownFields; |
|
|
|
|
} |
|
|
|
|
SchemaUtil.filterUnknownEnumList( |
|
|
|
|
message, |
|
|
|
|
number, |
|
|
|
|
(ProtobufList<Integer>) list, |
|
|
|
|
getEnumFieldVerifier(bufferPosition), |
|
|
|
|
null, |
|
|
|
|
(UnknownFieldSchema<UnknownFieldSetLite, UnknownFieldSetLite>) unknownFieldSchema); |
|
|
|
|
break; |
|
|
|
|
case 33: // SINT32_LIST:
|
|
|
|
|
case 47: // SINT32_LIST_PACKED:
|
|
|
|
@ -4774,20 +4779,11 @@ final class MessageSchema<T> implements Schema<T> { |
|
|
|
|
break; |
|
|
|
|
case 60: // ONEOF_MESSAGE:
|
|
|
|
|
if (wireType == WireFormat.WIRETYPE_LENGTH_DELIMITED) { |
|
|
|
|
final Object current = mutableOneofMessageFieldForMerge(message, number, bufferPosition); |
|
|
|
|
position = |
|
|
|
|
decodeMessageField( |
|
|
|
|
getMessageFieldSchema(bufferPosition), data, position, limit, registers); |
|
|
|
|
final Object oldValue = |
|
|
|
|
unsafe.getInt(message, oneofCaseOffset) == number |
|
|
|
|
? unsafe.getObject(message, fieldOffset) |
|
|
|
|
: null; |
|
|
|
|
if (oldValue == null) { |
|
|
|
|
unsafe.putObject(message, fieldOffset, registers.object1); |
|
|
|
|
} else { |
|
|
|
|
unsafe.putObject( |
|
|
|
|
message, fieldOffset, Internal.mergeMessage(oldValue, registers.object1)); |
|
|
|
|
} |
|
|
|
|
unsafe.putInt(message, oneofCaseOffset, number); |
|
|
|
|
mergeMessageField( |
|
|
|
|
current, getMessageFieldSchema(bufferPosition), data, position, limit, registers); |
|
|
|
|
storeOneofMessageField(message, number, bufferPosition, current); |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
case 61: // ONEOF_BYTES:
|
|
|
|
@ -4827,21 +4823,18 @@ final class MessageSchema<T> implements Schema<T> { |
|
|
|
|
break; |
|
|
|
|
case 68: // ONEOF_GROUP:
|
|
|
|
|
if (wireType == WireFormat.WIRETYPE_START_GROUP) { |
|
|
|
|
final Object current = mutableOneofMessageFieldForMerge(message, number, bufferPosition); |
|
|
|
|
final int endTag = (tag & ~0x7) | WireFormat.WIRETYPE_END_GROUP; |
|
|
|
|
position = |
|
|
|
|
decodeGroupField( |
|
|
|
|
getMessageFieldSchema(bufferPosition), data, position, limit, endTag, registers); |
|
|
|
|
final Object oldValue = |
|
|
|
|
unsafe.getInt(message, oneofCaseOffset) == number |
|
|
|
|
? unsafe.getObject(message, fieldOffset) |
|
|
|
|
: null; |
|
|
|
|
if (oldValue == null) { |
|
|
|
|
unsafe.putObject(message, fieldOffset, registers.object1); |
|
|
|
|
} else { |
|
|
|
|
unsafe.putObject( |
|
|
|
|
message, fieldOffset, Internal.mergeMessage(oldValue, registers.object1)); |
|
|
|
|
} |
|
|
|
|
unsafe.putInt(message, oneofCaseOffset, number); |
|
|
|
|
mergeGroupField( |
|
|
|
|
current, |
|
|
|
|
getMessageFieldSchema(bufferPosition), |
|
|
|
|
data, |
|
|
|
|
position, |
|
|
|
|
limit, |
|
|
|
|
endTag, |
|
|
|
|
registers); |
|
|
|
|
storeOneofMessageField(message, number, bufferPosition, current); |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
default: |
|
|
|
@ -4879,6 +4872,7 @@ final class MessageSchema<T> implements Schema<T> { |
|
|
|
|
int parseProto2Message( |
|
|
|
|
T message, byte[] data, int position, int limit, int endGroup, Registers registers) |
|
|
|
|
throws IOException { |
|
|
|
|
checkMutable(message); |
|
|
|
|
final sun.misc.Unsafe unsafe = UNSAFE; |
|
|
|
|
int currentPresenceFieldOffset = NO_PRESENCE_SENTINEL; |
|
|
|
|
int currentPresenceField = 0; |
|
|
|
@ -4995,18 +4989,11 @@ final class MessageSchema<T> implements Schema<T> { |
|
|
|
|
break; |
|
|
|
|
case 9: // MESSAGE
|
|
|
|
|
if (wireType == WireFormat.WIRETYPE_LENGTH_DELIMITED) { |
|
|
|
|
final Object current = mutableMessageFieldForMerge(message, pos); |
|
|
|
|
position = |
|
|
|
|
decodeMessageField( |
|
|
|
|
getMessageFieldSchema(pos), data, position, limit, registers); |
|
|
|
|
if ((currentPresenceField & presenceMask) == 0) { |
|
|
|
|
unsafe.putObject(message, fieldOffset, registers.object1); |
|
|
|
|
} else { |
|
|
|
|
unsafe.putObject( |
|
|
|
|
message, |
|
|
|
|
fieldOffset, |
|
|
|
|
Internal.mergeMessage( |
|
|
|
|
unsafe.getObject(message, fieldOffset), registers.object1)); |
|
|
|
|
} |
|
|
|
|
mergeMessageField( |
|
|
|
|
current, getMessageFieldSchema(pos), data, position, limit, registers); |
|
|
|
|
storeMessageField(message, pos, current); |
|
|
|
|
currentPresenceField |= presenceMask; |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
@ -5055,20 +5042,18 @@ final class MessageSchema<T> implements Schema<T> { |
|
|
|
|
break; |
|
|
|
|
case 17: // GROUP
|
|
|
|
|
if (wireType == WireFormat.WIRETYPE_START_GROUP) { |
|
|
|
|
final Object current = mutableMessageFieldForMerge(message, pos); |
|
|
|
|
final int endTag = (number << 3) | WireFormat.WIRETYPE_END_GROUP; |
|
|
|
|
position = |
|
|
|
|
decodeGroupField( |
|
|
|
|
getMessageFieldSchema(pos), data, position, limit, endTag, registers); |
|
|
|
|
if ((currentPresenceField & presenceMask) == 0) { |
|
|
|
|
unsafe.putObject(message, fieldOffset, registers.object1); |
|
|
|
|
} else { |
|
|
|
|
unsafe.putObject( |
|
|
|
|
message, |
|
|
|
|
fieldOffset, |
|
|
|
|
Internal.mergeMessage( |
|
|
|
|
unsafe.getObject(message, fieldOffset), registers.object1)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
mergeGroupField( |
|
|
|
|
current, |
|
|
|
|
getMessageFieldSchema(pos), |
|
|
|
|
data, |
|
|
|
|
position, |
|
|
|
|
limit, |
|
|
|
|
endTag, |
|
|
|
|
registers); |
|
|
|
|
storeMessageField(message, pos, current); |
|
|
|
|
currentPresenceField |= presenceMask; |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
@ -5166,7 +5151,8 @@ final class MessageSchema<T> implements Schema<T> { |
|
|
|
|
message, |
|
|
|
|
intArray[i], |
|
|
|
|
unknownFields, |
|
|
|
|
(UnknownFieldSchema<UnknownFieldSetLite, UnknownFieldSetLite>) unknownFieldSchema); |
|
|
|
|
(UnknownFieldSchema<UnknownFieldSetLite, UnknownFieldSetLite>) unknownFieldSchema, |
|
|
|
|
message); |
|
|
|
|
} |
|
|
|
|
if (unknownFields != null) { |
|
|
|
|
((UnknownFieldSchema<UnknownFieldSetLite, UnknownFieldSetLite>) unknownFieldSchema) |
|
|
|
@ -5184,10 +5170,66 @@ final class MessageSchema<T> implements Schema<T> { |
|
|
|
|
return position; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private Object mutableMessageFieldForMerge(T message, int pos) { |
|
|
|
|
final Schema fieldSchema = getMessageFieldSchema(pos); |
|
|
|
|
final long offset = offset(typeAndOffsetAt(pos)); |
|
|
|
|
|
|
|
|
|
// Field not present, create a new one
|
|
|
|
|
if (!isFieldPresent(message, pos)) { |
|
|
|
|
return fieldSchema.newInstance(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Field present, if mutable, ready to merge
|
|
|
|
|
final Object current = UNSAFE.getObject(message, offset); |
|
|
|
|
if (isMutable(current)) { |
|
|
|
|
return current; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Field present but immutable, make a new mutable copy
|
|
|
|
|
final Object newMessage = fieldSchema.newInstance(); |
|
|
|
|
if (current != null) { |
|
|
|
|
fieldSchema.mergeFrom(newMessage, current); |
|
|
|
|
} |
|
|
|
|
return newMessage; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private void storeMessageField(T message, int pos, Object field) { |
|
|
|
|
UNSAFE.putObject(message, offset(typeAndOffsetAt(pos)), field); |
|
|
|
|
setFieldPresent(message, pos); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private Object mutableOneofMessageFieldForMerge(T message, int fieldNumber, int pos) { |
|
|
|
|
final Schema fieldSchema = getMessageFieldSchema(pos); |
|
|
|
|
|
|
|
|
|
// Field not present, create it and mark it present
|
|
|
|
|
if (!isOneofPresent(message, fieldNumber, pos)) { |
|
|
|
|
return fieldSchema.newInstance(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Field present, if mutable, ready to merge
|
|
|
|
|
final Object current = UNSAFE.getObject(message, offset(typeAndOffsetAt(pos))); |
|
|
|
|
if (isMutable(current)) { |
|
|
|
|
return current; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Field present but immutable, make a new mutable copy
|
|
|
|
|
final Object newMessage = fieldSchema.newInstance(); |
|
|
|
|
if (current != null) { |
|
|
|
|
fieldSchema.mergeFrom(newMessage, current); |
|
|
|
|
} |
|
|
|
|
return newMessage; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private void storeOneofMessageField(T message, int fieldNumber, int pos, Object field) { |
|
|
|
|
UNSAFE.putObject(message, offset(typeAndOffsetAt(pos)), field); |
|
|
|
|
setOneofPresent(message, fieldNumber, pos); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** Parses a proto3 message and returns the limit if parsing is successful. */ |
|
|
|
|
@CanIgnoreReturnValue |
|
|
|
|
private int parseProto3Message( |
|
|
|
|
T message, byte[] data, int position, int limit, Registers registers) throws IOException { |
|
|
|
|
checkMutable(message); |
|
|
|
|
final sun.misc.Unsafe unsafe = UNSAFE; |
|
|
|
|
int currentPresenceFieldOffset = NO_PRESENCE_SENTINEL; |
|
|
|
|
int currentPresenceField = 0; |
|
|
|
@ -5309,16 +5351,11 @@ final class MessageSchema<T> implements Schema<T> { |
|
|
|
|
break; |
|
|
|
|
case 9: // MESSAGE:
|
|
|
|
|
if (wireType == WireFormat.WIRETYPE_LENGTH_DELIMITED) { |
|
|
|
|
final Object current = mutableMessageFieldForMerge(message, pos); |
|
|
|
|
position = |
|
|
|
|
decodeMessageField( |
|
|
|
|
getMessageFieldSchema(pos), data, position, limit, registers); |
|
|
|
|
final Object oldValue = unsafe.getObject(message, fieldOffset); |
|
|
|
|
if (oldValue == null) { |
|
|
|
|
unsafe.putObject(message, fieldOffset, registers.object1); |
|
|
|
|
} else { |
|
|
|
|
unsafe.putObject( |
|
|
|
|
message, fieldOffset, Internal.mergeMessage(oldValue, registers.object1)); |
|
|
|
|
} |
|
|
|
|
mergeMessageField( |
|
|
|
|
current, getMessageFieldSchema(pos), data, position, limit, registers); |
|
|
|
|
storeMessageField(message, pos, current); |
|
|
|
|
currentPresenceField |= presenceMask; |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
@ -5449,18 +5486,73 @@ final class MessageSchema<T> implements Schema<T> { |
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
|
public void makeImmutable(T message) { |
|
|
|
|
// Make all repeated/map fields immutable.
|
|
|
|
|
for (int i = checkInitializedCount; i < repeatedFieldOffsetStart; i++) { |
|
|
|
|
long offset = offset(typeAndOffsetAt(intArray[i])); |
|
|
|
|
Object mapField = UnsafeUtil.getObject(message, offset); |
|
|
|
|
if (mapField == null) { |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
UnsafeUtil.putObject(message, offset, mapFieldSchema.toImmutable(mapField)); |
|
|
|
|
if (!isMutable(message)) { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// TODO(b/248560713) decide if we're keeping support for Full in schema classes and handle this
|
|
|
|
|
// better.
|
|
|
|
|
if (message instanceof GeneratedMessageLite) { |
|
|
|
|
GeneratedMessageLite<?, ?> generatedMessage = ((GeneratedMessageLite<?, ?>) message); |
|
|
|
|
generatedMessage.clearMemoizedSerializedSize(); |
|
|
|
|
generatedMessage.clearMemoizedHashCode(); |
|
|
|
|
generatedMessage.markImmutable(); |
|
|
|
|
} |
|
|
|
|
final int length = intArray.length; |
|
|
|
|
for (int i = repeatedFieldOffsetStart; i < length; i++) { |
|
|
|
|
listFieldSchema.makeImmutableListAt(message, intArray[i]); |
|
|
|
|
|
|
|
|
|
final int bufferLength = buffer.length; |
|
|
|
|
for (int pos = 0; pos < bufferLength; pos += INTS_PER_FIELD) { |
|
|
|
|
final int typeAndOffset = typeAndOffsetAt(pos); |
|
|
|
|
final long offset = offset(typeAndOffset); |
|
|
|
|
switch (type(typeAndOffset)) { |
|
|
|
|
case 17: // GROUP
|
|
|
|
|
case 9: // MESSAGE
|
|
|
|
|
if (isFieldPresent(message, pos)) { |
|
|
|
|
getMessageFieldSchema(pos).makeImmutable(UNSAFE.getObject(message, offset)); |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
case 18: // DOUBLE_LIST:
|
|
|
|
|
case 19: // FLOAT_LIST:
|
|
|
|
|
case 20: // INT64_LIST:
|
|
|
|
|
case 21: // UINT64_LIST:
|
|
|
|
|
case 22: // INT32_LIST:
|
|
|
|
|
case 23: // FIXED64_LIST:
|
|
|
|
|
case 24: // FIXED32_LIST:
|
|
|
|
|
case 25: // BOOL_LIST:
|
|
|
|
|
case 26: // STRING_LIST:
|
|
|
|
|
case 27: // MESSAGE_LIST:
|
|
|
|
|
case 28: // BYTES_LIST:
|
|
|
|
|
case 29: // UINT32_LIST:
|
|
|
|
|
case 30: // ENUM_LIST:
|
|
|
|
|
case 31: // SFIXED32_LIST:
|
|
|
|
|
case 32: // SFIXED64_LIST:
|
|
|
|
|
case 33: // SINT32_LIST:
|
|
|
|
|
case 34: // SINT64_LIST:
|
|
|
|
|
case 35: // DOUBLE_LIST_PACKED:
|
|
|
|
|
case 36: // FLOAT_LIST_PACKED:
|
|
|
|
|
case 37: // INT64_LIST_PACKED:
|
|
|
|
|
case 38: // UINT64_LIST_PACKED:
|
|
|
|
|
case 39: // INT32_LIST_PACKED:
|
|
|
|
|
case 40: // FIXED64_LIST_PACKED:
|
|
|
|
|
case 41: // FIXED32_LIST_PACKED:
|
|
|
|
|
case 42: // BOOL_LIST_PACKED:
|
|
|
|
|
case 43: // UINT32_LIST_PACKED:
|
|
|
|
|
case 44: // ENUM_LIST_PACKED:
|
|
|
|
|
case 45: // SFIXED32_LIST_PACKED:
|
|
|
|
|
case 46: // SFIXED64_LIST_PACKED:
|
|
|
|
|
case 47: // SINT32_LIST_PACKED:
|
|
|
|
|
case 48: // SINT64_LIST_PACKED:
|
|
|
|
|
case 49: // GROUP_LIST:
|
|
|
|
|
listFieldSchema.makeImmutableListAt(message, offset); |
|
|
|
|
break; |
|
|
|
|
case 50: // MAP:
|
|
|
|
|
{ |
|
|
|
|
Object mapField = UNSAFE.getObject(message, offset); |
|
|
|
|
if (mapField != null) { |
|
|
|
|
UNSAFE.putObject(message, offset, mapFieldSchema.toImmutable(mapField)); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
unknownFieldSchema.makeImmutable(message); |
|
|
|
|
if (hasExtensions) { |
|
|
|
@ -5497,8 +5589,12 @@ final class MessageSchema<T> implements Schema<T> { |
|
|
|
|
extensionRegistry); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private final <UT, UB> UB filterMapUnknownEnumValues( |
|
|
|
|
Object message, int pos, UB unknownFields, UnknownFieldSchema<UT, UB> unknownFieldSchema) { |
|
|
|
|
private <UT, UB> UB filterMapUnknownEnumValues( |
|
|
|
|
Object message, |
|
|
|
|
int pos, |
|
|
|
|
UB unknownFields, |
|
|
|
|
UnknownFieldSchema<UT, UB> unknownFieldSchema, |
|
|
|
|
Object containerMessage) { |
|
|
|
|
int fieldNumber = numberAt(pos); |
|
|
|
|
long offset = offset(typeAndOffsetAt(pos)); |
|
|
|
|
Object mapField = UnsafeUtil.getObject(message, offset); |
|
|
|
@ -5513,25 +5609,32 @@ final class MessageSchema<T> implements Schema<T> { |
|
|
|
|
// Filter unknown enum values.
|
|
|
|
|
unknownFields = |
|
|
|
|
filterUnknownEnumMap( |
|
|
|
|
pos, fieldNumber, mapData, enumVerifier, unknownFields, unknownFieldSchema); |
|
|
|
|
pos, |
|
|
|
|
fieldNumber, |
|
|
|
|
mapData, |
|
|
|
|
enumVerifier, |
|
|
|
|
unknownFields, |
|
|
|
|
unknownFieldSchema, |
|
|
|
|
containerMessage); |
|
|
|
|
return unknownFields; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@SuppressWarnings("unchecked") |
|
|
|
|
private final <K, V, UT, UB> UB filterUnknownEnumMap( |
|
|
|
|
private <K, V, UT, UB> UB filterUnknownEnumMap( |
|
|
|
|
int pos, |
|
|
|
|
int number, |
|
|
|
|
Map<K, V> mapData, |
|
|
|
|
EnumVerifier enumVerifier, |
|
|
|
|
UB unknownFields, |
|
|
|
|
UnknownFieldSchema<UT, UB> unknownFieldSchema) { |
|
|
|
|
UnknownFieldSchema<UT, UB> unknownFieldSchema, |
|
|
|
|
Object containerMessage) { |
|
|
|
|
Metadata<K, V> metadata = |
|
|
|
|
(Metadata<K, V>) mapFieldSchema.forMapMetadata(getMapFieldDefaultEntry(pos)); |
|
|
|
|
for (Iterator<Map.Entry<K, V>> it = mapData.entrySet().iterator(); it.hasNext(); ) { |
|
|
|
|
Map.Entry<K, V> entry = it.next(); |
|
|
|
|
if (!enumVerifier.isInRange((Integer) entry.getValue())) { |
|
|
|
|
if (unknownFields == null) { |
|
|
|
|
unknownFields = unknownFieldSchema.newBuilder(); |
|
|
|
|
unknownFields = unknownFieldSchema.getBuilderFromMessage(containerMessage); |
|
|
|
|
} |
|
|
|
|
int entrySize = |
|
|
|
|
MapEntryLite.computeSerializedSize(metadata, entry.getKey(), entry.getValue()); |
|
|
|
@ -5748,6 +5851,28 @@ final class MessageSchema<T> implements Schema<T> { |
|
|
|
|
return value & OFFSET_MASK; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private static boolean isMutable(Object message) { |
|
|
|
|
if (message == null) { |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// TODO(b/248560713) decide if we're keeping support for Full in schema classes and handle this
|
|
|
|
|
// better.
|
|
|
|
|
if (message instanceof GeneratedMessageLite<?, ?>) { |
|
|
|
|
return ((GeneratedMessageLite<?, ?>) message).isMutable(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// For other types, we'll assume this is true because that's what was
|
|
|
|
|
// happening before we started checking.
|
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private static void checkMutable(Object message) { |
|
|
|
|
if (!isMutable(message)) { |
|
|
|
|
throw new IllegalArgumentException("Mutating immutable message: " + message); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private static <T> double doubleAt(T message, long offset) { |
|
|
|
|
return UnsafeUtil.getDouble(message, offset); |
|
|
|
|
} |
|
|
|
|