1b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// Protocol Buffers - Google's data interchange format
2b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// Copyright 2008 Google Inc.  All rights reserved.
3b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// https://developers.google.com/protocol-buffers/
4b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer//
5b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// Redistribution and use in source and binary forms, with or without
6b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// modification, are permitted provided that the following conditions are
7b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// met:
8b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer//
9b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer//     * Redistributions of source code must retain the above copyright
10b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// notice, this list of conditions and the following disclaimer.
11b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer//     * Redistributions in binary form must reproduce the above
12b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// copyright notice, this list of conditions and the following disclaimer
13b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// in the documentation and/or other materials provided with the
14b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// distribution.
15b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer//     * Neither the name of Google Inc. nor the names of its
16b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// contributors may be used to endorse or promote products derived from
17b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// this software without specific prior written permission.
18b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer//
19b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
31b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerpackage com.google.protobuf;
32b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
33b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerimport java.io.IOException;
34b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerimport java.util.Arrays;
35b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
36b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/**
37b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * {@code UnknownFieldSetLite} is used to keep track of fields which were seen
38b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * when parsing a protocol message but whose field numbers or types are
39b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * unrecognized. This most frequently occurs when new fields are added to a
40b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * message type and then messages containing those fields are read by old
41b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * software that was compiled before the new types were added.
42b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer *
43b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * <p>For use by generated code only.
44b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer *
45b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * @author dweis@google.com (Daniel Weis)
46b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */
47b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerpublic final class UnknownFieldSetLite {
48b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
49b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  // Arbitrarily chosen.
50b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  // TODO(dweis): Tune this number?
51b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  private static final int MIN_CAPACITY = 8;
52b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
53b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  private static final UnknownFieldSetLite DEFAULT_INSTANCE =
54b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      new UnknownFieldSetLite(0, new int[0], new Object[0], false /* isMutable */);
55b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
56b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /**
57b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * Get an empty {@code UnknownFieldSetLite}.
58b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   *
59b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * <p>For use by generated code only.
60b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   */
61b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  public static UnknownFieldSetLite getDefaultInstance() {
62b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return DEFAULT_INSTANCE;
63b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
64b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
65b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /**
66b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * Returns a new mutable instance.
67b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   */
68b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  static UnknownFieldSetLite newInstance() {
69b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return new UnknownFieldSetLite();
70b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
71b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
72b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /**
73b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * Returns a mutable {@code UnknownFieldSetLite} that is the composite of {@code first} and
74b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * {@code second}.
75b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   */
76b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  static UnknownFieldSetLite mutableCopyOf(UnknownFieldSetLite first, UnknownFieldSetLite second) {
77b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    int count = first.count + second.count;
78b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    int[] tags = Arrays.copyOf(first.tags, count);
79b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    System.arraycopy(second.tags, 0, tags, first.count, second.count);
80b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    Object[] objects = Arrays.copyOf(first.objects, count);
81b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    System.arraycopy(second.objects, 0, objects, first.count, second.count);
82b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return new UnknownFieldSetLite(count, tags, objects, true /* isMutable */);
83b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
84b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
85b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /**
86b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * The number of elements in the set.
87b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   */
88b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  private int count;
89b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
90b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /**
91b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * The tag numbers for the elements in the set.
92b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   */
93b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  private int[] tags;
94b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
95b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /**
96b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * The boxed values of the elements in the set.
97b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   */
98b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  private Object[] objects;
99b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
100b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /**
101b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * The lazily computed serialized size of the set.
102b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   */
103b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  private int memoizedSerializedSize = -1;
104b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
105b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /**
106b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * Indicates that this object is mutable.
107b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   */
108b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  private boolean isMutable;
109b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
110b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /**
111b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * Constructs a mutable {@code UnknownFieldSetLite}.
112b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   */
113b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  private UnknownFieldSetLite() {
114b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    this(0, new int[MIN_CAPACITY], new Object[MIN_CAPACITY], true /* isMutable */);
115b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
116b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
117b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /**
118b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * Constructs the {@code UnknownFieldSetLite}.
119b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   */
120b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  private UnknownFieldSetLite(int count, int[] tags, Object[] objects, boolean isMutable) {
121b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    this.count = count;
122b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    this.tags = tags;
123b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    this.objects = objects;
124b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    this.isMutable = isMutable;
125b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
126b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
127b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /**
128b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * Marks this object as immutable.
129b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   *
130b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * <p>Future calls to methods that attempt to modify this object will throw.
131b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   */
132b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  public void makeImmutable() {
133b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    this.isMutable = false;
134b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
135b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
136b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /**
137b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * Throws an {@link UnsupportedOperationException} if immutable.
138b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   */
139b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  void checkMutable() {
140b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (!isMutable) {
141b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      throw new UnsupportedOperationException();
142b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
143b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
144b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
145b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /**
146b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * Serializes the set and writes it to {@code output}.
147b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   *
148b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * <p>For use by generated code only.
149b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   */
150b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  public void writeTo(CodedOutputStream output) throws IOException {
151b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    for (int i = 0; i < count; i++) {
152b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      int tag = tags[i];
153b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      int fieldNumber = WireFormat.getTagFieldNumber(tag);
154b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      switch (WireFormat.getTagWireType(tag)) {
155b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        case WireFormat.WIRETYPE_VARINT:
156b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer          output.writeUInt64(fieldNumber, (Long) objects[i]);
157b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer          break;
158b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        case WireFormat.WIRETYPE_FIXED32:
159b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer          output.writeFixed32(fieldNumber, (Integer) objects[i]);
160b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer          break;
161b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        case WireFormat.WIRETYPE_FIXED64:
162b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer          output.writeFixed64(fieldNumber, (Long) objects[i]);
163b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer          break;
164b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        case WireFormat.WIRETYPE_LENGTH_DELIMITED:
165b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer          output.writeBytes(fieldNumber, (ByteString) objects[i]);
166b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer          break;
167b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        case WireFormat.WIRETYPE_START_GROUP:
168b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer          output.writeTag(fieldNumber, WireFormat.WIRETYPE_START_GROUP);
169b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer          ((UnknownFieldSetLite) objects[i]).writeTo(output);
170b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer          output.writeTag(fieldNumber, WireFormat.WIRETYPE_END_GROUP);
171b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer          break;
172b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        default:
173b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer          throw InvalidProtocolBufferException.invalidWireType();
174b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      }
175b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
176b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
177b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
178b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /**
179b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * Get the number of bytes required to encode this set.
180b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   *
181b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * <p>For use by generated code only.
182b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   */
183b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  public int getSerializedSize() {
184b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    int size = memoizedSerializedSize;
185b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (size != -1) {
186b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      return size;
187b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
188b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
189b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    size = 0;
190b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    for (int i = 0; i < count; i++) {
191b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      int tag = tags[i];
192b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      int fieldNumber = WireFormat.getTagFieldNumber(tag);
193b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      switch (WireFormat.getTagWireType(tag)) {
194b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        case WireFormat.WIRETYPE_VARINT:
195b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer          size += CodedOutputStream.computeUInt64Size(fieldNumber, (Long) objects[i]);
196b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer          break;
197b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        case WireFormat.WIRETYPE_FIXED32:
198b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer          size += CodedOutputStream.computeFixed32Size(fieldNumber, (Integer) objects[i]);
199b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer          break;
200b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        case WireFormat.WIRETYPE_FIXED64:
201b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer          size += CodedOutputStream.computeFixed64Size(fieldNumber, (Long) objects[i]);
202b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer          break;
203b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        case WireFormat.WIRETYPE_LENGTH_DELIMITED:
204b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer          size += CodedOutputStream.computeBytesSize(fieldNumber, (ByteString) objects[i]);
205b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer          break;
206b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        case WireFormat.WIRETYPE_START_GROUP:
207b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer          size +=  CodedOutputStream.computeTagSize(fieldNumber) * 2
208b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer              + ((UnknownFieldSetLite) objects[i]).getSerializedSize();
209b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer          break;
210b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        default:
211b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer          throw new IllegalStateException(InvalidProtocolBufferException.invalidWireType());
212b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      }
213b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
214b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
215b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    memoizedSerializedSize = size;
216b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
217b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return size;
218b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
219b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
220b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  @Override
221b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  public boolean equals(Object obj) {
222b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (this == obj) {
223b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      return true;
224b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
225b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
226b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (obj == null) {
227b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      return false;
228b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
229b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
230b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (!(obj instanceof UnknownFieldSetLite)) {
231b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      return false;
232b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
233b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
234b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    UnknownFieldSetLite other = (UnknownFieldSetLite) obj;
235b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (count != other.count
236b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        // TODO(dweis): Only have to compare up to count but at worst 2x worse than we need to do.
237b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        || !Arrays.equals(tags, other.tags)
238b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        || !Arrays.deepEquals(objects, other.objects)) {
239b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      return false;
240b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
241b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
242b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return true;
243b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
244b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
245b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  @Override
246b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  public int hashCode() {
247b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    int hashCode = 17;
248b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
249b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    hashCode = 31 * hashCode + count;
250b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    hashCode = 31 * hashCode + Arrays.hashCode(tags);
251b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    hashCode = 31 * hashCode + Arrays.deepHashCode(objects);
252b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
253b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return hashCode;
254b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
255b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
256b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /**
257b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * Prints a String representation of the unknown field set.
258b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   *
259b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * <p>For use by generated code only.
260b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   *
261b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * @param buffer the buffer to write to
262b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * @param indent the number of spaces the fields should be indented by
263b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   */
264b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  final void printWithIndent(StringBuilder buffer, int indent) {
265b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    for (int i = 0; i < count; i++) {
266b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      int fieldNumber = WireFormat.getTagFieldNumber(tags[i]);
267b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      MessageLiteToString.printField(buffer, indent, String.valueOf(fieldNumber), objects[i]);
268b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
269b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
270b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
271b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  private void storeField(int tag, Object value) {
272b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    ensureCapacity();
273b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
274b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    tags[count] = tag;
275b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    objects[count] = value;
276b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    count++;
277b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
278b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
279b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /**
280b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * Ensures that our arrays are long enough to store more metadata.
281b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   */
282b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  private void ensureCapacity() {
283b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (count == tags.length) {
284b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      int increment = count < (MIN_CAPACITY / 2) ? MIN_CAPACITY : count >> 1;
285b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      int newLength = count + increment;
286b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
287b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      tags = Arrays.copyOf(tags, newLength);
288b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      objects = Arrays.copyOf(objects, newLength);
289b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
290b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
291b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
292b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /**
293b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * Parse a single field from {@code input} and merge it into this set.
294b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   *
295b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * <p>For use by generated code only.
296b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   *
297b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * @param tag The field's tag number, which was already parsed.
298b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * @return {@code false} if the tag is an end group tag.
299b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   */
300b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  boolean mergeFieldFrom(final int tag, final CodedInputStream input) throws IOException {
301b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    checkMutable();
302b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    final int fieldNumber = WireFormat.getTagFieldNumber(tag);
303b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    switch (WireFormat.getTagWireType(tag)) {
304b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      case WireFormat.WIRETYPE_VARINT:
305b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        storeField(tag, input.readInt64());
306b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        return true;
307b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      case WireFormat.WIRETYPE_FIXED32:
308b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        storeField(tag, input.readFixed32());
309b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        return true;
310b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      case WireFormat.WIRETYPE_FIXED64:
311b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        storeField(tag, input.readFixed64());
312b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        return true;
313b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      case WireFormat.WIRETYPE_LENGTH_DELIMITED:
314b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        storeField(tag, input.readBytes());
315b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        return true;
316b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      case WireFormat.WIRETYPE_START_GROUP:
317b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        final UnknownFieldSetLite subFieldSet = new UnknownFieldSetLite();
318b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        subFieldSet.mergeFrom(input);
319b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        input.checkLastTagWas(
320b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer            WireFormat.makeTag(fieldNumber, WireFormat.WIRETYPE_END_GROUP));
321b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        storeField(tag, subFieldSet);
322b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        return true;
323b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      case WireFormat.WIRETYPE_END_GROUP:
324b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        return false;
325b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      default:
326b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        throw InvalidProtocolBufferException.invalidWireType();
327b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
328b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
329b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
330b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /**
331b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * Convenience method for merging a new field containing a single varint
332b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * value. This is used in particular when an unknown enum value is
333b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * encountered.
334b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   *
335b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * <p>For use by generated code only.
336b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   */
337b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UnknownFieldSetLite mergeVarintField(int fieldNumber, int value) {
338b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    checkMutable();
339b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (fieldNumber == 0) {
340b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      throw new IllegalArgumentException("Zero is not a valid field number.");
341b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
342b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
343b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    storeField(WireFormat.makeTag(fieldNumber, WireFormat.WIRETYPE_VARINT), (long) value);
344b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
345b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return this;
346b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
347b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
348b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /**
349b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * Convenience method for merging a length-delimited field.
350b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   *
351b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * <p>For use by generated code only.
352b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   */
353b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UnknownFieldSetLite mergeLengthDelimitedField(final int fieldNumber, final ByteString value) {
354b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    checkMutable();
355b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (fieldNumber == 0) {
356b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      throw new IllegalArgumentException("Zero is not a valid field number.");
357b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
358b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
359b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    storeField(WireFormat.makeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED), value);
360b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
361b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return this;
362b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
363b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
364b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /**
365b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * Parse an entire message from {@code input} and merge its fields into
366b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * this set.
367b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   */
368b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  private UnknownFieldSetLite mergeFrom(final CodedInputStream input) throws IOException {
369b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    // Ensures initialization in mergeFieldFrom.
370b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    while (true) {
371b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      final int tag = input.readTag();
372b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      if (tag == 0 || !mergeFieldFrom(tag, input)) {
373b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        break;
374b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      }
375b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
376b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return this;
377b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
378b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
379