com.google.protobuf.MapEntryLite Maven / Gradle / Ivy
Show all versions of protobuf-javalite Show documentation
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file or at
// https://developers.google.com/open-source/licenses/bsd
package com.google.protobuf;
import java.io.IOException;
import java.util.AbstractMap;
import java.util.Map;
/**
* Implements the lite version of map entry messages.
*
* This class serves as an utility class to help do serialization/parsing of map entries. It's
* used in generated code and also in the full version MapEntry message.
*
*
Protobuf internal. Users shouldn't use.
*/
public class MapEntryLite {
static class Metadata {
public final WireFormat.FieldType keyType;
public final K defaultKey;
public final WireFormat.FieldType valueType;
public final V defaultValue;
public Metadata(
WireFormat.FieldType keyType,
K defaultKey,
WireFormat.FieldType valueType,
V defaultValue) {
this.keyType = keyType;
this.defaultKey = defaultKey;
this.valueType = valueType;
this.defaultValue = defaultValue;
}
}
private static final int KEY_FIELD_NUMBER = 1;
private static final int VALUE_FIELD_NUMBER = 2;
private final Metadata metadata;
private final K key;
private final V value;
/** Creates a default MapEntryLite message instance. */
private MapEntryLite(
WireFormat.FieldType keyType, K defaultKey, WireFormat.FieldType valueType, V defaultValue) {
this.metadata = new Metadata(keyType, defaultKey, valueType, defaultValue);
this.key = defaultKey;
this.value = defaultValue;
}
/** Creates a new MapEntryLite message. */
private MapEntryLite(Metadata metadata, K key, V value) {
this.metadata = metadata;
this.key = key;
this.value = value;
}
public K getKey() {
return key;
}
public V getValue() {
return value;
}
/**
* Creates a default MapEntryLite message instance.
*
* This method is used by generated code to create the default instance for a map entry
* message. The created default instance should be used to create new map entry messages of the
* same type. For each map entry message, only one default instance should be created.
*/
public static MapEntryLite newDefaultInstance(
WireFormat.FieldType keyType, K defaultKey, WireFormat.FieldType valueType, V defaultValue) {
return new MapEntryLite(keyType, defaultKey, valueType, defaultValue);
}
static void writeTo(CodedOutputStream output, Metadata metadata, K key, V value)
throws IOException {
FieldSet.writeElement(output, metadata.keyType, KEY_FIELD_NUMBER, key);
FieldSet.writeElement(output, metadata.valueType, VALUE_FIELD_NUMBER, value);
}
static int computeSerializedSize(Metadata metadata, K key, V value) {
return FieldSet.computeElementSize(metadata.keyType, KEY_FIELD_NUMBER, key)
+ FieldSet.computeElementSize(metadata.valueType, VALUE_FIELD_NUMBER, value);
}
@SuppressWarnings("unchecked")
static T parseField(
CodedInputStream input,
ExtensionRegistryLite extensionRegistry,
WireFormat.FieldType type,
T value)
throws IOException {
switch (type) {
case MESSAGE:
MessageLite.Builder subBuilder = ((MessageLite) value).toBuilder();
input.readMessage(subBuilder, extensionRegistry);
return (T) subBuilder.buildPartial();
case ENUM:
return (T) (java.lang.Integer) input.readEnum();
case GROUP:
throw new RuntimeException("Groups are not allowed in maps.");
default:
return (T) FieldSet.readPrimitiveField(input, type, true);
}
}
/**
* Serializes the provided key and value as though they were wrapped by a {@link MapEntryLite} to
* the output stream. This helper method avoids allocation of a {@link MapEntryLite} built with a
* key and value and is called from generated code directly.
*/
public void serializeTo(CodedOutputStream output, int fieldNumber, K key, V value)
throws IOException {
output.writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
output.writeUInt32NoTag(computeSerializedSize(metadata, key, value));
writeTo(output, metadata, key, value);
}
/**
* Computes the message size for the provided key and value as though they were wrapped by a
* {@link MapEntryLite}. This helper method avoids allocation of a {@link MapEntryLite} built with
* a key and value and is called from generated code directly.
*/
public int computeMessageSize(int fieldNumber, K key, V value) {
return CodedOutputStream.computeTagSize(fieldNumber)
+ CodedOutputStream.computeLengthDelimitedFieldSize(
computeSerializedSize(metadata, key, value));
}
/**
* Parses an entry off of the input as a {@link Map.Entry}. This helper requires an allocation so
* using {@link #parseInto} is preferred if possible.
*/
public Map.Entry parseEntry(ByteString bytes, ExtensionRegistryLite extensionRegistry)
throws IOException {
return parseEntry(bytes.newCodedInput(), metadata, extensionRegistry);
}
static Map.Entry parseEntry(
CodedInputStream input, Metadata metadata, ExtensionRegistryLite extensionRegistry)
throws IOException {
K key = metadata.defaultKey;
V value = metadata.defaultValue;
while (true) {
int tag = input.readTag();
if (tag == 0) {
break;
}
if (tag == WireFormat.makeTag(KEY_FIELD_NUMBER, metadata.keyType.getWireType())) {
key = parseField(input, extensionRegistry, metadata.keyType, key);
} else if (tag == WireFormat.makeTag(VALUE_FIELD_NUMBER, metadata.valueType.getWireType())) {
value = parseField(input, extensionRegistry, metadata.valueType, value);
} else {
if (!input.skipField(tag)) {
break;
}
}
}
return new AbstractMap.SimpleImmutableEntry(key, value);
}
/**
* Parses an entry off of the input into the map. This helper avoids allocation of a {@link
* MapEntryLite} by parsing directly into the provided {@link MapFieldLite}.
*/
public void parseInto(
MapFieldLite map, CodedInputStream input, ExtensionRegistryLite extensionRegistry)
throws IOException {
int length = input.readRawVarint32();
final int oldLimit = input.pushLimit(length);
K key = metadata.defaultKey;
V value = metadata.defaultValue;
while (true) {
int tag = input.readTag();
if (tag == 0) {
break;
}
if (tag == WireFormat.makeTag(KEY_FIELD_NUMBER, metadata.keyType.getWireType())) {
key = parseField(input, extensionRegistry, metadata.keyType, key);
} else if (tag == WireFormat.makeTag(VALUE_FIELD_NUMBER, metadata.valueType.getWireType())) {
value = parseField(input, extensionRegistry, metadata.valueType, value);
} else {
if (!input.skipField(tag)) {
break;
}
}
}
input.checkLastTagWas(0);
input.popLimit(oldLimit);
map.put(key, value);
}
/** For experimental runtime internal use only. */
Metadata getMetadata() {
return metadata;
}
}