private static void eagerlyMergeMessageSetExtension( CodedInputStream input, ExtensionRegistry.ExtensionInfo extension, ExtensionRegistryLite extensionRegistry, Message.Builder builder, FieldSet<FieldDescriptor> extensions) throws IOException { FieldDescriptor field = extension.descriptor; Message value = null; if (hasOriginalMessage(builder, extensions, field)) { Message originalMessage = getOriginalMessage(builder, extensions, field); Message.Builder subBuilder = originalMessage.toBuilder(); input.readMessage(subBuilder, extensionRegistry); value = subBuilder.buildPartial(); } else { value = input.readMessage(extension.defaultInstance.getParserForType(), extensionRegistry); } if (builder != null) { builder.setField(field, value); } else { extensions.setField(field, value); } }
/** helper method to handle {@code builder} and {@code extensions}. */ private static Message getOriginalMessage( Message.Builder builder, FieldSet<FieldDescriptor> extensions, FieldDescriptor field) { if (builder != null) { return (Message) builder.getField(field); } else { return (Message) extensions.getField(field); } }
/** helper method to handle {@code builder} and {@code extensions}. */ private static boolean hasOriginalMessage( Message.Builder builder, FieldSet<FieldDescriptor> extensions, FieldDescriptor field) { if (builder != null) { return builder.hasField(field); } else { return extensions.hasField(field); } }
private static void mergeMessageSetExtensionFromBytes( ByteString rawBytes, ExtensionRegistry.ExtensionInfo extension, ExtensionRegistryLite extensionRegistry, Message.Builder builder, FieldSet<FieldDescriptor> extensions) throws IOException { FieldDescriptor field = extension.descriptor; boolean hasOriginalValue = hasOriginalMessage(builder, extensions, field); if (hasOriginalValue || ExtensionRegistryLite.isEagerlyParseMessageSets()) { // If the field already exists, we just parse the field. Message value = null; if (hasOriginalValue) { Message originalMessage = getOriginalMessage(builder, extensions, field); Message.Builder subBuilder = originalMessage.toBuilder(); subBuilder.mergeFrom(rawBytes, extensionRegistry); value = subBuilder.buildPartial(); } else { value = extension .defaultInstance .getParserForType() .parsePartialFrom(rawBytes, extensionRegistry); } setField(builder, extensions, field, value); } else { // Use LazyField to load MessageSet lazily. LazyField lazyField = new LazyField(extension.defaultInstance, extensionRegistry, rawBytes); if (builder != null) { // TODO(xiangl): it looks like this method can only be invoked by // ExtendableBuilder, but I'm not sure. So I double check the type of // builder here. It may be useless and need more investigation. if (builder instanceof ExtendableBuilder) { builder.setField(field, lazyField); } else { builder.setField(field, lazyField.getValue()); } } else { extensions.setField(field, lazyField); } } }
/** helper method to handle {@code builder} and {@code extensions}. */ private static void mergeOriginalMessage( Message.Builder builder, FieldSet<FieldDescriptor> extensions, FieldDescriptor field, Message.Builder subBuilder) { Message originalMessage = getOriginalMessage(builder, extensions, field); if (originalMessage != null) { subBuilder.mergeFrom(originalMessage); } }
/** helper method to handle {@code builder} and {@code extensions}. */ private static void setField( Message.Builder builder, FieldSet<FieldDescriptor> extensions, FieldDescriptor field, Object value) { if (builder != null) { builder.setField(field, value); } else { extensions.setField(field, value); } }
public void testParsingUninitialized() throws Exception { TestRequiredForeign.Builder builder = TestRequiredForeign.newBuilder(); builder.getOptionalMessageBuilder().setDummy2(10); ByteString bytes = builder.buildPartial().toByteString(); Message.Builder abstractMessageBuilder = new AbstractMessageWrapper.Builder(TestRequiredForeign.newBuilder()); // mergeFrom() should not throw initialization error. abstractMessageBuilder.mergeFrom(bytes).buildPartial(); try { abstractMessageBuilder.mergeFrom(bytes).build(); fail(); } catch (UninitializedMessageException ex) { // pass } // test DynamicMessage directly. Message.Builder dynamicMessageBuilder = DynamicMessage.newBuilder(TestRequiredForeign.getDescriptor()); // mergeFrom() should not throw initialization error. dynamicMessageBuilder.mergeFrom(bytes).buildPartial(); try { dynamicMessageBuilder.mergeFrom(bytes).build(); fail(); } catch (UninitializedMessageException ex) { // pass } }
@Override public boolean hasField(Descriptors.FieldDescriptor field) { return wrappedBuilder.hasField(field); }
@Override public Object getField(Descriptors.FieldDescriptor field) { return wrappedBuilder.getField(field); }
/** * Like {@link #mergeFrom(CodedInputStream, UnknownFieldSet.Builder, ExtensionRegistryLite, * Message.Builder)}, but parses a single field. Package-private because it is used by * GeneratedMessage.ExtendableMessage. * * @param tag The tag, which should have already been read. * @return {@code true} unless the tag is an end-group tag. */ @SuppressWarnings("unchecked") static boolean mergeFieldFrom( final CodedInputStream input, final UnknownFieldSet.Builder unknownFields, final ExtensionRegistryLite extensionRegistry, final Message.Builder builder, final int tag) throws IOException { final Descriptor type = builder.getDescriptorForType(); if (type.getOptions().getMessageSetWireFormat() && tag == WireFormat.MESSAGE_SET_ITEM_TAG) { mergeMessageSetExtensionFromCodedStream(input, unknownFields, extensionRegistry, builder); return true; } final int wireType = WireFormat.getTagWireType(tag); final int fieldNumber = WireFormat.getTagFieldNumber(tag); final FieldDescriptor field; Message defaultInstance = null; if (type.isExtensionNumber(fieldNumber)) { // extensionRegistry may be either ExtensionRegistry or // ExtensionRegistryLite. Since the type we are parsing is a full // message, only a full ExtensionRegistry could possibly contain // extensions of it. Otherwise we will treat the registry as if it // were empty. if (extensionRegistry instanceof ExtensionRegistry) { final ExtensionRegistry.ExtensionInfo extension = ((ExtensionRegistry) extensionRegistry).findExtensionByNumber(type, fieldNumber); if (extension == null) { field = null; } else { field = extension.descriptor; defaultInstance = extension.defaultInstance; } } else { field = null; } } else { field = type.findFieldByNumber(fieldNumber); } if (field == null || wireType != FieldSet.getWireFormatForFieldType( field.getLiteType(), field.getOptions().getPacked())) { // Unknown field or wrong wire type. Skip. return unknownFields.mergeFieldFrom(tag, input); } if (field.getOptions().getPacked()) { final int length = input.readRawVarint32(); final int limit = input.pushLimit(length); if (field.getLiteType() == WireFormat.FieldType.ENUM) { while (input.getBytesUntilLimit() > 0) { final int rawValue = input.readEnum(); final Object value = field.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; } builder.addRepeatedField(field, value); } } else { while (input.getBytesUntilLimit() > 0) { final Object value = FieldSet.readPrimitiveField(input, field.getLiteType()); builder.addRepeatedField(field, value); } } input.popLimit(limit); } else { final Object value; switch (field.getType()) { case GROUP: { final Message.Builder subBuilder; if (defaultInstance != null) { subBuilder = defaultInstance.newBuilderForType(); } else { subBuilder = builder.newBuilderForField(field); } if (!field.isRepeated()) { subBuilder.mergeFrom((Message) builder.getField(field)); } input.readGroup(field.getNumber(), subBuilder, extensionRegistry); value = subBuilder.build(); break; } case MESSAGE: { final Message.Builder subBuilder; if (defaultInstance != null) { subBuilder = defaultInstance.newBuilderForType(); } else { subBuilder = builder.newBuilderForField(field); } if (!field.isRepeated()) { subBuilder.mergeFrom((Message) builder.getField(field)); } input.readMessage(subBuilder, extensionRegistry); value = subBuilder.build(); break; } case ENUM: final int rawValue = input.readEnum(); value = field.getEnumType().findValueByNumber(rawValue); // If the number isn't recognized as a valid value for this enum, // drop it. if (value == null) { unknownFields.mergeVarintField(fieldNumber, rawValue); return true; } break; default: value = FieldSet.readPrimitiveField(input, field.getLiteType()); break; } if (field.isRepeated()) { builder.addRepeatedField(field, value); } else { builder.setField(field, value); } } return true; }
@Override public Builder newBuilderForField(Descriptors.FieldDescriptor field) { return new Builder(wrappedBuilder.newBuilderForField(field)); }
@Override public UnknownFieldSet getUnknownFields() { return wrappedBuilder.getUnknownFields(); }
@Override public Message.Builder getFieldBuilder(FieldDescriptor field) { return wrappedBuilder.getFieldBuilder(field); }
@Override public Builder setRepeatedField(Descriptors.FieldDescriptor field, int index, Object value) { wrappedBuilder.setRepeatedField(field, index, value); return this; }
@Override public int getRepeatedFieldCount(Descriptors.FieldDescriptor field) { return wrappedBuilder.getRepeatedFieldCount(field); }
@Override public Builder setField(Descriptors.FieldDescriptor field, Object value) { wrappedBuilder.setField(field, value); return this; }
/** Called by {@code #mergeFieldFrom()} to parse a MessageSet extension. */ private static void mergeMessageSetExtensionFromCodedStream( final CodedInputStream input, final UnknownFieldSet.Builder unknownFields, final ExtensionRegistryLite extensionRegistry, final Message.Builder builder) throws IOException { final Descriptor type = builder.getDescriptorForType(); // The wire format for MessageSet is: // message MessageSet { // repeated group Item = 1 { // required int32 typeId = 2; // required bytes message = 3; // } // } // "typeId" is the extension's field number. The extension can only be // a message type, where "message" contains the encoded bytes of that // message. // // In practice, we will probably never see a MessageSet item in which // the message appears before the type ID, or where either field does not // appear exactly once. However, in theory such cases are valid, so we // should be prepared to accept them. int typeId = 0; ByteString rawBytes = null; // If we encounter "message" before "typeId" Message.Builder subBuilder = null; FieldDescriptor field = null; while (true) { final int tag = input.readTag(); if (tag == 0) { break; } if (tag == WireFormat.MESSAGE_SET_TYPE_ID_TAG) { typeId = input.readUInt32(); // Zero is not a valid type ID. if (typeId != 0) { final ExtensionRegistry.ExtensionInfo extension; // extensionRegistry may be either ExtensionRegistry or // ExtensionRegistryLite. Since the type we are parsing is a full // message, only a full ExtensionRegistry could possibly contain // extensions of it. Otherwise we will treat the registry as if it // were empty. if (extensionRegistry instanceof ExtensionRegistry) { extension = ((ExtensionRegistry) extensionRegistry).findExtensionByNumber(type, typeId); } else { extension = null; } if (extension != null) { field = extension.descriptor; subBuilder = extension.defaultInstance.newBuilderForType(); final Message originalMessage = (Message) builder.getField(field); if (originalMessage != null) { subBuilder.mergeFrom(originalMessage); } if (rawBytes != null) { // We already encountered the message. Parse it now. subBuilder.mergeFrom(CodedInputStream.newInstance(rawBytes.newInput())); rawBytes = null; } } else { // Unknown extension number. If we already saw data, put it // in rawBytes. if (rawBytes != null) { unknownFields.mergeField( typeId, UnknownFieldSet.Field.newBuilder().addLengthDelimited(rawBytes).build()); rawBytes = null; } } } } else if (tag == WireFormat.MESSAGE_SET_MESSAGE_TAG) { if (typeId == 0) { // We haven't seen a type ID yet, so we have to store the raw bytes // for now. rawBytes = input.readBytes(); } else if (subBuilder == null) { // We don't know how to parse this. Ignore it. unknownFields.mergeField( typeId, UnknownFieldSet.Field.newBuilder().addLengthDelimited(input.readBytes()).build()); } else { // We already know the type, so we can parse directly from the input // with no copying. Hooray! input.readMessage(subBuilder, extensionRegistry); } } else { // Unknown tag. Skip it. if (!input.skipField(tag)) { break; // end of group } } } input.checkLastTagWas(WireFormat.MESSAGE_SET_ITEM_END_TAG); if (subBuilder != null) { builder.setField(field, subBuilder.build()); } }
/** * Like {@link #mergeFrom(CodedInputStream, ExtensionRegistryLite)}, but parses a single field. * * <p>When {@code builder} is not null, the method will parse and merge the field into {@code * builder}. Otherwise, it will try to parse the field into {@code extensions}, when it's called * by the parsing constructor in generated classes. * * <p>Package-private because it is used by GeneratedMessage.ExtendableMessage. * * @param tag The tag, which should have already been read. * @return {@code true} unless the tag is an end-group tag. */ static boolean mergeFieldFrom( CodedInputStream input, UnknownFieldSet.Builder unknownFields, ExtensionRegistryLite extensionRegistry, Descriptor type, Message.Builder builder, FieldSet<FieldDescriptor> extensions, int tag) throws IOException { if (type.getOptions().getMessageSetWireFormat() && tag == WireFormat.MESSAGE_SET_ITEM_TAG) { mergeMessageSetExtensionFromCodedStream( input, unknownFields, extensionRegistry, type, builder, extensions); return true; } final int wireType = WireFormat.getTagWireType(tag); final int fieldNumber = WireFormat.getTagFieldNumber(tag); final FieldDescriptor field; Message defaultInstance = null; if (type.isExtensionNumber(fieldNumber)) { // extensionRegistry may be either ExtensionRegistry or // ExtensionRegistryLite. Since the type we are parsing is a full // message, only a full ExtensionRegistry could possibly contain // extensions of it. Otherwise we will treat the registry as if it // were empty. if (extensionRegistry instanceof ExtensionRegistry) { final ExtensionRegistry.ExtensionInfo extension = ((ExtensionRegistry) extensionRegistry).findExtensionByNumber(type, fieldNumber); if (extension == null) { field = null; } else { field = extension.descriptor; defaultInstance = extension.defaultInstance; if (defaultInstance == null && field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) { throw new IllegalStateException( "Message-typed extension lacked default instance: " + field.getFullName()); } } } else { field = null; } } else if (builder != null) { field = type.findFieldByNumber(fieldNumber); } else { field = null; } boolean unknown = false; boolean packed = false; if (field == null) { unknown = true; // Unknown field. } else if (wireType == FieldSet.getWireFormatForFieldType(field.getLiteType(), false /* isPacked */)) { packed = false; } else if (field.isPackable() && wireType == FieldSet.getWireFormatForFieldType(field.getLiteType(), true /* isPacked */)) { packed = true; } else { unknown = true; // Unknown wire type. } if (unknown) { // Unknown field or wrong wire type. Skip. return unknownFields.mergeFieldFrom(tag, input); } if (packed) { final int length = input.readRawVarint32(); final int limit = input.pushLimit(length); if (field.getLiteType() == WireFormat.FieldType.ENUM) { while (input.getBytesUntilLimit() > 0) { final int rawValue = input.readEnum(); final Object value = field.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; } addRepeatedField(builder, extensions, field, value); } } else { while (input.getBytesUntilLimit() > 0) { final Object value = FieldSet.readPrimitiveField(input, field.getLiteType()); addRepeatedField(builder, extensions, field, value); } } input.popLimit(limit); } else { final Object value; switch (field.getType()) { case GROUP: { final Message.Builder subBuilder; if (defaultInstance != null) { subBuilder = defaultInstance.newBuilderForType(); } else { subBuilder = builder.newBuilderForField(field); } if (!field.isRepeated()) { mergeOriginalMessage(builder, extensions, field, subBuilder); } input.readGroup(field.getNumber(), subBuilder, extensionRegistry); value = subBuilder.buildPartial(); break; } case MESSAGE: { final Message.Builder subBuilder; if (defaultInstance != null) { subBuilder = defaultInstance.newBuilderForType(); } else { subBuilder = builder.newBuilderForField(field); } if (!field.isRepeated()) { mergeOriginalMessage(builder, extensions, field, subBuilder); } input.readMessage(subBuilder, extensionRegistry); value = subBuilder.buildPartial(); break; } case ENUM: final int rawValue = input.readEnum(); value = field.getEnumType().findValueByNumber(rawValue); // If the number isn't recognized as a valid value for this enum, // drop it. if (value == null) { unknownFields.mergeVarintField(fieldNumber, rawValue); return true; } break; default: value = FieldSet.readPrimitiveField(input, field.getLiteType()); break; } if (field.isRepeated()) { addRepeatedField(builder, extensions, field, value); } else { setField(builder, extensions, field, value); } } return true; }
@Override public Builder clearField(Descriptors.FieldDescriptor field) { wrappedBuilder.clearField(field); return this; }
@Override public AbstractMessageWrapper buildPartial() { return new AbstractMessageWrapper(wrappedBuilder.buildPartial()); }
@Override public Object getRepeatedField(Descriptors.FieldDescriptor field, int index) { return wrappedBuilder.getRepeatedField(field, index); }
@Override public Builder clone() { return new Builder(wrappedBuilder.clone()); }
@Override public Builder addRepeatedField(Descriptors.FieldDescriptor field, Object value) { wrappedBuilder.addRepeatedField(field, value); return this; }
@Override public Descriptors.Descriptor getDescriptorForType() { return wrappedBuilder.getDescriptorForType(); }
@Override public Builder setUnknownFields(UnknownFieldSet unknownFields) { wrappedBuilder.setUnknownFields(unknownFields); return this; }
@Override public AbstractMessageWrapper getDefaultInstanceForType() { return new AbstractMessageWrapper(wrappedBuilder.getDefaultInstanceForType()); }
@Override public Map<Descriptors.FieldDescriptor, Object> getAllFields() { return wrappedBuilder.getAllFields(); }
public AbstractMessageWrapper build() { return new AbstractMessageWrapper(wrappedBuilder.build()); }