All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.google.protobuf.MessageReflection Maven / Gradle / Ivy

There is a newer version: 9.8.0.76914
Show newest version
// 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.Descriptor;
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 [email protected] (Pherl Liu)
 */
class MessageReflection {

  static void writeMessageTo(
      Message message,
      Map fields,
      CodedOutputStream output,
      boolean alwaysWriteRequiredFields)
      throws IOException {
    final boolean isMessageSet =
        message.getDescriptorForType().getOptions().getMessageSetWireFormat();
    if (alwaysWriteRequiredFields) {
      fields = new TreeMap(fields);
      for (final FieldDescriptor field : message.getDescriptorForType().getFields()) {
        if (field.isRequired() && !fields.containsKey(field)) {
          fields.put(field, message.getField(field));
        }
      }
    }
    for (final Map.Entry 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, Map fields) {
    int size = 0;
    final boolean isMessageSet =
        message.getDescriptorForType().getOptions().getMessageSetWireFormat();

    for (final Map.Entry 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()) {
        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 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 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) 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 results) {
    for (final Descriptors.FieldDescriptor field : message.getDescriptorForType().getFields()) {
      if (field.isRequired() && !message.hasField(field)) {
        results.add(prefix + field.getName());
      }
    }

    for (final Map.Entry 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 findMissingFields(final MessageOrBuilder message) {
    final List results = new ArrayList();
    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 the given group field from the wire, merging with the existing field if it is already
     * present.
     *
     * 

For extensions, defaultInstance must be specified. For regular fields, defaultInstance can * be null. */ void mergeGroup( CodedInputStream input, ExtensionRegistryLite extensionRegistry, FieldDescriptor field, Message defaultInstance) throws IOException; /** * Read the given message field from the wire, merging with the existing field if it is already * present. * *

For extensions, defaultInstance must be specified. For regular fields, defaultInstance can * be null. */ void mergeMessage( CodedInputStream input, ExtensionRegistryLite extensionRegistry, FieldDescriptor field, Message defaultInstance) throws IOException; /** Returns the UTF8 validation level for the field. */ WireFormat.Utf8Validation getUtf8Validation(Descriptors.FieldDescriptor descriptor); /** * 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); /** * Returns an empty 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 newEmptyTargetForField( 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; private boolean hasNestedBuilders = true; @Override public Descriptors.Descriptor getDescriptorForType() { return builder.getDescriptorForType(); } public BuilderAdapter(Message.Builder builder) { this.builder = builder; } @Override public Object getField(Descriptors.FieldDescriptor field) { return builder.getField(field); } private Message.Builder getFieldBuilder(Descriptors.FieldDescriptor field) { if (hasNestedBuilders) { try { return builder.getFieldBuilder(field); } catch (UnsupportedOperationException e) { hasNestedBuilders = false; } } return null; } @Override public boolean hasField(Descriptors.FieldDescriptor field) { return builder.hasField(field); } @Override public MergeTarget setField(Descriptors.FieldDescriptor field, Object value) { if (!field.isRepeated() && value instanceof MessageLite.Builder) { if (value != getFieldBuilder(field)) { builder.setField(field, ((MessageLite.Builder) value).buildPartial()); } return this; } builder.setField(field, value); return this; } @Override public MergeTarget clearField(Descriptors.FieldDescriptor field) { builder.clearField(field); return this; } @Override public MergeTarget setRepeatedField( Descriptors.FieldDescriptor field, int index, Object value) { if (value instanceof MessageLite.Builder) { value = ((MessageLite.Builder) value).buildPartial(); } builder.setRepeatedField(field, index, value); return this; } @Override public MergeTarget addRepeatedField(Descriptors.FieldDescriptor field, Object value) { if (value instanceof MessageLite.Builder) { value = ((MessageLite.Builder) value).buildPartial(); } 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); } @Override public ContainerType getContainerType() { return ContainerType.MESSAGE; } @Override public ExtensionRegistry.ExtensionInfo findExtensionByName( ExtensionRegistry registry, String name) { return registry.findImmutableExtensionByName(name); } @Override public ExtensionRegistry.ExtensionInfo findExtensionByNumber( ExtensionRegistry registry, Descriptors.Descriptor containingType, int fieldNumber) { return registry.findImmutableExtensionByNumber(containingType, fieldNumber); } @Override 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(); } @Override 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(); } @Override 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(); } @Override public void mergeGroup( CodedInputStream input, ExtensionRegistryLite extensionRegistry, FieldDescriptor field, Message defaultInstance) throws IOException { if (!field.isRepeated()) { Message.Builder subBuilder; if (hasField(field)) { subBuilder = getFieldBuilder(field); if (subBuilder != null) { input.readGroup(field.getNumber(), subBuilder, extensionRegistry); return; } else { subBuilder = newMessageFieldInstance(field, defaultInstance); subBuilder.mergeFrom((Message) getField(field)); } } else { subBuilder = newMessageFieldInstance(field, defaultInstance); } input.readGroup(field.getNumber(), subBuilder, extensionRegistry); Object unused = setField(field, subBuilder.buildPartial()); } else { Message.Builder subBuilder = newMessageFieldInstance(field, defaultInstance); input.readGroup(field.getNumber(), subBuilder, extensionRegistry); Object unused = addRepeatedField(field, subBuilder.buildPartial()); } } @Override public void mergeMessage( CodedInputStream input, ExtensionRegistryLite extensionRegistry, Descriptors.FieldDescriptor field, Message defaultInstance) throws IOException { if (!field.isRepeated()) { Message.Builder subBuilder; if (hasField(field)) { subBuilder = getFieldBuilder(field); if (subBuilder != null) { input.readMessage(subBuilder, extensionRegistry); return; } else { subBuilder = newMessageFieldInstance(field, defaultInstance); subBuilder.mergeFrom((Message) getField(field)); } } else { subBuilder = newMessageFieldInstance(field, defaultInstance); } input.readMessage(subBuilder, extensionRegistry); Object unused = setField(field, subBuilder.buildPartial()); } else { Message.Builder subBuilder = newMessageFieldInstance(field, defaultInstance); input.readMessage(subBuilder, extensionRegistry); Object unused = addRepeatedField(field, subBuilder.buildPartial()); } } private Message.Builder newMessageFieldInstance( FieldDescriptor field, Message defaultInstance) { // When default instance is not null. The field is an extension field. if (defaultInstance != null) { return defaultInstance.newBuilderForType(); } else { return builder.newBuilderForField(field); } } @Override public MergeTarget newMergeTargetForField( Descriptors.FieldDescriptor field, Message defaultInstance) { Message.Builder subBuilder; if (!field.isRepeated() && hasField(field)) { subBuilder = getFieldBuilder(field); if (subBuilder != null) { return new BuilderAdapter(subBuilder); } } subBuilder = newMessageFieldInstance(field, defaultInstance); if (!field.isRepeated()) { Message originalMessage = (Message) getField(field); if (originalMessage != null) { subBuilder.mergeFrom(originalMessage); } } return new BuilderAdapter(subBuilder); } @Override public MergeTarget newEmptyTargetForField( Descriptors.FieldDescriptor field, Message defaultInstance) { Message.Builder subBuilder; if (defaultInstance != null) { subBuilder = defaultInstance.newBuilderForType(); } else { subBuilder = builder.newBuilderForField(field); } return new BuilderAdapter(subBuilder); } @Override public WireFormat.Utf8Validation getUtf8Validation(Descriptors.FieldDescriptor descriptor) { if (descriptor.needsUtf8Check()) { return WireFormat.Utf8Validation.STRICT; } // TODO(liujisi): support lazy strings for repeated fields. if (!descriptor.isRepeated() && builder instanceof GeneratedMessage.Builder) { return WireFormat.Utf8Validation.LAZY; } return WireFormat.Utf8Validation.LOOSE; } @Override public Object finish() { return builder; } } static class ExtensionAdapter implements MergeTarget { private final FieldSet extensions; ExtensionAdapter(FieldSet extensions) { this.extensions = extensions; } @Override public Descriptors.Descriptor getDescriptorForType() { throw new UnsupportedOperationException("getDescriptorForType() called on FieldSet object"); } @Override public Object getField(Descriptors.FieldDescriptor field) { return extensions.getField(field); } @Override public boolean hasField(Descriptors.FieldDescriptor field) { return extensions.hasField(field); } @Override public MergeTarget setField(Descriptors.FieldDescriptor field, Object value) { extensions.setField(field, value); return this; } @Override public MergeTarget clearField(Descriptors.FieldDescriptor field) { extensions.clearField(field); return this; } @Override public MergeTarget setRepeatedField( Descriptors.FieldDescriptor field, int index, Object value) { extensions.setRepeatedField(field, index, value); return this; } @Override 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; } @Override public ContainerType getContainerType() { return ContainerType.EXTENSION_SET; } @Override public ExtensionRegistry.ExtensionInfo findExtensionByName( ExtensionRegistry registry, String name) { return registry.findImmutableExtensionByName(name); } @Override public ExtensionRegistry.ExtensionInfo findExtensionByNumber( ExtensionRegistry registry, Descriptors.Descriptor containingType, int fieldNumber) { return registry.findImmutableExtensionByNumber(containingType, fieldNumber); } @Override 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(); } @Override 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(); } @Override public void mergeGroup( CodedInputStream input, ExtensionRegistryLite extensionRegistry, FieldDescriptor field, Message defaultInstance) throws IOException { if (!field.isRepeated()) { if (hasField(field)) { MessageLite.Builder current = ((MessageLite) getField(field)).toBuilder(); input.readGroup(field.getNumber(), current, extensionRegistry); Object unused = setField(field, current.buildPartial()); return; } Message.Builder subBuilder = defaultInstance.newBuilderForType(); input.readGroup(field.getNumber(), subBuilder, extensionRegistry); Object unused = setField(field, subBuilder.buildPartial()); } else { Message.Builder subBuilder = defaultInstance.newBuilderForType(); input.readGroup(field.getNumber(), subBuilder, extensionRegistry); Object unused = addRepeatedField(field, subBuilder.buildPartial()); } } @Override public void mergeMessage( CodedInputStream input, ExtensionRegistryLite extensionRegistry, FieldDescriptor field, Message defaultInstance) throws IOException { if (!field.isRepeated()) { if (hasField(field)) { MessageLite.Builder current = ((MessageLite) getField(field)).toBuilder(); input.readMessage(current, extensionRegistry); Object unused = setField(field, current.buildPartial()); return; } Message.Builder subBuilder = defaultInstance.newBuilderForType(); input.readMessage(subBuilder, extensionRegistry); Object unused = setField(field, subBuilder.buildPartial()); } else { Message.Builder subBuilder = defaultInstance.newBuilderForType(); input.readMessage(subBuilder, extensionRegistry); Object unused = addRepeatedField(field, subBuilder.buildPartial()); } } @Override 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(); } @Override public MergeTarget newMergeTargetForField( Descriptors.FieldDescriptor descriptor, Message defaultInstance) { throw new UnsupportedOperationException("newMergeTargetForField() called on FieldSet object"); } @Override public MergeTarget newEmptyTargetForField( Descriptors.FieldDescriptor descriptor, Message defaultInstance) { throw new UnsupportedOperationException("newEmptyTargetForField() called on FieldSet object"); } @Override public WireFormat.Utf8Validation getUtf8Validation(Descriptors.FieldDescriptor descriptor) { if (descriptor.needsUtf8Check()) { return WireFormat.Utf8Validation.STRICT; } // TODO(b/248145492): support lazy strings for ExtesnsionSet. return WireFormat.Utf8Validation.LOOSE; } @Override public Object finish() { throw new UnsupportedOperationException("finish() called on FieldSet object"); } } static class ExtensionBuilderAdapter implements MergeTarget { private final FieldSet.Builder extensions; ExtensionBuilderAdapter(FieldSet.Builder extensions) { this.extensions = extensions; } @Override public Descriptors.Descriptor getDescriptorForType() { throw new UnsupportedOperationException("getDescriptorForType() called on FieldSet object"); } @Override public Object getField(Descriptors.FieldDescriptor field) { return extensions.getField(field); } @Override public boolean hasField(Descriptors.FieldDescriptor field) { return extensions.hasField(field); } @Override @CanIgnoreReturnValue public MergeTarget setField(Descriptors.FieldDescriptor field, Object value) { extensions.setField(field, value); return this; } @Override @CanIgnoreReturnValue public MergeTarget clearField(Descriptors.FieldDescriptor field) { extensions.clearField(field); return this; } @Override @CanIgnoreReturnValue public MergeTarget setRepeatedField( Descriptors.FieldDescriptor field, int index, Object value) { extensions.setRepeatedField(field, index, value); return this; } @Override @CanIgnoreReturnValue public MergeTarget addRepeatedField(Descriptors.FieldDescriptor field, Object value) { extensions.addRepeatedField(field, value); return this; } @Override public boolean hasOneof(Descriptors.OneofDescriptor oneof) { return false; } @Override @CanIgnoreReturnValue public MergeTarget clearOneof(Descriptors.OneofDescriptor oneof) { // Nothing to clear. return this; } @Override public Descriptors.FieldDescriptor getOneofFieldDescriptor(Descriptors.OneofDescriptor oneof) { return null; } @Override public ContainerType getContainerType() { return ContainerType.EXTENSION_SET; } @Override public ExtensionRegistry.ExtensionInfo findExtensionByName( ExtensionRegistry registry, String name) { return registry.findImmutableExtensionByName(name); } @Override public ExtensionRegistry.ExtensionInfo findExtensionByNumber( ExtensionRegistry registry, Descriptors.Descriptor containingType, int fieldNumber) { return registry.findImmutableExtensionByNumber(containingType, fieldNumber); } @Override 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(); } @Override 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(); } @Override public void mergeGroup( CodedInputStream input, ExtensionRegistryLite extensionRegistry, FieldDescriptor field, Message defaultInstance) throws IOException { if (!field.isRepeated()) { if (hasField(field)) { Object fieldOrBuilder = extensions.getFieldAllowBuilders(field); MessageLite.Builder subBuilder; if (fieldOrBuilder instanceof MessageLite.Builder) { subBuilder = (MessageLite.Builder) fieldOrBuilder; } else { subBuilder = ((MessageLite) fieldOrBuilder).toBuilder(); extensions.setField(field, subBuilder); } input.readGroup(field.getNumber(), subBuilder, extensionRegistry); return; } Message.Builder subBuilder = defaultInstance.newBuilderForType(); input.readGroup(field.getNumber(), subBuilder, extensionRegistry); Object unused = setField(field, subBuilder); } else { Message.Builder subBuilder = defaultInstance.newBuilderForType(); input.readGroup(field.getNumber(), subBuilder, extensionRegistry); Object unused = addRepeatedField(field, subBuilder.buildPartial()); } } @Override public void mergeMessage( CodedInputStream input, ExtensionRegistryLite extensionRegistry, FieldDescriptor field, Message defaultInstance) throws IOException { if (!field.isRepeated()) { if (hasField(field)) { Object fieldOrBuilder = extensions.getFieldAllowBuilders(field); MessageLite.Builder subBuilder; if (fieldOrBuilder instanceof MessageLite.Builder) { subBuilder = (MessageLite.Builder) fieldOrBuilder; } else { subBuilder = ((MessageLite) fieldOrBuilder).toBuilder(); extensions.setField(field, subBuilder); } input.readMessage(subBuilder, extensionRegistry); return; } Message.Builder subBuilder = defaultInstance.newBuilderForType(); input.readMessage(subBuilder, extensionRegistry); Object unused = setField(field, subBuilder); } else { Message.Builder subBuilder = defaultInstance.newBuilderForType(); input.readMessage(subBuilder, extensionRegistry); Object unused = addRepeatedField(field, subBuilder.buildPartial()); } } @Override 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(); } @Override public MergeTarget newMergeTargetForField( Descriptors.FieldDescriptor descriptor, Message defaultInstance) { throw new UnsupportedOperationException("newMergeTargetForField() called on FieldSet object"); } @Override public MergeTarget newEmptyTargetForField( Descriptors.FieldDescriptor descriptor, Message defaultInstance) { throw new UnsupportedOperationException("newEmptyTargetForField() called on FieldSet object"); } @Override public WireFormat.Utf8Validation getUtf8Validation(Descriptors.FieldDescriptor descriptor) { if (descriptor.needsUtf8Check()) { return WireFormat.Utf8Validation.STRICT; } // TODO(b/248145492): support lazy strings for ExtesnsionSet. return WireFormat.Utf8Validation.LOOSE; } @Override 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. * @param unknownFields If not null, unknown fields will be merged to this {@link * UnknownFieldSet}, otherwise unknown fields will be discarded. * @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(), /* isPacked= */ false)) { packed = false; } else if (field.isPackable() && wireType == FieldSet.getWireFormatForFieldType(field.getLiteType(), /* isPacked= */ true)) { packed = true; } else { unknown = true; // Unknown wire type. } if (unknown) { // Unknown field or wrong wire type. Skip. if (unknownFields != null) { return unknownFields.mergeFieldFrom(tag, input); } else { return input.skipField(tag); } } 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(); if (field.getFile().supportsUnknownEnumValue()) { target.addRepeatedField( field, field.getEnumType().findValueByNumberCreatingIfUnknown(rawValue)); } else { final Object value = field.getEnumType().findValueByNumber(rawValue); // If the number isn't recognized as a valid value for this enum, // add it to the unknown fields. if (value == null) { if (unknownFields != null) { unknownFields.mergeVarintField(fieldNumber, rawValue); } } else { target.addRepeatedField(field, value); } } } } else { while (input.getBytesUntilLimit() > 0) { final Object value = WireFormat.readPrimitiveField( input, field.getLiteType(), target.getUtf8Validation(field)); target.addRepeatedField(field, value); } } input.popLimit(limit); } else { final Object value; switch (field.getType()) { case GROUP: { target.mergeGroup(input, extensionRegistry, field, defaultInstance); return true; } case MESSAGE: { target.mergeMessage(input, extensionRegistry, field, defaultInstance); return true; } case ENUM: final int rawValue = input.readEnum(); if (field.getFile().supportsUnknownEnumValue()) { value = field.getEnumType().findValueByNumberCreatingIfUnknown(rawValue); } else { value = field.getEnumType().findValueByNumber(rawValue); // If the number isn't recognized as a valid value for this enum, // add it to the unknown fields. if (value == null) { if (unknownFields != null) { unknownFields.mergeVarintField(fieldNumber, rawValue); } return true; } } break; default: value = WireFormat.readPrimitiveField( input, field.getLiteType(), target.getUtf8Validation(field)); break; } if (field.isRepeated()) { target.addRepeatedField(field, value); } else { target.setField(field, value); } } return true; } /** Read a message from the given input stream into the provided target and UnknownFieldSet. */ static void mergeMessageFrom( Message.Builder target, UnknownFieldSet.Builder unknownFields, CodedInputStream input, ExtensionRegistryLite extensionRegistry) throws IOException { BuilderAdapter builderAdapter = new BuilderAdapter(target); Descriptor descriptorForType = target.getDescriptorForType(); while (true) { final int tag = input.readTag(); if (tag == 0) { break; } if (!mergeFieldFrom( input, unknownFields, extensionRegistry, descriptorForType, builderAdapter, tag)) { // end group tag break; } } } /** 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 uint32 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 != 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); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy