aboutsummaryrefslogtreecommitdiffhomepage
path: root/java/src/main/java/com/google/protobuf/GeneratedMessageLite.java
diff options
context:
space:
mode:
Diffstat (limited to 'java/src/main/java/com/google/protobuf/GeneratedMessageLite.java')
-rw-r--r--java/src/main/java/com/google/protobuf/GeneratedMessageLite.java352
1 files changed, 184 insertions, 168 deletions
diff --git a/java/src/main/java/com/google/protobuf/GeneratedMessageLite.java b/java/src/main/java/com/google/protobuf/GeneratedMessageLite.java
index a535b718..4316efee 100644
--- a/java/src/main/java/com/google/protobuf/GeneratedMessageLite.java
+++ b/java/src/main/java/com/google/protobuf/GeneratedMessageLite.java
@@ -62,9 +62,8 @@ public abstract class GeneratedMessageLite<
private static final long serialVersionUID = 1L;
- /** For use by generated code only. */
- protected UnknownFieldSetLite unknownFields =
- UnknownFieldSetLite.getDefaultInstance();
+ /** For use by generated code only. Lazily initialized to reduce allocations. */
+ protected UnknownFieldSetLite unknownFields = null;
/** For use by generated code only. */
protected int memoizedSerializedSize = -1;
@@ -84,19 +83,56 @@ public abstract class GeneratedMessageLite<
return (BuilderType) dynamicMethod(MethodToInvoke.NEW_BUILDER);
}
+ // The general strategy for unknown fields is to use an UnknownFieldSetLite that is treated as
+ // mutable during the parsing constructor and immutable after. This allows us to avoid
+ // any unnecessary intermediary allocations while reducing the generated code size.
+
+ /**
+ * Lazily initializes unknown fields.
+ */
+ private final void ensureUnknownFieldsInitialized() {
+ if (unknownFields == null) {
+ unknownFields = UnknownFieldSetLite.newInstance();
+ }
+ }
+
/**
- * Called by subclasses to parse an unknown field. For use by generated code
- * only.
+ * Called by subclasses to parse an unknown field. For use by generated code only.
+ *
* @return {@code true} unless the tag is an end-group tag.
*/
- protected static boolean parseUnknownField(
- CodedInputStream input,
- UnknownFieldSetLite.Builder unknownFields,
- ExtensionRegistryLite extensionRegistry,
- int tag) throws IOException {
+ protected boolean parseUnknownField(int tag, CodedInputStream input) throws IOException {
+ ensureUnknownFieldsInitialized();
return unknownFields.mergeFieldFrom(tag, input);
}
+ /**
+ * Called by subclasses to parse an unknown field. For use by generated code only.
+ */
+ protected void mergeVarintField(int tag, int value) {
+ ensureUnknownFieldsInitialized();
+ unknownFields.mergeVarintField(tag, value);
+ }
+
+ /**
+ * Called by subclasses to parse an unknown field. For use by generated code only.
+ */
+ protected void mergeLengthDelimitedField(int fieldNumber, ByteString value) {
+ ensureUnknownFieldsInitialized();
+ unknownFields.mergeLengthDelimitedField(fieldNumber, value);
+ }
+
+ /**
+ * Called by subclasses to complete parsing. For use by generated code only.
+ */
+ protected void doneParsing() {
+ if (unknownFields == null) {
+ unknownFields = UnknownFieldSetLite.getDefaultInstance();
+ } else {
+ unknownFields.makeImmutable();
+ }
+ }
+
public final boolean isInitialized() {
return dynamicMethod(MethodToInvoke.IS_INITIALIZED, Boolean.TRUE) != null;
}
@@ -171,7 +207,7 @@ public abstract class GeneratedMessageLite<
* <p>For use by generated code only.
*/
protected final void mergeUnknownFields(UnknownFieldSetLite unknownFields) {
- this.unknownFields = UnknownFieldSetLite.concat(this.unknownFields, unknownFields);
+ this.unknownFields = UnknownFieldSetLite.mutableCopyOf(this.unknownFields, unknownFields);
}
@SuppressWarnings("unchecked")
@@ -225,7 +261,13 @@ public abstract class GeneratedMessageLite<
//@Override (Java 1.6 override semantics, but we must support 1.5)
public MessageType buildPartial() {
+ if (isBuilt) {
+ return instance;
+ }
+
instance.dynamicMethod(MethodToInvoke.MAKE_IMMUTABLE);
+ instance.unknownFields.makeImmutable();
+
isBuilt = true;
return instance;
}
@@ -249,18 +291,6 @@ public abstract class GeneratedMessageLite<
public MessageType getDefaultInstanceForType() {
return defaultInstance;
}
-
- /**
- * Called by subclasses to parse an unknown field.
- * @return {@code true} unless the tag is an end-group tag.
- */
- protected boolean parseUnknownField(
- CodedInputStream input,
- UnknownFieldSetLite.Builder unknownFields,
- ExtensionRegistryLite extensionRegistry,
- int tag) throws IOException {
- return unknownFields.mergeFieldFrom(tag, input);
- }
public BuilderType mergeFrom(
com.google.protobuf.CodedInputStream input,
@@ -334,6 +364,130 @@ public abstract class GeneratedMessageLite<
extensions.mergeFrom(((ExtendableMessage) other).extensions);
}
+ /**
+ * Parse an unknown field or an extension. For use by generated code only.
+ *
+ * <p>For use by generated code only.
+ *
+ * @return {@code true} unless the tag is an end-group tag.
+ */
+ protected <MessageType extends MessageLite> boolean parseUnknownField(
+ MessageType defaultInstance,
+ CodedInputStream input,
+ ExtensionRegistryLite extensionRegistry,
+ int tag) throws IOException {
+ int wireType = WireFormat.getTagWireType(tag);
+ int fieldNumber = WireFormat.getTagFieldNumber(tag);
+
+ // TODO(dweis): How much bytecode would be saved by not requiring the generated code to
+ // provide the default instance?
+ GeneratedExtension<MessageType, ?> extension = extensionRegistry.findLiteExtensionByNumber(
+ defaultInstance, fieldNumber);
+
+ boolean unknown = false;
+ boolean packed = false;
+ if (extension == null) {
+ unknown = true; // Unknown field.
+ } else if (wireType == FieldSet.getWireFormatForFieldType(
+ extension.descriptor.getLiteType(),
+ false /* isPacked */)) {
+ packed = false; // Normal, unpacked value.
+ } else if (extension.descriptor.isRepeated &&
+ extension.descriptor.type.isPackable() &&
+ wireType == FieldSet.getWireFormatForFieldType(
+ extension.descriptor.getLiteType(),
+ true /* isPacked */)) {
+ packed = true; // Packed value.
+ } else {
+ unknown = true; // Wrong wire type.
+ }
+
+ if (unknown) { // Unknown field or wrong wire type. Skip.
+ return parseUnknownField(tag, input);
+ }
+
+ if (packed) {
+ int length = input.readRawVarint32();
+ int limit = input.pushLimit(length);
+ if (extension.descriptor.getLiteType() == WireFormat.FieldType.ENUM) {
+ while (input.getBytesUntilLimit() > 0) {
+ int rawValue = input.readEnum();
+ Object value =
+ extension.descriptor.getEnumType().findValueByNumber(rawValue);
+ if (value == null) {
+ // If the number isn't recognized as a valid value for this
+ // enum, drop it (don't even add it to unknownFields).
+ return true;
+ }
+ extensions.addRepeatedField(extension.descriptor,
+ extension.singularToFieldSetType(value));
+ }
+ } else {
+ while (input.getBytesUntilLimit() > 0) {
+ Object value =
+ FieldSet.readPrimitiveField(input,
+ extension.descriptor.getLiteType(),
+ /*checkUtf8=*/ false);
+ extensions.addRepeatedField(extension.descriptor, value);
+ }
+ }
+ input.popLimit(limit);
+ } else {
+ Object value;
+ switch (extension.descriptor.getLiteJavaType()) {
+ case MESSAGE: {
+ MessageLite.Builder subBuilder = null;
+ if (!extension.descriptor.isRepeated()) {
+ MessageLite existingValue =
+ (MessageLite) extensions.getField(extension.descriptor);
+ if (existingValue != null) {
+ subBuilder = existingValue.toBuilder();
+ }
+ }
+ if (subBuilder == null) {
+ subBuilder = extension.getMessageDefaultInstance()
+ .newBuilderForType();
+ }
+ if (extension.descriptor.getLiteType() ==
+ WireFormat.FieldType.GROUP) {
+ input.readGroup(extension.getNumber(),
+ subBuilder, extensionRegistry);
+ } else {
+ input.readMessage(subBuilder, extensionRegistry);
+ }
+ value = subBuilder.build();
+ break;
+ }
+ case ENUM:
+ int rawValue = input.readEnum();
+ value = extension.descriptor.getEnumType()
+ .findValueByNumber(rawValue);
+ // If the number isn't recognized as a valid value for this enum,
+ // write it to unknown fields object.
+ if (value == null) {
+ mergeVarintField(fieldNumber, rawValue);
+ return true;
+ }
+ break;
+ default:
+ value = FieldSet.readPrimitiveField(input,
+ extension.descriptor.getLiteType(),
+ /*checkUtf8=*/ false);
+ break;
+ }
+
+ if (extension.descriptor.isRepeated()) {
+ extensions.addRepeatedField(extension.descriptor,
+ extension.singularToFieldSetType(value));
+ } else {
+ extensions.setField(extension.descriptor,
+ extension.singularToFieldSetType(value));
+ }
+ }
+
+ return true;
+ }
+
private void verifyExtensionContainingType(
final GeneratedExtension<MessageType, ?> extension) {
if (extension.getContainingTypeDefaultInstance() !=
@@ -404,11 +558,10 @@ public abstract class GeneratedMessageLite<
}
- /**
- * Used by parsing constructors in generated classes.
- */
- protected static void makeExtensionsImmutable(
- FieldSet<ExtensionDescriptor> extensions) {
+ @Override
+ protected final void doneParsing() {
+ super.doneParsing();
+
extensions.makeImmutable();
}
@@ -619,131 +772,6 @@ public abstract class GeneratedMessageLite<
}
}
- //-----------------------------------------------------------------
-
- /**
- * Parse an unknown field or an extension. For use by generated code only.
- * @return {@code true} unless the tag is an end-group tag.
- */
- protected static <MessageType extends MessageLite>
- boolean parseUnknownField(
- FieldSet<ExtensionDescriptor> extensions,
- MessageType defaultInstance,
- CodedInputStream input,
- UnknownFieldSetLite.Builder unknownFields,
- ExtensionRegistryLite extensionRegistry,
- int tag) throws IOException {
- int wireType = WireFormat.getTagWireType(tag);
- int fieldNumber = WireFormat.getTagFieldNumber(tag);
-
- GeneratedExtension<MessageType, ?> extension =
- extensionRegistry.findLiteExtensionByNumber(
- defaultInstance, fieldNumber);
-
- boolean unknown = false;
- boolean packed = false;
- if (extension == null) {
- unknown = true; // Unknown field.
- } else if (wireType == FieldSet.getWireFormatForFieldType(
- extension.descriptor.getLiteType(),
- false /* isPacked */)) {
- packed = false; // Normal, unpacked value.
- } else if (extension.descriptor.isRepeated &&
- extension.descriptor.type.isPackable() &&
- wireType == FieldSet.getWireFormatForFieldType(
- extension.descriptor.getLiteType(),
- true /* isPacked */)) {
- packed = true; // Packed value.
- } else {
- unknown = true; // Wrong wire type.
- }
-
- if (unknown) { // Unknown field or wrong wire type. Skip.
- return unknownFields.mergeFieldFrom(tag, input);
- }
-
- if (packed) {
- int length = input.readRawVarint32();
- int limit = input.pushLimit(length);
- if (extension.descriptor.getLiteType() == WireFormat.FieldType.ENUM) {
- while (input.getBytesUntilLimit() > 0) {
- int rawValue = input.readEnum();
- Object value =
- extension.descriptor.getEnumType().findValueByNumber(rawValue);
- if (value == null) {
- // If the number isn't recognized as a valid value for this
- // enum, drop it (don't even add it to unknownFields).
- return true;
- }
- extensions.addRepeatedField(extension.descriptor,
- extension.singularToFieldSetType(value));
- }
- } else {
- while (input.getBytesUntilLimit() > 0) {
- Object value =
- FieldSet.readPrimitiveField(input,
- extension.descriptor.getLiteType(),
- /*checkUtf8=*/ false);
- extensions.addRepeatedField(extension.descriptor, value);
- }
- }
- input.popLimit(limit);
- } else {
- Object value;
- switch (extension.descriptor.getLiteJavaType()) {
- case MESSAGE: {
- MessageLite.Builder subBuilder = null;
- if (!extension.descriptor.isRepeated()) {
- MessageLite existingValue =
- (MessageLite) extensions.getField(extension.descriptor);
- if (existingValue != null) {
- subBuilder = existingValue.toBuilder();
- }
- }
- if (subBuilder == null) {
- subBuilder = extension.getMessageDefaultInstance()
- .newBuilderForType();
- }
- if (extension.descriptor.getLiteType() ==
- WireFormat.FieldType.GROUP) {
- input.readGroup(extension.getNumber(),
- subBuilder, extensionRegistry);
- } else {
- input.readMessage(subBuilder, extensionRegistry);
- }
- value = subBuilder.build();
- break;
- }
- case ENUM:
- int rawValue = input.readEnum();
- value = extension.descriptor.getEnumType()
- .findValueByNumber(rawValue);
- // If the number isn't recognized as a valid value for this enum,
- // write it to unknown fields object.
- if (value == null) {
- unknownFields.mergeVarintField(fieldNumber, rawValue);
- return true;
- }
- break;
- default:
- value = FieldSet.readPrimitiveField(input,
- extension.descriptor.getLiteType(),
- /*checkUtf8=*/ false);
- break;
- }
-
- if (extension.descriptor.isRepeated()) {
- extensions.addRepeatedField(extension.descriptor,
- extension.singularToFieldSetType(value));
- } else {
- extensions.setField(extension.descriptor,
- extension.singularToFieldSetType(value));
- }
- }
-
- return true;
- }
-
// -----------------------------------------------------------------
/** For use by generated code only. */
@@ -893,7 +921,7 @@ public abstract class GeneratedMessageLite<
extends ExtensionLite<ContainingType, Type> {
/**
- * Create a new isntance with the given parameters.
+ * Create a new instance with the given parameters.
*
* The last parameter {@code singularType} is only needed for enum types.
* We store integer values for enum types in a {@link ExtendableMessage}
@@ -905,7 +933,7 @@ public abstract class GeneratedMessageLite<
final Type defaultValue,
final MessageLite messageDefaultInstance,
final ExtensionDescriptor descriptor,
- Class singularType) {
+ final Class singularType) {
// Defensive checks to verify the correct initialization order of
// GeneratedExtensions and their related GeneratedMessages.
if (containingTypeDefaultInstance == null) {
@@ -921,24 +949,12 @@ public abstract class GeneratedMessageLite<
this.defaultValue = defaultValue;
this.messageDefaultInstance = messageDefaultInstance;
this.descriptor = descriptor;
-
- // Use Java reflection to invoke the static method {@code valueOf} of
- // enum types in order to convert integers to concrete enum objects.
- this.singularType = singularType;
- if (Internal.EnumLite.class.isAssignableFrom(singularType)) {
- this.enumValueOf = getMethodOrDie(
- singularType, "valueOf", int.class);
- } else {
- this.enumValueOf = null;
- }
}
final ContainingType containingTypeDefaultInstance;
final Type defaultValue;
final MessageLite messageDefaultInstance;
final ExtensionDescriptor descriptor;
- final Class singularType;
- final Method enumValueOf;
/**
* Default instance of the type being extended, used to identify that type.
@@ -980,7 +996,7 @@ public abstract class GeneratedMessageLite<
Object singularFromFieldSetType(final Object value) {
if (descriptor.getLiteJavaType() == WireFormat.JavaType.ENUM) {
- return invokeOrDie(enumValueOf, null, (Integer) value);
+ return descriptor.enumTypeMap.findValueByNumber((Integer) value);
} else {
return value;
}