diff options
Diffstat (limited to 'java/src/main/java/com/google/protobuf/MessageReflection.java')
-rw-r--r-- | java/src/main/java/com/google/protobuf/MessageReflection.java | 931 |
1 files changed, 0 insertions, 931 deletions
diff --git a/java/src/main/java/com/google/protobuf/MessageReflection.java b/java/src/main/java/com/google/protobuf/MessageReflection.java deleted file mode 100644 index edb5b5c..0000000 --- a/java/src/main/java/com/google/protobuf/MessageReflection.java +++ /dev/null @@ -1,931 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -package com.google.protobuf; - -import com.google.protobuf.Descriptors.FieldDescriptor; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.TreeMap; - -/** - * Reflection utility methods shared by both mutable and immutable messages. - * - * @author liujisi@google.com (Pherl Liu) - */ -class MessageReflection { - - static void writeMessageTo(Message message, CodedOutputStream output, - boolean alwaysWriteRequiredFields) - throws IOException { - final boolean isMessageSet = - message.getDescriptorForType().getOptions().getMessageSetWireFormat(); - - Map<FieldDescriptor, Object> fields = message.getAllFields(); - if (alwaysWriteRequiredFields) { - fields = new TreeMap<FieldDescriptor, Object>(fields); - for (final FieldDescriptor field : - message.getDescriptorForType().getFields()) { - if (field.isRequired() && !fields.containsKey(field)) { - fields.put(field, message.getField(field)); - } - } - } - for (final Map.Entry<Descriptors.FieldDescriptor, Object> entry : - fields.entrySet()) { - final Descriptors.FieldDescriptor field = entry.getKey(); - final Object value = entry.getValue(); - if (isMessageSet && field.isExtension() && - field.getType() == Descriptors.FieldDescriptor.Type.MESSAGE && - !field.isRepeated()) { - output.writeMessageSetExtension(field.getNumber(), (Message) value); - } else { - FieldSet.writeField(field, value, output); - } - } - - final UnknownFieldSet unknownFields = message.getUnknownFields(); - if (isMessageSet) { - unknownFields.writeAsMessageSetTo(output); - } else { - unknownFields.writeTo(output); - } - } - - static int getSerializedSize(Message message) { - int size = 0; - final boolean isMessageSet = - message.getDescriptorForType().getOptions().getMessageSetWireFormat(); - - for (final Map.Entry<Descriptors.FieldDescriptor, Object> entry : - message.getAllFields().entrySet()) { - final Descriptors.FieldDescriptor field = entry.getKey(); - final Object value = entry.getValue(); - if (isMessageSet && field.isExtension() && - field.getType() == Descriptors.FieldDescriptor.Type.MESSAGE && - !field.isRepeated()) { - size += CodedOutputStream.computeMessageSetExtensionSize( - field.getNumber(), (Message) value); - } else { - size += FieldSet.computeFieldSize(field, value); - } - } - - final UnknownFieldSet unknownFields = message.getUnknownFields(); - if (isMessageSet) { - size += unknownFields.getSerializedSizeAsMessageSet(); - } else { - size += unknownFields.getSerializedSize(); - } - return size; - } - - static String delimitWithCommas(List<String> parts) { - StringBuilder result = new StringBuilder(); - for (String part : parts) { - if (result.length() > 0) { - result.append(", "); - } - result.append(part); - } - return result.toString(); - } - - @SuppressWarnings("unchecked") - static boolean isInitialized(MessageOrBuilder message) { - // Check that all required fields are present. - for (final Descriptors.FieldDescriptor field : message - .getDescriptorForType() - .getFields()) { - if (field.isRequired()) { - if (!message.hasField(field)) { - return false; - } - } - } - - // Check that embedded messages are initialized. - for (final Map.Entry<Descriptors.FieldDescriptor, Object> entry : - message.getAllFields().entrySet()) { - final Descriptors.FieldDescriptor field = entry.getKey(); - if (field.getJavaType() == Descriptors.FieldDescriptor.JavaType.MESSAGE) { - if (field.isRepeated()) { - for (final Message element - : (List<Message>) entry.getValue()) { - if (!element.isInitialized()) { - return false; - } - } - } else { - if (!((Message) entry.getValue()).isInitialized()) { - return false; - } - } - } - } - - return true; - } - - private static String subMessagePrefix(final String prefix, - final Descriptors.FieldDescriptor field, - final int index) { - final StringBuilder result = new StringBuilder(prefix); - if (field.isExtension()) { - result.append('(') - .append(field.getFullName()) - .append(')'); - } else { - result.append(field.getName()); - } - if (index != -1) { - result.append('[') - .append(index) - .append(']'); - } - result.append('.'); - return result.toString(); - } - - private static void findMissingFields(final MessageOrBuilder message, - final String prefix, - final List<String> results) { - for (final Descriptors.FieldDescriptor field : - message.getDescriptorForType().getFields()) { - if (field.isRequired() && !message.hasField(field)) { - results.add(prefix + field.getName()); - } - } - - for (final Map.Entry<Descriptors.FieldDescriptor, Object> entry : - message.getAllFields().entrySet()) { - final Descriptors.FieldDescriptor field = entry.getKey(); - final Object value = entry.getValue(); - - if (field.getJavaType() == Descriptors.FieldDescriptor.JavaType.MESSAGE) { - if (field.isRepeated()) { - int i = 0; - for (final Object element : (List) value) { - findMissingFields((MessageOrBuilder) element, - subMessagePrefix(prefix, field, i++), - results); - } - } else { - if (message.hasField(field)) { - findMissingFields((MessageOrBuilder) value, - subMessagePrefix(prefix, field, -1), - results); - } - } - } - } - } - - /** - * Populates {@code this.missingFields} with the full "path" of each missing - * required field in the given message. - */ - static List<String> findMissingFields( - final MessageOrBuilder message) { - final List<String> results = new ArrayList<String>(); - findMissingFields(message, "", results); - return results; - } - - static interface MergeTarget { - enum ContainerType { - MESSAGE, EXTENSION_SET - } - - /** - * Returns the descriptor for the target. - */ - public Descriptors.Descriptor getDescriptorForType(); - - public ContainerType getContainerType(); - - public ExtensionRegistry.ExtensionInfo findExtensionByName( - ExtensionRegistry registry, String name); - - public ExtensionRegistry.ExtensionInfo findExtensionByNumber( - ExtensionRegistry registry, Descriptors.Descriptor containingType, - int fieldNumber); - - /** - * Obtains the value of the given field, or the default value if it is not - * set. For primitive fields, the boxed primitive value is returned. For - * enum fields, the EnumValueDescriptor for the value is returned. For - * embedded message fields, the sub-message is returned. For repeated - * fields, a java.util.List is returned. - */ - public Object getField(Descriptors.FieldDescriptor field); - - /** - * Returns true if the given field is set. This is exactly equivalent to - * calling the generated "has" accessor method corresponding to the field. - * - * @throws IllegalArgumentException The field is a repeated field, or {@code - * field.getContainingType() != getDescriptorForType()}. - */ - boolean hasField(Descriptors.FieldDescriptor field); - - /** - * Sets a field to the given value. The value must be of the correct type - * for this field, i.e. the same type that - * {@link Message#getField(Descriptors.FieldDescriptor)} - * would return. - */ - MergeTarget setField(Descriptors.FieldDescriptor field, Object value); - - /** - * Clears the field. This is exactly equivalent to calling the generated - * "clear" accessor method corresponding to the field. - */ - MergeTarget clearField(Descriptors.FieldDescriptor field); - - /** - * Sets an element of a repeated field to the given value. The value must - * be of the correct type for this field, i.e. the same type that {@link - * Message#getRepeatedField(Descriptors.FieldDescriptor, int)} would return. - * - * @throws IllegalArgumentException The field is not a repeated field, or - * {@code field.getContainingType() != - * getDescriptorForType()}. - */ - MergeTarget setRepeatedField(Descriptors.FieldDescriptor field, - int index, Object value); - - /** - * Like {@code setRepeatedField}, but appends the value as a new element. - * - * @throws IllegalArgumentException The field is not a repeated field, or - * {@code field.getContainingType() != - * getDescriptorForType()}. - */ - MergeTarget addRepeatedField(Descriptors.FieldDescriptor field, - Object value); - - /** - * Returns true if the given oneof is set. - * - * @throws IllegalArgumentException if - * {@code oneof.getContainingType() != getDescriptorForType()}. - */ - boolean hasOneof(Descriptors.OneofDescriptor oneof); - - /** - * Clears the oneof. This is exactly equivalent to calling the generated - * "clear" accessor method corresponding to the oneof. - */ - MergeTarget clearOneof(Descriptors.OneofDescriptor oneof); - - /** - * Obtains the FieldDescriptor if the given oneof is set. Returns null - * if no field is set. - */ - Descriptors.FieldDescriptor getOneofFieldDescriptor(Descriptors.OneofDescriptor oneof); - - /** - * Parse the input stream into a sub field group defined based on either - * FieldDescriptor or the default instance. - */ - Object parseGroup(CodedInputStream input, ExtensionRegistryLite registry, - Descriptors.FieldDescriptor descriptor, Message defaultInstance) - throws IOException; - - /** - * Parse the input stream into a sub field message defined based on either - * FieldDescriptor or the default instance. - */ - Object parseMessage(CodedInputStream input, ExtensionRegistryLite registry, - Descriptors.FieldDescriptor descriptor, Message defaultInstance) - throws IOException; - - /** - * Parse from a ByteString into a sub field message defined based on either - * FieldDescriptor or the default instance. There isn't a varint indicating - * the length of the message at the beginning of the input ByteString. - */ - Object parseMessageFromBytes( - ByteString bytes, ExtensionRegistryLite registry, - Descriptors.FieldDescriptor descriptor, Message defaultInstance) - throws IOException; - - /** - * Read a primitive field from input. Note that builders and mutable - * messages may use different Java types to represent a primtive field. - */ - Object readPrimitiveField( - CodedInputStream input, WireFormat.FieldType type, - boolean checkUtf8) throws IOException; - - /** - * Returns a new merge target for a sub-field. When defaultInstance is - * provided, it indicates the descriptor is for an extension type, and - * implementations should create a new instance from the defaultInstance - * prototype directly. - */ - MergeTarget newMergeTargetForField( - Descriptors.FieldDescriptor descriptor, - Message defaultInstance); - - /** - * Finishes the merge and returns the underlying object. - */ - Object finish(); - } - - static class BuilderAdapter implements MergeTarget { - - private final Message.Builder builder; - - public Descriptors.Descriptor getDescriptorForType() { - return builder.getDescriptorForType(); - } - - public BuilderAdapter(Message.Builder builder) { - this.builder = builder; - } - - public Object getField(Descriptors.FieldDescriptor field) { - return builder.getField(field); - } - - @Override - public boolean hasField(Descriptors.FieldDescriptor field) { - return builder.hasField(field); - } - - public MergeTarget setField(Descriptors.FieldDescriptor field, - Object value) { - builder.setField(field, value); - return this; - } - - public MergeTarget clearField(Descriptors.FieldDescriptor field) { - builder.clearField(field); - return this; - } - - public MergeTarget setRepeatedField( - Descriptors.FieldDescriptor field, int index, Object value) { - builder.setRepeatedField(field, index, value); - return this; - } - - public MergeTarget addRepeatedField( - Descriptors.FieldDescriptor field, Object value) { - builder.addRepeatedField(field, value); - return this; - } - - @Override - public boolean hasOneof(Descriptors.OneofDescriptor oneof) { - return builder.hasOneof(oneof); - } - - @Override - public MergeTarget clearOneof(Descriptors.OneofDescriptor oneof) { - builder.clearOneof(oneof); - return this; - } - - @Override - public Descriptors.FieldDescriptor getOneofFieldDescriptor(Descriptors.OneofDescriptor oneof) { - return builder.getOneofFieldDescriptor(oneof); - } - - public ContainerType getContainerType() { - return ContainerType.MESSAGE; - } - - public ExtensionRegistry.ExtensionInfo findExtensionByName( - ExtensionRegistry registry, String name) { - return registry.findImmutableExtensionByName(name); - } - - public ExtensionRegistry.ExtensionInfo findExtensionByNumber( - ExtensionRegistry registry, Descriptors.Descriptor containingType, - int fieldNumber) { - return registry.findImmutableExtensionByNumber(containingType, - fieldNumber); - } - - public Object parseGroup(CodedInputStream input, - ExtensionRegistryLite extensionRegistry, - Descriptors.FieldDescriptor field, Message defaultInstance) - throws IOException { - Message.Builder subBuilder; - // When default instance is not null. The field is an extension field. - if (defaultInstance != null) { - subBuilder = defaultInstance.newBuilderForType(); - } else { - subBuilder = builder.newBuilderForField(field); - } - if (!field.isRepeated()) { - Message originalMessage = (Message) getField(field); - if (originalMessage != null) { - subBuilder.mergeFrom(originalMessage); - } - } - input.readGroup(field.getNumber(), subBuilder, extensionRegistry); - return subBuilder.buildPartial(); - } - - public Object parseMessage(CodedInputStream input, - ExtensionRegistryLite extensionRegistry, - Descriptors.FieldDescriptor field, Message defaultInstance) - throws IOException { - Message.Builder subBuilder; - // When default instance is not null. The field is an extension field. - if (defaultInstance != null) { - subBuilder = defaultInstance.newBuilderForType(); - } else { - subBuilder = builder.newBuilderForField(field); - } - if (!field.isRepeated()) { - Message originalMessage = (Message) getField(field); - if (originalMessage != null) { - subBuilder.mergeFrom(originalMessage); - } - } - input.readMessage(subBuilder, extensionRegistry); - return subBuilder.buildPartial(); - } - - public Object parseMessageFromBytes(ByteString bytes, - ExtensionRegistryLite extensionRegistry, - Descriptors.FieldDescriptor field, Message defaultInstance) - throws IOException { - Message.Builder subBuilder; - // When default instance is not null. The field is an extension field. - if (defaultInstance != null) { - subBuilder = defaultInstance.newBuilderForType(); - } else { - subBuilder = builder.newBuilderForField(field); - } - if (!field.isRepeated()) { - Message originalMessage = (Message) getField(field); - if (originalMessage != null) { - subBuilder.mergeFrom(originalMessage); - } - } - subBuilder.mergeFrom(bytes, extensionRegistry); - return subBuilder.buildPartial(); - } - - public MergeTarget newMergeTargetForField(Descriptors.FieldDescriptor field, - Message defaultInstance) { - if (defaultInstance != null) { - return new BuilderAdapter( - defaultInstance.newBuilderForType()); - } else { - return new BuilderAdapter(builder.newBuilderForField(field)); - } - } - - public Object readPrimitiveField( - CodedInputStream input, WireFormat.FieldType type, - boolean checkUtf8) throws IOException { - return FieldSet.readPrimitiveField(input, type, checkUtf8); - } - - public Object finish() { - return builder.buildPartial(); - } - } - - - static class ExtensionAdapter implements MergeTarget { - - private final FieldSet<Descriptors.FieldDescriptor> extensions; - - ExtensionAdapter(FieldSet<Descriptors.FieldDescriptor> extensions) { - this.extensions = extensions; - } - - public Descriptors.Descriptor getDescriptorForType() { - throw new UnsupportedOperationException( - "getDescriptorForType() called on FieldSet object"); - } - - public Object getField(Descriptors.FieldDescriptor field) { - return extensions.getField(field); - } - - public boolean hasField(Descriptors.FieldDescriptor field) { - return extensions.hasField(field); - } - - public MergeTarget setField(Descriptors.FieldDescriptor field, - Object value) { - extensions.setField(field, value); - return this; - } - - public MergeTarget clearField(Descriptors.FieldDescriptor field) { - extensions.clearField(field); - return this; - } - - public MergeTarget setRepeatedField( - Descriptors.FieldDescriptor field, int index, Object value) { - extensions.setRepeatedField(field, index, value); - return this; - } - - public MergeTarget addRepeatedField( - Descriptors.FieldDescriptor field, Object value) { - extensions.addRepeatedField(field, value); - return this; - } - - @Override - public boolean hasOneof(Descriptors.OneofDescriptor oneof) { - return false; - } - - @Override - public MergeTarget clearOneof(Descriptors.OneofDescriptor oneof) { - // Nothing to clear. - return this; - } - - @Override - public Descriptors.FieldDescriptor getOneofFieldDescriptor(Descriptors.OneofDescriptor oneof) { - return null; - } - - public ContainerType getContainerType() { - return ContainerType.EXTENSION_SET; - } - - public ExtensionRegistry.ExtensionInfo findExtensionByName( - ExtensionRegistry registry, String name) { - return registry.findImmutableExtensionByName(name); - } - - public ExtensionRegistry.ExtensionInfo findExtensionByNumber( - ExtensionRegistry registry, Descriptors.Descriptor containingType, - int fieldNumber) { - return registry.findImmutableExtensionByNumber(containingType, - fieldNumber); - } - - public Object parseGroup(CodedInputStream input, - ExtensionRegistryLite registry, Descriptors.FieldDescriptor field, - Message defaultInstance) throws IOException { - Message.Builder subBuilder = - defaultInstance.newBuilderForType(); - if (!field.isRepeated()) { - Message originalMessage = (Message) getField(field); - if (originalMessage != null) { - subBuilder.mergeFrom(originalMessage); - } - } - input.readGroup(field.getNumber(), subBuilder, registry); - return subBuilder.buildPartial(); - } - - public Object parseMessage(CodedInputStream input, - ExtensionRegistryLite registry, Descriptors.FieldDescriptor field, - Message defaultInstance) throws IOException { - Message.Builder subBuilder = - defaultInstance.newBuilderForType(); - if (!field.isRepeated()) { - Message originalMessage = (Message) getField(field); - if (originalMessage != null) { - subBuilder.mergeFrom(originalMessage); - } - } - input.readMessage(subBuilder, registry); - return subBuilder.buildPartial(); - } - - public Object parseMessageFromBytes(ByteString bytes, - ExtensionRegistryLite registry, Descriptors.FieldDescriptor field, - Message defaultInstance) throws IOException { - Message.Builder subBuilder = defaultInstance.newBuilderForType(); - if (!field.isRepeated()) { - Message originalMessage = (Message) getField(field); - if (originalMessage != null) { - subBuilder.mergeFrom(originalMessage); - } - } - subBuilder.mergeFrom(bytes, registry); - return subBuilder.buildPartial(); - } - - public MergeTarget newMergeTargetForField( - Descriptors.FieldDescriptor descriptor, Message defaultInstance) { - throw new UnsupportedOperationException( - "newMergeTargetForField() called on FieldSet object"); - } - - public Object readPrimitiveField( - CodedInputStream input, WireFormat.FieldType type, - boolean checkUtf8) throws IOException { - return FieldSet.readPrimitiveField(input, type, checkUtf8); - } - - public Object finish() { - throw new UnsupportedOperationException( - "finish() called on FieldSet object"); - } - } - - /** - * Parses a single field into MergeTarget. The target can be Message.Builder, - * FieldSet or MutableMessage. - * - * 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, - Descriptors.Descriptor type, - MergeTarget target, - int tag) throws IOException { - if (type.getOptions().getMessageSetWireFormat() && - tag == WireFormat.MESSAGE_SET_ITEM_TAG) { - mergeMessageSetExtensionFromCodedStream( - input, unknownFields, extensionRegistry, type, target); - return true; - } - - final int wireType = WireFormat.getTagWireType(tag); - final int fieldNumber = WireFormat.getTagFieldNumber(tag); - - final Descriptors.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 = - target.findExtensionByNumber((ExtensionRegistry) extensionRegistry, - type, fieldNumber); - if (extension == null) { - field = null; - } else { - field = extension.descriptor; - defaultInstance = extension.defaultInstance; - if (defaultInstance == null && - field.getJavaType() - == Descriptors.FieldDescriptor.JavaType.MESSAGE) { - throw new IllegalStateException( - "Message-typed extension lacked default instance: " + - field.getFullName()); - } - } - } else { - field = null; - } - } else if (target.getContainerType() == MergeTarget.ContainerType.MESSAGE) { - 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; - } - target.addRepeatedField(field, value); - } - } else { - while (input.getBytesUntilLimit() > 0) { - final Object value = - target.readPrimitiveField(input, field.getLiteType(), field.needsUtf8Check()); - target.addRepeatedField(field, value); - } - } - input.popLimit(limit); - } else { - final Object value; - switch (field.getType()) { - case GROUP: { - value = target - .parseGroup(input, extensionRegistry, field, defaultInstance); - break; - } - case MESSAGE: { - value = target - .parseMessage(input, extensionRegistry, field, defaultInstance); - 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 = target.readPrimitiveField(input, field.getLiteType(), field.needsUtf8Check()); - break; - } - - if (field.isRepeated()) { - target.addRepeatedField(field, value); - } else { - target.setField(field, value); - } - } - - return true; - } - - /** - * Called by {@code #mergeFieldFrom()} to parse a MessageSet extension into - * MergeTarget. - */ - private static void mergeMessageSetExtensionFromCodedStream( - CodedInputStream input, - UnknownFieldSet.Builder unknownFields, - ExtensionRegistryLite extensionRegistry, - Descriptors.Descriptor type, - MergeTarget target) throws IOException { - - // 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" - ExtensionRegistry.ExtensionInfo extension = null; - - // Read bytes from input, if we get it's type first then parse it eagerly, - // otherwise we store the raw bytes in a local variable. - while (true) { - final int tag = input.readTag(); - if (tag == 0) { - break; - } - - if (tag == WireFormat.MESSAGE_SET_TYPE_ID_TAG) { - typeId = input.readUInt32(); - if (typeId != 0) { - // 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 = target.findExtensionByNumber( - (ExtensionRegistry) extensionRegistry, type, typeId); - } - } - - } else if (tag == WireFormat.MESSAGE_SET_MESSAGE_TAG) { - if (typeId != 0) { - if (extension != null && - ExtensionRegistryLite.isEagerlyParseMessageSets()) { - // We already know the type, so we can parse directly from the - // input with no copying. Hooray! - eagerlyMergeMessageSetExtension( - input, extension, extensionRegistry, target); - rawBytes = null; - continue; - } - } - // We haven't seen a type ID yet or we want parse message lazily. - rawBytes = input.readBytes(); - - } else { // Unknown tag. Skip it. - if (!input.skipField(tag)) { - break; // End of group - } - } - } - input.checkLastTagWas(WireFormat.MESSAGE_SET_ITEM_END_TAG); - - // Process the raw bytes. - if (rawBytes != null && typeId != 0) { // Zero is not a valid type ID. - if (extension != null) { // We known the type - mergeMessageSetExtensionFromBytes( - rawBytes, extension, extensionRegistry, target); - } else { // We don't know how to parse this. Ignore it. - if (rawBytes != null) { - unknownFields.mergeField(typeId, UnknownFieldSet.Field.newBuilder() - .addLengthDelimited(rawBytes).build()); - } - } - } - } - - private static void mergeMessageSetExtensionFromBytes( - ByteString rawBytes, - ExtensionRegistry.ExtensionInfo extension, - ExtensionRegistryLite extensionRegistry, - MergeTarget target) throws IOException { - - Descriptors.FieldDescriptor field = extension.descriptor; - boolean hasOriginalValue = target.hasField(field); - - if (hasOriginalValue || ExtensionRegistryLite.isEagerlyParseMessageSets()) { - // If the field already exists, we just parse the field. - Object value = target.parseMessageFromBytes( - rawBytes, extensionRegistry,field, extension.defaultInstance); - target.setField(field, value); - } else { - // Use LazyField to load MessageSet lazily. - LazyField lazyField = new LazyField( - extension.defaultInstance, extensionRegistry, rawBytes); - target.setField(field, lazyField); - } - } - - private static void eagerlyMergeMessageSetExtension( - CodedInputStream input, - ExtensionRegistry.ExtensionInfo extension, - ExtensionRegistryLite extensionRegistry, - MergeTarget target) throws IOException { - Descriptors.FieldDescriptor field = extension.descriptor; - Object value = target.parseMessage(input, extensionRegistry, field, - extension.defaultInstance); - target.setField(field, value); - } -} |