Home | History | Annotate | Download | only in protobuf
      1 // Protocol Buffers - Google's data interchange format
      2 // Copyright 2008 Google Inc.  All rights reserved.
      3 // https://developers.google.com/protocol-buffers/
      4 //
      5 // Redistribution and use in source and binary forms, with or without
      6 // modification, are permitted provided that the following conditions are
      7 // met:
      8 //
      9 //     * Redistributions of source code must retain the above copyright
     10 // notice, this list of conditions and the following disclaimer.
     11 //     * Redistributions in binary form must reproduce the above
     12 // copyright notice, this list of conditions and the following disclaimer
     13 // in the documentation and/or other materials provided with the
     14 // distribution.
     15 //     * Neither the name of Google Inc. nor the names of its
     16 // contributors may be used to endorse or promote products derived from
     17 // this software without specific prior written permission.
     18 //
     19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     30 
     31 package com.google.protobuf;
     32 
     33 import com.google.protobuf.Descriptors.FieldDescriptor;
     34 
     35 import java.io.IOException;
     36 import java.util.ArrayList;
     37 import java.util.List;
     38 import java.util.Map;
     39 import java.util.TreeMap;
     40 
     41 /**
     42  * Reflection utility methods shared by both mutable and immutable messages.
     43  *
     44  * @author liujisi (at) google.com (Pherl Liu)
     45  */
     46 class MessageReflection {
     47 
     48   static void writeMessageTo(Message message, CodedOutputStream output,
     49       boolean alwaysWriteRequiredFields)
     50       throws IOException {
     51     final boolean isMessageSet =
     52         message.getDescriptorForType().getOptions().getMessageSetWireFormat();
     53 
     54     Map<FieldDescriptor, Object> fields = message.getAllFields();
     55     if (alwaysWriteRequiredFields) {
     56       fields = new TreeMap<FieldDescriptor, Object>(fields);
     57       for (final FieldDescriptor field :
     58           message.getDescriptorForType().getFields()) {
     59         if (field.isRequired() && !fields.containsKey(field)) {
     60           fields.put(field, message.getField(field));
     61         }
     62       }
     63     }
     64     for (final Map.Entry<Descriptors.FieldDescriptor, Object> entry :
     65         fields.entrySet()) {
     66       final Descriptors.FieldDescriptor field = entry.getKey();
     67       final Object value = entry.getValue();
     68       if (isMessageSet && field.isExtension() &&
     69           field.getType() == Descriptors.FieldDescriptor.Type.MESSAGE &&
     70           !field.isRepeated()) {
     71         output.writeMessageSetExtension(field.getNumber(), (Message) value);
     72       } else {
     73         FieldSet.writeField(field, value, output);
     74       }
     75     }
     76 
     77     final UnknownFieldSet unknownFields = message.getUnknownFields();
     78     if (isMessageSet) {
     79       unknownFields.writeAsMessageSetTo(output);
     80     } else {
     81       unknownFields.writeTo(output);
     82     }
     83   }
     84 
     85   static int getSerializedSize(Message message) {
     86     int size = 0;
     87     final boolean isMessageSet =
     88         message.getDescriptorForType().getOptions().getMessageSetWireFormat();
     89 
     90     for (final Map.Entry<Descriptors.FieldDescriptor, Object> entry :
     91         message.getAllFields().entrySet()) {
     92       final Descriptors.FieldDescriptor field = entry.getKey();
     93       final Object value = entry.getValue();
     94       if (isMessageSet && field.isExtension() &&
     95           field.getType() == Descriptors.FieldDescriptor.Type.MESSAGE &&
     96           !field.isRepeated()) {
     97         size += CodedOutputStream.computeMessageSetExtensionSize(
     98             field.getNumber(), (Message) value);
     99       } else {
    100         size += FieldSet.computeFieldSize(field, value);
    101       }
    102     }
    103 
    104     final UnknownFieldSet unknownFields = message.getUnknownFields();
    105     if (isMessageSet) {
    106       size += unknownFields.getSerializedSizeAsMessageSet();
    107     } else {
    108       size += unknownFields.getSerializedSize();
    109     }
    110     return size;
    111   }
    112 
    113   static String delimitWithCommas(List<String> parts) {
    114     StringBuilder result = new StringBuilder();
    115     for (String part : parts) {
    116       if (result.length() > 0) {
    117         result.append(", ");
    118       }
    119       result.append(part);
    120     }
    121     return result.toString();
    122   }
    123 
    124   @SuppressWarnings("unchecked")
    125   static boolean isInitialized(MessageOrBuilder message) {
    126     // Check that all required fields are present.
    127     for (final Descriptors.FieldDescriptor field : message
    128         .getDescriptorForType()
    129         .getFields()) {
    130       if (field.isRequired()) {
    131         if (!message.hasField(field)) {
    132           return false;
    133         }
    134       }
    135     }
    136 
    137     // Check that embedded messages are initialized.
    138     for (final Map.Entry<Descriptors.FieldDescriptor, Object> entry :
    139         message.getAllFields().entrySet()) {
    140       final Descriptors.FieldDescriptor field = entry.getKey();
    141       if (field.getJavaType() == Descriptors.FieldDescriptor.JavaType.MESSAGE) {
    142         if (field.isRepeated()) {
    143           for (final Message element
    144               : (List<Message>) entry.getValue()) {
    145             if (!element.isInitialized()) {
    146               return false;
    147             }
    148           }
    149         } else {
    150           if (!((Message) entry.getValue()).isInitialized()) {
    151             return false;
    152           }
    153         }
    154       }
    155     }
    156 
    157     return true;
    158   }
    159 
    160   private static String subMessagePrefix(final String prefix,
    161       final Descriptors.FieldDescriptor field,
    162       final int index) {
    163     final StringBuilder result = new StringBuilder(prefix);
    164     if (field.isExtension()) {
    165       result.append('(')
    166           .append(field.getFullName())
    167           .append(')');
    168     } else {
    169       result.append(field.getName());
    170     }
    171     if (index != -1) {
    172       result.append('[')
    173           .append(index)
    174           .append(']');
    175     }
    176     result.append('.');
    177     return result.toString();
    178   }
    179 
    180   private static void findMissingFields(final MessageOrBuilder message,
    181       final String prefix,
    182       final List<String> results) {
    183     for (final Descriptors.FieldDescriptor field :
    184         message.getDescriptorForType().getFields()) {
    185       if (field.isRequired() && !message.hasField(field)) {
    186         results.add(prefix + field.getName());
    187       }
    188     }
    189 
    190     for (final Map.Entry<Descriptors.FieldDescriptor, Object> entry :
    191         message.getAllFields().entrySet()) {
    192       final Descriptors.FieldDescriptor field = entry.getKey();
    193       final Object value = entry.getValue();
    194 
    195       if (field.getJavaType() == Descriptors.FieldDescriptor.JavaType.MESSAGE) {
    196         if (field.isRepeated()) {
    197           int i = 0;
    198           for (final Object element : (List) value) {
    199             findMissingFields((MessageOrBuilder) element,
    200                 subMessagePrefix(prefix, field, i++),
    201                 results);
    202           }
    203         } else {
    204           if (message.hasField(field)) {
    205             findMissingFields((MessageOrBuilder) value,
    206                 subMessagePrefix(prefix, field, -1),
    207                 results);
    208           }
    209         }
    210       }
    211     }
    212   }
    213 
    214   /**
    215    * Populates {@code this.missingFields} with the full "path" of each missing
    216    * required field in the given message.
    217    */
    218   static List<String> findMissingFields(
    219       final MessageOrBuilder message) {
    220     final List<String> results = new ArrayList<String>();
    221     findMissingFields(message, "", results);
    222     return results;
    223   }
    224 
    225   static interface MergeTarget {
    226     enum ContainerType {
    227       MESSAGE, EXTENSION_SET
    228     }
    229 
    230     /**
    231      * Returns the descriptor for the target.
    232      */
    233     public Descriptors.Descriptor getDescriptorForType();
    234 
    235     public ContainerType getContainerType();
    236 
    237     public ExtensionRegistry.ExtensionInfo findExtensionByName(
    238         ExtensionRegistry registry, String name);
    239 
    240     public ExtensionRegistry.ExtensionInfo findExtensionByNumber(
    241         ExtensionRegistry registry, Descriptors.Descriptor containingType,
    242         int fieldNumber);
    243 
    244     /**
    245      * Obtains the value of the given field, or the default value if it is not
    246      * set.  For primitive fields, the boxed primitive value is returned. For
    247      * enum fields, the EnumValueDescriptor for the value is returned. For
    248      * embedded message fields, the sub-message is returned.  For repeated
    249      * fields, a java.util.List is returned.
    250      */
    251     public Object getField(Descriptors.FieldDescriptor field);
    252 
    253     /**
    254      * Returns true if the given field is set.  This is exactly equivalent to
    255      * calling the generated "has" accessor method corresponding to the field.
    256      *
    257      * @throws IllegalArgumentException The field is a repeated field, or {@code
    258      *     field.getContainingType() != getDescriptorForType()}.
    259      */
    260     boolean hasField(Descriptors.FieldDescriptor field);
    261 
    262     /**
    263      * Sets a field to the given value.  The value must be of the correct type
    264      * for this field, i.e. the same type that
    265      * {@link Message#getField(Descriptors.FieldDescriptor)}
    266      * would return.
    267      */
    268     MergeTarget setField(Descriptors.FieldDescriptor field, Object value);
    269 
    270     /**
    271      * Clears the field.  This is exactly equivalent to calling the generated
    272      * "clear" accessor method corresponding to the field.
    273      */
    274     MergeTarget clearField(Descriptors.FieldDescriptor field);
    275 
    276     /**
    277      * Sets an element of a repeated field to the given value.  The value must
    278      * be of the correct type for this field, i.e. the same type that {@link
    279      * Message#getRepeatedField(Descriptors.FieldDescriptor, int)} would return.
    280      *
    281      * @throws IllegalArgumentException The field is not a repeated field, or
    282      *                                  {@code field.getContainingType() !=
    283      *                                  getDescriptorForType()}.
    284      */
    285     MergeTarget setRepeatedField(Descriptors.FieldDescriptor field,
    286         int index, Object value);
    287 
    288     /**
    289      * Like {@code setRepeatedField}, but appends the value as a new element.
    290      *
    291      * @throws IllegalArgumentException The field is not a repeated field, or
    292      *                                  {@code field.getContainingType() !=
    293      *                                  getDescriptorForType()}.
    294      */
    295     MergeTarget addRepeatedField(Descriptors.FieldDescriptor field,
    296         Object value);
    297 
    298     /**
    299      * Returns true if the given oneof is set.
    300      *
    301      * @throws IllegalArgumentException if
    302      *           {@code oneof.getContainingType() != getDescriptorForType()}.
    303      */
    304     boolean hasOneof(Descriptors.OneofDescriptor oneof);
    305 
    306     /**
    307      * Clears the oneof.  This is exactly equivalent to calling the generated
    308      * "clear" accessor method corresponding to the oneof.
    309      */
    310     MergeTarget clearOneof(Descriptors.OneofDescriptor oneof);
    311 
    312     /**
    313      * Obtains the FieldDescriptor if the given oneof is set. Returns null
    314      * if no field is set.
    315      */
    316     Descriptors.FieldDescriptor getOneofFieldDescriptor(Descriptors.OneofDescriptor oneof);
    317 
    318     /**
    319      * Parse the input stream into a sub field group defined based on either
    320      * FieldDescriptor or the default instance.
    321      */
    322     Object parseGroup(CodedInputStream input, ExtensionRegistryLite registry,
    323         Descriptors.FieldDescriptor descriptor, Message defaultInstance)
    324         throws IOException;
    325 
    326     /**
    327      * Parse the input stream into a sub field message defined based on either
    328      * FieldDescriptor or the default instance.
    329      */
    330     Object parseMessage(CodedInputStream input, ExtensionRegistryLite registry,
    331         Descriptors.FieldDescriptor descriptor, Message defaultInstance)
    332         throws IOException;
    333 
    334     /**
    335      * Parse from a ByteString into a sub field message defined based on either
    336      * FieldDescriptor or the default instance.  There isn't a varint indicating
    337      * the length of the message at the beginning of the input ByteString.
    338      */
    339     Object parseMessageFromBytes(
    340         ByteString bytes, ExtensionRegistryLite registry,
    341         Descriptors.FieldDescriptor descriptor, Message defaultInstance)
    342         throws IOException;
    343 
    344     /**
    345      * Read a primitive field from input. Note that builders and mutable
    346      * messages may use different Java types to represent a primtive field.
    347      */
    348     Object readPrimitiveField(
    349         CodedInputStream input, WireFormat.FieldType type,
    350         boolean checkUtf8) throws IOException;
    351 
    352     /**
    353      * Returns a new merge target for a sub-field. When defaultInstance is
    354      * provided, it indicates the descriptor is for an extension type, and
    355      * implementations should create a new instance from the defaultInstance
    356      * prototype directly.
    357      */
    358     MergeTarget newMergeTargetForField(
    359         Descriptors.FieldDescriptor descriptor,
    360         Message defaultInstance);
    361 
    362     /**
    363      * Finishes the merge and returns the underlying object.
    364      */
    365     Object finish();
    366   }
    367 
    368   static class BuilderAdapter implements MergeTarget {
    369 
    370     private final Message.Builder builder;
    371 
    372     public Descriptors.Descriptor getDescriptorForType() {
    373       return builder.getDescriptorForType();
    374     }
    375 
    376     public BuilderAdapter(Message.Builder builder) {
    377       this.builder = builder;
    378     }
    379 
    380     public Object getField(Descriptors.FieldDescriptor field) {
    381       return builder.getField(field);
    382     }
    383 
    384     @Override
    385     public boolean hasField(Descriptors.FieldDescriptor field) {
    386       return builder.hasField(field);
    387     }
    388 
    389     public MergeTarget setField(Descriptors.FieldDescriptor field,
    390         Object value) {
    391       builder.setField(field, value);
    392       return this;
    393     }
    394 
    395     public MergeTarget clearField(Descriptors.FieldDescriptor field) {
    396       builder.clearField(field);
    397       return this;
    398     }
    399 
    400     public MergeTarget setRepeatedField(
    401         Descriptors.FieldDescriptor field, int index, Object value) {
    402       builder.setRepeatedField(field, index, value);
    403       return this;
    404     }
    405 
    406     public MergeTarget addRepeatedField(
    407         Descriptors.FieldDescriptor field, Object value) {
    408       builder.addRepeatedField(field, value);
    409       return this;
    410     }
    411 
    412     @Override
    413     public boolean hasOneof(Descriptors.OneofDescriptor oneof) {
    414       return builder.hasOneof(oneof);
    415     }
    416 
    417     @Override
    418     public MergeTarget clearOneof(Descriptors.OneofDescriptor oneof) {
    419       builder.clearOneof(oneof);
    420       return this;
    421     }
    422 
    423     @Override
    424     public Descriptors.FieldDescriptor getOneofFieldDescriptor(Descriptors.OneofDescriptor oneof) {
    425       return builder.getOneofFieldDescriptor(oneof);
    426     }
    427 
    428     public ContainerType getContainerType() {
    429       return ContainerType.MESSAGE;
    430     }
    431 
    432     public ExtensionRegistry.ExtensionInfo findExtensionByName(
    433         ExtensionRegistry registry, String name) {
    434       return registry.findImmutableExtensionByName(name);
    435     }
    436 
    437     public ExtensionRegistry.ExtensionInfo findExtensionByNumber(
    438         ExtensionRegistry registry, Descriptors.Descriptor containingType,
    439         int fieldNumber) {
    440       return registry.findImmutableExtensionByNumber(containingType,
    441           fieldNumber);
    442     }
    443 
    444     public Object parseGroup(CodedInputStream input,
    445         ExtensionRegistryLite extensionRegistry,
    446         Descriptors.FieldDescriptor field, Message defaultInstance)
    447         throws IOException {
    448       Message.Builder subBuilder;
    449       // When default instance is not null. The field is an extension field.
    450       if (defaultInstance != null) {
    451         subBuilder = defaultInstance.newBuilderForType();
    452       } else {
    453         subBuilder = builder.newBuilderForField(field);
    454       }
    455       if (!field.isRepeated()) {
    456         Message originalMessage = (Message) getField(field);
    457         if (originalMessage != null) {
    458           subBuilder.mergeFrom(originalMessage);
    459         }
    460       }
    461       input.readGroup(field.getNumber(), subBuilder, extensionRegistry);
    462       return subBuilder.buildPartial();
    463     }
    464 
    465     public Object parseMessage(CodedInputStream input,
    466         ExtensionRegistryLite extensionRegistry,
    467         Descriptors.FieldDescriptor field, Message defaultInstance)
    468         throws IOException {
    469       Message.Builder subBuilder;
    470       // When default instance is not null. The field is an extension field.
    471       if (defaultInstance != null) {
    472         subBuilder = defaultInstance.newBuilderForType();
    473       } else {
    474         subBuilder = builder.newBuilderForField(field);
    475       }
    476       if (!field.isRepeated()) {
    477         Message originalMessage = (Message) getField(field);
    478         if (originalMessage != null) {
    479           subBuilder.mergeFrom(originalMessage);
    480         }
    481       }
    482       input.readMessage(subBuilder, extensionRegistry);
    483       return subBuilder.buildPartial();
    484     }
    485 
    486     public Object parseMessageFromBytes(ByteString bytes,
    487         ExtensionRegistryLite extensionRegistry,
    488         Descriptors.FieldDescriptor field, Message defaultInstance)
    489         throws IOException {
    490       Message.Builder subBuilder;
    491       // When default instance is not null. The field is an extension field.
    492       if (defaultInstance != null) {
    493         subBuilder = defaultInstance.newBuilderForType();
    494       } else {
    495         subBuilder = builder.newBuilderForField(field);
    496       }
    497       if (!field.isRepeated()) {
    498         Message originalMessage = (Message) getField(field);
    499         if (originalMessage != null) {
    500           subBuilder.mergeFrom(originalMessage);
    501         }
    502       }
    503       subBuilder.mergeFrom(bytes, extensionRegistry);
    504       return subBuilder.buildPartial();
    505     }
    506 
    507     public MergeTarget newMergeTargetForField(Descriptors.FieldDescriptor field,
    508         Message defaultInstance) {
    509       if (defaultInstance != null) {
    510         return new BuilderAdapter(
    511             defaultInstance.newBuilderForType());
    512       } else {
    513         return new BuilderAdapter(builder.newBuilderForField(field));
    514       }
    515     }
    516 
    517     public Object readPrimitiveField(
    518         CodedInputStream input, WireFormat.FieldType type,
    519         boolean checkUtf8) throws IOException {
    520       return FieldSet.readPrimitiveField(input, type, checkUtf8);
    521     }
    522 
    523     public Object finish() {
    524       return builder.buildPartial();
    525     }
    526   }
    527 
    528 
    529   static class ExtensionAdapter implements MergeTarget {
    530 
    531     private final FieldSet<Descriptors.FieldDescriptor> extensions;
    532 
    533     ExtensionAdapter(FieldSet<Descriptors.FieldDescriptor> extensions) {
    534       this.extensions = extensions;
    535     }
    536 
    537     public Descriptors.Descriptor getDescriptorForType() {
    538       throw new UnsupportedOperationException(
    539           "getDescriptorForType() called on FieldSet object");
    540     }
    541 
    542     public Object getField(Descriptors.FieldDescriptor field) {
    543       return extensions.getField(field);
    544     }
    545 
    546     public boolean hasField(Descriptors.FieldDescriptor field) {
    547       return extensions.hasField(field);
    548     }
    549 
    550     public MergeTarget setField(Descriptors.FieldDescriptor field,
    551         Object value) {
    552       extensions.setField(field, value);
    553       return this;
    554     }
    555 
    556     public MergeTarget clearField(Descriptors.FieldDescriptor field) {
    557       extensions.clearField(field);
    558       return this;
    559     }
    560 
    561     public MergeTarget setRepeatedField(
    562         Descriptors.FieldDescriptor field, int index, Object value) {
    563       extensions.setRepeatedField(field, index, value);
    564       return this;
    565     }
    566 
    567     public MergeTarget addRepeatedField(
    568         Descriptors.FieldDescriptor field, Object value) {
    569       extensions.addRepeatedField(field, value);
    570       return this;
    571     }
    572 
    573     @Override
    574     public boolean hasOneof(Descriptors.OneofDescriptor oneof) {
    575       return false;
    576     }
    577 
    578     @Override
    579     public MergeTarget clearOneof(Descriptors.OneofDescriptor oneof) {
    580       // Nothing to clear.
    581       return this;
    582     }
    583 
    584     @Override
    585     public Descriptors.FieldDescriptor getOneofFieldDescriptor(Descriptors.OneofDescriptor oneof) {
    586       return null;
    587     }
    588 
    589     public ContainerType getContainerType() {
    590       return ContainerType.EXTENSION_SET;
    591     }
    592 
    593     public ExtensionRegistry.ExtensionInfo findExtensionByName(
    594         ExtensionRegistry registry, String name) {
    595       return registry.findImmutableExtensionByName(name);
    596     }
    597 
    598     public ExtensionRegistry.ExtensionInfo findExtensionByNumber(
    599         ExtensionRegistry registry, Descriptors.Descriptor containingType,
    600         int fieldNumber) {
    601       return registry.findImmutableExtensionByNumber(containingType,
    602           fieldNumber);
    603     }
    604 
    605     public Object parseGroup(CodedInputStream input,
    606         ExtensionRegistryLite registry, Descriptors.FieldDescriptor field,
    607         Message defaultInstance) throws IOException {
    608       Message.Builder subBuilder =
    609           defaultInstance.newBuilderForType();
    610       if (!field.isRepeated()) {
    611         Message originalMessage = (Message) getField(field);
    612         if (originalMessage != null) {
    613           subBuilder.mergeFrom(originalMessage);
    614         }
    615       }
    616       input.readGroup(field.getNumber(), subBuilder, registry);
    617       return subBuilder.buildPartial();
    618     }
    619 
    620     public Object parseMessage(CodedInputStream input,
    621         ExtensionRegistryLite registry, Descriptors.FieldDescriptor field,
    622         Message defaultInstance) throws IOException {
    623       Message.Builder subBuilder =
    624           defaultInstance.newBuilderForType();
    625       if (!field.isRepeated()) {
    626         Message originalMessage = (Message) getField(field);
    627         if (originalMessage != null) {
    628           subBuilder.mergeFrom(originalMessage);
    629         }
    630       }
    631       input.readMessage(subBuilder, registry);
    632       return subBuilder.buildPartial();
    633     }
    634 
    635     public Object parseMessageFromBytes(ByteString bytes,
    636         ExtensionRegistryLite registry, Descriptors.FieldDescriptor field,
    637         Message defaultInstance) throws IOException {
    638       Message.Builder subBuilder =  defaultInstance.newBuilderForType();
    639       if (!field.isRepeated()) {
    640         Message originalMessage = (Message) getField(field);
    641         if (originalMessage != null) {
    642           subBuilder.mergeFrom(originalMessage);
    643         }
    644       }
    645       subBuilder.mergeFrom(bytes, registry);
    646       return subBuilder.buildPartial();
    647     }
    648 
    649     public MergeTarget newMergeTargetForField(
    650         Descriptors.FieldDescriptor descriptor, Message defaultInstance) {
    651       throw new UnsupportedOperationException(
    652           "newMergeTargetForField() called on FieldSet object");
    653     }
    654 
    655     public Object readPrimitiveField(
    656         CodedInputStream input, WireFormat.FieldType type,
    657         boolean checkUtf8) throws IOException {
    658       return FieldSet.readPrimitiveField(input, type, checkUtf8);
    659     }
    660 
    661     public Object finish() {
    662       throw new UnsupportedOperationException(
    663           "finish() called on FieldSet object");
    664     }
    665   }
    666 
    667   /**
    668    * Parses a single field into MergeTarget. The target can be Message.Builder,
    669    * FieldSet or MutableMessage.
    670    *
    671    * Package-private because it is used by GeneratedMessage.ExtendableMessage.
    672    *
    673    * @param tag The tag, which should have already been read.
    674    * @return {@code true} unless the tag is an end-group tag.
    675    */
    676   static boolean mergeFieldFrom(
    677       CodedInputStream input,
    678       UnknownFieldSet.Builder unknownFields,
    679       ExtensionRegistryLite extensionRegistry,
    680       Descriptors.Descriptor type,
    681       MergeTarget target,
    682       int tag) throws IOException {
    683     if (type.getOptions().getMessageSetWireFormat() &&
    684         tag == WireFormat.MESSAGE_SET_ITEM_TAG) {
    685       mergeMessageSetExtensionFromCodedStream(
    686           input, unknownFields, extensionRegistry, type, target);
    687       return true;
    688     }
    689 
    690     final int wireType = WireFormat.getTagWireType(tag);
    691     final int fieldNumber = WireFormat.getTagFieldNumber(tag);
    692 
    693     final Descriptors.FieldDescriptor field;
    694     Message defaultInstance = null;
    695 
    696     if (type.isExtensionNumber(fieldNumber)) {
    697       // extensionRegistry may be either ExtensionRegistry or
    698       // ExtensionRegistryLite.  Since the type we are parsing is a full
    699       // message, only a full ExtensionRegistry could possibly contain
    700       // extensions of it.  Otherwise we will treat the registry as if it
    701       // were empty.
    702       if (extensionRegistry instanceof ExtensionRegistry) {
    703         final ExtensionRegistry.ExtensionInfo extension =
    704             target.findExtensionByNumber((ExtensionRegistry) extensionRegistry,
    705                 type, fieldNumber);
    706         if (extension == null) {
    707           field = null;
    708         } else {
    709           field = extension.descriptor;
    710           defaultInstance = extension.defaultInstance;
    711           if (defaultInstance == null &&
    712               field.getJavaType()
    713                   == Descriptors.FieldDescriptor.JavaType.MESSAGE) {
    714             throw new IllegalStateException(
    715                 "Message-typed extension lacked default instance: " +
    716                     field.getFullName());
    717           }
    718         }
    719       } else {
    720         field = null;
    721       }
    722     } else if (target.getContainerType() == MergeTarget.ContainerType.MESSAGE) {
    723       field = type.findFieldByNumber(fieldNumber);
    724     } else {
    725       field = null;
    726     }
    727 
    728     boolean unknown = false;
    729     boolean packed = false;
    730     if (field == null) {
    731       unknown = true;  // Unknown field.
    732     } else if (wireType == FieldSet.getWireFormatForFieldType(
    733         field.getLiteType(),
    734         false  /* isPacked */)) {
    735       packed = false;
    736     } else if (field.isPackable() &&
    737         wireType == FieldSet.getWireFormatForFieldType(
    738             field.getLiteType(),
    739             true  /* isPacked */)) {
    740       packed = true;
    741     } else {
    742       unknown = true;  // Unknown wire type.
    743     }
    744 
    745     if (unknown) {  // Unknown field or wrong wire type.  Skip.
    746       return unknownFields.mergeFieldFrom(tag, input);
    747     }
    748 
    749     if (packed) {
    750       final int length = input.readRawVarint32();
    751       final int limit = input.pushLimit(length);
    752       if (field.getLiteType() == WireFormat.FieldType.ENUM) {
    753         while (input.getBytesUntilLimit() > 0) {
    754           final int rawValue = input.readEnum();
    755           final Object value = field.getEnumType().findValueByNumber(rawValue);
    756           if (value == null) {
    757             // If the number isn't recognized as a valid value for this
    758             // enum, drop it (don't even add it to unknownFields).
    759             return true;
    760           }
    761           target.addRepeatedField(field, value);
    762         }
    763       } else {
    764         while (input.getBytesUntilLimit() > 0) {
    765           final Object value =
    766               target.readPrimitiveField(input, field.getLiteType(), field.needsUtf8Check());
    767           target.addRepeatedField(field, value);
    768         }
    769       }
    770       input.popLimit(limit);
    771     } else {
    772       final Object value;
    773       switch (field.getType()) {
    774         case GROUP: {
    775           value = target
    776               .parseGroup(input, extensionRegistry, field, defaultInstance);
    777           break;
    778         }
    779         case MESSAGE: {
    780           value = target
    781               .parseMessage(input, extensionRegistry, field, defaultInstance);
    782           break;
    783         }
    784         case ENUM:
    785           final int rawValue = input.readEnum();
    786           value = field.getEnumType().findValueByNumber(rawValue);
    787           // If the number isn't recognized as a valid value for this enum,
    788           // drop it.
    789           if (value == null) {
    790             unknownFields.mergeVarintField(fieldNumber, rawValue);
    791             return true;
    792           }
    793           break;
    794         default:
    795           value = target.readPrimitiveField(input, field.getLiteType(), field.needsUtf8Check());
    796           break;
    797       }
    798 
    799       if (field.isRepeated()) {
    800         target.addRepeatedField(field, value);
    801       } else {
    802         target.setField(field, value);
    803       }
    804     }
    805 
    806     return true;
    807   }
    808 
    809   /**
    810    * Called by {@code #mergeFieldFrom()} to parse a MessageSet extension into
    811    * MergeTarget.
    812    */
    813   private static void mergeMessageSetExtensionFromCodedStream(
    814       CodedInputStream input,
    815       UnknownFieldSet.Builder unknownFields,
    816       ExtensionRegistryLite extensionRegistry,
    817       Descriptors.Descriptor type,
    818       MergeTarget target) throws IOException {
    819 
    820     // The wire format for MessageSet is:
    821     //   message MessageSet {
    822     //     repeated group Item = 1 {
    823     //       required int32 typeId = 2;
    824     //       required bytes message = 3;
    825     //     }
    826     //   }
    827     // "typeId" is the extension's field number.  The extension can only be
    828     // a message type, where "message" contains the encoded bytes of that
    829     // message.
    830     //
    831     // In practice, we will probably never see a MessageSet item in which
    832     // the message appears before the type ID, or where either field does not
    833     // appear exactly once.  However, in theory such cases are valid, so we
    834     // should be prepared to accept them.
    835 
    836     int typeId = 0;
    837     ByteString rawBytes = null; // If we encounter "message" before "typeId"
    838     ExtensionRegistry.ExtensionInfo extension = null;
    839 
    840     // Read bytes from input, if we get it's type first then parse it eagerly,
    841     // otherwise we store the raw bytes in a local variable.
    842     while (true) {
    843       final int tag = input.readTag();
    844       if (tag == 0) {
    845         break;
    846       }
    847 
    848       if (tag == WireFormat.MESSAGE_SET_TYPE_ID_TAG) {
    849         typeId = input.readUInt32();
    850         if (typeId != 0) {
    851           // extensionRegistry may be either ExtensionRegistry or
    852           // ExtensionRegistryLite. Since the type we are parsing is a full
    853           // message, only a full ExtensionRegistry could possibly contain
    854           // extensions of it. Otherwise we will treat the registry as if it
    855           // were empty.
    856           if (extensionRegistry instanceof ExtensionRegistry) {
    857             extension = target.findExtensionByNumber(
    858                 (ExtensionRegistry) extensionRegistry, type, typeId);
    859           }
    860         }
    861 
    862       } else if (tag == WireFormat.MESSAGE_SET_MESSAGE_TAG) {
    863         if (typeId != 0) {
    864           if (extension != null &&
    865               ExtensionRegistryLite.isEagerlyParseMessageSets()) {
    866             // We already know the type, so we can parse directly from the
    867             // input with no copying.  Hooray!
    868             eagerlyMergeMessageSetExtension(
    869                 input, extension, extensionRegistry, target);
    870             rawBytes = null;
    871             continue;
    872           }
    873         }
    874         // We haven't seen a type ID yet or we want parse message lazily.
    875         rawBytes = input.readBytes();
    876 
    877       } else { // Unknown tag. Skip it.
    878         if (!input.skipField(tag)) {
    879           break; // End of group
    880         }
    881       }
    882     }
    883     input.checkLastTagWas(WireFormat.MESSAGE_SET_ITEM_END_TAG);
    884 
    885     // Process the raw bytes.
    886     if (rawBytes != null && typeId != 0) { // Zero is not a valid type ID.
    887       if (extension != null) { // We known the type
    888         mergeMessageSetExtensionFromBytes(
    889             rawBytes, extension, extensionRegistry, target);
    890       } else { // We don't know how to parse this. Ignore it.
    891         if (rawBytes != null) {
    892           unknownFields.mergeField(typeId, UnknownFieldSet.Field.newBuilder()
    893               .addLengthDelimited(rawBytes).build());
    894         }
    895       }
    896     }
    897   }
    898 
    899   private static void mergeMessageSetExtensionFromBytes(
    900       ByteString rawBytes,
    901       ExtensionRegistry.ExtensionInfo extension,
    902       ExtensionRegistryLite extensionRegistry,
    903       MergeTarget target) throws IOException {
    904 
    905     Descriptors.FieldDescriptor field = extension.descriptor;
    906     boolean hasOriginalValue = target.hasField(field);
    907 
    908     if (hasOriginalValue || ExtensionRegistryLite.isEagerlyParseMessageSets()) {
    909       // If the field already exists, we just parse the field.
    910       Object value = target.parseMessageFromBytes(
    911           rawBytes, extensionRegistry,field, extension.defaultInstance);
    912       target.setField(field, value);
    913     } else {
    914       // Use LazyField to load MessageSet lazily.
    915       LazyField lazyField = new LazyField(
    916           extension.defaultInstance, extensionRegistry, rawBytes);
    917       target.setField(field, lazyField);
    918     }
    919   }
    920 
    921   private static void eagerlyMergeMessageSetExtension(
    922       CodedInputStream input,
    923       ExtensionRegistry.ExtensionInfo extension,
    924       ExtensionRegistryLite extensionRegistry,
    925       MergeTarget target) throws IOException {
    926     Descriptors.FieldDescriptor field = extension.descriptor;
    927     Object value = target.parseMessage(input, extensionRegistry, field,
    928                                        extension.defaultInstance);
    929     target.setField(field, value);
    930   }
    931 }
    932