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