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