MessageNano.java 7.2 KB

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