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 31 package com.google.protobuf.nano; 32 33 import java.io.IOException; 34 35 /** 36 * Abstract interface implemented by Protocol Message objects. 37 * 38 * @author wink@google.com Wink Saville 39 */ 40 public abstract class MessageNano { 41 protected volatile int cachedSize = -1; 42 43 /** 44 * Get the number of bytes required to encode this message. 45 * Returns the cached size or calls getSerializedSize which 46 * sets the cached size. This is used internally when serializing 47 * so the size is only computed once. If a member is modified 48 * then this could be stale call getSerializedSize if in doubt. 49 */ getCachedSize()50 public int getCachedSize() { 51 if (cachedSize < 0) { 52 // getSerializedSize sets cachedSize 53 getSerializedSize(); 54 } 55 return cachedSize; 56 } 57 58 /** 59 * Computes the number of bytes required to encode this message. 60 * The size is cached and the cached result can be retrieved 61 * using getCachedSize(). 62 */ getSerializedSize()63 public int getSerializedSize() { 64 int size = computeSerializedSize(); 65 cachedSize = size; 66 return size; 67 } 68 69 /** 70 * Computes the number of bytes required to encode this message. This does not update the 71 * cached size. 72 */ computeSerializedSize()73 protected int computeSerializedSize() { 74 // This is overridden if the generated message has serialized fields. 75 return 0; 76 } 77 78 /** 79 * Serializes the message and writes it to {@code output}. 80 * 81 * @param output the output to receive the serialized form. 82 * @throws IOException if an error occurred writing to {@code output}. 83 */ writeTo(CodedOutputByteBufferNano output)84 public void writeTo(CodedOutputByteBufferNano output) throws IOException { 85 // Does nothing by default. Overridden by subclasses which have data to write. 86 } 87 88 /** 89 * Parse {@code input} as a message of this type and merge it with the 90 * message being built. 91 */ mergeFrom(CodedInputByteBufferNano input)92 public abstract MessageNano mergeFrom(CodedInputByteBufferNano input) throws IOException; 93 94 /** 95 * Serialize to a byte array. 96 * @return byte array with the serialized data. 97 */ toByteArray(MessageNano msg)98 public static final byte[] toByteArray(MessageNano msg) { 99 final byte[] result = new byte[msg.getSerializedSize()]; 100 toByteArray(msg, result, 0, result.length); 101 return result; 102 } 103 104 /** 105 * Serialize to a byte array starting at offset through length. The 106 * method getSerializedSize must have been called prior to calling 107 * this method so the proper length is know. If an attempt to 108 * write more than length bytes OutOfSpaceException will be thrown 109 * and if length bytes are not written then IllegalStateException 110 * is thrown. 111 */ toByteArray(MessageNano msg, byte[] data, int offset, int length)112 public static final void toByteArray(MessageNano msg, byte[] data, int offset, int length) { 113 try { 114 final CodedOutputByteBufferNano output = 115 CodedOutputByteBufferNano.newInstance(data, offset, length); 116 msg.writeTo(output); 117 output.checkNoSpaceLeft(); 118 } catch (IOException e) { 119 throw new RuntimeException("Serializing to a byte array threw an IOException " 120 + "(should never happen).", e); 121 } 122 } 123 124 /** 125 * Parse {@code data} as a message of this type and merge it with the 126 * message being built. 127 */ mergeFrom(T msg, final byte[] data)128 public static final <T extends MessageNano> T mergeFrom(T msg, final byte[] data) 129 throws InvalidProtocolBufferNanoException { 130 return mergeFrom(msg, data, 0, data.length); 131 } 132 133 /** 134 * Parse {@code data} as a message of this type and merge it with the 135 * message being built. 136 */ mergeFrom(T msg, final byte[] data, final int off, final int len)137 public static final <T extends MessageNano> T mergeFrom(T msg, final byte[] data, 138 final int off, final int len) throws InvalidProtocolBufferNanoException { 139 try { 140 final CodedInputByteBufferNano input = 141 CodedInputByteBufferNano.newInstance(data, off, len); 142 msg.mergeFrom(input); 143 input.checkLastTagWas(0); 144 return msg; 145 } catch (InvalidProtocolBufferNanoException e) { 146 throw e; 147 } catch (IOException e) { 148 throw new RuntimeException("Reading from a byte array threw an IOException (should " 149 + "never happen)."); 150 } 151 } 152 153 /** 154 * Returns a string that is (mostly) compatible with ProtoBuffer's TextFormat. Note that groups 155 * (which are deprecated) are not serialized with the correct field name. 156 * 157 * <p>This is implemented using reflection, so it is not especially fast nor is it guaranteed 158 * to find all fields if you have method removal turned on for proguard. 159 */ 160 @Override toString()161 public String toString() { 162 return MessageNanoPrinter.print(this); 163 } 164 } 165