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