• 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 static com.google.protobuf.MessageSchema.getMutableUnknownFields;
34 
35 import com.google.protobuf.Internal.ProtobufList;
36 import java.io.IOException;
37 
38 /**
39  * Helper functions to decode protobuf wire format from a byte array.
40  *
41  * <p>Note that these functions don't do boundary check on the byte array but instead rely on Java
42  * VM to check it. That means parsing rountines utilizing these functions must catch
43  * IndexOutOfBoundsException and convert it to protobuf's InvalidProtocolBufferException when
44  * crossing protobuf public API boundaries.
45  */
46 final class ArrayDecoders {
47   /**
48    * A helper used to return multiple values in a Java function. Java doesn't natively support
49    * returning multiple values in a function. Creating a new Object to hold the return values will
50    * be too expensive. Instead, we pass a Registers instance to functions that want to return
51    * multiple values and let the function set the return value in this Registers instance instead.
52    *
53    * <p>TODO(xiaofeng): This could be merged into CodedInputStream or CodedInputStreamReader which
54    * is already being passed through all the parsing rountines.
55    */
56   static final class Registers {
57     public int int1;
58     public long long1;
59     public Object object1;
60     public final ExtensionRegistryLite extensionRegistry;
61 
Registers()62     Registers() {
63       this.extensionRegistry = ExtensionRegistryLite.getEmptyRegistry();
64     }
65 
Registers(ExtensionRegistryLite extensionRegistry)66     Registers(ExtensionRegistryLite extensionRegistry) {
67       if (extensionRegistry == null) {
68         throw new NullPointerException();
69       }
70       this.extensionRegistry = extensionRegistry;
71     }
72   }
73 
74   /**
75    * Decodes a varint. Returns the position after the varint. The decoded varint is stored in
76    * registers.int1.
77    */
decodeVarint32(byte[] data, int position, Registers registers)78   static int decodeVarint32(byte[] data, int position, Registers registers) {
79     int value = data[position++];
80     if (value >= 0) {
81       registers.int1 = value;
82       return position;
83     }
84     return decodeVarint32(value, data, position, registers);
85   }
86 
87   /** Like decodeVarint32 except that the first byte is already read. */
decodeVarint32(int firstByte, byte[] data, int position, Registers registers)88   static int decodeVarint32(int firstByte, byte[] data, int position, Registers registers) {
89     int value = firstByte & 0x7F;
90     final byte b2 = data[position++];
91     if (b2 >= 0) {
92       registers.int1 = value | ((int) b2 << 7);
93       return position;
94     }
95     value |= (b2 & 0x7F) << 7;
96 
97     final byte b3 = data[position++];
98     if (b3 >= 0) {
99       registers.int1 = value | ((int) b3 << 14);
100       return position;
101     }
102     value |= (b3 & 0x7F) << 14;
103 
104     final byte b4 = data[position++];
105     if (b4 >= 0) {
106       registers.int1 = value | ((int) b4 << 21);
107       return position;
108     }
109     value |= (b4 & 0x7F) << 21;
110 
111     final byte b5 = data[position++];
112     if (b5 >= 0) {
113       registers.int1 = value | ((int) b5 << 28);
114       return position;
115     }
116     value |= (b5 & 0x7F) << 28;
117 
118     while (data[position++] < 0) {}
119 
120     registers.int1 = value;
121     return position;
122   }
123 
124   /**
125    * Decodes a varint. Returns the position after the varint. The decoded varint is stored in
126    * registers.long1.
127    */
decodeVarint64(byte[] data, int position, Registers registers)128   static int decodeVarint64(byte[] data, int position, Registers registers) {
129     long value = data[position++];
130     if (value >= 0) {
131       registers.long1 = value;
132       return position;
133     } else {
134       return decodeVarint64(value, data, position, registers);
135     }
136   }
137 
138   /** Like decodeVarint64 except that the first byte is already read. */
decodeVarint64(long firstByte, byte[] data, int position, Registers registers)139   static int decodeVarint64(long firstByte, byte[] data, int position, Registers registers) {
140     long value = firstByte & 0x7F;
141     byte next = data[position++];
142     int shift = 7;
143     value |= (long) (next & 0x7F) << 7;
144     while (next < 0) {
145       next = data[position++];
146       shift += 7;
147       value |= (long) (next & 0x7F) << shift;
148     }
149     registers.long1 = value;
150     return position;
151   }
152 
153   /** Decodes and returns a fixed32 value. */
decodeFixed32(byte[] data, int position)154   static int decodeFixed32(byte[] data, int position) {
155     return (data[position] & 0xff)
156         | ((data[position + 1] & 0xff) << 8)
157         | ((data[position + 2] & 0xff) << 16)
158         | ((data[position + 3] & 0xff) << 24);
159   }
160 
161   /** Decodes and returns a fixed64 value. */
decodeFixed64(byte[] data, int position)162   static long decodeFixed64(byte[] data, int position) {
163     return (data[position] & 0xffL)
164         | ((data[position + 1] & 0xffL) << 8)
165         | ((data[position + 2] & 0xffL) << 16)
166         | ((data[position + 3] & 0xffL) << 24)
167         | ((data[position + 4] & 0xffL) << 32)
168         | ((data[position + 5] & 0xffL) << 40)
169         | ((data[position + 6] & 0xffL) << 48)
170         | ((data[position + 7] & 0xffL) << 56);
171   }
172 
173   /** Decodes and returns a double value. */
decodeDouble(byte[] data, int position)174   static double decodeDouble(byte[] data, int position) {
175     return Double.longBitsToDouble(decodeFixed64(data, position));
176   }
177 
178   /** Decodes and returns a float value. */
decodeFloat(byte[] data, int position)179   static float decodeFloat(byte[] data, int position) {
180     return Float.intBitsToFloat(decodeFixed32(data, position));
181   }
182 
183   /** Decodes a string value. */
decodeString(byte[] data, int position, Registers registers)184   static int decodeString(byte[] data, int position, Registers registers)
185       throws InvalidProtocolBufferException {
186     position = decodeVarint32(data, position, registers);
187     final int length = registers.int1;
188     if (length < 0) {
189       throw InvalidProtocolBufferException.negativeSize();
190     } else if (length == 0) {
191       registers.object1 = "";
192       return position;
193     } else {
194       registers.object1 = new String(data, position, length, Internal.UTF_8);
195       return position + length;
196     }
197   }
198 
199   /** Decodes a string value with utf8 check. */
decodeStringRequireUtf8(byte[] data, int position, Registers registers)200   static int decodeStringRequireUtf8(byte[] data, int position, Registers registers)
201       throws InvalidProtocolBufferException {
202     position = decodeVarint32(data, position, registers);
203     final int length = registers.int1;
204     if (length < 0) {
205       throw InvalidProtocolBufferException.negativeSize();
206     } else if (length == 0) {
207       registers.object1 = "";
208       return position;
209     } else {
210       registers.object1 = Utf8.decodeUtf8(data, position, length);
211       return position + length;
212     }
213   }
214 
215   /** Decodes a bytes value. */
decodeBytes(byte[] data, int position, Registers registers)216   static int decodeBytes(byte[] data, int position, Registers registers)
217       throws InvalidProtocolBufferException {
218     position = decodeVarint32(data, position, registers);
219     final int length = registers.int1;
220     if (length < 0) {
221       throw InvalidProtocolBufferException.negativeSize();
222     } else if (length > data.length - position) {
223       throw InvalidProtocolBufferException.truncatedMessage();
224     } else if (length == 0) {
225       registers.object1 = ByteString.EMPTY;
226       return position;
227     } else {
228       registers.object1 = ByteString.copyFrom(data, position, length);
229       return position + length;
230     }
231   }
232 
233   /** Decodes a message value. */
234   @SuppressWarnings({"unchecked", "rawtypes"})
decodeMessageField( Schema schema, byte[] data, int position, int limit, Registers registers)235   static int decodeMessageField(
236       Schema schema, byte[] data, int position, int limit, Registers registers) throws IOException {
237     int length = data[position++];
238     if (length < 0) {
239       position = decodeVarint32(length, data, position, registers);
240       length = registers.int1;
241     }
242     if (length < 0 || length > limit - position) {
243       throw InvalidProtocolBufferException.truncatedMessage();
244     }
245     Object result = schema.newInstance();
246     schema.mergeFrom(result, data, position, position + length, registers);
247     schema.makeImmutable(result);
248     registers.object1 = result;
249     return position + length;
250   }
251 
252   /** Decodes a group value. */
253   @SuppressWarnings({"unchecked", "rawtypes"})
decodeGroupField( Schema schema, byte[] data, int position, int limit, int endGroup, Registers registers)254   static int decodeGroupField(
255       Schema schema, byte[] data, int position, int limit, int endGroup, Registers registers)
256       throws IOException {
257     // A group field must has a MessageSchema (the only other subclass of Schema is MessageSetSchema
258     // and it can't be used in group fields).
259     final MessageSchema messageSchema = (MessageSchema) schema;
260     Object result = messageSchema.newInstance();
261     // It's OK to directly use parseProto2Message since proto3 doesn't have group.
262     final int endPosition =
263         messageSchema.parseProto2Message(result, data, position, limit, endGroup, registers);
264     messageSchema.makeImmutable(result);
265     registers.object1 = result;
266     return endPosition;
267   }
268 
269   /** Decodes a repeated 32-bit varint field. Returns the position after all read values. */
decodeVarint32List( int tag, byte[] data, int position, int limit, ProtobufList<?> list, Registers registers)270   static int decodeVarint32List(
271       int tag, byte[] data, int position, int limit, ProtobufList<?> list, Registers registers) {
272     final IntArrayList output = (IntArrayList) list;
273     position = decodeVarint32(data, position, registers);
274     output.addInt(registers.int1);
275     while (position < limit) {
276       int nextPosition = decodeVarint32(data, position, registers);
277       if (tag != registers.int1) {
278         break;
279       }
280       position = decodeVarint32(data, nextPosition, registers);
281       output.addInt(registers.int1);
282     }
283     return position;
284   }
285 
286   /** Decodes a repeated 64-bit varint field. Returns the position after all read values. */
decodeVarint64List( int tag, byte[] data, int position, int limit, ProtobufList<?> list, Registers registers)287   static int decodeVarint64List(
288       int tag, byte[] data, int position, int limit, ProtobufList<?> list, Registers registers) {
289     final LongArrayList output = (LongArrayList) list;
290     position = decodeVarint64(data, position, registers);
291     output.addLong(registers.long1);
292     while (position < limit) {
293       int nextPosition = decodeVarint32(data, position, registers);
294       if (tag != registers.int1) {
295         break;
296       }
297       position = decodeVarint64(data, nextPosition, registers);
298       output.addLong(registers.long1);
299     }
300     return position;
301   }
302 
303   /** Decodes a repeated fixed32 field. Returns the position after all read values. */
decodeFixed32List( int tag, byte[] data, int position, int limit, ProtobufList<?> list, Registers registers)304   static int decodeFixed32List(
305       int tag, byte[] data, int position, int limit, ProtobufList<?> list, Registers registers) {
306     final IntArrayList output = (IntArrayList) list;
307     output.addInt(decodeFixed32(data, position));
308     position += 4;
309     while (position < limit) {
310       int nextPosition = decodeVarint32(data, position, registers);
311       if (tag != registers.int1) {
312         break;
313       }
314       output.addInt(decodeFixed32(data, nextPosition));
315       position = nextPosition + 4;
316     }
317     return position;
318   }
319 
320   /** Decodes a repeated fixed64 field. Returns the position after all read values. */
decodeFixed64List( int tag, byte[] data, int position, int limit, ProtobufList<?> list, Registers registers)321   static int decodeFixed64List(
322       int tag, byte[] data, int position, int limit, ProtobufList<?> list, Registers registers) {
323     final LongArrayList output = (LongArrayList) list;
324     output.addLong(decodeFixed64(data, position));
325     position += 8;
326     while (position < limit) {
327       int nextPosition = decodeVarint32(data, position, registers);
328       if (tag != registers.int1) {
329         break;
330       }
331       output.addLong(decodeFixed64(data, nextPosition));
332       position = nextPosition + 8;
333     }
334     return position;
335   }
336 
337   /** Decodes a repeated float field. Returns the position after all read values. */
decodeFloatList( int tag, byte[] data, int position, int limit, ProtobufList<?> list, Registers registers)338   static int decodeFloatList(
339       int tag, byte[] data, int position, int limit, ProtobufList<?> list, Registers registers) {
340     final FloatArrayList output = (FloatArrayList) list;
341     output.addFloat(decodeFloat(data, position));
342     position += 4;
343     while (position < limit) {
344       int nextPosition = decodeVarint32(data, position, registers);
345       if (tag != registers.int1) {
346         break;
347       }
348       output.addFloat(decodeFloat(data, nextPosition));
349       position = nextPosition + 4;
350     }
351     return position;
352   }
353 
354   /** Decodes a repeated double field. Returns the position after all read values. */
decodeDoubleList( int tag, byte[] data, int position, int limit, ProtobufList<?> list, Registers registers)355   static int decodeDoubleList(
356       int tag, byte[] data, int position, int limit, ProtobufList<?> list, Registers registers) {
357     final DoubleArrayList output = (DoubleArrayList) list;
358     output.addDouble(decodeDouble(data, position));
359     position += 8;
360     while (position < limit) {
361       int nextPosition = decodeVarint32(data, position, registers);
362       if (tag != registers.int1) {
363         break;
364       }
365       output.addDouble(decodeDouble(data, nextPosition));
366       position = nextPosition + 8;
367     }
368     return position;
369   }
370 
371   /** Decodes a repeated boolean field. Returns the position after all read values. */
decodeBoolList( int tag, byte[] data, int position, int limit, ProtobufList<?> list, Registers registers)372   static int decodeBoolList(
373       int tag, byte[] data, int position, int limit, ProtobufList<?> list, Registers registers) {
374     final BooleanArrayList output = (BooleanArrayList) list;
375     position = decodeVarint64(data, position, registers);
376     output.addBoolean(registers.long1 != 0);
377     while (position < limit) {
378       int nextPosition = decodeVarint32(data, position, registers);
379       if (tag != registers.int1) {
380         break;
381       }
382       position = decodeVarint64(data, nextPosition, registers);
383       output.addBoolean(registers.long1 != 0);
384     }
385     return position;
386   }
387 
388   /** Decodes a repeated sint32 field. Returns the position after all read values. */
decodeSInt32List( int tag, byte[] data, int position, int limit, ProtobufList<?> list, Registers registers)389   static int decodeSInt32List(
390       int tag, byte[] data, int position, int limit, ProtobufList<?> list, Registers registers) {
391     final IntArrayList output = (IntArrayList) list;
392     position = decodeVarint32(data, position, registers);
393     output.addInt(CodedInputStream.decodeZigZag32(registers.int1));
394     while (position < limit) {
395       int nextPosition = decodeVarint32(data, position, registers);
396       if (tag != registers.int1) {
397         break;
398       }
399       position = decodeVarint32(data, nextPosition, registers);
400       output.addInt(CodedInputStream.decodeZigZag32(registers.int1));
401     }
402     return position;
403   }
404 
405   /** Decodes a repeated sint64 field. Returns the position after all read values. */
decodeSInt64List( int tag, byte[] data, int position, int limit, ProtobufList<?> list, Registers registers)406   static int decodeSInt64List(
407       int tag, byte[] data, int position, int limit, ProtobufList<?> list, Registers registers) {
408     final LongArrayList output = (LongArrayList) list;
409     position = decodeVarint64(data, position, registers);
410     output.addLong(CodedInputStream.decodeZigZag64(registers.long1));
411     while (position < limit) {
412       int nextPosition = decodeVarint32(data, position, registers);
413       if (tag != registers.int1) {
414         break;
415       }
416       position = decodeVarint64(data, nextPosition, registers);
417       output.addLong(CodedInputStream.decodeZigZag64(registers.long1));
418     }
419     return position;
420   }
421 
422   /** Decodes a packed 32-bit varint field. Returns the position after all read values. */
decodePackedVarint32List( byte[] data, int position, ProtobufList<?> list, Registers registers)423   static int decodePackedVarint32List(
424       byte[] data, int position, ProtobufList<?> list, Registers registers) throws IOException {
425     final IntArrayList output = (IntArrayList) list;
426     position = decodeVarint32(data, position, registers);
427     final int fieldLimit = position + registers.int1;
428     while (position < fieldLimit) {
429       position = decodeVarint32(data, position, registers);
430       output.addInt(registers.int1);
431     }
432     if (position != fieldLimit) {
433       throw InvalidProtocolBufferException.truncatedMessage();
434     }
435     return position;
436   }
437 
438   /** Decodes a packed 64-bit varint field. Returns the position after all read values. */
decodePackedVarint64List( byte[] data, int position, ProtobufList<?> list, Registers registers)439   static int decodePackedVarint64List(
440       byte[] data, int position, ProtobufList<?> list, Registers registers) throws IOException {
441     final LongArrayList output = (LongArrayList) list;
442     position = decodeVarint32(data, position, registers);
443     final int fieldLimit = position + registers.int1;
444     while (position < fieldLimit) {
445       position = decodeVarint64(data, position, registers);
446       output.addLong(registers.long1);
447     }
448     if (position != fieldLimit) {
449       throw InvalidProtocolBufferException.truncatedMessage();
450     }
451     return position;
452   }
453 
454   /** Decodes a packed fixed32 field. Returns the position after all read values. */
decodePackedFixed32List( byte[] data, int position, ProtobufList<?> list, Registers registers)455   static int decodePackedFixed32List(
456       byte[] data, int position, ProtobufList<?> list, Registers registers) throws IOException {
457     final IntArrayList output = (IntArrayList) list;
458     position = decodeVarint32(data, position, registers);
459     final int fieldLimit = position + registers.int1;
460     while (position < fieldLimit) {
461       output.addInt(decodeFixed32(data, position));
462       position += 4;
463     }
464     if (position != fieldLimit) {
465       throw InvalidProtocolBufferException.truncatedMessage();
466     }
467     return position;
468   }
469 
470   /** Decodes a packed fixed64 field. Returns the position after all read values. */
decodePackedFixed64List( byte[] data, int position, ProtobufList<?> list, Registers registers)471   static int decodePackedFixed64List(
472       byte[] data, int position, ProtobufList<?> list, Registers registers) throws IOException {
473     final LongArrayList output = (LongArrayList) list;
474     position = decodeVarint32(data, position, registers);
475     final int fieldLimit = position + registers.int1;
476     while (position < fieldLimit) {
477       output.addLong(decodeFixed64(data, position));
478       position += 8;
479     }
480     if (position != fieldLimit) {
481       throw InvalidProtocolBufferException.truncatedMessage();
482     }
483     return position;
484   }
485 
486   /** Decodes a packed float field. Returns the position after all read values. */
decodePackedFloatList( byte[] data, int position, ProtobufList<?> list, Registers registers)487   static int decodePackedFloatList(
488       byte[] data, int position, ProtobufList<?> list, Registers registers) throws IOException {
489     final FloatArrayList output = (FloatArrayList) list;
490     position = decodeVarint32(data, position, registers);
491     final int fieldLimit = position + registers.int1;
492     while (position < fieldLimit) {
493       output.addFloat(decodeFloat(data, position));
494       position += 4;
495     }
496     if (position != fieldLimit) {
497       throw InvalidProtocolBufferException.truncatedMessage();
498     }
499     return position;
500   }
501 
502   /** Decodes a packed double field. Returns the position after all read values. */
decodePackedDoubleList( byte[] data, int position, ProtobufList<?> list, Registers registers)503   static int decodePackedDoubleList(
504       byte[] data, int position, ProtobufList<?> list, Registers registers) throws IOException {
505     final DoubleArrayList output = (DoubleArrayList) list;
506     position = decodeVarint32(data, position, registers);
507     final int fieldLimit = position + registers.int1;
508     while (position < fieldLimit) {
509       output.addDouble(decodeDouble(data, position));
510       position += 8;
511     }
512     if (position != fieldLimit) {
513       throw InvalidProtocolBufferException.truncatedMessage();
514     }
515     return position;
516   }
517 
518   /** Decodes a packed boolean field. Returns the position after all read values. */
decodePackedBoolList( byte[] data, int position, ProtobufList<?> list, Registers registers)519   static int decodePackedBoolList(
520       byte[] data, int position, ProtobufList<?> list, Registers registers) throws IOException {
521     final BooleanArrayList output = (BooleanArrayList) list;
522     position = decodeVarint32(data, position, registers);
523     final int fieldLimit = position + registers.int1;
524     while (position < fieldLimit) {
525       position = decodeVarint64(data, position, registers);
526       output.addBoolean(registers.long1 != 0);
527     }
528     if (position != fieldLimit) {
529       throw InvalidProtocolBufferException.truncatedMessage();
530     }
531     return position;
532   }
533 
534   /** Decodes a packed sint32 field. Returns the position after all read values. */
decodePackedSInt32List( byte[] data, int position, ProtobufList<?> list, Registers registers)535   static int decodePackedSInt32List(
536       byte[] data, int position, ProtobufList<?> list, Registers registers) throws IOException {
537     final IntArrayList output = (IntArrayList) list;
538     position = decodeVarint32(data, position, registers);
539     final int fieldLimit = position + registers.int1;
540     while (position < fieldLimit) {
541       position = decodeVarint32(data, position, registers);
542       output.addInt(CodedInputStream.decodeZigZag32(registers.int1));
543     }
544     if (position != fieldLimit) {
545       throw InvalidProtocolBufferException.truncatedMessage();
546     }
547     return position;
548   }
549 
550   /** Decodes a packed sint64 field. Returns the position after all read values. */
551   @SuppressWarnings("unchecked")
decodePackedSInt64List( byte[] data, int position, ProtobufList<?> list, Registers registers)552   static int decodePackedSInt64List(
553       byte[] data, int position, ProtobufList<?> list, Registers registers) throws IOException {
554     final LongArrayList output = (LongArrayList) list;
555     position = decodeVarint32(data, position, registers);
556     final int fieldLimit = position + registers.int1;
557     while (position < fieldLimit) {
558       position = decodeVarint64(data, position, registers);
559       output.addLong(CodedInputStream.decodeZigZag64(registers.long1));
560     }
561     if (position != fieldLimit) {
562       throw InvalidProtocolBufferException.truncatedMessage();
563     }
564     return position;
565   }
566 
567   /** Decodes a repeated string field. Returns the position after all read values. */
568   @SuppressWarnings("unchecked")
decodeStringList( int tag, byte[] data, int position, int limit, ProtobufList<?> list, Registers registers)569   static int decodeStringList(
570       int tag, byte[] data, int position, int limit, ProtobufList<?> list, Registers registers)
571       throws InvalidProtocolBufferException {
572     final ProtobufList<String> output = (ProtobufList<String>) list;
573     position = decodeVarint32(data, position, registers);
574     final int length = registers.int1;
575     if (length < 0) {
576       throw InvalidProtocolBufferException.negativeSize();
577     } else if (length == 0) {
578       output.add("");
579     } else {
580       String value = new String(data, position, length, Internal.UTF_8);
581       output.add(value);
582       position += length;
583     }
584     while (position < limit) {
585       int nextPosition = decodeVarint32(data, position, registers);
586       if (tag != registers.int1) {
587         break;
588       }
589       position = decodeVarint32(data, nextPosition, registers);
590       final int nextLength = registers.int1;
591       if (nextLength < 0) {
592         throw InvalidProtocolBufferException.negativeSize();
593       } else if (nextLength == 0) {
594         output.add("");
595       } else {
596         String value = new String(data, position, nextLength, Internal.UTF_8);
597         output.add(value);
598         position += nextLength;
599       }
600     }
601     return position;
602   }
603 
604   /**
605    * Decodes a repeated string field with utf8 check. Returns the position after all read values.
606    */
607   @SuppressWarnings("unchecked")
decodeStringListRequireUtf8( int tag, byte[] data, int position, int limit, ProtobufList<?> list, Registers registers)608   static int decodeStringListRequireUtf8(
609       int tag, byte[] data, int position, int limit, ProtobufList<?> list, Registers registers)
610       throws InvalidProtocolBufferException {
611     final ProtobufList<String> output = (ProtobufList<String>) list;
612     position = decodeVarint32(data, position, registers);
613     final int length = registers.int1;
614     if (length < 0) {
615       throw InvalidProtocolBufferException.negativeSize();
616     } else if (length == 0) {
617       output.add("");
618     } else {
619       if (!Utf8.isValidUtf8(data, position, position + length)) {
620         throw InvalidProtocolBufferException.invalidUtf8();
621       }
622       String value = new String(data, position, length, Internal.UTF_8);
623       output.add(value);
624       position += length;
625     }
626     while (position < limit) {
627       int nextPosition = decodeVarint32(data, position, registers);
628       if (tag != registers.int1) {
629         break;
630       }
631       position = decodeVarint32(data, nextPosition, registers);
632       final int nextLength = registers.int1;
633       if (nextLength < 0) {
634         throw InvalidProtocolBufferException.negativeSize();
635       } else if (nextLength == 0) {
636         output.add("");
637       } else {
638         if (!Utf8.isValidUtf8(data, position, position + nextLength)) {
639           throw InvalidProtocolBufferException.invalidUtf8();
640         }
641         String value = new String(data, position, nextLength, Internal.UTF_8);
642         output.add(value);
643         position += nextLength;
644       }
645     }
646     return position;
647   }
648 
649   /** Decodes a repeated bytes field. Returns the position after all read values. */
650   @SuppressWarnings("unchecked")
decodeBytesList( int tag, byte[] data, int position, int limit, ProtobufList<?> list, Registers registers)651   static int decodeBytesList(
652       int tag, byte[] data, int position, int limit, ProtobufList<?> list, Registers registers)
653       throws InvalidProtocolBufferException {
654     final ProtobufList<ByteString> output = (ProtobufList<ByteString>) list;
655     position = decodeVarint32(data, position, registers);
656     final int length = registers.int1;
657     if (length < 0) {
658       throw InvalidProtocolBufferException.negativeSize();
659     } else if (length > data.length - position) {
660       throw InvalidProtocolBufferException.truncatedMessage();
661     } else if (length == 0) {
662       output.add(ByteString.EMPTY);
663     } else {
664       output.add(ByteString.copyFrom(data, position, length));
665       position += length;
666     }
667     while (position < limit) {
668       int nextPosition = decodeVarint32(data, position, registers);
669       if (tag != registers.int1) {
670         break;
671       }
672       position = decodeVarint32(data, nextPosition, registers);
673       final int nextLength = registers.int1;
674       if (nextLength < 0) {
675         throw InvalidProtocolBufferException.negativeSize();
676       } else if (nextLength > data.length - position) {
677         throw InvalidProtocolBufferException.truncatedMessage();
678       } else if (nextLength == 0) {
679         output.add(ByteString.EMPTY);
680       } else {
681         output.add(ByteString.copyFrom(data, position, nextLength));
682         position += nextLength;
683       }
684     }
685     return position;
686   }
687 
688   /**
689    * Decodes a repeated message field
690    *
691    * @return The position of after read all messages
692    */
693   @SuppressWarnings({"unchecked"})
decodeMessageList( Schema<?> schema, int tag, byte[] data, int position, int limit, ProtobufList<?> list, Registers registers)694   static int decodeMessageList(
695       Schema<?> schema,
696       int tag,
697       byte[] data,
698       int position,
699       int limit,
700       ProtobufList<?> list,
701       Registers registers)
702       throws IOException {
703     final ProtobufList<Object> output = (ProtobufList<Object>) list;
704     position = decodeMessageField(schema, data, position, limit, registers);
705     output.add(registers.object1);
706     while (position < limit) {
707       int nextPosition = decodeVarint32(data, position, registers);
708       if (tag != registers.int1) {
709         break;
710       }
711       position = decodeMessageField(schema, data, nextPosition, limit, registers);
712       output.add(registers.object1);
713     }
714     return position;
715   }
716 
717   /**
718    * Decodes a repeated group field
719    *
720    * @return The position of after read all groups
721    */
722   @SuppressWarnings({"unchecked", "rawtypes"})
decodeGroupList( Schema schema, int tag, byte[] data, int position, int limit, ProtobufList<?> list, Registers registers)723   static int decodeGroupList(
724       Schema schema,
725       int tag,
726       byte[] data,
727       int position,
728       int limit,
729       ProtobufList<?> list,
730       Registers registers)
731       throws IOException {
732     final ProtobufList<Object> output = (ProtobufList<Object>) list;
733     final int endgroup = (tag & ~0x7) | WireFormat.WIRETYPE_END_GROUP;
734     position = decodeGroupField(schema, data, position, limit, endgroup, registers);
735     output.add(registers.object1);
736     while (position < limit) {
737       int nextPosition = decodeVarint32(data, position, registers);
738       if (tag != registers.int1) {
739         break;
740       }
741       position = decodeGroupField(schema, data, nextPosition, limit, endgroup, registers);
742       output.add(registers.object1);
743     }
744     return position;
745   }
746 
decodeExtensionOrUnknownField( int tag, byte[] data, int position, int limit, Object message, MessageLite defaultInstance, UnknownFieldSchema<UnknownFieldSetLite, UnknownFieldSetLite> unknownFieldSchema, Registers registers)747   static int decodeExtensionOrUnknownField(
748       int tag, byte[] data, int position, int limit,
749       Object message,
750       MessageLite defaultInstance,
751       UnknownFieldSchema<UnknownFieldSetLite, UnknownFieldSetLite> unknownFieldSchema,
752       Registers registers)
753       throws IOException {
754     final int number = tag >>> 3;
755     GeneratedMessageLite.GeneratedExtension extension =
756         registers.extensionRegistry.findLiteExtensionByNumber(defaultInstance, number);
757     if (extension == null) {
758       return decodeUnknownField(
759           tag, data, position, limit, getMutableUnknownFields(message), registers);
760     } else  {
761       ((GeneratedMessageLite.ExtendableMessage<?, ?>) message).ensureExtensionsAreMutable();
762       return decodeExtension(
763           tag, data, position, limit, (GeneratedMessageLite.ExtendableMessage) message,
764           extension, unknownFieldSchema, registers);
765     }
766   }
767 
decodeExtension( int tag, byte[] data, int position, int limit, GeneratedMessageLite.ExtendableMessage<?, ?> message, GeneratedMessageLite.GeneratedExtension<?, ?> extension, UnknownFieldSchema<UnknownFieldSetLite, UnknownFieldSetLite> unknownFieldSchema, Registers registers)768   static int decodeExtension(
769       int tag,
770       byte[] data,
771       int position,
772       int limit,
773       GeneratedMessageLite.ExtendableMessage<?, ?> message,
774       GeneratedMessageLite.GeneratedExtension<?, ?> extension,
775       UnknownFieldSchema<UnknownFieldSetLite, UnknownFieldSetLite> unknownFieldSchema,
776       Registers registers)
777       throws IOException {
778     final FieldSet<GeneratedMessageLite.ExtensionDescriptor> extensions = message.extensions;
779     final int fieldNumber = tag >>> 3;
780     if (extension.descriptor.isRepeated() && extension.descriptor.isPacked()) {
781       switch (extension.getLiteType()) {
782         case DOUBLE:
783         {
784           DoubleArrayList list = new DoubleArrayList();
785           position = decodePackedDoubleList(data, position, list, registers);
786           extensions.setField(extension.descriptor, list);
787           break;
788         }
789         case FLOAT:
790         {
791           FloatArrayList list = new FloatArrayList();
792           position = decodePackedFloatList(data, position, list, registers);
793           extensions.setField(extension.descriptor, list);
794           break;
795         }
796         case INT64:
797         case UINT64:
798         {
799           LongArrayList list = new LongArrayList();
800           position = decodePackedVarint64List(data, position, list, registers);
801           extensions.setField(extension.descriptor, list);
802           break;
803         }
804         case INT32:
805         case UINT32:
806         {
807           IntArrayList list = new IntArrayList();
808           position = decodePackedVarint32List(data, position, list, registers);
809           extensions.setField(extension.descriptor, list);
810           break;
811         }
812         case FIXED64:
813         case SFIXED64:
814         {
815           LongArrayList list = new LongArrayList();
816           position = decodePackedFixed64List(data, position, list, registers);
817           extensions.setField(extension.descriptor, list);
818           break;
819         }
820         case FIXED32:
821         case SFIXED32:
822         {
823           IntArrayList list = new IntArrayList();
824           position = decodePackedFixed32List(data, position, list, registers);
825           extensions.setField(extension.descriptor, list);
826           break;
827         }
828         case BOOL:
829         {
830           BooleanArrayList list = new BooleanArrayList();
831           position = decodePackedBoolList(data, position, list, registers);
832           extensions.setField(extension.descriptor, list);
833           break;
834         }
835         case SINT32:
836         {
837           IntArrayList list = new IntArrayList();
838           position = decodePackedSInt32List(data, position, list, registers);
839           extensions.setField(extension.descriptor, list);
840           break;
841         }
842         case SINT64:
843         {
844           LongArrayList list = new LongArrayList();
845           position = decodePackedSInt64List(data, position, list, registers);
846           extensions.setField(extension.descriptor, list);
847           break;
848         }
849         case ENUM:
850         {
851           IntArrayList list = new IntArrayList();
852           position = decodePackedVarint32List(data, position, list, registers);
853           UnknownFieldSetLite unknownFields = message.unknownFields;
854           if (unknownFields == UnknownFieldSetLite.getDefaultInstance()) {
855             unknownFields = null;
856           }
857           unknownFields =
858               SchemaUtil.filterUnknownEnumList(
859                   fieldNumber,
860                   list,
861                   extension.descriptor.getEnumType(),
862                   unknownFields,
863                   unknownFieldSchema);
864           if (unknownFields != null) {
865             message.unknownFields = unknownFields;
866           }
867           extensions.setField(extension.descriptor, list);
868           break;
869         }
870         default:
871           throw new IllegalStateException(
872               "Type cannot be packed: " + extension.descriptor.getLiteType());
873       }
874     } else {
875       Object value = null;
876       // Enum is a special case becasue unknown enum values will be put into UnknownFieldSetLite.
877       if (extension.getLiteType() == WireFormat.FieldType.ENUM) {
878         position = decodeVarint32(data, position, registers);
879         Object enumValue = extension.descriptor.getEnumType().findValueByNumber(registers.int1);
880         if (enumValue == null) {
881           UnknownFieldSetLite unknownFields = ((GeneratedMessageLite) message).unknownFields;
882           if (unknownFields == UnknownFieldSetLite.getDefaultInstance()) {
883             unknownFields = UnknownFieldSetLite.newInstance();
884             ((GeneratedMessageLite) message).unknownFields = unknownFields;
885           }
886           SchemaUtil.storeUnknownEnum(
887               fieldNumber, registers.int1, unknownFields, unknownFieldSchema);
888           return position;
889         }
890         // Note, we store the integer value instead of the actual enum object in FieldSet.
891         // This is also different from full-runtime where we store EnumValueDescriptor.
892         value = registers.int1;
893       } else {
894         switch (extension.getLiteType()) {
895           case DOUBLE:
896             value = decodeDouble(data, position);
897             position += 8;
898             break;
899           case FLOAT:
900             value = decodeFloat(data, position);
901             position += 4;
902             break;
903           case INT64:
904           case UINT64:
905             position = decodeVarint64(data, position, registers);
906             value = registers.long1;
907             break;
908           case INT32:
909           case UINT32:
910             position = decodeVarint32(data, position, registers);
911             value = registers.int1;
912             break;
913           case FIXED64:
914           case SFIXED64:
915             value = decodeFixed64(data, position);
916             position += 8;
917             break;
918           case FIXED32:
919           case SFIXED32:
920             value = decodeFixed32(data, position);
921             position += 4;
922             break;
923           case BOOL:
924             position = decodeVarint64(data, position, registers);
925             value = (registers.long1 != 0);
926             break;
927           case BYTES:
928             position = decodeBytes(data, position, registers);
929             value = registers.object1;
930             break;
931           case SINT32:
932             position = decodeVarint32(data, position, registers);
933             value = CodedInputStream.decodeZigZag32(registers.int1);
934             break;
935           case SINT64:
936             position = decodeVarint64(data, position, registers);
937             value = CodedInputStream.decodeZigZag64(registers.long1);
938             break;
939           case STRING:
940             position = decodeString(data, position, registers);
941             value = registers.object1;
942             break;
943           case GROUP:
944             final int endTag = (fieldNumber << 3) | WireFormat.WIRETYPE_END_GROUP;
945             position = decodeGroupField(
946                 Protobuf.getInstance().schemaFor(extension.getMessageDefaultInstance().getClass()),
947                 data, position, limit, endTag, registers);
948             value = registers.object1;
949             break;
950 
951           case MESSAGE:
952             position = decodeMessageField(
953                 Protobuf.getInstance().schemaFor(extension.getMessageDefaultInstance().getClass()),
954                 data, position, limit, registers);
955             value = registers.object1;
956             break;
957 
958           case ENUM:
959             throw new IllegalStateException("Shouldn't reach here.");
960         }
961       }
962       if (extension.isRepeated()) {
963         extensions.addRepeatedField(extension.descriptor, value);
964       } else {
965         switch (extension.getLiteType()) {
966           case MESSAGE:
967           case GROUP:
968             Object oldValue = extensions.getField(extension.descriptor);
969             if (oldValue != null) {
970               value = Internal.mergeMessage(oldValue, value);
971             }
972             break;
973           default:
974             break;
975         }
976         extensions.setField(extension.descriptor, value);
977       }
978     }
979     return position;
980   }
981 
982   /** Decodes an unknown field. */
decodeUnknownField( int tag, byte[] data, int position, int limit, UnknownFieldSetLite unknownFields, Registers registers)983   static int decodeUnknownField(
984       int tag,
985       byte[] data,
986       int position,
987       int limit,
988       UnknownFieldSetLite unknownFields,
989       Registers registers)
990       throws InvalidProtocolBufferException {
991     if (WireFormat.getTagFieldNumber(tag) == 0) {
992       throw InvalidProtocolBufferException.invalidTag();
993     }
994     switch (WireFormat.getTagWireType(tag)) {
995       case WireFormat.WIRETYPE_VARINT:
996         position = decodeVarint64(data, position, registers);
997         unknownFields.storeField(tag, registers.long1);
998         return position;
999       case WireFormat.WIRETYPE_FIXED32:
1000         unknownFields.storeField(tag, decodeFixed32(data, position));
1001         return position + 4;
1002       case WireFormat.WIRETYPE_FIXED64:
1003         unknownFields.storeField(tag, decodeFixed64(data, position));
1004         return position + 8;
1005       case WireFormat.WIRETYPE_LENGTH_DELIMITED:
1006         position = decodeVarint32(data, position, registers);
1007         final int length = registers.int1;
1008         if (length < 0) {
1009           throw InvalidProtocolBufferException.negativeSize();
1010         } else if (length > data.length - position) {
1011           throw InvalidProtocolBufferException.truncatedMessage();
1012         } else if (length == 0) {
1013           unknownFields.storeField(tag, ByteString.EMPTY);
1014         } else {
1015           unknownFields.storeField(tag, ByteString.copyFrom(data, position, length));
1016         }
1017         return position + length;
1018       case WireFormat.WIRETYPE_START_GROUP:
1019         final UnknownFieldSetLite child = UnknownFieldSetLite.newInstance();
1020         final int endGroup = (tag & ~0x7) | WireFormat.WIRETYPE_END_GROUP;
1021         int lastTag = 0;
1022         while (position < limit) {
1023           position = decodeVarint32(data, position, registers);
1024           lastTag = registers.int1;
1025           if (lastTag == endGroup) {
1026             break;
1027           }
1028           position = decodeUnknownField(lastTag, data, position, limit, child, registers);
1029         }
1030         if (position > limit || lastTag != endGroup) {
1031           throw InvalidProtocolBufferException.parseFailure();
1032         }
1033         unknownFields.storeField(tag, child);
1034         return position;
1035       default:
1036         throw InvalidProtocolBufferException.invalidTag();
1037     }
1038   }
1039 
1040   /** Skips an unknown field. */
skipField(int tag, byte[] data, int position, int limit, Registers registers)1041   static int skipField(int tag, byte[] data, int position, int limit, Registers registers)
1042       throws InvalidProtocolBufferException {
1043     if (WireFormat.getTagFieldNumber(tag) == 0) {
1044       throw InvalidProtocolBufferException.invalidTag();
1045     }
1046     switch (WireFormat.getTagWireType(tag)) {
1047       case WireFormat.WIRETYPE_VARINT:
1048         position = decodeVarint64(data, position, registers);
1049         return position;
1050       case WireFormat.WIRETYPE_FIXED32:
1051         return position + 4;
1052       case WireFormat.WIRETYPE_FIXED64:
1053         return position + 8;
1054       case WireFormat.WIRETYPE_LENGTH_DELIMITED:
1055         position = decodeVarint32(data, position, registers);
1056         return position + registers.int1;
1057       case WireFormat.WIRETYPE_START_GROUP:
1058         final int endGroup = (tag & ~0x7) | WireFormat.WIRETYPE_END_GROUP;
1059         int lastTag = 0;
1060         while (position < limit) {
1061           position = decodeVarint32(data, position, registers);
1062           lastTag = registers.int1;
1063           if (lastTag == endGroup) {
1064             break;
1065           }
1066           position = skipField(lastTag, data, position, limit, registers);
1067         }
1068         if (position > limit || lastTag != endGroup) {
1069           throw InvalidProtocolBufferException.parseFailure();
1070         }
1071         return position;
1072       default:
1073         throw InvalidProtocolBufferException.invalidTag();
1074     }
1075   }
1076 }
1077