| Index: third_party/protobuf/java/core/src/main/java/com/google/protobuf/MapEntry.java
|
| diff --git a/third_party/protobuf/java/core/src/main/java/com/google/protobuf/MapEntry.java b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/MapEntry.java
|
| index 31414bb49abb09d44b72933c6e4b5dd2df919f60..179c3348a1e097f00279d3b59ebc433bf5b7a25d 100644
|
| --- a/third_party/protobuf/java/core/src/main/java/com/google/protobuf/MapEntry.java
|
| +++ b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/MapEntry.java
|
| @@ -41,63 +41,83 @@ import java.util.TreeMap;
|
|
|
| /**
|
| * Implements MapEntry messages.
|
| - *
|
| + *
|
| * In reflection API, map fields will be treated as repeated message fields and
|
| * each map entry is accessed as a message. This MapEntry class is used to
|
| * represent these map entry messages in reflection API.
|
| - *
|
| + *
|
| * Protobuf internal. Users shouldn't use this class.
|
| */
|
| public final class MapEntry<K, V> extends AbstractMessage {
|
| - private static class Metadata<K, V> {
|
| - public final Descriptor descriptor;
|
| - public final MapEntry<K, V> defaultInstance;
|
| - public final AbstractParser<MapEntry<K, V>> parser;
|
| -
|
| +
|
| + private static final class Metadata<K, V> extends MapEntryLite.Metadata<K, V> {
|
| +
|
| + public final Descriptor descriptor;
|
| + public final Parser<MapEntry<K, V>> parser;
|
| +
|
| public Metadata(
|
| - final Descriptor descriptor, final MapEntry<K, V> defaultInstance) {
|
| + Descriptor descriptor,
|
| + MapEntry<K, V> defaultInstance,
|
| + WireFormat.FieldType keyType,
|
| + WireFormat.FieldType valueType) {
|
| + super(keyType, defaultInstance.key, valueType, defaultInstance.value);
|
| this.descriptor = descriptor;
|
| - this.defaultInstance = defaultInstance;
|
| - final Metadata<K, V> thisMetadata = this;
|
| this.parser = new AbstractParser<MapEntry<K, V>>() {
|
| - private final Parser<MapEntryLite<K, V>> dataParser =
|
| - defaultInstance.data.getParserForType();
|
| +
|
| @Override
|
| public MapEntry<K, V> parsePartialFrom(
|
| CodedInputStream input, ExtensionRegistryLite extensionRegistry)
|
| throws InvalidProtocolBufferException {
|
| - MapEntryLite<K, V> data =
|
| - dataParser.parsePartialFrom(input, extensionRegistry);
|
| - return new MapEntry<K, V>(thisMetadata, data);
|
| + return new MapEntry<K, V>(Metadata.this, input, extensionRegistry);
|
| }
|
| -
|
| };
|
| }
|
| }
|
| -
|
| +
|
| + private final K key;
|
| + private final V value;
|
| private final Metadata<K, V> metadata;
|
| - private final MapEntryLite<K, V> data;
|
| -
|
| +
|
| /** Create a default MapEntry instance. */
|
| - private MapEntry(Descriptor descriptor,
|
| + private MapEntry(
|
| + Descriptor descriptor,
|
| WireFormat.FieldType keyType, K defaultKey,
|
| WireFormat.FieldType valueType, V defaultValue) {
|
| - this.data = MapEntryLite.newDefaultInstance(
|
| - keyType, defaultKey, valueType, defaultValue);
|
| - this.metadata = new Metadata<K, V>(descriptor, this);
|
| + this.key = defaultKey;
|
| + this.value = defaultValue;
|
| + this.metadata = new Metadata<K, V>(descriptor, this, keyType, valueType);
|
| }
|
| -
|
| - /** Create a new MapEntry message. */
|
| - private MapEntry(Metadata<K, V> metadata, MapEntryLite<K, V> data) {
|
| +
|
| + /** Create a MapEntry with the provided key and value. */
|
| + private MapEntry(Metadata metadata, K key, V value) {
|
| + this.key = key;
|
| + this.value = value;
|
| this.metadata = metadata;
|
| - this.data = data;
|
| }
|
| -
|
| +
|
| + /** Parsing constructor. */
|
| + private MapEntry(
|
| + Metadata<K, V> metadata,
|
| + CodedInputStream input,
|
| + ExtensionRegistryLite extensionRegistry)
|
| + throws InvalidProtocolBufferException {
|
| + try {
|
| + this.metadata = metadata;
|
| + Map.Entry<K, V> entry = MapEntryLite.parseEntry(input, metadata, extensionRegistry);
|
| + this.key = entry.getKey();
|
| + this.value = entry.getValue();
|
| + } catch (InvalidProtocolBufferException e) {
|
| + throw e.setUnfinishedMessage(this);
|
| + } catch (IOException e) {
|
| + throw new InvalidProtocolBufferException(e).setUnfinishedMessage(this);
|
| + }
|
| + }
|
| +
|
| /**
|
| * Create a default MapEntry instance. A default MapEntry instance should be
|
| * created only once for each map entry message type. Generated code should
|
| * store the created default instance and use it later to create new MapEntry
|
| - * messages of the same type.
|
| + * messages of the same type.
|
| */
|
| public static <K, V> MapEntry<K, V> newDefaultInstance(
|
| Descriptor descriptor,
|
| @@ -106,30 +126,38 @@ public final class MapEntry<K, V> extends AbstractMessage {
|
| return new MapEntry<K, V>(
|
| descriptor, keyType, defaultKey, valueType, defaultValue);
|
| }
|
| -
|
| +
|
| public K getKey() {
|
| - return data.getKey();
|
| + return key;
|
| }
|
| -
|
| +
|
| public V getValue() {
|
| - return data.getValue();
|
| + return value;
|
| }
|
| -
|
| +
|
| + private volatile int cachedSerializedSize = -1;
|
| +
|
| @Override
|
| public int getSerializedSize() {
|
| - return data.getSerializedSize();
|
| + if (cachedSerializedSize != -1) {
|
| + return cachedSerializedSize;
|
| + }
|
| +
|
| + int size = MapEntryLite.computeSerializedSize(metadata, key, value);
|
| + cachedSerializedSize = size;
|
| + return size;
|
| }
|
| -
|
| +
|
| @Override
|
| public void writeTo(CodedOutputStream output) throws IOException {
|
| - data.writeTo(output);
|
| + MapEntryLite.writeTo(output, metadata, key, value);
|
| }
|
| -
|
| +
|
| @Override
|
| public boolean isInitialized() {
|
| - return data.isInitialized();
|
| + return isInitialized(metadata, value);
|
| }
|
| -
|
| +
|
| @Override
|
| public Parser<MapEntry<K, V>> getParserForType() {
|
| return metadata.parser;
|
| @@ -139,15 +167,15 @@ public final class MapEntry<K, V> extends AbstractMessage {
|
| public Builder<K, V> newBuilderForType() {
|
| return new Builder<K, V>(metadata);
|
| }
|
| -
|
| +
|
| @Override
|
| public Builder<K, V> toBuilder() {
|
| - return new Builder<K, V>(metadata, data);
|
| + return new Builder<K, V>(metadata, key, value);
|
| }
|
|
|
| @Override
|
| public MapEntry<K, V> getDefaultInstanceForType() {
|
| - return metadata.defaultInstance;
|
| + return new MapEntry<K, V>(metadata, metadata.defaultKey, metadata.defaultValue);
|
| }
|
|
|
| @Override
|
| @@ -157,8 +185,7 @@ public final class MapEntry<K, V> extends AbstractMessage {
|
|
|
| @Override
|
| public Map<FieldDescriptor, Object> getAllFields() {
|
| - final TreeMap<FieldDescriptor, Object> result =
|
| - new TreeMap<FieldDescriptor, Object>();
|
| + TreeMap<FieldDescriptor, Object> result = new TreeMap<FieldDescriptor, Object>();
|
| for (final FieldDescriptor field : metadata.descriptor.getFields()) {
|
| if (hasField(field)) {
|
| result.put(field, getField(field));
|
| @@ -166,12 +193,12 @@ public final class MapEntry<K, V> extends AbstractMessage {
|
| }
|
| return Collections.unmodifiableMap(result);
|
| }
|
| -
|
| +
|
| private void checkFieldDescriptor(FieldDescriptor field) {
|
| if (field.getContainingType() != metadata.descriptor) {
|
| throw new RuntimeException(
|
| "Wrong FieldDescriptor \"" + field.getFullName()
|
| - + "\" used in message \"" + metadata.descriptor.getFullName());
|
| + + "\" used in message \"" + metadata.descriptor.getFullName());
|
| }
|
| }
|
|
|
| @@ -217,56 +244,44 @@ public final class MapEntry<K, V> extends AbstractMessage {
|
| public static class Builder<K, V>
|
| extends AbstractMessage.Builder<Builder<K, V>> {
|
| private final Metadata<K, V> metadata;
|
| - private MapEntryLite<K, V> data;
|
| - private MapEntryLite.Builder<K, V> dataBuilder;
|
| -
|
| + private K key;
|
| + private V value;
|
| +
|
| private Builder(Metadata<K, V> metadata) {
|
| - this.metadata = metadata;
|
| - this.data = metadata.defaultInstance.data;
|
| - this.dataBuilder = null;
|
| + this(metadata, metadata.defaultKey, metadata.defaultValue);
|
| }
|
| -
|
| - private Builder(Metadata<K, V> metadata, MapEntryLite<K, V> data) {
|
| +
|
| + private Builder(Metadata<K, V> metadata, K key, V value) {
|
| this.metadata = metadata;
|
| - this.data = data;
|
| - this.dataBuilder = null;
|
| + this.key = key;
|
| + this.value = value;
|
| }
|
| -
|
| +
|
| public K getKey() {
|
| - return dataBuilder == null ? data.getKey() : dataBuilder.getKey();
|
| + return key;
|
| }
|
| -
|
| +
|
| public V getValue() {
|
| - return dataBuilder == null ? data.getValue() : dataBuilder.getValue();
|
| - }
|
| -
|
| - private void ensureMutable() {
|
| - if (dataBuilder == null) {
|
| - dataBuilder = data.toBuilder();
|
| - }
|
| + return value;
|
| }
|
| -
|
| +
|
| public Builder<K, V> setKey(K key) {
|
| - ensureMutable();
|
| - dataBuilder.setKey(key);
|
| + this.key = key;
|
| return this;
|
| }
|
| -
|
| +
|
| public Builder<K, V> clearKey() {
|
| - ensureMutable();
|
| - dataBuilder.clearKey();
|
| + this.key = metadata.defaultKey;
|
| return this;
|
| }
|
| -
|
| +
|
| public Builder<K, V> setValue(V value) {
|
| - ensureMutable();
|
| - dataBuilder.setValue(value);
|
| + this.value = value;
|
| return this;
|
| }
|
| -
|
| +
|
| public Builder<K, V> clearValue() {
|
| - ensureMutable();
|
| - dataBuilder.clearValue();
|
| + this.value = metadata.defaultValue;
|
| return this;
|
| }
|
|
|
| @@ -281,29 +296,24 @@ public final class MapEntry<K, V> extends AbstractMessage {
|
|
|
| @Override
|
| public MapEntry<K, V> buildPartial() {
|
| - if (dataBuilder != null) {
|
| - data = dataBuilder.buildPartial();
|
| - dataBuilder = null;
|
| - }
|
| - return new MapEntry<K, V>(metadata, data);
|
| + return new MapEntry<K, V>(metadata, key, value);
|
| }
|
|
|
| @Override
|
| public Descriptor getDescriptorForType() {
|
| return metadata.descriptor;
|
| }
|
| -
|
| +
|
| private void checkFieldDescriptor(FieldDescriptor field) {
|
| if (field.getContainingType() != metadata.descriptor) {
|
| throw new RuntimeException(
|
| "Wrong FieldDescriptor \"" + field.getFullName()
|
| - + "\" used in message \"" + metadata.descriptor.getFullName());
|
| + + "\" used in message \"" + metadata.descriptor.getFullName());
|
| }
|
| }
|
|
|
| @Override
|
| - public com.google.protobuf.Message.Builder newBuilderForField(
|
| - FieldDescriptor field) {
|
| + public Message.Builder newBuilderForField(FieldDescriptor field) {
|
| checkFieldDescriptor(field);;
|
| // This method should be called for message fields and in a MapEntry
|
| // message only the value field can possibly be a message field.
|
| @@ -312,7 +322,7 @@ public final class MapEntry<K, V> extends AbstractMessage {
|
| throw new RuntimeException(
|
| "\"" + field.getFullName() + "\" is not a message value field.");
|
| }
|
| - return ((Message) data.getValue()).newBuilderForType();
|
| + return ((Message) value).newBuilderForType();
|
| }
|
|
|
| @SuppressWarnings("unchecked")
|
| @@ -324,6 +334,15 @@ public final class MapEntry<K, V> extends AbstractMessage {
|
| } else {
|
| if (field.getType() == FieldDescriptor.Type.ENUM) {
|
| value = ((EnumValueDescriptor) value).getNumber();
|
| + } else if (field.getType() == FieldDescriptor.Type.MESSAGE) {
|
| + if (value != null && !metadata.defaultValue.getClass().isInstance(value)) {
|
| + // The value is not the exact right message type. However, if it
|
| + // is an alternative implementation of the same type -- e.g. a
|
| + // DynamicMessage -- we should accept it. In this case we can make
|
| + // a copy of the message.
|
| + value =
|
| + ((Message) metadata.defaultValue).toBuilder().mergeFrom((Message) value).build();
|
| + }
|
| }
|
| setValue((V) value);
|
| }
|
| @@ -362,22 +381,17 @@ public final class MapEntry<K, V> extends AbstractMessage {
|
|
|
| @Override
|
| public MapEntry<K, V> getDefaultInstanceForType() {
|
| - return metadata.defaultInstance;
|
| + return new MapEntry<K, V>(metadata, metadata.defaultKey, metadata.defaultValue);
|
| }
|
|
|
| @Override
|
| public boolean isInitialized() {
|
| - if (dataBuilder != null) {
|
| - return dataBuilder.isInitialized();
|
| - } else {
|
| - return data.isInitialized();
|
| - }
|
| + return MapEntry.isInitialized(metadata, value);
|
| }
|
|
|
| @Override
|
| public Map<FieldDescriptor, Object> getAllFields() {
|
| - final TreeMap<FieldDescriptor, Object> result =
|
| - new TreeMap<FieldDescriptor, Object>();
|
| + final TreeMap<FieldDescriptor, Object> result = new TreeMap<FieldDescriptor, Object>();
|
| for (final FieldDescriptor field : metadata.descriptor.getFields()) {
|
| if (hasField(field)) {
|
| result.put(field, getField(field));
|
| @@ -398,8 +412,7 @@ public final class MapEntry<K, V> extends AbstractMessage {
|
| Object result = field.getNumber() == 1 ? getKey() : getValue();
|
| // Convert enums to EnumValueDescriptor.
|
| if (field.getType() == FieldDescriptor.Type.ENUM) {
|
| - result = field.getEnumType().findValueByNumberCreatingIfUnknown(
|
| - (java.lang.Integer) result);
|
| + result = field.getEnumType().findValueByNumberCreatingIfUnknown((Integer) result);
|
| }
|
| return result;
|
| }
|
| @@ -409,13 +422,13 @@ public final class MapEntry<K, V> extends AbstractMessage {
|
| throw new RuntimeException(
|
| "There is no repeated field in a map entry message.");
|
| }
|
| -
|
| +
|
| @Override
|
| public Object getRepeatedField(FieldDescriptor field, int index) {
|
| throw new RuntimeException(
|
| "There is no repeated field in a map entry message.");
|
| }
|
| -
|
| +
|
| @Override
|
| public UnknownFieldSet getUnknownFields() {
|
| return UnknownFieldSet.getDefaultInstance();
|
| @@ -423,11 +436,14 @@ public final class MapEntry<K, V> extends AbstractMessage {
|
|
|
| @Override
|
| public Builder<K, V> clone() {
|
| - if (dataBuilder == null) {
|
| - return new Builder<K, V>(metadata, data);
|
| - } else {
|
| - return new Builder<K, V>(metadata, dataBuilder.build());
|
| - }
|
| + return new Builder(metadata, key, value);
|
| }
|
| }
|
| +
|
| + private static <V> boolean isInitialized(Metadata metadata, V value) {
|
| + if (metadata.valueType.getJavaType() == WireFormat.JavaType.MESSAGE) {
|
| + return ((MessageLite) value).isInitialized();
|
| + }
|
| + return true;
|
| + }
|
| }
|
|
|