• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 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;
32 
33 import java.io.FilterInputStream;
34 import java.io.IOException;
35 import java.io.InputStream;
36 import java.io.OutputStream;
37 import java.util.Collection;
38 
39 /**
40  * A partial implementation of the {@link MessageLite} interface which
41  * implements as many methods of that interface as possible in terms of other
42  * methods.
43  *
44  * @author kenton@google.com Kenton Varda
45  */
46 public abstract class AbstractMessageLite<
47     MessageType extends AbstractMessageLite<MessageType, BuilderType>,
48     BuilderType extends AbstractMessageLite.Builder<MessageType, BuilderType>>
49         implements MessageLite {
50   protected int memoizedHashCode = 0;
51 
52   @Override
toByteString()53   public ByteString toByteString() {
54     try {
55       final ByteString.CodedBuilder out =
56         ByteString.newCodedBuilder(getSerializedSize());
57       writeTo(out.getCodedOutput());
58       return out.build();
59     } catch (IOException e) {
60       throw new RuntimeException(
61         "Serializing to a ByteString threw an IOException (should " +
62         "never happen).", e);
63     }
64   }
65 
66   @Override
toByteArray()67   public byte[] toByteArray() {
68     try {
69       final byte[] result = new byte[getSerializedSize()];
70       final CodedOutputStream output = CodedOutputStream.newInstance(result);
71       writeTo(output);
72       output.checkNoSpaceLeft();
73       return result;
74     } catch (IOException e) {
75       throw new RuntimeException(
76         "Serializing to a byte array threw an IOException " +
77         "(should never happen).", e);
78     }
79   }
80 
81   @Override
writeTo(final OutputStream output)82   public void writeTo(final OutputStream output) throws IOException {
83     final int bufferSize =
84         CodedOutputStream.computePreferredBufferSize(getSerializedSize());
85     final CodedOutputStream codedOutput =
86         CodedOutputStream.newInstance(output, bufferSize);
87     writeTo(codedOutput);
88     codedOutput.flush();
89   }
90 
91   @Override
writeDelimitedTo(final OutputStream output)92   public void writeDelimitedTo(final OutputStream output) throws IOException {
93     final int serialized = getSerializedSize();
94     final int bufferSize = CodedOutputStream.computePreferredBufferSize(
95         CodedOutputStream.computeRawVarint32Size(serialized) + serialized);
96     final CodedOutputStream codedOutput =
97         CodedOutputStream.newInstance(output, bufferSize);
98     codedOutput.writeRawVarint32(serialized);
99     writeTo(codedOutput);
100     codedOutput.flush();
101   }
102 
103 
104   /**
105    * Package private helper method for AbstractParser to create
106    * UninitializedMessageException.
107    */
newUninitializedMessageException()108   UninitializedMessageException newUninitializedMessageException() {
109     return new UninitializedMessageException(this);
110   }
111 
checkByteStringIsUtf8(ByteString byteString)112   protected static void checkByteStringIsUtf8(ByteString byteString)
113       throws IllegalArgumentException {
114     if (!byteString.isValidUtf8()) {
115       throw new IllegalArgumentException("Byte string is not UTF-8.");
116     }
117   }
118 
addAll(final Iterable<T> values, final Collection<? super T> list)119   protected static <T> void addAll(final Iterable<T> values,
120       final Collection<? super T> list) {
121     Builder.addAll(values, list);
122   }
123 
124   /**
125    * A partial implementation of the {@link Message.Builder} interface which
126    * implements as many methods of that interface as possible in terms of
127    * other methods.
128    */
129   @SuppressWarnings("unchecked")
130   public abstract static class Builder<
131       MessageType extends AbstractMessageLite<MessageType, BuilderType>,
132       BuilderType extends Builder<MessageType, BuilderType>>
133       implements MessageLite.Builder {
134     // The compiler produces an error if this is not declared explicitly.
135     @Override
clone()136     public abstract BuilderType clone();
137 
138     @Override
mergeFrom(final CodedInputStream input)139     public BuilderType mergeFrom(final CodedInputStream input) throws IOException {
140       return mergeFrom(input, ExtensionRegistryLite.getEmptyRegistry());
141     }
142 
143     // Re-defined here for return type covariance.
144     @Override
mergeFrom( final CodedInputStream input, final ExtensionRegistryLite extensionRegistry)145     public abstract BuilderType mergeFrom(
146         final CodedInputStream input, final ExtensionRegistryLite extensionRegistry)
147         throws IOException;
148 
149     @Override
mergeFrom(final ByteString data)150     public BuilderType mergeFrom(final ByteString data) throws InvalidProtocolBufferException {
151       try {
152         final CodedInputStream input = data.newCodedInput();
153         mergeFrom(input);
154         input.checkLastTagWas(0);
155         return (BuilderType) this;
156       } catch (InvalidProtocolBufferException e) {
157         throw e;
158       } catch (IOException e) {
159         throw new RuntimeException(
160           "Reading from a ByteString threw an IOException (should " +
161           "never happen).", e);
162       }
163     }
164 
165     @Override
mergeFrom( final ByteString data, final ExtensionRegistryLite extensionRegistry)166     public BuilderType mergeFrom(
167         final ByteString data, final ExtensionRegistryLite extensionRegistry)
168         throws InvalidProtocolBufferException {
169       try {
170         final CodedInputStream input = data.newCodedInput();
171         mergeFrom(input, extensionRegistry);
172         input.checkLastTagWas(0);
173         return (BuilderType) this;
174       } catch (InvalidProtocolBufferException e) {
175         throw e;
176       } catch (IOException e) {
177         throw new RuntimeException(
178           "Reading from a ByteString threw an IOException (should " +
179           "never happen).", e);
180       }
181     }
182 
183     @Override
mergeFrom(final byte[] data)184     public BuilderType mergeFrom(final byte[] data) throws InvalidProtocolBufferException {
185       return mergeFrom(data, 0, data.length);
186     }
187 
188     @Override
mergeFrom(final byte[] data, final int off, final int len)189     public BuilderType mergeFrom(final byte[] data, final int off, final int len)
190         throws InvalidProtocolBufferException {
191       try {
192         final CodedInputStream input =
193             CodedInputStream.newInstance(data, off, len);
194         mergeFrom(input);
195         input.checkLastTagWas(0);
196         return (BuilderType) this;
197       } catch (InvalidProtocolBufferException e) {
198         throw e;
199       } catch (IOException e) {
200         throw new RuntimeException(
201           "Reading from a byte array threw an IOException (should " +
202           "never happen).", e);
203       }
204     }
205 
206     @Override
mergeFrom(final byte[] data, final ExtensionRegistryLite extensionRegistry)207     public BuilderType mergeFrom(final byte[] data, final ExtensionRegistryLite extensionRegistry)
208         throws InvalidProtocolBufferException {
209       return mergeFrom(data, 0, data.length, extensionRegistry);
210     }
211 
212     @Override
mergeFrom( final byte[] data, final int off, final int len, final ExtensionRegistryLite extensionRegistry)213     public BuilderType mergeFrom(
214         final byte[] data,
215         final int off,
216         final int len,
217         final ExtensionRegistryLite extensionRegistry)
218         throws InvalidProtocolBufferException {
219       try {
220         final CodedInputStream input =
221             CodedInputStream.newInstance(data, off, len);
222         mergeFrom(input, extensionRegistry);
223         input.checkLastTagWas(0);
224         return (BuilderType) this;
225       } catch (InvalidProtocolBufferException e) {
226         throw e;
227       } catch (IOException e) {
228         throw new RuntimeException(
229           "Reading from a byte array threw an IOException (should " +
230           "never happen).", e);
231       }
232     }
233 
234     @Override
mergeFrom(final InputStream input)235     public BuilderType mergeFrom(final InputStream input) throws IOException {
236       final CodedInputStream codedInput = CodedInputStream.newInstance(input);
237       mergeFrom(codedInput);
238       codedInput.checkLastTagWas(0);
239       return (BuilderType) this;
240     }
241 
242     @Override
mergeFrom( final InputStream input, final ExtensionRegistryLite extensionRegistry)243     public BuilderType mergeFrom(
244         final InputStream input, final ExtensionRegistryLite extensionRegistry) throws IOException {
245       final CodedInputStream codedInput = CodedInputStream.newInstance(input);
246       mergeFrom(codedInput, extensionRegistry);
247       codedInput.checkLastTagWas(0);
248       return (BuilderType) this;
249     }
250 
251     /**
252      * An InputStream implementations which reads from some other InputStream
253      * but is limited to a particular number of bytes.  Used by
254      * mergeDelimitedFrom().  This is intentionally package-private so that
255      * UnknownFieldSet can share it.
256      */
257     static final class LimitedInputStream extends FilterInputStream {
258       private int limit;
259 
LimitedInputStream(InputStream in, int limit)260       LimitedInputStream(InputStream in, int limit) {
261         super(in);
262         this.limit = limit;
263       }
264 
265       @Override
available()266       public int available() throws IOException {
267         return Math.min(super.available(), limit);
268       }
269 
270       @Override
read()271       public int read() throws IOException {
272         if (limit <= 0) {
273           return -1;
274         }
275         final int result = super.read();
276         if (result >= 0) {
277           --limit;
278         }
279         return result;
280       }
281 
282       @Override
read(final byte[] b, final int off, int len)283       public int read(final byte[] b, final int off, int len)
284                       throws IOException {
285         if (limit <= 0) {
286           return -1;
287         }
288         len = Math.min(len, limit);
289         final int result = super.read(b, off, len);
290         if (result >= 0) {
291           limit -= result;
292         }
293         return result;
294       }
295 
296       @Override
skip(final long n)297       public long skip(final long n) throws IOException {
298         final long result = super.skip(Math.min(n, limit));
299         if (result >= 0) {
300           limit -= result;
301         }
302         return result;
303       }
304     }
305 
306     @Override
mergeDelimitedFrom( final InputStream input, final ExtensionRegistryLite extensionRegistry)307     public boolean mergeDelimitedFrom(
308         final InputStream input, final ExtensionRegistryLite extensionRegistry) throws IOException {
309       final int firstByte = input.read();
310       if (firstByte == -1) {
311         return false;
312       }
313       final int size = CodedInputStream.readRawVarint32(firstByte, input);
314       final InputStream limitedInput = new LimitedInputStream(input, size);
315       mergeFrom(limitedInput, extensionRegistry);
316       return true;
317     }
318 
319     @Override
mergeDelimitedFrom(final InputStream input)320     public boolean mergeDelimitedFrom(final InputStream input) throws IOException {
321       return mergeDelimitedFrom(input,
322           ExtensionRegistryLite.getEmptyRegistry());
323     }
324 
325     @Override
326     @SuppressWarnings("unchecked") // isInstance takes care of this
mergeFrom(final MessageLite other)327     public BuilderType mergeFrom(final MessageLite other) {
328       if (!getDefaultInstanceForType().getClass().isInstance(other)) {
329         throw new IllegalArgumentException(
330             "mergeFrom(MessageLite) can only merge messages of the same type.");
331       }
332 
333       return internalMergeFrom((MessageType) other);
334     }
335 
internalMergeFrom(MessageType message)336     protected abstract BuilderType internalMergeFrom(MessageType message);
337 
338     /**
339      * Construct an UninitializedMessageException reporting missing fields in
340      * the given message.
341      */
342     protected static UninitializedMessageException
newUninitializedMessageException(MessageLite message)343         newUninitializedMessageException(MessageLite message) {
344       return new UninitializedMessageException(message);
345     }
346 
347     /**
348      * Adds the {@code values} to the {@code list}.  This is a helper method
349      * used by generated code.  Users should ignore it.
350      *
351      * @throws NullPointerException if {@code values} or any of the elements of
352      * {@code values} is null. When that happens, some elements of
353      * {@code values} may have already been added to the result {@code list}.
354      */
addAll(final Iterable<T> values, final Collection<? super T> list)355     protected static <T> void addAll(final Iterable<T> values,
356                                      final Collection<? super T> list) {
357       if (values == null) {
358         throw new NullPointerException();
359       }
360       if (values instanceof LazyStringList) {
361         // For StringOrByteStringLists, check the underlying elements to avoid
362         // forcing conversions of ByteStrings to Strings.
363         checkForNullValues(((LazyStringList) values).getUnderlyingElements());
364         list.addAll((Collection<T>) values);
365       } else if (values instanceof Collection) {
366         checkForNullValues(values);
367         list.addAll((Collection<T>) values);
368       } else {
369         for (final T value : values) {
370           if (value == null) {
371             throw new NullPointerException();
372           }
373           list.add(value);
374         }
375       }
376     }
377 
checkForNullValues(final Iterable<?> values)378     private static void checkForNullValues(final Iterable<?> values) {
379       for (final Object value : values) {
380         if (value == null) {
381           throw new NullPointerException();
382         }
383       }
384     }
385   }
386 }
387