// Protocol Buffers - Google's data interchange format // Copyright 2008 Google Inc. All rights reserved. // https://developers.google.com/protocol-buffers/ // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package com.google.protobuf; import java.io.IOException; /** * 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 extends AbstractMessageLite, MapEntryLite.Builder> { private static class Metadata { public final MapEntryLite defaultInstance; public final WireFormat.FieldType keyType; public final WireFormat.FieldType valueType; public final Parser> parser; public Metadata( MapEntryLite defaultInstance, WireFormat.FieldType keyType, WireFormat.FieldType valueType) { this.defaultInstance = defaultInstance; this.keyType = keyType; this.valueType = valueType; final Metadata finalThis = this; this.parser = new AbstractParser>() { @Override public MapEntryLite parsePartialFrom( CodedInputStream input, ExtensionRegistryLite extensionRegistry) throws InvalidProtocolBufferException { return new MapEntryLite(finalThis, input, extensionRegistry); } }; } } 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(this, keyType, valueType); 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); } @Override public void writeTo(CodedOutputStream output) throws IOException { writeField(KEY_FIELD_NUMBER, metadata.keyType, key, output); writeField(VALUE_FIELD_NUMBER, metadata.valueType, value, output); } private void writeField( int number, WireFormat.FieldType type, Object value, CodedOutputStream output) throws IOException { output.writeTag(number, type.getWireType()); FieldSet.writeElementNoTag(output, type, value); } private volatile int cachedSerializedSize = -1; @Override public int getSerializedSize() { if (cachedSerializedSize != -1) { return cachedSerializedSize; } int size = 0; size += getFieldSize(KEY_FIELD_NUMBER, metadata.keyType, key); size += getFieldSize(VALUE_FIELD_NUMBER, metadata.valueType, value); cachedSerializedSize = size; return size; } private int getFieldSize( int number, WireFormat.FieldType type, Object value) { return CodedOutputStream.computeTagSize(number) + FieldSet.computeElementSizeNoTag(type, value); } /** Parsing constructor. */ private MapEntryLite( Metadata metadata, CodedInputStream input, ExtensionRegistryLite extensionRegistry) throws InvalidProtocolBufferException { try { K key = metadata.defaultInstance.key; V value = metadata.defaultInstance.value; while (true) { int tag = input.readTag(); if (tag == 0) { break; } if (tag == WireFormat.makeTag( KEY_FIELD_NUMBER, metadata.keyType.getWireType())) { key = mergeField( input, extensionRegistry, metadata.keyType, key); } else if (tag == WireFormat.makeTag( VALUE_FIELD_NUMBER, metadata.valueType.getWireType())) { value = mergeField( input, extensionRegistry, metadata.valueType, value); } else { if (!input.skipField(tag)) { break; } } } this.metadata = metadata; this.key = key; this.value = value; } catch (InvalidProtocolBufferException e) { throw e.setUnfinishedMessage(this); } catch (IOException e) { throw new InvalidProtocolBufferException(e.getMessage()) .setUnfinishedMessage(this); } } @SuppressWarnings("unchecked") private T mergeField( 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); } } @Override public Parser> getParserForType() { return metadata.parser; } @Override public Builder newBuilderForType() { return new Builder(metadata); } @Override public Builder toBuilder() { return new Builder(metadata, key, value); } @Override public MapEntryLite getDefaultInstanceForType() { return metadata.defaultInstance; } @Override public boolean isInitialized() { if (metadata.valueType.getJavaType() == WireFormat.JavaType.MESSAGE) { return ((MessageLite) value).isInitialized(); } return true; } /** * Builder used to create {@link MapEntryLite} messages. */ public static class Builder extends AbstractMessageLite.Builder, Builder> { private final Metadata metadata; private K key; private V value; private Builder(Metadata metadata) { this.metadata = metadata; this.key = metadata.defaultInstance.key; this.value = metadata.defaultInstance.value; } public K getKey() { return key; } public V getValue() { return value; } public Builder setKey(K key) { this.key = key; return this; } public Builder setValue(V value) { this.value = value; return this; } public Builder clearKey() { this.key = metadata.defaultInstance.key; return this; } public Builder clearValue() { this.value = metadata.defaultInstance.value; return this; } @Override public Builder clear() { this.key = metadata.defaultInstance.key; this.value = metadata.defaultInstance.value; return this; } @Override public MapEntryLite build() { MapEntryLite result = buildPartial(); if (!result.isInitialized()) { throw newUninitializedMessageException(result); } return result; } @Override public MapEntryLite buildPartial() { return new MapEntryLite(metadata, key, value); } @Override public MessageLite getDefaultInstanceForType() { return metadata.defaultInstance; } @Override public boolean isInitialized() { if (metadata.valueType.getJavaType() == WireFormat.JavaType.MESSAGE) { return ((MessageLite) value).isInitialized(); } return true; } private Builder(Metadata metadata, K key, V value) { this.metadata = metadata; this.key = key; this.value = value; } @Override public Builder clone() { return new Builder(metadata, key, value); } @Override public Builder mergeFrom( CodedInputStream input, ExtensionRegistryLite extensionRegistry) throws IOException { MapEntryLite entry = new MapEntryLite(metadata, input, extensionRegistry); this.key = entry.key; this.value = entry.value; return this; } @Override protected Builder internalMergeFrom(MapEntryLite message) { throw new UnsupportedOperationException(); } } }