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