Subversion Repositories Code-Repo

Rev

Details | Last modification | View Log | RSS feed

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