ExtendableMessageNano.java revision 382ddccb550e1c822ef26a0e65988998f7446624
1// Protocol Buffers - Google's data interchange format 2// Copyright 2013 Google Inc. All rights reserved. 3// http://code.google.com/p/protobuf/ 4// 5// Redistribution and use in source and binary forms, with or without 6// modification, are permitted provided that the following conditions are 7// met: 8// 9// * Redistributions of source code must retain the above copyright 10// notice, this list of conditions and the following disclaimer. 11// * Redistributions in binary form must reproduce the above 12// copyright notice, this list of conditions and the following disclaimer 13// in the documentation and/or other materials provided with the 14// distribution. 15// * Neither the name of Google Inc. nor the names of its 16// contributors may be used to endorse or promote products derived from 17// this software without specific prior written permission. 18// 19// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 31package com.google.protobuf.nano; 32 33import java.io.IOException; 34import java.util.ArrayList; 35import java.util.List; 36 37/** 38 * Base class of those Protocol Buffer messages that need to store unknown fields, 39 * such as extensions. 40 */ 41public abstract class ExtendableMessageNano<M extends ExtendableMessageNano<M>> 42 extends MessageNano { 43 /** 44 * A container for fields unknown to the message, including extensions. Extension fields can 45 * can be accessed through the {@link #getExtension} and {@link #setExtension} methods. 46 */ 47 protected List<UnknownFieldData> unknownFieldData; 48 49 @Override 50 public int getSerializedSize() { 51 int size = 0; 52 int unknownFieldCount = unknownFieldData == null ? 0 : unknownFieldData.size(); 53 for (int i = 0; i < unknownFieldCount; i++) { 54 UnknownFieldData unknownField = unknownFieldData.get(i); 55 size += CodedOutputByteBufferNano.computeRawVarint32Size(unknownField.tag); 56 size += unknownField.bytes.length; 57 } 58 cachedSize = size; 59 return size; 60 } 61 62 @Override 63 public void writeTo(CodedOutputByteBufferNano output) throws IOException { 64 int unknownFieldCount = unknownFieldData == null ? 0 : unknownFieldData.size(); 65 for (int i = 0; i < unknownFieldCount; i++) { 66 UnknownFieldData unknownField = unknownFieldData.get(i); 67 output.writeRawVarint32(unknownField.tag); 68 output.writeRawBytes(unknownField.bytes); 69 } 70 } 71 72 /** 73 * Gets the value stored in the specified extension of this message. 74 */ 75 public final <T> T getExtension(Extension<M, T> extension) { 76 return extension.getValueFrom(unknownFieldData); 77 } 78 79 /** 80 * Sets the value of the specified extension of this message. 81 */ 82 public final <T> M setExtension(Extension<M, T> extension, T value) { 83 unknownFieldData = extension.setValueTo(value, unknownFieldData); 84 85 @SuppressWarnings("unchecked") // Generated code should guarantee type safety 86 M typedThis = (M) this; 87 return typedThis; 88 } 89 90 /** 91 * Stores the binary data of an unknown field. 92 * 93 * <p>Generated messages will call this for unknown fields if the store_unknown_fields 94 * option is on. 95 * 96 * <p>Note that the tag might be a end-group tag (rather than the start of an unknown field) in 97 * which case we do not want to add an unknown field entry. 98 * 99 * @param input the input buffer. 100 * @param tag the tag of the field. 101 102 * @return {@literal true} unless the tag is an end-group tag. 103 */ 104 protected final boolean storeUnknownField(CodedInputByteBufferNano input, int tag) 105 throws IOException { 106 int startPos = input.getPosition(); 107 if (!input.skipField(tag)) { 108 return false; // This wasn't an unknown field, it's an end-group tag. 109 } 110 if (unknownFieldData == null) { 111 unknownFieldData = new ArrayList<UnknownFieldData>(); 112 } 113 int endPos = input.getPosition(); 114 byte[] bytes = input.getData(startPos, endPos - startPos); 115 unknownFieldData.add(new UnknownFieldData(tag, bytes)); 116 return true; 117 } 118} 119