• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.AbstractMessageLite.Builder.LimitedInputStream;
34 
35 import java.io.IOException;
36 import java.io.InputStream;
37 import java.io.OutputStream;
38 import java.util.ArrayList;
39 import java.util.Arrays;
40 import java.util.Collections;
41 import java.util.List;
42 import java.util.Map;
43 import java.util.TreeMap;
44 
45 /**
46  * {@code UnknownFieldSet} is used to keep track of fields which were seen when
47  * parsing a protocol message but whose field numbers or types are unrecognized.
48  * This most frequently occurs when new fields are added to a message type
49  * and then messages containing those fields are read by old software that was
50  * compiled before the new types were added.
51  *
52  * <p>Every {@link Message} contains an {@code UnknownFieldSet} (and every
53  * {@link Message.Builder} contains an {@link Builder}).
54  *
55  * <p>Most users will never need to use this class.
56  *
57  * @author kenton@google.com Kenton Varda
58  */
59 public final class UnknownFieldSet implements MessageLite {
UnknownFieldSet()60   private UnknownFieldSet() {}
61 
62   /** Create a new {@link Builder}. */
newBuilder()63   public static Builder newBuilder() {
64     return Builder.create();
65   }
66 
67   /**
68    * Create a new {@link Builder} and initialize it to be a copy
69    * of {@code copyFrom}.
70    */
newBuilder(final UnknownFieldSet copyFrom)71   public static Builder newBuilder(final UnknownFieldSet copyFrom) {
72     return newBuilder().mergeFrom(copyFrom);
73   }
74 
75   /** Get an empty {@code UnknownFieldSet}. */
getDefaultInstance()76   public static UnknownFieldSet getDefaultInstance() {
77     return defaultInstance;
78   }
getDefaultInstanceForType()79   public UnknownFieldSet getDefaultInstanceForType() {
80     return defaultInstance;
81   }
82   private static final UnknownFieldSet defaultInstance =
83     new UnknownFieldSet(Collections.<Integer, Field>emptyMap());
84 
85   /**
86    * Construct an {@code UnknownFieldSet} around the given map.  The map is
87    * expected to be immutable.
88    */
UnknownFieldSet(final Map<Integer, Field> fields)89   private UnknownFieldSet(final Map<Integer, Field> fields) {
90     this.fields = fields;
91   }
92   private Map<Integer, Field> fields;
93 
94 
95   @Override
equals(final Object other)96   public boolean equals(final Object other) {
97     if (this == other) {
98       return true;
99     }
100     return (other instanceof UnknownFieldSet) &&
101            fields.equals(((UnknownFieldSet) other).fields);
102   }
103 
104   @Override
hashCode()105   public int hashCode() {
106     return fields.hashCode();
107   }
108 
109   /** Get a map of fields in the set by number. */
asMap()110   public Map<Integer, Field> asMap() {
111     return fields;
112   }
113 
114   /** Check if the given field number is present in the set. */
hasField(final int number)115   public boolean hasField(final int number) {
116     return fields.containsKey(number);
117   }
118 
119   /**
120    * Get a field by number.  Returns an empty field if not present.  Never
121    * returns {@code null}.
122    */
getField(final int number)123   public Field getField(final int number) {
124     final Field result = fields.get(number);
125     return (result == null) ? Field.getDefaultInstance() : result;
126   }
127 
128   /** Serializes the set and writes it to {@code output}. */
writeTo(final CodedOutputStream output)129   public void writeTo(final CodedOutputStream output) throws IOException {
130     for (final Map.Entry<Integer, Field> entry : fields.entrySet()) {
131       entry.getValue().writeTo(entry.getKey(), output);
132     }
133   }
134 
135   /**
136    * Converts the set to a string in protocol buffer text format. This is
137    * just a trivial wrapper around
138    * {@link TextFormat#printToString(UnknownFieldSet)}.
139    */
140   @Override
toString()141   public String toString() {
142     return TextFormat.printToString(this);
143   }
144 
145   /**
146    * Serializes the message to a {@code ByteString} and returns it. This is
147    * just a trivial wrapper around {@link #writeTo(CodedOutputStream)}.
148    */
toByteString()149   public ByteString toByteString() {
150     try {
151       final ByteString.CodedBuilder out =
152         ByteString.newCodedBuilder(getSerializedSize());
153       writeTo(out.getCodedOutput());
154       return out.build();
155     } catch (final IOException e) {
156       throw new RuntimeException(
157         "Serializing to a ByteString threw an IOException (should " +
158         "never happen).", e);
159     }
160   }
161 
162   /**
163    * Serializes the message to a {@code byte} array and returns it.  This is
164    * just a trivial wrapper around {@link #writeTo(CodedOutputStream)}.
165    */
toByteArray()166   public byte[] toByteArray() {
167     try {
168       final byte[] result = new byte[getSerializedSize()];
169       final CodedOutputStream output = CodedOutputStream.newInstance(result);
170       writeTo(output);
171       output.checkNoSpaceLeft();
172       return result;
173     } catch (final IOException e) {
174       throw new RuntimeException(
175         "Serializing to a byte array threw an IOException " +
176         "(should never happen).", e);
177     }
178   }
179 
180   /**
181    * Serializes the message and writes it to {@code output}.  This is just a
182    * trivial wrapper around {@link #writeTo(CodedOutputStream)}.
183    */
writeTo(final OutputStream output)184   public void writeTo(final OutputStream output) throws IOException {
185     final CodedOutputStream codedOutput = CodedOutputStream.newInstance(output);
186     writeTo(codedOutput);
187     codedOutput.flush();
188   }
189 
writeDelimitedTo(OutputStream output)190   public void writeDelimitedTo(OutputStream output) throws IOException {
191     final CodedOutputStream codedOutput = CodedOutputStream.newInstance(output);
192     codedOutput.writeRawVarint32(getSerializedSize());
193     writeTo(codedOutput);
194     codedOutput.flush();
195   }
196 
197   /** Get the number of bytes required to encode this set. */
getSerializedSize()198   public int getSerializedSize() {
199     int result = 0;
200     for (final Map.Entry<Integer, Field> entry : fields.entrySet()) {
201       result += entry.getValue().getSerializedSize(entry.getKey());
202     }
203     return result;
204   }
205 
206   /**
207    * Serializes the set and writes it to {@code output} using
208    * {@code MessageSet} wire format.
209    */
writeAsMessageSetTo(final CodedOutputStream output)210   public void writeAsMessageSetTo(final CodedOutputStream output)
211       throws IOException {
212     for (final Map.Entry<Integer, Field> entry : fields.entrySet()) {
213       entry.getValue().writeAsMessageSetExtensionTo(
214         entry.getKey(), output);
215     }
216   }
217 
218   /**
219    * Get the number of bytes required to encode this set using
220    * {@code MessageSet} wire format.
221    */
getSerializedSizeAsMessageSet()222   public int getSerializedSizeAsMessageSet() {
223     int result = 0;
224     for (final Map.Entry<Integer, Field> entry : fields.entrySet()) {
225       result += entry.getValue().getSerializedSizeAsMessageSetExtension(
226         entry.getKey());
227     }
228     return result;
229   }
230 
isInitialized()231   public boolean isInitialized() {
232     // UnknownFieldSets do not have required fields, so they are always
233     // initialized.
234     return true;
235   }
236 
237   /** Parse an {@code UnknownFieldSet} from the given input stream. */
parseFrom(final CodedInputStream input)238   public static UnknownFieldSet parseFrom(final CodedInputStream input)
239                                           throws IOException {
240     return newBuilder().mergeFrom(input).build();
241   }
242 
243   /** Parse {@code data} as an {@code UnknownFieldSet} and return it. */
parseFrom(final ByteString data)244   public static UnknownFieldSet parseFrom(final ByteString data)
245       throws InvalidProtocolBufferException {
246     return newBuilder().mergeFrom(data).build();
247   }
248 
249   /** Parse {@code data} as an {@code UnknownFieldSet} and return it. */
parseFrom(final byte[] data)250   public static UnknownFieldSet parseFrom(final byte[] data)
251       throws InvalidProtocolBufferException {
252     return newBuilder().mergeFrom(data).build();
253   }
254 
255   /** Parse an {@code UnknownFieldSet} from {@code input} and return it. */
parseFrom(final InputStream input)256   public static UnknownFieldSet parseFrom(final InputStream input)
257                                           throws IOException {
258     return newBuilder().mergeFrom(input).build();
259   }
260 
newBuilderForType()261   public Builder newBuilderForType() {
262     return newBuilder();
263   }
264 
toBuilder()265   public Builder toBuilder() {
266     return newBuilder().mergeFrom(this);
267   }
268 
269   /**
270    * Builder for {@link UnknownFieldSet}s.
271    *
272    * <p>Note that this class maintains {@link Field.Builder}s for all fields
273    * in the set.  Thus, adding one element to an existing {@link Field} does not
274    * require making a copy.  This is important for efficient parsing of
275    * unknown repeated fields.  However, it implies that {@link Field}s cannot
276    * be constructed independently, nor can two {@link UnknownFieldSet}s share
277    * the same {@code Field} object.
278    *
279    * <p>Use {@link UnknownFieldSet#newBuilder()} to construct a {@code Builder}.
280    */
281   public static final class Builder implements MessageLite.Builder {
282     // This constructor should never be called directly (except from 'create').
Builder()283     private Builder() {}
284 
285     private Map<Integer, Field> fields;
286 
287     // Optimization:  We keep around a builder for the last field that was
288     //   modified so that we can efficiently add to it multiple times in a
289     //   row (important when parsing an unknown repeated field).
290     private int lastFieldNumber;
291     private Field.Builder lastField;
292 
create()293     private static Builder create() {
294       Builder builder = new Builder();
295       builder.reinitialize();
296       return builder;
297     }
298 
299     /**
300      * Get a field builder for the given field number which includes any
301      * values that already exist.
302      */
getFieldBuilder(final int number)303     private Field.Builder getFieldBuilder(final int number) {
304       if (lastField != null) {
305         if (number == lastFieldNumber) {
306           return lastField;
307         }
308         // Note:  addField() will reset lastField and lastFieldNumber.
309         addField(lastFieldNumber, lastField.build());
310       }
311       if (number == 0) {
312         return null;
313       } else {
314         final Field existing = fields.get(number);
315         lastFieldNumber = number;
316         lastField = Field.newBuilder();
317         if (existing != null) {
318           lastField.mergeFrom(existing);
319         }
320         return lastField;
321       }
322     }
323 
324     /**
325      * Build the {@link UnknownFieldSet} and return it.
326      *
327      * <p>Once {@code build()} has been called, the {@code Builder} will no
328      * longer be usable.  Calling any method after {@code build()} will result
329      * in undefined behavior and can cause a {@code NullPointerException} to be
330      * thrown.
331      */
build()332     public UnknownFieldSet build() {
333       getFieldBuilder(0);  // Force lastField to be built.
334       final UnknownFieldSet result;
335       if (fields.isEmpty()) {
336         result = getDefaultInstance();
337       } else {
338         result = new UnknownFieldSet(Collections.unmodifiableMap(fields));
339       }
340       fields = null;
341       return result;
342     }
343 
buildPartial()344     public UnknownFieldSet buildPartial() {
345       // No required fields, so this is the same as build().
346       return build();
347     }
348 
349     @Override
clone()350     public Builder clone() {
351       getFieldBuilder(0);  // Force lastField to be built.
352       return UnknownFieldSet.newBuilder().mergeFrom(
353           new UnknownFieldSet(fields));
354     }
355 
getDefaultInstanceForType()356     public UnknownFieldSet getDefaultInstanceForType() {
357       return UnknownFieldSet.getDefaultInstance();
358     }
359 
reinitialize()360     private void reinitialize() {
361       fields = Collections.emptyMap();
362       lastFieldNumber = 0;
363       lastField = null;
364     }
365 
366     /** Reset the builder to an empty set. */
clear()367     public Builder clear() {
368       reinitialize();
369       return this;
370     }
371 
372     /** Clear fields from the set with a given field number. */
clearField(final int number)373     public Builder clearField(final int number) {
374       if (number == 0) {
375         throw new IllegalArgumentException("Zero is not a valid field number.");
376       }
377       if (lastField != null && lastFieldNumber == number) {
378         // Discard this.
379         lastField = null;
380         lastFieldNumber = 0;
381       }
382       if (fields.containsKey(number)) {
383         fields.remove(number);
384       }
385       return this;
386     }
387 
388     /**
389      * Merge the fields from {@code other} into this set.  If a field number
390      * exists in both sets, {@code other}'s values for that field will be
391      * appended to the values in this set.
392      */
mergeFrom(final UnknownFieldSet other)393     public Builder mergeFrom(final UnknownFieldSet other) {
394       if (other != getDefaultInstance()) {
395         for (final Map.Entry<Integer, Field> entry : other.fields.entrySet()) {
396           mergeField(entry.getKey(), entry.getValue());
397         }
398       }
399       return this;
400     }
401 
402     /**
403      * Add a field to the {@code UnknownFieldSet}.  If a field with the same
404      * number already exists, the two are merged.
405      */
mergeField(final int number, final Field field)406     public Builder mergeField(final int number, final Field field) {
407       if (number == 0) {
408         throw new IllegalArgumentException("Zero is not a valid field number.");
409       }
410       if (hasField(number)) {
411         getFieldBuilder(number).mergeFrom(field);
412       } else {
413         // Optimization:  We could call getFieldBuilder(number).mergeFrom(field)
414         // in this case, but that would create a copy of the Field object.
415         // We'd rather reuse the one passed to us, so call addField() instead.
416         addField(number, field);
417       }
418       return this;
419     }
420 
421     /**
422      * Convenience method for merging a new field containing a single varint
423      * value.  This is used in particular when an unknown enum value is
424      * encountered.
425      */
mergeVarintField(final int number, final int value)426     public Builder mergeVarintField(final int number, final int value) {
427       if (number == 0) {
428         throw new IllegalArgumentException("Zero is not a valid field number.");
429       }
430       getFieldBuilder(number).addVarint(value);
431       return this;
432     }
433 
434     /** Check if the given field number is present in the set. */
hasField(final int number)435     public boolean hasField(final int number) {
436       if (number == 0) {
437         throw new IllegalArgumentException("Zero is not a valid field number.");
438       }
439       return number == lastFieldNumber || fields.containsKey(number);
440     }
441 
442     /**
443      * Add a field to the {@code UnknownFieldSet}.  If a field with the same
444      * number already exists, it is removed.
445      */
addField(final int number, final Field field)446     public Builder addField(final int number, final Field field) {
447       if (number == 0) {
448         throw new IllegalArgumentException("Zero is not a valid field number.");
449       }
450       if (lastField != null && lastFieldNumber == number) {
451         // Discard this.
452         lastField = null;
453         lastFieldNumber = 0;
454       }
455       if (fields.isEmpty()) {
456         fields = new TreeMap<Integer,Field>();
457       }
458       fields.put(number, field);
459       return this;
460     }
461 
462     /**
463      * Get all present {@code Field}s as an immutable {@code Map}.  If more
464      * fields are added, the changes may or may not be reflected in this map.
465      */
asMap()466     public Map<Integer, Field> asMap() {
467       getFieldBuilder(0);  // Force lastField to be built.
468       return Collections.unmodifiableMap(fields);
469     }
470 
471     /**
472      * Parse an entire message from {@code input} and merge its fields into
473      * this set.
474      */
mergeFrom(final CodedInputStream input)475     public Builder mergeFrom(final CodedInputStream input) throws IOException {
476       while (true) {
477         final int tag = input.readTag();
478         if (tag == 0 || !mergeFieldFrom(tag, input)) {
479           break;
480         }
481       }
482       return this;
483     }
484 
485     /**
486      * Parse a single field from {@code input} and merge it into this set.
487      * @param tag The field's tag number, which was already parsed.
488      * @return {@code false} if the tag is an end group tag.
489      */
mergeFieldFrom(final int tag, final CodedInputStream input)490     public boolean mergeFieldFrom(final int tag, final CodedInputStream input)
491                                   throws IOException {
492       final int number = WireFormat.getTagFieldNumber(tag);
493       switch (WireFormat.getTagWireType(tag)) {
494         case WireFormat.WIRETYPE_VARINT:
495           getFieldBuilder(number).addVarint(input.readInt64());
496           return true;
497         case WireFormat.WIRETYPE_FIXED64:
498           getFieldBuilder(number).addFixed64(input.readFixed64());
499           return true;
500         case WireFormat.WIRETYPE_LENGTH_DELIMITED:
501           getFieldBuilder(number).addLengthDelimited(input.readBytes());
502           return true;
503         case WireFormat.WIRETYPE_START_GROUP:
504           final Builder subBuilder = newBuilder();
505           input.readGroup(number, subBuilder,
506                           ExtensionRegistry.getEmptyRegistry());
507           getFieldBuilder(number).addGroup(subBuilder.build());
508           return true;
509         case WireFormat.WIRETYPE_END_GROUP:
510           return false;
511         case WireFormat.WIRETYPE_FIXED32:
512           getFieldBuilder(number).addFixed32(input.readFixed32());
513           return true;
514         default:
515           throw InvalidProtocolBufferException.invalidWireType();
516       }
517     }
518 
519     /**
520      * Parse {@code data} as an {@code UnknownFieldSet} and merge it with the
521      * set being built.  This is just a small wrapper around
522      * {@link #mergeFrom(CodedInputStream)}.
523      */
mergeFrom(final ByteString data)524     public Builder mergeFrom(final ByteString data)
525         throws InvalidProtocolBufferException {
526       try {
527         final CodedInputStream input = data.newCodedInput();
528         mergeFrom(input);
529         input.checkLastTagWas(0);
530         return this;
531       } catch (final InvalidProtocolBufferException e) {
532         throw e;
533       } catch (final IOException e) {
534         throw new RuntimeException(
535           "Reading from a ByteString threw an IOException (should " +
536           "never happen).", e);
537       }
538     }
539 
540     /**
541      * Parse {@code data} as an {@code UnknownFieldSet} and merge it with the
542      * set being built.  This is just a small wrapper around
543      * {@link #mergeFrom(CodedInputStream)}.
544      */
mergeFrom(final byte[] data)545     public Builder mergeFrom(final byte[] data)
546         throws InvalidProtocolBufferException {
547       try {
548         final CodedInputStream input = CodedInputStream.newInstance(data);
549         mergeFrom(input);
550         input.checkLastTagWas(0);
551         return this;
552       } catch (final InvalidProtocolBufferException e) {
553         throw e;
554       } catch (final IOException e) {
555         throw new RuntimeException(
556           "Reading from a byte array threw an IOException (should " +
557           "never happen).", e);
558       }
559     }
560 
561     /**
562      * Parse an {@code UnknownFieldSet} from {@code input} and merge it with the
563      * set being built.  This is just a small wrapper around
564      * {@link #mergeFrom(CodedInputStream)}.
565      */
mergeFrom(final InputStream input)566     public Builder mergeFrom(final InputStream input) throws IOException {
567       final CodedInputStream codedInput = CodedInputStream.newInstance(input);
568       mergeFrom(codedInput);
569       codedInput.checkLastTagWas(0);
570       return this;
571     }
572 
mergeDelimitedFrom(InputStream input)573     public boolean mergeDelimitedFrom(InputStream input)
574         throws IOException {
575       final int firstByte = input.read();
576       if (firstByte == -1) {
577         return false;
578       }
579       final int size = CodedInputStream.readRawVarint32(firstByte, input);
580       final InputStream limitedInput = new LimitedInputStream(input, size);
581       mergeFrom(limitedInput);
582       return true;
583     }
584 
mergeDelimitedFrom( InputStream input, ExtensionRegistryLite extensionRegistry)585     public boolean mergeDelimitedFrom(
586         InputStream input,
587         ExtensionRegistryLite extensionRegistry) throws IOException {
588       // UnknownFieldSet has no extensions.
589       return mergeDelimitedFrom(input);
590     }
591 
mergeFrom( CodedInputStream input, ExtensionRegistryLite extensionRegistry)592     public Builder mergeFrom(
593         CodedInputStream input,
594         ExtensionRegistryLite extensionRegistry) throws IOException {
595       // UnknownFieldSet has no extensions.
596       return mergeFrom(input);
597     }
598 
mergeFrom( ByteString data, ExtensionRegistryLite extensionRegistry)599     public Builder mergeFrom(
600         ByteString data,
601         ExtensionRegistryLite extensionRegistry)
602         throws InvalidProtocolBufferException {
603       // UnknownFieldSet has no extensions.
604       return mergeFrom(data);
605     }
606 
mergeFrom(byte[] data, int off, int len)607     public Builder mergeFrom(byte[] data, int off, int len)
608         throws InvalidProtocolBufferException {
609       try {
610         final CodedInputStream input =
611             CodedInputStream.newInstance(data, off, len);
612         mergeFrom(input);
613         input.checkLastTagWas(0);
614         return this;
615       } catch (InvalidProtocolBufferException e) {
616         throw e;
617       } catch (IOException e) {
618         throw new RuntimeException(
619           "Reading from a byte array threw an IOException (should " +
620           "never happen).", e);
621       }
622     }
623 
mergeFrom( byte[] data, ExtensionRegistryLite extensionRegistry)624     public Builder mergeFrom(
625         byte[] data,
626         ExtensionRegistryLite extensionRegistry)
627         throws InvalidProtocolBufferException {
628       // UnknownFieldSet has no extensions.
629       return mergeFrom(data);
630     }
631 
mergeFrom( byte[] data, int off, int len, ExtensionRegistryLite extensionRegistry)632     public Builder mergeFrom(
633         byte[] data, int off, int len,
634         ExtensionRegistryLite extensionRegistry)
635         throws InvalidProtocolBufferException {
636       // UnknownFieldSet has no extensions.
637       return mergeFrom(data, off, len);
638     }
639 
mergeFrom( InputStream input, ExtensionRegistryLite extensionRegistry)640     public Builder mergeFrom(
641         InputStream input,
642         ExtensionRegistryLite extensionRegistry) throws IOException {
643       // UnknownFieldSet has no extensions.
644       return mergeFrom(input);
645     }
646 
isInitialized()647     public boolean isInitialized() {
648       // UnknownFieldSets do not have required fields, so they are always
649       // initialized.
650       return true;
651     }
652   }
653 
654   /**
655    * Represents a single field in an {@code UnknownFieldSet}.
656    *
657    * <p>A {@code Field} consists of five lists of values.  The lists correspond
658    * to the five "wire types" used in the protocol buffer binary format.
659    * The wire type of each field can be determined from the encoded form alone,
660    * without knowing the field's declared type.  So, we are able to parse
661    * unknown values at least this far and separate them.  Normally, only one
662    * of the five lists will contain any values, since it is impossible to
663    * define a valid message type that declares two different types for the
664    * same field number.  However, the code is designed to allow for the case
665    * where the same unknown field number is encountered using multiple different
666    * wire types.
667    *
668    * <p>{@code Field} is an immutable class.  To construct one, you must use a
669    * {@link Builder}.
670    *
671    * @see UnknownFieldSet
672    */
673   public static final class Field {
Field()674     private Field() {}
675 
676     /** Construct a new {@link Builder}. */
newBuilder()677     public static Builder newBuilder() {
678       return Builder.create();
679     }
680 
681     /**
682      * Construct a new {@link Builder} and initialize it to a copy of
683      * {@code copyFrom}.
684      */
newBuilder(final Field copyFrom)685     public static Builder newBuilder(final Field copyFrom) {
686       return newBuilder().mergeFrom(copyFrom);
687     }
688 
689     /** Get an empty {@code Field}. */
getDefaultInstance()690     public static Field getDefaultInstance() {
691       return fieldDefaultInstance;
692     }
693     private static final Field fieldDefaultInstance = newBuilder().build();
694 
695     /** Get the list of varint values for this field. */
getVarintList()696     public List<Long> getVarintList()               { return varint;          }
697 
698     /** Get the list of fixed32 values for this field. */
getFixed32List()699     public List<Integer> getFixed32List()           { return fixed32;         }
700 
701     /** Get the list of fixed64 values for this field. */
getFixed64List()702     public List<Long> getFixed64List()              { return fixed64;         }
703 
704     /** Get the list of length-delimited values for this field. */
getLengthDelimitedList()705     public List<ByteString> getLengthDelimitedList() { return lengthDelimited; }
706 
707     /**
708      * Get the list of embedded group values for this field.  These are
709      * represented using {@link UnknownFieldSet}s rather than {@link Message}s
710      * since the group's type is presumably unknown.
711      */
getGroupList()712     public List<UnknownFieldSet> getGroupList()      { return group;           }
713 
714     @Override
equals(final Object other)715     public boolean equals(final Object other) {
716       if (this == other) {
717         return true;
718       }
719       if (!(other instanceof Field)) {
720         return false;
721       }
722       return Arrays.equals(getIdentityArray(),
723           ((Field) other).getIdentityArray());
724     }
725 
726     @Override
hashCode()727     public int hashCode() {
728       return Arrays.hashCode(getIdentityArray());
729     }
730 
731     /**
732      * Returns the array of objects to be used to uniquely identify this
733      * {@link Field} instance.
734      */
getIdentityArray()735     private Object[] getIdentityArray() {
736       return new Object[] {
737           varint,
738           fixed32,
739           fixed64,
740           lengthDelimited,
741           group};
742     }
743 
744     /**
745      * Serializes the field, including field number, and writes it to
746      * {@code output}.
747      */
writeTo(final int fieldNumber, final CodedOutputStream output)748     public void writeTo(final int fieldNumber, final CodedOutputStream output)
749                         throws IOException {
750       for (final long value : varint) {
751         output.writeUInt64(fieldNumber, value);
752       }
753       for (final int value : fixed32) {
754         output.writeFixed32(fieldNumber, value);
755       }
756       for (final long value : fixed64) {
757         output.writeFixed64(fieldNumber, value);
758       }
759       for (final ByteString value : lengthDelimited) {
760         output.writeBytes(fieldNumber, value);
761       }
762       for (final UnknownFieldSet value : group) {
763         output.writeGroup(fieldNumber, value);
764       }
765     }
766 
767     /**
768      * Get the number of bytes required to encode this field, including field
769      * number.
770      */
getSerializedSize(final int fieldNumber)771     public int getSerializedSize(final int fieldNumber) {
772       int result = 0;
773       for (final long value : varint) {
774         result += CodedOutputStream.computeUInt64Size(fieldNumber, value);
775       }
776       for (final int value : fixed32) {
777         result += CodedOutputStream.computeFixed32Size(fieldNumber, value);
778       }
779       for (final long value : fixed64) {
780         result += CodedOutputStream.computeFixed64Size(fieldNumber, value);
781       }
782       for (final ByteString value : lengthDelimited) {
783         result += CodedOutputStream.computeBytesSize(fieldNumber, value);
784       }
785       for (final UnknownFieldSet value : group) {
786         result += CodedOutputStream.computeGroupSize(fieldNumber, value);
787       }
788       return result;
789     }
790 
791     /**
792      * Serializes the field, including field number, and writes it to
793      * {@code output}, using {@code MessageSet} wire format.
794      */
writeAsMessageSetExtensionTo( final int fieldNumber, final CodedOutputStream output)795     public void writeAsMessageSetExtensionTo(
796         final int fieldNumber,
797         final CodedOutputStream output)
798         throws IOException {
799       for (final ByteString value : lengthDelimited) {
800         output.writeRawMessageSetExtension(fieldNumber, value);
801       }
802     }
803 
804     /**
805      * Get the number of bytes required to encode this field, including field
806      * number, using {@code MessageSet} wire format.
807      */
getSerializedSizeAsMessageSetExtension(final int fieldNumber)808     public int getSerializedSizeAsMessageSetExtension(final int fieldNumber) {
809       int result = 0;
810       for (final ByteString value : lengthDelimited) {
811         result += CodedOutputStream.computeRawMessageSetExtensionSize(
812           fieldNumber, value);
813       }
814       return result;
815     }
816 
817     private List<Long> varint;
818     private List<Integer> fixed32;
819     private List<Long> fixed64;
820     private List<ByteString> lengthDelimited;
821     private List<UnknownFieldSet> group;
822 
823     /**
824      * Used to build a {@link Field} within an {@link UnknownFieldSet}.
825      *
826      * <p>Use {@link Field#newBuilder()} to construct a {@code Builder}.
827      */
828     public static final class Builder {
829       // This constructor should never be called directly (except from 'create').
Builder()830       private Builder() {}
831 
create()832       private static Builder create() {
833         Builder builder = new Builder();
834         builder.result = new Field();
835         return builder;
836       }
837 
838       private Field result;
839 
840       /**
841        * Build the field.  After {@code build()} has been called, the
842        * {@code Builder} is no longer usable.  Calling any other method will
843        * result in undefined behavior and can cause a
844        * {@code NullPointerException} to be thrown.
845        */
build()846       public Field build() {
847         if (result.varint == null) {
848           result.varint = Collections.emptyList();
849         } else {
850           result.varint = Collections.unmodifiableList(result.varint);
851         }
852         if (result.fixed32 == null) {
853           result.fixed32 = Collections.emptyList();
854         } else {
855           result.fixed32 = Collections.unmodifiableList(result.fixed32);
856         }
857         if (result.fixed64 == null) {
858           result.fixed64 = Collections.emptyList();
859         } else {
860           result.fixed64 = Collections.unmodifiableList(result.fixed64);
861         }
862         if (result.lengthDelimited == null) {
863           result.lengthDelimited = Collections.emptyList();
864         } else {
865           result.lengthDelimited =
866             Collections.unmodifiableList(result.lengthDelimited);
867         }
868         if (result.group == null) {
869           result.group = Collections.emptyList();
870         } else {
871           result.group = Collections.unmodifiableList(result.group);
872         }
873 
874         final Field returnMe = result;
875         result = null;
876         return returnMe;
877       }
878 
879       /** Discard the field's contents. */
clear()880       public Builder clear() {
881         result = new Field();
882         return this;
883       }
884 
885       /**
886        * Merge the values in {@code other} into this field.  For each list
887        * of values, {@code other}'s values are append to the ones in this
888        * field.
889        */
mergeFrom(final Field other)890       public Builder mergeFrom(final Field other) {
891         if (!other.varint.isEmpty()) {
892           if (result.varint == null) {
893             result.varint = new ArrayList<Long>();
894           }
895           result.varint.addAll(other.varint);
896         }
897         if (!other.fixed32.isEmpty()) {
898           if (result.fixed32 == null) {
899             result.fixed32 = new ArrayList<Integer>();
900           }
901           result.fixed32.addAll(other.fixed32);
902         }
903         if (!other.fixed64.isEmpty()) {
904           if (result.fixed64 == null) {
905             result.fixed64 = new ArrayList<Long>();
906           }
907           result.fixed64.addAll(other.fixed64);
908         }
909         if (!other.lengthDelimited.isEmpty()) {
910           if (result.lengthDelimited == null) {
911             result.lengthDelimited = new ArrayList<ByteString>();
912           }
913           result.lengthDelimited.addAll(other.lengthDelimited);
914         }
915         if (!other.group.isEmpty()) {
916           if (result.group == null) {
917             result.group = new ArrayList<UnknownFieldSet>();
918           }
919           result.group.addAll(other.group);
920         }
921         return this;
922       }
923 
924       /** Add a varint value. */
addVarint(final long value)925       public Builder addVarint(final long value) {
926         if (result.varint == null) {
927           result.varint = new ArrayList<Long>();
928         }
929         result.varint.add(value);
930         return this;
931       }
932 
933       /** Add a fixed32 value. */
addFixed32(final int value)934       public Builder addFixed32(final int value) {
935         if (result.fixed32 == null) {
936           result.fixed32 = new ArrayList<Integer>();
937         }
938         result.fixed32.add(value);
939         return this;
940       }
941 
942       /** Add a fixed64 value. */
addFixed64(final long value)943       public Builder addFixed64(final long value) {
944         if (result.fixed64 == null) {
945           result.fixed64 = new ArrayList<Long>();
946         }
947         result.fixed64.add(value);
948         return this;
949       }
950 
951       /** Add a length-delimited value. */
addLengthDelimited(final ByteString value)952       public Builder addLengthDelimited(final ByteString value) {
953         if (result.lengthDelimited == null) {
954           result.lengthDelimited = new ArrayList<ByteString>();
955         }
956         result.lengthDelimited.add(value);
957         return this;
958       }
959 
960       /** Add an embedded group. */
addGroup(final UnknownFieldSet value)961       public Builder addGroup(final UnknownFieldSet value) {
962         if (result.group == null) {
963           result.group = new ArrayList<UnknownFieldSet>();
964         }
965         result.group.add(value);
966         return this;
967       }
968     }
969   }
970 
971   /**
972    * Parser to implement MessageLite interface.
973    */
974   public static final class Parser extends AbstractParser<UnknownFieldSet> {
parsePartialFrom( CodedInputStream input, ExtensionRegistryLite extensionRegistry)975     public UnknownFieldSet parsePartialFrom(
976         CodedInputStream input, ExtensionRegistryLite extensionRegistry)
977         throws InvalidProtocolBufferException {
978       Builder builder = newBuilder();
979       try {
980         builder.mergeFrom(input);
981       } catch (InvalidProtocolBufferException e) {
982         throw e.setUnfinishedMessage(builder.buildPartial());
983       } catch (IOException e) {
984         throw new InvalidProtocolBufferException(e.getMessage())
985             .setUnfinishedMessage(builder.buildPartial());
986       }
987       return builder.buildPartial();
988     }
989   }
990 
991   private static final Parser PARSER = new Parser();
getParserForType()992   public final Parser getParserForType() {
993     return PARSER;
994   }
995 }
996