| Index: third_party/protobuf/java/src/main/java/com/google/protobuf/FieldSet.java
|
| ===================================================================
|
| --- third_party/protobuf/java/src/main/java/com/google/protobuf/FieldSet.java (revision 216642)
|
| +++ third_party/protobuf/java/src/main/java/com/google/protobuf/FieldSet.java (working copy)
|
| @@ -30,12 +30,14 @@
|
|
|
| package com.google.protobuf;
|
|
|
| +import com.google.protobuf.LazyField.LazyIterator;
|
| +
|
| +import java.io.IOException;
|
| import java.util.ArrayList;
|
| import java.util.Collections;
|
| import java.util.Iterator;
|
| import java.util.List;
|
| import java.util.Map;
|
| -import java.io.IOException;
|
|
|
| /**
|
| * A class which represents an arbitrary set of fields of some message type.
|
| @@ -68,6 +70,7 @@
|
|
|
| private final SmallSortedMap<FieldDescriptorType, Object> fields;
|
| private boolean isImmutable;
|
| + private boolean hasLazyField = false;
|
|
|
| /** Construct a new FieldSet. */
|
| private FieldSet() {
|
| @@ -95,7 +98,7 @@
|
| FieldSet<T> emptySet() {
|
| return DEFAULT_INSTANCE;
|
| }
|
| - @SuppressWarnings("unchecked")
|
| + @SuppressWarnings("rawtypes")
|
| private static final FieldSet DEFAULT_INSTANCE = new FieldSet(true);
|
|
|
| /** Make this FieldSet immutable from this point forward. */
|
| @@ -109,7 +112,7 @@
|
| }
|
|
|
| /**
|
| - * Retuns whether the FieldSet is immutable. This is true if it is the
|
| + * Returns whether the FieldSet is immutable. This is true if it is the
|
| * {@link #emptySet} or if {@link #makeImmutable} were called.
|
| *
|
| * @return whether the FieldSet is immutable.
|
| @@ -139,6 +142,7 @@
|
| FieldDescriptorType descriptor = entry.getKey();
|
| clone.setField(descriptor, entry.getValue());
|
| }
|
| + clone.hasLazyField = hasLazyField;
|
| return clone;
|
| }
|
|
|
| @@ -147,21 +151,52 @@
|
| /** See {@link Message.Builder#clear()}. */
|
| public void clear() {
|
| fields.clear();
|
| + hasLazyField = false;
|
| }
|
|
|
| /**
|
| * Get a simple map containing all the fields.
|
| */
|
| public Map<FieldDescriptorType, Object> getAllFields() {
|
| + if (hasLazyField) {
|
| + SmallSortedMap<FieldDescriptorType, Object> result =
|
| + SmallSortedMap.newFieldMap(16);
|
| + for (int i = 0; i < fields.getNumArrayEntries(); i++) {
|
| + cloneFieldEntry(result, fields.getArrayEntryAt(i));
|
| + }
|
| + for (Map.Entry<FieldDescriptorType, Object> entry :
|
| + fields.getOverflowEntries()) {
|
| + cloneFieldEntry(result, entry);
|
| + }
|
| + if (fields.isImmutable()) {
|
| + result.makeImmutable();
|
| + }
|
| + return result;
|
| + }
|
| return fields.isImmutable() ? fields : Collections.unmodifiableMap(fields);
|
| }
|
|
|
| + private void cloneFieldEntry(Map<FieldDescriptorType, Object> map,
|
| + Map.Entry<FieldDescriptorType, Object> entry) {
|
| + FieldDescriptorType key = entry.getKey();
|
| + Object value = entry.getValue();
|
| + if (value instanceof LazyField) {
|
| + map.put(key, ((LazyField) value).getValue());
|
| + } else {
|
| + map.put(key, value);
|
| + }
|
| + }
|
| +
|
| /**
|
| * Get an iterator to the field map. This iterator should not be leaked out
|
| - * of the protobuf library as it is not protected from mutation when
|
| - * fields is not immutable.
|
| + * of the protobuf library as it is not protected from mutation when fields
|
| + * is not immutable.
|
| */
|
| public Iterator<Map.Entry<FieldDescriptorType, Object>> iterator() {
|
| + if (hasLazyField) {
|
| + return new LazyIterator<FieldDescriptorType>(
|
| + fields.entrySet().iterator());
|
| + }
|
| return fields.entrySet().iterator();
|
| }
|
|
|
| @@ -185,14 +220,18 @@
|
| * to the caller to fetch the field's default value.
|
| */
|
| public Object getField(final FieldDescriptorType descriptor) {
|
| - return fields.get(descriptor);
|
| + Object o = fields.get(descriptor);
|
| + if (o instanceof LazyField) {
|
| + return ((LazyField) o).getValue();
|
| + }
|
| + return o;
|
| }
|
|
|
| /**
|
| * Useful for implementing
|
| * {@link Message.Builder#setField(Descriptors.FieldDescriptor,Object)}.
|
| */
|
| - @SuppressWarnings("unchecked")
|
| + @SuppressWarnings({"unchecked", "rawtypes"})
|
| public void setField(final FieldDescriptorType descriptor,
|
| Object value) {
|
| if (descriptor.isRepeated()) {
|
| @@ -204,7 +243,7 @@
|
| // Wrap the contents in a new list so that the caller cannot change
|
| // the list's contents after setting it.
|
| final List newList = new ArrayList();
|
| - newList.addAll((List)value);
|
| + newList.addAll((List) value);
|
| for (final Object element : newList) {
|
| verifyType(descriptor.getLiteType(), element);
|
| }
|
| @@ -213,6 +252,9 @@
|
| verifyType(descriptor.getLiteType(), value);
|
| }
|
|
|
| + if (value instanceof LazyField) {
|
| + hasLazyField = true;
|
| + }
|
| fields.put(descriptor, value);
|
| }
|
|
|
| @@ -222,6 +264,9 @@
|
| */
|
| public void clearField(final FieldDescriptorType descriptor) {
|
| fields.remove(descriptor);
|
| + if (fields.isEmpty()) {
|
| + hasLazyField = false;
|
| + }
|
| }
|
|
|
| /**
|
| @@ -234,7 +279,7 @@
|
| "getRepeatedField() can only be called on repeated fields.");
|
| }
|
|
|
| - final Object value = fields.get(descriptor);
|
| + final Object value = getField(descriptor);
|
| if (value == null) {
|
| return 0;
|
| } else {
|
| @@ -253,7 +298,7 @@
|
| "getRepeatedField() can only be called on repeated fields.");
|
| }
|
|
|
| - final Object value = fields.get(descriptor);
|
| + final Object value = getField(descriptor);
|
|
|
| if (value == null) {
|
| throw new IndexOutOfBoundsException();
|
| @@ -275,13 +320,13 @@
|
| "getRepeatedField() can only be called on repeated fields.");
|
| }
|
|
|
| - final Object list = fields.get(descriptor);
|
| + final Object list = getField(descriptor);
|
| if (list == null) {
|
| throw new IndexOutOfBoundsException();
|
| }
|
|
|
| verifyType(descriptor.getLiteType(), value);
|
| - ((List) list).set(index, value);
|
| + ((List<Object>) list).set(index, value);
|
| }
|
|
|
| /**
|
| @@ -298,13 +343,13 @@
|
|
|
| verifyType(descriptor.getLiteType(), value);
|
|
|
| - final Object existingValue = fields.get(descriptor);
|
| - List list;
|
| + final Object existingValue = getField(descriptor);
|
| + List<Object> list;
|
| if (existingValue == null) {
|
| - list = new ArrayList();
|
| + list = new ArrayList<Object>();
|
| fields.put(descriptor, list);
|
| } else {
|
| - list = (List) existingValue;
|
| + list = (List<Object>) existingValue;
|
| }
|
|
|
| list.add(value);
|
| @@ -338,7 +383,8 @@
|
| break;
|
| case MESSAGE:
|
| // TODO(kenton): Caller must do type checking here, I guess.
|
| - isValid = value instanceof MessageLite;
|
| + isValid =
|
| + (value instanceof MessageLite) || (value instanceof LazyField);
|
| break;
|
| }
|
|
|
| @@ -392,8 +438,16 @@
|
| }
|
| }
|
| } else {
|
| - if (!((MessageLite) entry.getValue()).isInitialized()) {
|
| - return false;
|
| + Object value = entry.getValue();
|
| + if (value instanceof MessageLite) {
|
| + if (!((MessageLite) value).isInitialized()) {
|
| + return false;
|
| + }
|
| + } else if (value instanceof LazyField) {
|
| + return true;
|
| + } else {
|
| + throw new IllegalArgumentException(
|
| + "Wrong object type used with protocol message reflection.");
|
| }
|
| }
|
| }
|
| @@ -416,7 +470,8 @@
|
| }
|
|
|
| /**
|
| - * Like {@link #mergeFrom(Message)}, but merges from another {@link FieldSet}.
|
| + * Like {@link Message.Builder#mergeFrom(Message)}, but merges from another
|
| + * {@link FieldSet}.
|
| */
|
| public void mergeFrom(final FieldSet<FieldDescriptorType> other) {
|
| for (int i = 0; i < other.fields.getNumArrayEntries(); i++) {
|
| @@ -428,14 +483,17 @@
|
| }
|
| }
|
|
|
| - @SuppressWarnings("unchecked")
|
| + @SuppressWarnings({"unchecked", "rawtypes"})
|
| private void mergeFromField(
|
| final Map.Entry<FieldDescriptorType, Object> entry) {
|
| final FieldDescriptorType descriptor = entry.getKey();
|
| - final Object otherValue = entry.getValue();
|
| + Object otherValue = entry.getValue();
|
| + if (otherValue instanceof LazyField) {
|
| + otherValue = ((LazyField) otherValue).getValue();
|
| + }
|
|
|
| if (descriptor.isRepeated()) {
|
| - Object value = fields.get(descriptor);
|
| + Object value = getField(descriptor);
|
| if (value == null) {
|
| // Our list is empty, but we still need to make a defensive copy of
|
| // the other list since we don't know if the other FieldSet is still
|
| @@ -446,7 +504,7 @@
|
| ((List) value).addAll((List) otherValue);
|
| }
|
| } else if (descriptor.getLiteJavaType() == WireFormat.JavaType.MESSAGE) {
|
| - Object value = fields.get(descriptor);
|
| + Object value = getField(descriptor);
|
| if (value == null) {
|
| fields.put(descriptor, otherValue);
|
| } else {
|
| @@ -457,7 +515,6 @@
|
| ((MessageLite) value).toBuilder(), (MessageLite) otherValue)
|
| .build());
|
| }
|
| -
|
| } else {
|
| fields.put(descriptor, otherValue);
|
| }
|
| @@ -646,7 +703,11 @@
|
| }
|
| }
|
| } else {
|
| - writeElement(output, type, number, value);
|
| + if (value instanceof LazyField) {
|
| + writeElement(output, type, number, ((LazyField) value).getValue());
|
| + } else {
|
| + writeElement(output, type, number, value);
|
| + }
|
| }
|
| }
|
|
|
| @@ -686,12 +747,18 @@
|
| private int getMessageSetSerializedSize(
|
| final Map.Entry<FieldDescriptorType, Object> entry) {
|
| final FieldDescriptorType descriptor = entry.getKey();
|
| - if (descriptor.getLiteJavaType() == WireFormat.JavaType.MESSAGE &&
|
| - !descriptor.isRepeated() && !descriptor.isPacked()) {
|
| - return CodedOutputStream.computeMessageSetExtensionSize(
|
| - entry.getKey().getNumber(), (MessageLite) entry.getValue());
|
| + Object value = entry.getValue();
|
| + if (descriptor.getLiteJavaType() == WireFormat.JavaType.MESSAGE
|
| + && !descriptor.isRepeated() && !descriptor.isPacked()) {
|
| + if (value instanceof LazyField) {
|
| + return CodedOutputStream.computeLazyFieldMessageSetExtensionSize(
|
| + entry.getKey().getNumber(), (LazyField) value);
|
| + } else {
|
| + return CodedOutputStream.computeMessageSetExtensionSize(
|
| + entry.getKey().getNumber(), (MessageLite) value);
|
| + }
|
| } else {
|
| - return computeFieldSize(descriptor, entry.getValue());
|
| + return computeFieldSize(descriptor, value);
|
| }
|
| }
|
|
|
| @@ -741,7 +808,6 @@
|
| case BOOL : return CodedOutputStream.computeBoolSizeNoTag ((Boolean )value);
|
| case STRING : return CodedOutputStream.computeStringSizeNoTag ((String )value);
|
| case GROUP : return CodedOutputStream.computeGroupSizeNoTag ((MessageLite)value);
|
| - case MESSAGE : return CodedOutputStream.computeMessageSizeNoTag ((MessageLite)value);
|
| case BYTES : return CodedOutputStream.computeBytesSizeNoTag ((ByteString )value);
|
| case UINT32 : return CodedOutputStream.computeUInt32SizeNoTag ((Integer )value);
|
| case SFIXED32: return CodedOutputStream.computeSFixed32SizeNoTag((Integer )value);
|
| @@ -749,6 +815,13 @@
|
| case SINT32 : return CodedOutputStream.computeSInt32SizeNoTag ((Integer )value);
|
| case SINT64 : return CodedOutputStream.computeSInt64SizeNoTag ((Long )value);
|
|
|
| + case MESSAGE:
|
| + if (value instanceof LazyField) {
|
| + return CodedOutputStream.computeLazyFieldSizeNoTag((LazyField) value);
|
| + } else {
|
| + return CodedOutputStream.computeMessageSizeNoTag((MessageLite) value);
|
| + }
|
| +
|
| case ENUM:
|
| return CodedOutputStream.computeEnumSizeNoTag(
|
| ((Internal.EnumLite) value).getNumber());
|
|
|