aboutsummaryrefslogtreecommitdiffstats
path: root/java/src/main/java/com/google/protobuf/UnknownFieldSet.java
diff options
context:
space:
mode:
Diffstat (limited to 'java/src/main/java/com/google/protobuf/UnknownFieldSet.java')
-rw-r--r--java/src/main/java/com/google/protobuf/UnknownFieldSet.java947
1 files changed, 947 insertions, 0 deletions
diff --git a/java/src/main/java/com/google/protobuf/UnknownFieldSet.java b/java/src/main/java/com/google/protobuf/UnknownFieldSet.java
new file mode 100644
index 0000000..7f7e493
--- /dev/null
+++ b/java/src/main/java/com/google/protobuf/UnknownFieldSet.java
@@ -0,0 +1,947 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package com.google.protobuf;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+
+/**
+ * {@code UnknownFieldSet} is used to keep track of fields which were seen when
+ * parsing a protocol message but whose field numbers or types are unrecognized.
+ * This most frequently occurs when new fields are added to a message type
+ * and then messages containing those feilds are read by old software that was
+ * compiled before the new types were added.
+ *
+ * <p>Every {@link Message} contains an {@code UnknownFieldSet} (and every
+ * {@link Message.Builder} contains an {@link Builder}).
+ *
+ * <p>Most users will never need to use this class.
+ *
+ * @author kenton@google.com Kenton Varda
+ */
+public final class UnknownFieldSet implements MessageLite {
+ private UnknownFieldSet() {}
+
+ /** Create a new {@link Builder}. */
+ public static Builder newBuilder() {
+ return Builder.create();
+ }
+
+ /**
+ * Create a new {@link Builder} and initialize it to be a copy
+ * of {@code copyFrom}.
+ */
+ public static Builder newBuilder(final UnknownFieldSet copyFrom) {
+ return newBuilder().mergeFrom(copyFrom);
+ }
+
+ /** Get an empty {@code UnknownFieldSet}. */
+ public static UnknownFieldSet getDefaultInstance() {
+ return defaultInstance;
+ }
+ public UnknownFieldSet getDefaultInstanceForType() {
+ return defaultInstance;
+ }
+ private static final UnknownFieldSet defaultInstance =
+ new UnknownFieldSet(Collections.<Integer, Field>emptyMap());
+
+ /**
+ * Construct an {@code UnknownFieldSet} around the given map. The map is
+ * expected to be immutable.
+ */
+ private UnknownFieldSet(final Map<Integer, Field> fields) {
+ this.fields = fields;
+ }
+ private Map<Integer, Field> fields;
+
+ @Override
+ public boolean equals(final Object other) {
+ if (this == other) {
+ return true;
+ }
+ return (other instanceof UnknownFieldSet) &&
+ fields.equals(((UnknownFieldSet) other).fields);
+ }
+
+ @Override
+ public int hashCode() {
+ return fields.hashCode();
+ }
+
+ /** Get a map of fields in the set by number. */
+ public Map<Integer, Field> asMap() {
+ return fields;
+ }
+
+ /** Check if the given field number is present in the set. */
+ public boolean hasField(final int number) {
+ return fields.containsKey(number);
+ }
+
+ /**
+ * Get a field by number. Returns an empty field if not present. Never
+ * returns {@code null}.
+ */
+ public Field getField(final int number) {
+ final Field result = fields.get(number);
+ return (result == null) ? Field.getDefaultInstance() : result;
+ }
+
+ /** Serializes the set and writes it to {@code output}. */
+ public void writeTo(final CodedOutputStream output) throws IOException {
+ for (final Map.Entry<Integer, Field> entry : fields.entrySet()) {
+ entry.getValue().writeTo(entry.getKey(), output);
+ }
+ }
+
+ /**
+ * Converts the set to a string in protocol buffer text format. This is
+ * just a trivial wrapper around
+ * {@link TextFormat#printToString(UnknownFieldSet)}.
+ */
+ @Override
+ public String toString() {
+ return TextFormat.printToString(this);
+ }
+
+ /**
+ * Serializes the message to a {@code ByteString} and returns it. This is
+ * just a trivial wrapper around {@link #writeTo(CodedOutputStream)}.
+ */
+ public ByteString toByteString() {
+ try {
+ final ByteString.CodedBuilder out =
+ ByteString.newCodedBuilder(getSerializedSize());
+ writeTo(out.getCodedOutput());
+ return out.build();
+ } catch (final IOException e) {
+ throw new RuntimeException(
+ "Serializing to a ByteString threw an IOException (should " +
+ "never happen).", e);
+ }
+ }
+
+ /**
+ * Serializes the message to a {@code byte} array and returns it. This is
+ * just a trivial wrapper around {@link #writeTo(CodedOutputStream)}.
+ */
+ public byte[] toByteArray() {
+ try {
+ final byte[] result = new byte[getSerializedSize()];
+ final CodedOutputStream output = CodedOutputStream.newInstance(result);
+ writeTo(output);
+ output.checkNoSpaceLeft();
+ return result;
+ } catch (final IOException e) {
+ throw new RuntimeException(
+ "Serializing to a byte array threw an IOException " +
+ "(should never happen).", e);
+ }
+ }
+
+ /**
+ * Serializes the message and writes it to {@code output}. This is just a
+ * trivial wrapper around {@link #writeTo(CodedOutputStream)}.
+ */
+ public void writeTo(final OutputStream output) throws IOException {
+ final CodedOutputStream codedOutput = CodedOutputStream.newInstance(output);
+ writeTo(codedOutput);
+ codedOutput.flush();
+ }
+
+ public void writeDelimitedTo(OutputStream output) throws IOException {
+ final CodedOutputStream codedOutput = CodedOutputStream.newInstance(output);
+ codedOutput.writeRawVarint32(getSerializedSize());
+ writeTo(codedOutput);
+ codedOutput.flush();
+ }
+
+ /** Get the number of bytes required to encode this set. */
+ public int getSerializedSize() {
+ int result = 0;
+ for (final Map.Entry<Integer, Field> entry : fields.entrySet()) {
+ result += entry.getValue().getSerializedSize(entry.getKey());
+ }
+ return result;
+ }
+
+ /**
+ * Serializes the set and writes it to {@code output} using
+ * {@code MessageSet} wire format.
+ */
+ public void writeAsMessageSetTo(final CodedOutputStream output)
+ throws IOException {
+ for (final Map.Entry<Integer, Field> entry : fields.entrySet()) {
+ entry.getValue().writeAsMessageSetExtensionTo(
+ entry.getKey(), output);
+ }
+ }
+
+ /**
+ * Get the number of bytes required to encode this set using
+ * {@code MessageSet} wire format.
+ */
+ public int getSerializedSizeAsMessageSet() {
+ int result = 0;
+ for (final Map.Entry<Integer, Field> entry : fields.entrySet()) {
+ result += entry.getValue().getSerializedSizeAsMessageSetExtension(
+ entry.getKey());
+ }
+ return result;
+ }
+
+ public boolean isInitialized() {
+ // UnknownFieldSets do not have required fields, so they are always
+ // initialized.
+ return true;
+ }
+
+ /** Parse an {@code UnknownFieldSet} from the given input stream. */
+ public static UnknownFieldSet parseFrom(final CodedInputStream input)
+ throws IOException {
+ return newBuilder().mergeFrom(input).build();
+ }
+
+ /** Parse {@code data} as an {@code UnknownFieldSet} and return it. */
+ public static UnknownFieldSet parseFrom(final ByteString data)
+ throws InvalidProtocolBufferException {
+ return newBuilder().mergeFrom(data).build();
+ }
+
+ /** Parse {@code data} as an {@code UnknownFieldSet} and return it. */
+ public static UnknownFieldSet parseFrom(final byte[] data)
+ throws InvalidProtocolBufferException {
+ return newBuilder().mergeFrom(data).build();
+ }
+
+ /** Parse an {@code UnknownFieldSet} from {@code input} and return it. */
+ public static UnknownFieldSet parseFrom(final InputStream input)
+ throws IOException {
+ return newBuilder().mergeFrom(input).build();
+ }
+
+ public Builder newBuilderForType() {
+ return newBuilder();
+ }
+
+ public Builder toBuilder() {
+ return newBuilder().mergeFrom(this);
+ }
+
+ /**
+ * Builder for {@link UnknownFieldSet}s.
+ *
+ * <p>Note that this class maintains {@link Field.Builder}s for all fields
+ * in the set. Thus, adding one element to an existing {@link Field} does not
+ * require making a copy. This is important for efficient parsing of
+ * unknown repeated fields. However, it implies that {@link Field}s cannot
+ * be constructed independently, nor can two {@link UnknownFieldSet}s share
+ * the same {@code Field} object.
+ *
+ * <p>Use {@link UnknownFieldSet#newBuilder()} to construct a {@code Builder}.
+ */
+ public static final class Builder implements MessageLite.Builder {
+ // This constructor should never be called directly (except from 'create').
+ private Builder() {}
+
+ private Map<Integer, Field> fields;
+
+ // Optimization: We keep around a builder for the last field that was
+ // modified so that we can efficiently add to it multiple times in a
+ // row (important when parsing an unknown repeated field).
+ private int lastFieldNumber;
+ private Field.Builder lastField;
+
+ private static Builder create() {
+ Builder builder = new Builder();
+ builder.reinitialize();
+ return builder;
+ }
+
+ /**
+ * Get a field builder for the given field number which includes any
+ * values that already exist.
+ */
+ private Field.Builder getFieldBuilder(final int number) {
+ if (lastField != null) {
+ if (number == lastFieldNumber) {
+ return lastField;
+ }
+ // Note: addField() will reset lastField and lastFieldNumber.
+ addField(lastFieldNumber, lastField.build());
+ }
+ if (number == 0) {
+ return null;
+ } else {
+ final Field existing = fields.get(number);
+ lastFieldNumber = number;
+ lastField = Field.newBuilder();
+ if (existing != null) {
+ lastField.mergeFrom(existing);
+ }
+ return lastField;
+ }
+ }
+
+ /**
+ * Build the {@link UnknownFieldSet} and return it.
+ *
+ * <p>Once {@code build()} has been called, the {@code Builder} will no
+ * longer be usable. Calling any method after {@code build()} will result
+ * in undefined behavior and can cause a {@code NullPointerException} to be
+ * thrown.
+ */
+ public UnknownFieldSet build() {
+ getFieldBuilder(0); // Force lastField to be built.
+ final UnknownFieldSet result;
+ if (fields.isEmpty()) {
+ result = getDefaultInstance();
+ } else {
+ result = new UnknownFieldSet(Collections.unmodifiableMap(fields));
+ }
+ fields = null;
+ return result;
+ }
+
+ public UnknownFieldSet buildPartial() {
+ // No required fields, so this is the same as build().
+ return build();
+ }
+
+ @Override
+ public Builder clone() {
+ getFieldBuilder(0); // Force lastField to be built.
+ return UnknownFieldSet.newBuilder().mergeFrom(
+ new UnknownFieldSet(fields));
+ }
+
+ public UnknownFieldSet getDefaultInstanceForType() {
+ return UnknownFieldSet.getDefaultInstance();
+ }
+
+ private void reinitialize() {
+ fields = Collections.emptyMap();
+ lastFieldNumber = 0;
+ lastField = null;
+ }
+
+ /** Reset the builder to an empty set. */
+ public Builder clear() {
+ reinitialize();
+ return this;
+ }
+
+ /**
+ * Merge the fields from {@code other} into this set. If a field number
+ * exists in both sets, {@code other}'s values for that field will be
+ * appended to the values in this set.
+ */
+ public Builder mergeFrom(final UnknownFieldSet other) {
+ if (other != getDefaultInstance()) {
+ for (final Map.Entry<Integer, Field> entry : other.fields.entrySet()) {
+ mergeField(entry.getKey(), entry.getValue());
+ }
+ }
+ return this;
+ }
+
+ /**
+ * Add a field to the {@code UnknownFieldSet}. If a field with the same
+ * number already exists, the two are merged.
+ */
+ public Builder mergeField(final int number, final Field field) {
+ if (number == 0) {
+ throw new IllegalArgumentException("Zero is not a valid field number.");
+ }
+ if (hasField(number)) {
+ getFieldBuilder(number).mergeFrom(field);
+ } else {
+ // Optimization: We could call getFieldBuilder(number).mergeFrom(field)
+ // in this case, but that would create a copy of the Field object.
+ // We'd rather reuse the one passed to us, so call addField() instead.
+ addField(number, field);
+ }
+ return this;
+ }
+
+ /**
+ * Convenience method for merging a new field containing a single varint
+ * value. This is used in particular when an unknown enum value is
+ * encountered.
+ */
+ public Builder mergeVarintField(final int number, final int value) {
+ if (number == 0) {
+ throw new IllegalArgumentException("Zero is not a valid field number.");
+ }
+ getFieldBuilder(number).addVarint(value);
+ return this;
+ }
+
+ /** Check if the given field number is present in the set. */
+ public boolean hasField(final int number) {
+ if (number == 0) {
+ throw new IllegalArgumentException("Zero is not a valid field number.");
+ }
+ return number == lastFieldNumber || fields.containsKey(number);
+ }
+
+ /**
+ * Add a field to the {@code UnknownFieldSet}. If a field with the same
+ * number already exists, it is removed.
+ */
+ public Builder addField(final int number, final Field field) {
+ if (number == 0) {
+ throw new IllegalArgumentException("Zero is not a valid field number.");
+ }
+ if (lastField != null && lastFieldNumber == number) {
+ // Discard this.
+ lastField = null;
+ lastFieldNumber = 0;
+ }
+ if (fields.isEmpty()) {
+ fields = new TreeMap<Integer,Field>();
+ }
+ fields.put(number, field);
+ return this;
+ }
+
+ /**
+ * Get all present {@code Field}s as an immutable {@code Map}. If more
+ * fields are added, the changes may or may not be reflected in this map.
+ */
+ public Map<Integer, Field> asMap() {
+ getFieldBuilder(0); // Force lastField to be built.
+ return Collections.unmodifiableMap(fields);
+ }
+
+ /**
+ * Parse an entire message from {@code input} and merge its fields into
+ * this set.
+ */
+ public Builder mergeFrom(final CodedInputStream input) throws IOException {
+ while (true) {
+ final int tag = input.readTag();
+ if (tag == 0 || !mergeFieldFrom(tag, input)) {
+ break;
+ }
+ }
+ return this;
+ }
+
+ /**
+ * Parse a single field from {@code input} and merge it into this set.
+ * @param tag The field's tag number, which was already parsed.
+ * @return {@code false} if the tag is an engroup tag.
+ */
+ public boolean mergeFieldFrom(final int tag, final CodedInputStream input)
+ throws IOException {
+ final int number = WireFormat.getTagFieldNumber(tag);
+ switch (WireFormat.getTagWireType(tag)) {
+ case WireFormat.WIRETYPE_VARINT:
+ getFieldBuilder(number).addVarint(input.readInt64());
+ return true;
+ case WireFormat.WIRETYPE_FIXED64:
+ getFieldBuilder(number).addFixed64(input.readFixed64());
+ return true;
+ case WireFormat.WIRETYPE_LENGTH_DELIMITED:
+ getFieldBuilder(number).addLengthDelimited(input.readBytes());
+ return true;
+ case WireFormat.WIRETYPE_START_GROUP:
+ final Builder subBuilder = newBuilder();
+ input.readGroup(number, subBuilder,
+ ExtensionRegistry.getEmptyRegistry());
+ getFieldBuilder(number).addGroup(subBuilder.build());
+ return true;
+ case WireFormat.WIRETYPE_END_GROUP:
+ return false;
+ case WireFormat.WIRETYPE_FIXED32:
+ getFieldBuilder(number).addFixed32(input.readFixed32());
+ return true;
+ default:
+ throw InvalidProtocolBufferException.invalidWireType();
+ }
+ }
+
+ /**
+ * Parse {@code data} as an {@code UnknownFieldSet} and merge it with the
+ * set being built. This is just a small wrapper around
+ * {@link #mergeFrom(CodedInputStream)}.
+ */
+ public Builder mergeFrom(final ByteString data)
+ throws InvalidProtocolBufferException {
+ try {
+ final CodedInputStream input = data.newCodedInput();
+ mergeFrom(input);
+ input.checkLastTagWas(0);
+ return this;
+ } catch (final InvalidProtocolBufferException e) {
+ throw e;
+ } catch (final IOException e) {
+ throw new RuntimeException(
+ "Reading from a ByteString threw an IOException (should " +
+ "never happen).", e);
+ }
+ }
+
+ /**
+ * Parse {@code data} as an {@code UnknownFieldSet} and merge it with the
+ * set being built. This is just a small wrapper around
+ * {@link #mergeFrom(CodedInputStream)}.
+ */
+ public Builder mergeFrom(final byte[] data)
+ throws InvalidProtocolBufferException {
+ try {
+ final CodedInputStream input = CodedInputStream.newInstance(data);
+ mergeFrom(input);
+ input.checkLastTagWas(0);
+ return this;
+ } catch (final InvalidProtocolBufferException e) {
+ throw e;
+ } catch (final IOException e) {
+ throw new RuntimeException(
+ "Reading from a byte array threw an IOException (should " +
+ "never happen).", e);
+ }
+ }
+
+ /**
+ * Parse an {@code UnknownFieldSet} from {@code input} and merge it with the
+ * set being built. This is just a small wrapper around
+ * {@link #mergeFrom(CodedInputStream)}.
+ */
+ public Builder mergeFrom(final InputStream input) throws IOException {
+ final CodedInputStream codedInput = CodedInputStream.newInstance(input);
+ mergeFrom(codedInput);
+ codedInput.checkLastTagWas(0);
+ return this;
+ }
+
+ public Builder mergeDelimitedFrom(InputStream input)
+ throws IOException {
+ final int size = CodedInputStream.readRawVarint32(input);
+ final InputStream limitedInput =
+ new AbstractMessage.Builder.LimitedInputStream(input, size);
+ return mergeFrom(limitedInput, null);
+ }
+
+ public Builder mergeDelimitedFrom(
+ InputStream input,
+ ExtensionRegistryLite extensionRegistry) throws IOException {
+ // UnknownFieldSet has no extensions.
+ return mergeFrom(input);
+ }
+
+ public Builder mergeFrom(
+ CodedInputStream input,
+ ExtensionRegistryLite extensionRegistry) throws IOException {
+ // UnknownFieldSet has no extensions.
+ return mergeFrom(input);
+ }
+
+ public Builder mergeFrom(
+ ByteString data,
+ ExtensionRegistryLite extensionRegistry)
+ throws InvalidProtocolBufferException {
+ // UnknownFieldSet has no extensions.
+ return mergeFrom(data);
+ }
+
+ public Builder mergeFrom(byte[] data, int off, int len)
+ throws InvalidProtocolBufferException {
+ try {
+ final CodedInputStream input =
+ CodedInputStream.newInstance(data, off, len);
+ mergeFrom(input);
+ input.checkLastTagWas(0);
+ return this;
+ } catch (InvalidProtocolBufferException e) {
+ throw e;
+ } catch (IOException e) {
+ throw new RuntimeException(
+ "Reading from a byte array threw an IOException (should " +
+ "never happen).", e);
+ }
+ }
+
+ public Builder mergeFrom(
+ byte[] data,
+ ExtensionRegistryLite extensionRegistry)
+ throws InvalidProtocolBufferException {
+ // UnknownFieldSet has no extensions.
+ return mergeFrom(data);
+ }
+
+ public Builder mergeFrom(
+ byte[] data, int off, int len,
+ ExtensionRegistryLite extensionRegistry)
+ throws InvalidProtocolBufferException {
+ // UnknownFieldSet has no extensions.
+ return mergeFrom(data, off, len);
+ }
+
+ public Builder mergeFrom(
+ InputStream input,
+ ExtensionRegistryLite extensionRegistry) throws IOException {
+ // UnknownFieldSet has no extensions.
+ return mergeFrom(input);
+ }
+
+ public boolean isInitialized() {
+ // UnknownFieldSets do not have required fields, so they are always
+ // initialized.
+ return true;
+ }
+ }
+
+ /**
+ * Represents a single field in an {@code UnknownFieldSet}.
+ *
+ * <p>A {@code Field} consists of five lists of values. The lists correspond
+ * to the five "wire types" used in the protocol buffer binary format.
+ * The wire type of each field can be determined from the encoded form alone,
+ * without knowing the field's declared type. So, we are able to parse
+ * unknown values at least this far and separate them. Normally, only one
+ * of the five lists will contain any values, since it is impossible to
+ * define a valid message type that declares two different types for the
+ * same field number. However, the code is designed to allow for the case
+ * where the same unknown field number is encountered using multiple different
+ * wire types.
+ *
+ * <p>{@code Field} is an immutable class. To construct one, you must use a
+ * {@link Builder}.
+ *
+ * @see UnknownFieldSet
+ */
+ public static final class Field {
+ private Field() {}
+
+ /** Construct a new {@link Builder}. */
+ public static Builder newBuilder() {
+ return Builder.create();
+ }
+
+ /**
+ * Construct a new {@link Builder} and initialize it to a copy of
+ * {@code copyFrom}.
+ */
+ public static Builder newBuilder(final Field copyFrom) {
+ return newBuilder().mergeFrom(copyFrom);
+ }
+
+ /** Get an empty {@code Field}. */
+ public static Field getDefaultInstance() {
+ return fieldDefaultInstance;
+ }
+ private static final Field fieldDefaultInstance = newBuilder().build();
+
+ /** Get the list of varint values for this field. */
+ public List<Long> getVarintList() { return varint; }
+
+ /** Get the list of fixed32 values for this field. */
+ public List<Integer> getFixed32List() { return fixed32; }
+
+ /** Get the list of fixed64 values for this field. */
+ public List<Long> getFixed64List() { return fixed64; }
+
+ /** Get the list of length-delimited values for this field. */
+ public List<ByteString> getLengthDelimitedList() { return lengthDelimited; }
+
+ /**
+ * Get the list of embedded group values for this field. These are
+ * represented using {@link UnknownFieldSet}s rather than {@link Message}s
+ * since the group's type is presumably unknown.
+ */
+ public List<UnknownFieldSet> getGroupList() { return group; }
+
+ @Override
+ public boolean equals(final Object other) {
+ if (this == other) {
+ return true;
+ }
+ if (!(other instanceof Field)) {
+ return false;
+ }
+ return Arrays.equals(getIdentityArray(),
+ ((Field) other).getIdentityArray());
+ }
+
+ @Override
+ public int hashCode() {
+ return Arrays.hashCode(getIdentityArray());
+ }
+
+ /**
+ * Returns the array of objects to be used to uniquely identify this
+ * {@link Field} instance.
+ */
+ private Object[] getIdentityArray() {
+ return new Object[] {
+ varint,
+ fixed32,
+ fixed64,
+ lengthDelimited,
+ group};
+ }
+
+ /**
+ * Serializes the field, including field number, and writes it to
+ * {@code output}.
+ */
+ public void writeTo(final int fieldNumber, final CodedOutputStream output)
+ throws IOException {
+ for (final long value : varint) {
+ output.writeUInt64(fieldNumber, value);
+ }
+ for (final int value : fixed32) {
+ output.writeFixed32(fieldNumber, value);
+ }
+ for (final long value : fixed64) {
+ output.writeFixed64(fieldNumber, value);
+ }
+ for (final ByteString value : lengthDelimited) {
+ output.writeBytes(fieldNumber, value);
+ }
+ for (final UnknownFieldSet value : group) {
+ output.writeGroup(fieldNumber, value);
+ }
+ }
+
+ /**
+ * Get the number of bytes required to encode this field, including field
+ * number.
+ */
+ public int getSerializedSize(final int fieldNumber) {
+ int result = 0;
+ for (final long value : varint) {
+ result += CodedOutputStream.computeUInt64Size(fieldNumber, value);
+ }
+ for (final int value : fixed32) {
+ result += CodedOutputStream.computeFixed32Size(fieldNumber, value);
+ }
+ for (final long value : fixed64) {
+ result += CodedOutputStream.computeFixed64Size(fieldNumber, value);
+ }
+ for (final ByteString value : lengthDelimited) {
+ result += CodedOutputStream.computeBytesSize(fieldNumber, value);
+ }
+ for (final UnknownFieldSet value : group) {
+ result += CodedOutputStream.computeGroupSize(fieldNumber, value);
+ }
+ return result;
+ }
+
+ /**
+ * Serializes the field, including field number, and writes it to
+ * {@code output}, using {@code MessageSet} wire format.
+ */
+ public void writeAsMessageSetExtensionTo(
+ final int fieldNumber,
+ final CodedOutputStream output)
+ throws IOException {
+ for (final ByteString value : lengthDelimited) {
+ output.writeRawMessageSetExtension(fieldNumber, value);
+ }
+ }
+
+ /**
+ * Get the number of bytes required to encode this field, including field
+ * number, using {@code MessageSet} wire format.
+ */
+ public int getSerializedSizeAsMessageSetExtension(final int fieldNumber) {
+ int result = 0;
+ for (final ByteString value : lengthDelimited) {
+ result += CodedOutputStream.computeRawMessageSetExtensionSize(
+ fieldNumber, value);
+ }
+ return result;
+ }
+
+ private List<Long> varint;
+ private List<Integer> fixed32;
+ private List<Long> fixed64;
+ private List<ByteString> lengthDelimited;
+ private List<UnknownFieldSet> group;
+
+ /**
+ * Used to build a {@link Field} within an {@link UnknownFieldSet}.
+ *
+ * <p>Use {@link Field#newBuilder()} to construct a {@code Builder}.
+ */
+ public static final class Builder {
+ // This constructor should never be called directly (except from 'create').
+ private Builder() {}
+
+ private static Builder create() {
+ Builder builder = new Builder();
+ builder.result = new Field();
+ return builder;
+ }
+
+ private Field result;
+
+ /**
+ * Build the field. After {@code build()} has been called, the
+ * {@code Builder} is no longer usable. Calling any other method will
+ * result in undefined behavior and can cause a
+ * {@code NullPointerException} to be thrown.
+ */
+ public Field build() {
+ if (result.varint == null) {
+ result.varint = Collections.emptyList();
+ } else {
+ result.varint = Collections.unmodifiableList(result.varint);
+ }
+ if (result.fixed32 == null) {
+ result.fixed32 = Collections.emptyList();
+ } else {
+ result.fixed32 = Collections.unmodifiableList(result.fixed32);
+ }
+ if (result.fixed64 == null) {
+ result.fixed64 = Collections.emptyList();
+ } else {
+ result.fixed64 = Collections.unmodifiableList(result.fixed64);
+ }
+ if (result.lengthDelimited == null) {
+ result.lengthDelimited = Collections.emptyList();
+ } else {
+ result.lengthDelimited =
+ Collections.unmodifiableList(result.lengthDelimited);
+ }
+ if (result.group == null) {
+ result.group = Collections.emptyList();
+ } else {
+ result.group = Collections.unmodifiableList(result.group);
+ }
+
+ final Field returnMe = result;
+ result = null;
+ return returnMe;
+ }
+
+ /** Discard the field's contents. */
+ public Builder clear() {
+ result = new Field();
+ return this;
+ }
+
+ /**
+ * Merge the values in {@code other} into this field. For each list
+ * of values, {@code other}'s values are append to the ones in this
+ * field.
+ */
+ public Builder mergeFrom(final Field other) {
+ if (!other.varint.isEmpty()) {
+ if (result.varint == null) {
+ result.varint = new ArrayList<Long>();
+ }
+ result.varint.addAll(other.varint);
+ }
+ if (!other.fixed32.isEmpty()) {
+ if (result.fixed32 == null) {
+ result.fixed32 = new ArrayList<Integer>();
+ }
+ result.fixed32.addAll(other.fixed32);
+ }
+ if (!other.fixed64.isEmpty()) {
+ if (result.fixed64 == null) {
+ result.fixed64 = new ArrayList<Long>();
+ }
+ result.fixed64.addAll(other.fixed64);
+ }
+ if (!other.lengthDelimited.isEmpty()) {
+ if (result.lengthDelimited == null) {
+ result.lengthDelimited = new ArrayList<ByteString>();
+ }
+ result.lengthDelimited.addAll(other.lengthDelimited);
+ }
+ if (!other.group.isEmpty()) {
+ if (result.group == null) {
+ result.group = new ArrayList<UnknownFieldSet>();
+ }
+ result.group.addAll(other.group);
+ }
+ return this;
+ }
+
+ /** Add a varint value. */
+ public Builder addVarint(final long value) {
+ if (result.varint == null) {
+ result.varint = new ArrayList<Long>();
+ }
+ result.varint.add(value);
+ return this;
+ }
+
+ /** Add a fixed32 value. */
+ public Builder addFixed32(final int value) {
+ if (result.fixed32 == null) {
+ result.fixed32 = new ArrayList<Integer>();
+ }
+ result.fixed32.add(value);
+ return this;
+ }
+
+ /** Add a fixed64 value. */
+ public Builder addFixed64(final long value) {
+ if (result.fixed64 == null) {
+ result.fixed64 = new ArrayList<Long>();
+ }
+ result.fixed64.add(value);
+ return this;
+ }
+
+ /** Add a length-delimited value. */
+ public Builder addLengthDelimited(final ByteString value) {
+ if (result.lengthDelimited == null) {
+ result.lengthDelimited = new ArrayList<ByteString>();
+ }
+ result.lengthDelimited.add(value);
+ return this;
+ }
+
+ /** Add an embedded group. */
+ public Builder addGroup(final UnknownFieldSet value) {
+ if (result.group == null) {
+ result.group = new ArrayList<UnknownFieldSet>();
+ }
+ result.group.add(value);
+ return this;
+ }
+ }
+ }
+}