com.baidu.bjf.remoting.protobuf.MapEntryLite Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jprotobuf Show documentation
Show all versions of jprotobuf Show documentation
A useful utility library for java programmer using google protobuf.
/*
* Copyright (c) Baidu Inc. All rights reserved.
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.baidu.bjf.remoting.protobuf;
import java.io.IOException;
import java.util.AbstractMap;
import java.util.Map;
import com.baidu.bjf.remoting.protobuf.code.CodedConstant;
import com.google.protobuf.ByteString;
import com.google.protobuf.CodedInputStream;
import com.google.protobuf.CodedOutputStream;
import com.google.protobuf.ExtensionRegistryLite;
import com.google.protobuf.WireFormat;
/**
* 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.
*
* @param the key type
* @param the value type
*/
public class MapEntryLite {
/**
* The Class Metadata.
*
* @param the key type
* @param the value type
*/
static class Metadata {
/** The key type. */
public final WireFormat.FieldType keyType;
/** The default key. */
public final K defaultKey;
/** The value type. */
public final WireFormat.FieldType valueType;
/** The default value. */
public final V defaultValue;
/**
* Instantiates a new metadata.
*
* @param keyType the key type
* @param defaultKey the default key
* @param valueType the value type
* @param defaultValue the default value
*/
public Metadata(WireFormat.FieldType keyType, K defaultKey, WireFormat.FieldType valueType, V defaultValue) {
this.keyType = keyType;
this.defaultKey = defaultKey;
this.valueType = valueType;
this.defaultValue = defaultValue;
}
}
/** The Constant KEY_FIELD_NUMBER. */
private static final int KEY_FIELD_NUMBER = 1;
/** The Constant VALUE_FIELD_NUMBER. */
private static final int VALUE_FIELD_NUMBER = 2;
/** The metadata. */
private final Metadata metadata;
/** The key. */
private final K key;
/** The value. */
private final V value;
/**
* Creates a default MapEntryLite message instance.
*
* @param keyType the key type
* @param defaultKey the default key
* @param valueType the value type
* @param defaultValue the default value
*/
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.
*
* @param metadata the metadata
* @param key the key
* @param value the value
*/
private MapEntryLite(Metadata metadata, K key, V value) {
this.metadata = metadata;
this.key = key;
this.value = value;
}
/**
* Gets the key.
*
* @return the key
*/
public K getKey() {
return key;
}
/**
* Gets the value.
*
* @return the value
*/
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.
*
* @param the key type
* @param the value type
* @param keyType the key type
* @param defaultKey the default key
* @param valueType the value type
* @param defaultValue the default value
* @return the map entry lite
*/
public static MapEntryLite newDefaultInstance(WireFormat.FieldType keyType, K defaultKey,
WireFormat.FieldType valueType, V defaultValue) {
return new MapEntryLite(keyType, defaultKey, valueType, defaultValue);
}
/**
* Write to.
*
* @param the key type
* @param the value type
* @param output the output
* @param metadata the metadata
* @param key the key
* @param value the value
* @throws IOException Signals that an I/O exception has occurred.
*/
static void writeTo(CodedOutputStream output, Metadata metadata, K key, V value) throws IOException {
CodedConstant.writeElement(output, metadata.keyType, KEY_FIELD_NUMBER, key);
CodedConstant.writeElement(output, metadata.valueType, VALUE_FIELD_NUMBER, value);
}
/**
* Compute serialized size.
*
* @param the key type
* @param the value type
* @param metadata the metadata
* @param key the key
* @param value the value
* @return the int
*/
static int computeSerializedSize(Metadata metadata, K key, V value) {
return CodedConstant.computeElementSize(metadata.keyType, KEY_FIELD_NUMBER, key)
+ CodedConstant.computeElementSize(metadata.valueType, VALUE_FIELD_NUMBER, value);
}
/**
* Parses the field.
*
* @param the generic type
* @param input the input
* @param extensionRegistry the extension registry
* @param type the type
* @param value the value
* @return the t
* @throws IOException Signals that an I/O exception has occurred.
*/
@SuppressWarnings("unchecked")
static T parseField(CodedInputStream input, ExtensionRegistryLite extensionRegistry, WireFormat.FieldType type,
T value) throws IOException {
switch (type) {
case MESSAGE:
int length = input.readRawVarint32();
final int oldLimit = input.pushLimit(length);
Codec extends Object> codec = ProtobufProxy.create(value.getClass());
T ret = (T) codec.decode(input.readRawBytes(length));
input.popLimit(oldLimit);
return ret;
case ENUM:
return (T) (java.lang.Integer) input.readEnum();
case GROUP:
throw new RuntimeException("Groups are not allowed in maps.");
default:
return (T) CodedConstant.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.
*
* @param output the output
* @param fieldNumber the field number
* @param key the key
* @param value the value
* @throws IOException Signals that an I/O exception has occurred.
*/
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.
*
* @param fieldNumber the field number
* @param key the key
* @param value the value
* @return the int
*/
public int computeMessageSize(int fieldNumber, K key, V value) {
return CodedOutputStream.computeTagSize(fieldNumber)
+ CodedConstant.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.
*
* @param bytes the bytes
* @param extensionRegistry the extension registry
* @return the map. entry
* @throws IOException Signals that an I/O exception has occurred.
*/
public Map.Entry parseEntry(ByteString bytes, ExtensionRegistryLite extensionRegistry) throws IOException {
return parseEntry(bytes.newCodedInput(), metadata, extensionRegistry);
}
/**
* Parses the entry.
*
* @param the key type
* @param the value type
* @param input the input
* @param metadata the metadata
* @param extensionRegistry the extension registry
* @return the map. entry
* @throws IOException Signals that an I/O exception has occurred.
*/
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 == CodedConstant.makeTag(KEY_FIELD_NUMBER, metadata.keyType.getWireType())) {
key = parseField(input, extensionRegistry, metadata.keyType, key);
} else if (tag == CodedConstant.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 allocaton of a {@link MapEntryLite} by parsing
* directly into the provided {@link MapFieldLite}.
*
* @param map the map
* @param input the input
* @param extensionRegistry the extension registry
* @throws IOException Signals that an I/O exception has occurred.
*/
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 == CodedConstant.makeTag(KEY_FIELD_NUMBER, metadata.keyType.getWireType())) {
key = parseField(input, extensionRegistry, metadata.keyType, key);
} else if (tag == CodedConstant.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);
}
}