@ -94,6 +94,17 @@ final class MessageSchema<T> implements Schema<T> {
private static final int NO_PRESENCE_SENTINEL = - 1 & OFFSET_MASK ;
private static final int [ ] EMPTY_INT_ARRAY = new int [ 0 ] ;
/ * *
* Bit masks for field type extra feature bits encoded in Java gencode via
* GetExperimentalJavaFieldType in helpers . cc .
* /
private static final int REQUIRED_BIT = 0x100 ;
private static final int UTF8_CHECK_BIT = 0x200 ;
private static final int CHECK_INITIALIZED_BIT = 0x400 ;
private static final int LEGACY_ENUM_IS_CLOSED_BIT = 0x800 ;
private static final int HAS_HAS_BIT = 0x1000 ;
/** An offset applied to the field type ID for scalar fields that are a member of a oneof. */
static final int ONEOF_TYPE_OFFSET = 51 /* FieldType.MAP + 1 */ ;
@ -154,7 +165,7 @@ final class MessageSchema<T> implements Schema<T> {
private final MessageLite defaultInstance ;
private final boolean hasExtensions ;
private final boolean lite ;
private final boolean proto3 ;
private final ProtoSyntax syntax ;
// TODO(xiaofeng): Make both full-runtime and lite-runtime support cached field size.
private final boolean useCachedSizeField ;
@ -185,7 +196,7 @@ final class MessageSchema<T> implements Schema<T> {
int minFieldNumber ,
int maxFieldNumber ,
MessageLite defaultInstance ,
boolean proto3 ,
ProtoSyntax syntax ,
boolean useCachedSizeField ,
int [ ] intArray ,
int checkInitialized ,
@ -201,7 +212,7 @@ final class MessageSchema<T> implements Schema<T> {
this . maxFieldNumber = maxFieldNumber ;
this . lite = defaultInstance instanceof GeneratedMessageLite ;
this . proto3 = proto3 ;
this . syntax = syntax ;
this . hasExtensions = extensionSchema ! = null & & extensionSchema . hasExtensions ( defaultInstance ) ;
this . useCachedSizeField = useCachedSizeField ;
@ -252,8 +263,6 @@ final class MessageSchema<T> implements Schema<T> {
UnknownFieldSchema < ? , ? > unknownFieldSchema ,
ExtensionSchema < ? > extensionSchema ,
MapFieldSchema mapFieldSchema ) {
final boolean isProto3 = messageInfo . getSyntax ( ) = = ProtoSyntax . PROTO3 ;
String info = messageInfo . getStringInfo ( ) ;
final int length = info . length ( ) ;
int i = 0 ;
@ -445,7 +454,7 @@ final class MessageSchema<T> implements Schema<T> {
fieldTypeWithExtraBits = next ;
fieldType = fieldTypeWithExtraBits & 0xFF ;
if ( ( fieldTypeWithExtraBits & 0x400 ) ! = 0 ) {
if ( ( fieldTypeWithExtraBits & CHECK_INITIALIZED_BIT ) ! = 0 ) {
intArray [ checkInitializedPosition + + ] = bufferIndex ;
}
@ -472,7 +481,10 @@ final class MessageSchema<T> implements Schema<T> {
| | oneofFieldType = = 17 /* FieldType.GROUP */ ) {
objects [ bufferIndex / INTS_PER_FIELD * 2 + 1 ] = messageInfoObjects [ objectsPosition + + ] ;
} else if ( oneofFieldType = = 12 /* FieldType.ENUM */ ) {
if ( ! isProto3 ) {
// TODO(b/279034699): Remove proto2 check once legacy gencode not setting this bit
// no longer needs to be supported.
if ( messageInfo . getSyntax ( ) . equals ( ProtoSyntax . PROTO2 )
| | ( fieldTypeWithExtraBits & LEGACY_ENUM_IS_CLOSED_BIT ) ! = 0 ) {
objects [ bufferIndex / INTS_PER_FIELD * 2 + 1 ] = messageInfoObjects [ objectsPosition + + ] ;
}
}
@ -515,19 +527,22 @@ final class MessageSchema<T> implements Schema<T> {
} else if ( fieldType = = 12 /* FieldType.ENUM */
| | fieldType = = 30 /* FieldType.ENUM_LIST */
| | fieldType = = 44 /* FieldType.ENUM_LIST_PACKED */ ) {
if ( ! isProto3 ) {
// TODO(b/279034699): Remove proto2 check once legacy gencode not setting this bit
// no longer needs to be supported.
if ( messageInfo . getSyntax ( ) = = ProtoSyntax . PROTO2
| | ( fieldTypeWithExtraBits & LEGACY_ENUM_IS_CLOSED_BIT ) ! = 0 ) {
objects [ bufferIndex / INTS_PER_FIELD * 2 + 1 ] = messageInfoObjects [ objectsPosition + + ] ;
}
} else if ( fieldType = = 50 /* FieldType.MAP */ ) {
intArray [ mapFieldIndex + + ] = bufferIndex ;
objects [ bufferIndex / INTS_PER_FIELD * 2 ] = messageInfoObjects [ objectsPosition + + ] ;
if ( ( fieldTypeWithExtraBits & 0x800 ) ! = 0 ) {
if ( ( fieldTypeWithExtraBits & LEGACY_ENUM_IS_CLOSED_BIT ) ! = 0 ) {
objects [ bufferIndex / INTS_PER_FIELD * 2 + 1 ] = messageInfoObjects [ objectsPosition + + ] ;
}
}
fieldOffset = ( int ) unsafe . objectFieldOffset ( field ) ;
boolean hasHasBit = ( fieldTypeWithExtraBits & 0x1000 ) = = 0x100 0;
boolean hasHasBit = ( fieldTypeWithExtraBits & HAS_HAS_BIT ) ! = 0 ;
if ( hasHasBit & & fieldType < = 17 /* FieldType.GROUP */ ) {
next = info . charAt ( i + + ) ;
if ( next > = 0xD800 ) {
@ -567,8 +582,8 @@ final class MessageSchema<T> implements Schema<T> {
buffer [ bufferIndex + + ] = fieldNumber ;
buffer [ bufferIndex + + ] =
( ( fieldTypeWithExtraBits & 0x200 ) ! = 0 ? ENFORCE_UTF8_MASK : 0 )
| ( ( fieldTypeWithExtraBits & 0x100 ) ! = 0 ? REQUIRED_MASK : 0 )
( ( fieldTypeWithExtraBits & UTF8_CHECK_BIT ) ! = 0 ? ENFORCE_UTF8_MASK : 0 )
| ( ( fieldTypeWithExtraBits & REQUIRED_BIT ) ! = 0 ? REQUIRED_MASK : 0 )
| ( fieldType < < OFFSET_BITS )
| fieldOffset ;
buffer [ bufferIndex + + ] = ( presenceMaskShift < < OFFSET_BITS ) | presenceFieldOffset ;
@ -580,7 +595,7 @@ final class MessageSchema<T> implements Schema<T> {
minFieldNumber ,
maxFieldNumber ,
messageInfo . getDefaultInstance ( ) ,
isProto3 ,
messageInfo . getSyntax ( ) ,
/* useCachedSizeField= */ false ,
intArray ,
checkInitialized ,
@ -624,7 +639,6 @@ final class MessageSchema<T> implements Schema<T> {
UnknownFieldSchema < ? , ? > unknownFieldSchema ,
ExtensionSchema < ? > extensionSchema ,
MapFieldSchema mapFieldSchema ) {
final boolean isProto3 = messageInfo . getSyntax ( ) = = ProtoSyntax . PROTO3 ;
FieldInfo [ ] fis = messageInfo . getFields ( ) ;
final int minFieldNumber ;
final int maxFieldNumber ;
@ -714,7 +728,7 @@ final class MessageSchema<T> implements Schema<T> {
minFieldNumber ,
maxFieldNumber ,
messageInfo . getDefaultInstance ( ) ,
isProto3 ,
messageInfo . getSyntax ( ) ,
/* useCachedSizeField= */ true ,
combined ,
checkInitialized . length ,
@ -1458,7 +1472,13 @@ final class MessageSchema<T> implements Schema<T> {
@Override
public int getSerializedSize ( T message ) {
return proto3 ? getSerializedSizeProto3 ( message ) : getSerializedSizeProto2 ( message ) ;
switch ( syntax ) {
case PROTO2 :
return getSerializedSizeProto2 ( message ) ;
case PROTO3 :
return getSerializedSizeProto3 ( message ) ;
}
throw new IllegalArgumentException ( "Unsupported syntax: " + syntax ) ;
}
@SuppressWarnings ( "unchecked" )
@ -2580,10 +2600,13 @@ final class MessageSchema<T> implements Schema<T> {
if ( writer . fieldOrder ( ) = = Writer . FieldOrder . DESCENDING ) {
writeFieldsInDescendingOrder ( message , writer ) ;
} else {
if ( proto3 ) {
writeFieldsInAscendingOrderProto3 ( message , writer ) ;
} else {
writeFieldsInAscendingOrderProto2 ( message , writer ) ;
switch ( syntax ) {
case PROTO3 :
writeFieldsInAscendingOrderProto3 ( message , writer ) ;
break ;
case PROTO2 :
writeFieldsInAscendingOrderProto2 ( message , writer ) ;
break ;
}
}
}
@ -5477,10 +5500,13 @@ final class MessageSchema<T> implements Schema<T> {
@Override
public void mergeFrom ( T message , byte [ ] data , int position , int limit , Registers registers )
throws IOException {
if ( proto3 ) {
parseProto3Message ( message , data , position , limit , registers ) ;
} else {
parseProto2Message ( message , data , position , limit , 0 , registers ) ;
switch ( syntax ) {
case PROTO3 :
parseProto3Message ( message , data , position , limit , registers ) ;
break ;
case PROTO2 :
parseProto2Message ( message , data , position , limit , 0 , registers ) ;
break ;
}
}
@ -5683,7 +5709,7 @@ final class MessageSchema<T> implements Schema<T> {
message , pos , currentPresenceFieldOffset , currentPresenceField , presenceMask ) ) {
return false ;
}
// If a required message field is set but has no required fields of it' s own, we still
// If a required message field is set but has no required fields of its own, we still
// proceed and check the message is initialized. It should be fairly cheap to check these
// messages but is worth documenting.
}