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()); |