• 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 routines 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 routines.
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     Object msg = schema.newInstance();
238     int offset = mergeMessageField(msg, schema, data, position, limit, registers);
239     schema.makeImmutable(msg);
240     registers.object1 = msg;
241     return offset;
242   }
243 
244   /** Decodes a group value. */
245   @SuppressWarnings({"unchecked", "rawtypes"})
decodeGroupField( Schema schema, byte[] data, int position, int limit, int endGroup, Registers registers)246   static int decodeGroupField(
247       Schema schema, byte[] data, int position, int limit, int endGroup, Registers registers)
248       throws IOException {
249     Object msg = schema.newInstance();
250     int offset = mergeGroupField(msg, schema, data, position, limit, endGroup, registers);
251     schema.makeImmutable(msg);
252     registers.object1 = msg;
253     return offset;
254   }
255 
256   @SuppressWarnings({"unchecked", "rawtypes"})
mergeMessageField( Object msg, Schema schema, byte[] data, int position, int limit, Registers registers)257   static int mergeMessageField(
258       Object msg, Schema schema, byte[] data, int position, int limit, Registers registers)
259       throws IOException {
260     int length = data[position++];
261     if (length < 0) {
262       position = decodeVarint32(length, data, position, registers);
263       length = registers.int1;
264     }
265     if (length < 0 || length > limit - position) {
266       throw InvalidProtocolBufferException.truncatedMessage();
267     }
268     schema.mergeFrom(msg, data, position, position + length, registers);
269     registers.object1 = msg;
270     return position + length;
271   }
272 
273   @SuppressWarnings({"unchecked", "rawtypes"})
mergeGroupField( Object msg, Schema schema, byte[] data, int position, int limit, int endGroup, Registers registers)274   static int mergeGroupField(
275       Object msg,
276       Schema schema,
277       byte[] data,
278       int position,
279       int limit,
280       int endGroup,
281       Registers registers)
282       throws IOException {
283     // A group field must has a MessageSchema (the only other subclass of Schema is MessageSetSchema
284     // and it can't be used in group fields).
285     final MessageSchema messageSchema = (MessageSchema) schema;
286     // It's OK to directly use parseProto2Message since proto3 doesn't have group.
287     final int endPosition =
288         messageSchema.parseProto2Message(msg, data, position, limit, endGroup, registers);
289     registers.object1 = msg;
290     return endPosition;
291   }
292 
293   /** 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)294   static int decodeVarint32List(
295       int tag, byte[] data, int position, int limit, ProtobufList<?> list, Registers registers) {
296     final IntArrayList output = (IntArrayList) list;
297     position = decodeVarint32(data, position, registers);
298     output.addInt(registers.int1);
299     while (position < limit) {
300       int nextPosition = decodeVarint32(data, position, registers);
301       if (tag != registers.int1) {
302         break;
303       }
304       position = decodeVarint32(data, nextPosition, registers);
305       output.addInt(registers.int1);
306     }
307     return position;
308   }
309 
310   /** 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)311   static int decodeVarint64List(
312       int tag, byte[] data, int position, int limit, ProtobufList<?> list, Registers registers) {
313     final LongArrayList output = (LongArrayList) list;
314     position = decodeVarint64(data, position, registers);
315     output.addLong(registers.long1);
316     while (position < limit) {
317       int nextPosition = decodeVarint32(data, position, registers);
318       if (tag != registers.int1) {
319         break;
320       }
321       position = decodeVarint64(data, nextPosition, registers);
322       output.addLong(registers.long1);
323     }
324     return position;
325   }
326 
327   /** 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)328   static int decodeFixed32List(
329       int tag, byte[] data, int position, int limit, ProtobufList<?> list, Registers registers) {
330     final IntArrayList output = (IntArrayList) list;
331     output.addInt(decodeFixed32(data, position));
332     position += 4;
333     while (position < limit) {
334       int nextPosition = decodeVarint32(data, position, registers);
335       if (tag != registers.int1) {
336         break;
337       }
338       output.addInt(decodeFixed32(data, nextPosition));
339       position = nextPosition + 4;
340     }
341     return position;
342   }
343 
344   /** 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)345   static int decodeFixed64List(
346       int tag, byte[] data, int position, int limit, ProtobufList<?> list, Registers registers) {
347     final LongArrayList output = (LongArrayList) list;
348     output.addLong(decodeFixed64(data, position));
349     position += 8;
350     while (position < limit) {
351       int nextPosition = decodeVarint32(data, position, registers);
352       if (tag != registers.int1) {
353         break;
354       }
355       output.addLong(decodeFixed64(data, nextPosition));
356       position = nextPosition + 8;
357     }
358     return position;
359   }
360 
361   /** 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)362   static int decodeFloatList(
363       int tag, byte[] data, int position, int limit, ProtobufList<?> list, Registers registers) {
364     final FloatArrayList output = (FloatArrayList) list;
365     output.addFloat(decodeFloat(data, position));
366     position += 4;
367     while (position < limit) {
368       int nextPosition = decodeVarint32(data, position, registers);
369       if (tag != registers.int1) {
370         break;
371       }
372       output.addFloat(decodeFloat(data, nextPosition));
373       position = nextPosition + 4;
374     }
375     return position;
376   }
377 
378   /** 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)379   static int decodeDoubleList(
380       int tag, byte[] data, int position, int limit, ProtobufList<?> list, Registers registers) {
381     final DoubleArrayList output = (DoubleArrayList) list;
382     output.addDouble(decodeDouble(data, position));
383     position += 8;
384     while (position < limit) {
385       int nextPosition = decodeVarint32(data, position, registers);
386       if (tag != registers.int1) {
387         break;
388       }
389       output.addDouble(decodeDouble(data, nextPosition));
390       position = nextPosition + 8;
391     }
392     return position;
393   }
394 
395   /** 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)396   static int decodeBoolList(
397       int tag, byte[] data, int position, int limit, ProtobufList<?> list, Registers registers) {
398     final BooleanArrayList output = (BooleanArrayList) list;
399     position = decodeVarint64(data, position, registers);
400     output.addBoolean(registers.long1 != 0);
401     while (position < limit) {
402       int nextPosition = decodeVarint32(data, position, registers);
403       if (tag != registers.int1) {
404         break;
405       }
406       position = decodeVarint64(data, nextPosition, registers);
407       output.addBoolean(registers.long1 != 0);
408     }
409     return position;
410   }
411 
412   /** 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)413   static int decodeSInt32List(
414       int tag, byte[] data, int position, int limit, ProtobufList<?> list, Registers registers) {
415     final IntArrayList output = (IntArrayList) list;
416     position = decodeVarint32(data, position, registers);
417     output.addInt(CodedInputStream.decodeZigZag32(registers.int1));
418     while (position < limit) {
419       int nextPosition = decodeVarint32(data, position, registers);
420       if (tag != registers.int1) {
421         break;
422       }
423       position = decodeVarint32(data, nextPosition, registers);
424       output.addInt(CodedInputStream.decodeZigZag32(registers.int1));
425     }
426     return position;
427   }
428 
429   /** 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)430   static int decodeSInt64List(
431       int tag, byte[] data, int position, int limit, ProtobufList<?> list, Registers registers) {
432     final LongArrayList output = (LongArrayList) list;
433     position = decodeVarint64(data, position, registers);
434     output.addLong(CodedInputStream.decodeZigZag64(registers.long1));
435     while (position < limit) {
436       int nextPosition = decodeVarint32(data, position, registers);
437       if (tag != registers.int1) {
438         break;
439       }
440       position = decodeVarint64(data, nextPosition, registers);
441       output.addLong(CodedInputStream.decodeZigZag64(registers.long1));
442     }
443     return position;
444   }
445 
446   /** Decodes a packed 32-bit varint field. Returns the position after all read values. */
decodePackedVarint32List( byte[] data, int position, ProtobufList<?> list, Registers registers)447   static int decodePackedVarint32List(
448       byte[] data, int position, ProtobufList<?> list, Registers registers) throws IOException {
449     final IntArrayList output = (IntArrayList) list;
450     position = decodeVarint32(data, position, registers);
451     final int fieldLimit = position + registers.int1;
452     while (position < fieldLimit) {
453       position = decodeVarint32(data, position, registers);
454       output.addInt(registers.int1);
455     }
456     if (position != fieldLimit) {
457       throw InvalidProtocolBufferException.truncatedMessage();
458     }
459     return position;
460   }
461 
462   /** Decodes a packed 64-bit varint field. Returns the position after all read values. */
decodePackedVarint64List( byte[] data, int position, ProtobufList<?> list, Registers registers)463   static int decodePackedVarint64List(
464       byte[] data, int position, ProtobufList<?> list, Registers registers) throws IOException {
465     final LongArrayList output = (LongArrayList) list;
466     position = decodeVarint32(data, position, registers);
467     final int fieldLimit = position + registers.int1;
468     while (position < fieldLimit) {
469       position = decodeVarint64(data, position, registers);
470       output.addLong(registers.long1);
471     }
472     if (position != fieldLimit) {
473       throw InvalidProtocolBufferException.truncatedMessage();
474     }
475     return position;
476   }
477 
478   /** Decodes a packed fixed32 field. Returns the position after all read values. */
decodePackedFixed32List( byte[] data, int position, ProtobufList<?> list, Registers registers)479   static int decodePackedFixed32List(
480       byte[] data, int position, ProtobufList<?> list, Registers registers) throws IOException {
481     final IntArrayList output = (IntArrayList) list;
482     position = decodeVarint32(data, position, registers);
483     final int fieldLimit = position + registers.int1;
484     while (position < fieldLimit) {
485       output.addInt(decodeFixed32(data, position));
486       position += 4;
487     }
488     if (position != fieldLimit) {
489       throw InvalidProtocolBufferException.truncatedMessage();
490     }
491     return position;
492   }
493 
494   /** Decodes a packed fixed64 field. Returns the position after all read values. */
decodePackedFixed64List( byte[] data, int position, ProtobufList<?> list, Registers registers)495   static int decodePackedFixed64List(
496       byte[] data, int position, ProtobufList<?> list, Registers registers) throws IOException {
497     final LongArrayList output = (LongArrayList) list;
498     position = decodeVarint32(data, position, registers);
499     final int fieldLimit = position + registers.int1;
500     while (position < fieldLimit) {
501       output.addLong(decodeFixed64(data, position));
502       position += 8;
503     }
504     if (position != fieldLimit) {
505       throw InvalidProtocolBufferException.truncatedMessage();
506     }
507     return position;
508   }
509 
510   /** Decodes a packed float field. Returns the position after all read values. */
decodePackedFloatList( byte[] data, int position, ProtobufList<?> list, Registers registers)511   static int decodePackedFloatList(
512       byte[] data, int position, ProtobufList<?> list, Registers registers) throws IOException {
513     final FloatArrayList output = (FloatArrayList) list;
514     position = decodeVarint32(data, position, registers);
515     final int fieldLimit = position + registers.int1;
516     while (position < fieldLimit) {
517       output.addFloat(decodeFloat(data, position));
518       position += 4;
519     }
520     if (position != fieldLimit) {
521       throw InvalidProtocolBufferException.truncatedMessage();
522     }
523     return position;
524   }
525 
526   /** Decodes a packed double field. Returns the position after all read values. */
decodePackedDoubleList( byte[] data, int position, ProtobufList<?> list, Registers registers)527   static int decodePackedDoubleList(
528       byte[] data, int position, ProtobufList<?> list, Registers registers) throws IOException {
529     final DoubleArrayList output = (DoubleArrayList) list;
530     position = decodeVarint32(data, position, registers);
531     final int fieldLimit = position + registers.int1;
532     while (position < fieldLimit) {
533       output.addDouble(decodeDouble(data, position));
534       position += 8;
535     }
536     if (position != fieldLimit) {
537       throw InvalidProtocolBufferException.truncatedMessage();
538     }
539     return position;
540   }
541 
542   /** Decodes a packed boolean field. Returns the position after all read values. */
decodePackedBoolList( byte[] data, int position, ProtobufList<?> list, Registers registers)543   static int decodePackedBoolList(
544       byte[] data, int position, ProtobufList<?> list, Registers registers) throws IOException {
545     final BooleanArrayList output = (BooleanArrayList) list;
546     position = decodeVarint32(data, position, registers);
547     final int fieldLimit = position + registers.int1;
548     while (position < fieldLimit) {
549       position = decodeVarint64(data, position, registers);
550       output.addBoolean(registers.long1 != 0);
551     }
552     if (position != fieldLimit) {
553       throw InvalidProtocolBufferException.truncatedMessage();
554     }
555     return position;
556   }
557 
558   /** Decodes a packed sint32 field. Returns the position after all read values. */
decodePackedSInt32List( byte[] data, int position, ProtobufList<?> list, Registers registers)559   static int decodePackedSInt32List(
560       byte[] data, int position, ProtobufList<?> list, Registers registers) throws IOException {
561     final IntArrayList output = (IntArrayList) list;
562     position = decodeVarint32(data, position, registers);
563     final int fieldLimit = position + registers.int1;
564     while (position < fieldLimit) {
565       position = decodeVarint32(data, position, registers);
566       output.addInt(CodedInputStream.decodeZigZag32(registers.int1));
567     }
568     if (position != fieldLimit) {
569       throw InvalidProtocolBufferException.truncatedMessage();
570     }
571     return position;
572   }
573 
574   /** Decodes a packed sint64 field. Returns the position after all read values. */
575   @SuppressWarnings("unchecked")
decodePackedSInt64List( byte[] data, int position, ProtobufList<?> list, Registers registers)576   static int decodePackedSInt64List(
577       byte[] data, int position, ProtobufList<?> list, Registers registers) throws IOException {
578     final LongArrayList output = (LongArrayList) list;
579     position = decodeVarint32(data, position, registers);
580     final int fieldLimit = position + registers.int1;
581     while (position < fieldLimit) {
582       position = decodeVarint64(data, position, registers);
583       output.addLong(CodedInputStream.decodeZigZag64(registers.long1));
584     }
585     if (position != fieldLimit) {
586       throw InvalidProtocolBufferException.truncatedMessage();
587     }
588     return position;
589   }
590 
591   /** Decodes a repeated string field. Returns the position after all read values. */
592   @SuppressWarnings("unchecked")
decodeStringList( int tag, byte[] data, int position, int limit, ProtobufList<?> list, Registers registers)593   static int decodeStringList(
594       int tag, byte[] data, int position, int limit, ProtobufList<?> list, Registers registers)
595       throws InvalidProtocolBufferException {
596     final ProtobufList<String> output = (ProtobufList<String>) list;
597     position = decodeVarint32(data, position, registers);
598     final int length = registers.int1;
599     if (length < 0) {
600       throw InvalidProtocolBufferException.negativeSize();
601     } else if (length == 0) {
602       output.add("");
603     } else {
604       String value = new String(data, position, length, Internal.UTF_8);
605       output.add(value);
606       position += length;
607     }
608     while (position < limit) {
609       int nextPosition = decodeVarint32(data, position, registers);
610       if (tag != registers.int1) {
611         break;
612       }
613       position = decodeVarint32(data, nextPosition, registers);
614       final int nextLength = registers.int1;
615       if (nextLength < 0) {
616         throw InvalidProtocolBufferException.negativeSize();
617       } else if (nextLength == 0) {
618         output.add("");
619       } else {
620         String value = new String(data, position, nextLength, Internal.UTF_8);
621         output.add(value);
622         position += nextLength;
623       }
624     }
625     return position;
626   }
627 
628   /**
629    * Decodes a repeated string field with utf8 check. Returns the position after all read values.
630    */
631   @SuppressWarnings("unchecked")
decodeStringListRequireUtf8( int tag, byte[] data, int position, int limit, ProtobufList<?> list, Registers registers)632   static int decodeStringListRequireUtf8(
633       int tag, byte[] data, int position, int limit, ProtobufList<?> list, Registers registers)
634       throws InvalidProtocolBufferException {
635     final ProtobufList<String> output = (ProtobufList<String>) list;
636     position = decodeVarint32(data, position, registers);
637     final int length = registers.int1;
638     if (length < 0) {
639       throw InvalidProtocolBufferException.negativeSize();
640     } else if (length == 0) {
641       output.add("");
642     } else {
643       if (!Utf8.isValidUtf8(data, position, position + length)) {
644         throw InvalidProtocolBufferException.invalidUtf8();
645       }
646       String value = new String(data, position, length, Internal.UTF_8);
647       output.add(value);
648       position += length;
649     }
650     while (position < limit) {
651       int nextPosition = decodeVarint32(data, position, registers);
652       if (tag != registers.int1) {
653         break;
654       }
655       position = decodeVarint32(data, nextPosition, registers);
656       final int nextLength = registers.int1;
657       if (nextLength < 0) {
658         throw InvalidProtocolBufferException.negativeSize();
659       } else if (nextLength == 0) {
660         output.add("");
661       } else {
662         if (!Utf8.isValidUtf8(data, position, position + nextLength)) {
663           throw InvalidProtocolBufferException.invalidUtf8();
664         }
665         String value = new String(data, position, nextLength, Internal.UTF_8);
666         output.add(value);
667         position += nextLength;
668       }
669     }
670     return position;
671   }
672 
673   /** Decodes a repeated bytes field. Returns the position after all read values. */
674   @SuppressWarnings("unchecked")
decodeBytesList( int tag, byte[] data, int position, int limit, ProtobufList<?> list, Registers registers)675   static int decodeBytesList(
676       int tag, byte[] data, int position, int limit, ProtobufList<?> list, Registers registers)
677       throws InvalidProtocolBufferException {
678     final ProtobufList<ByteString> output = (ProtobufList<ByteString>) list;
679     position = decodeVarint32(data, position, registers);
680     final int length = registers.int1;
681     if (length < 0) {
682       throw InvalidProtocolBufferException.negativeSize();
683     } else if (length > data.length - position) {
684       throw InvalidProtocolBufferException.truncatedMessage();
685     } else if (length == 0) {
686       output.add(ByteString.EMPTY);
687     } else {
688       output.add(ByteString.copyFrom(data, position, length));
689       position += length;
690     }
691     while (position < limit) {
692       int nextPosition = decodeVarint32(data, position, registers);
693       if (tag != registers.int1) {
694         break;
695       }
696       position = decodeVarint32(data, nextPosition, registers);
697       final int nextLength = registers.int1;
698       if (nextLength < 0) {
699         throw InvalidProtocolBufferException.negativeSize();
700       } else if (nextLength > data.length - position) {
701         throw InvalidProtocolBufferException.truncatedMessage();
702       } else if (nextLength == 0) {
703         output.add(ByteString.EMPTY);
704       } else {
705         output.add(ByteString.copyFrom(data, position, nextLength));
706         position += nextLength;
707       }
708     }
709     return position;
710   }
711 
712   /**
713    * Decodes a repeated message field
714    *
715    * @return The position of after read all messages
716    */
717   @SuppressWarnings({"unchecked"})
decodeMessageList( Schema<?> schema, int tag, byte[] data, int position, int limit, ProtobufList<?> list, Registers registers)718   static int decodeMessageList(
719       Schema<?> schema,
720       int tag,
721       byte[] data,
722       int position,
723       int limit,
724       ProtobufList<?> list,
725       Registers registers)
726       throws IOException {
727     final ProtobufList<Object> output = (ProtobufList<Object>) list;
728     position = decodeMessageField(schema, data, position, limit, registers);
729     output.add(registers.object1);
730     while (position < limit) {
731       int nextPosition = decodeVarint32(data, position, registers);
732       if (tag != registers.int1) {
733         break;
734       }
735       position = decodeMessageField(schema, data, nextPosition, limit, registers);
736       output.add(registers.object1);
737     }
738     return position;
739   }
740 
741   /**
742    * Decodes a repeated group field
743    *
744    * @return The position of after read all groups
745    */
746   @SuppressWarnings({"unchecked", "rawtypes"})
decodeGroupList( Schema schema, int tag, byte[] data, int position, int limit, ProtobufList<?> list, Registers registers)747   static int decodeGroupList(
748       Schema schema,
749       int tag,
750       byte[] data,
751       int position,
752       int limit,
753       ProtobufList<?> list,
754       Registers registers)
755       throws IOException {
756     final ProtobufList<Object> output = (ProtobufList<Object>) list;
757     final int endgroup = (tag & ~0x7) | WireFormat.WIRETYPE_END_GROUP;
758     position = decodeGroupField(schema, data, position, limit, endgroup, registers);
759     output.add(registers.object1);
760     while (position < limit) {
761       int nextPosition = decodeVarint32(data, position, registers);
762       if (tag != registers.int1) {
763         break;
764       }
765       position = decodeGroupField(schema, data, nextPosition, limit, endgroup, registers);
766       output.add(registers.object1);
767     }
768     return position;
769   }
770 
decodeExtensionOrUnknownField( int tag, byte[] data, int position, int limit, Object message, MessageLite defaultInstance, UnknownFieldSchema<UnknownFieldSetLite, UnknownFieldSetLite> unknownFieldSchema, Registers registers)771   static int decodeExtensionOrUnknownField(
772       int tag, byte[] data, int position, int limit,
773       Object message,
774       MessageLite defaultInstance,
775       UnknownFieldSchema<UnknownFieldSetLite, UnknownFieldSetLite> unknownFieldSchema,
776       Registers registers)
777       throws IOException {
778     final int number = tag >>> 3;
779     GeneratedMessageLite.GeneratedExtension extension =
780         registers.extensionRegistry.findLiteExtensionByNumber(defaultInstance, number);
781     if (extension == null) {
782       return decodeUnknownField(
783           tag, data, position, limit, getMutableUnknownFields(message), registers);
784     } else  {
785       ((GeneratedMessageLite.ExtendableMessage<?, ?>) message).ensureExtensionsAreMutable();
786       return decodeExtension(
787           tag, data, position, limit, (GeneratedMessageLite.ExtendableMessage) message,
788           extension, unknownFieldSchema, registers);
789     }
790   }
791 
decodeExtension( int tag, byte[] data, int position, int limit, GeneratedMessageLite.ExtendableMessage<?, ?> message, GeneratedMessageLite.GeneratedExtension<?, ?> extension, UnknownFieldSchema<UnknownFieldSetLite, UnknownFieldSetLite> unknownFieldSchema, Registers registers)792   static int decodeExtension(
793       int tag,
794       byte[] data,
795       int position,
796       int limit,
797       GeneratedMessageLite.ExtendableMessage<?, ?> message,
798       GeneratedMessageLite.GeneratedExtension<?, ?> extension,
799       UnknownFieldSchema<UnknownFieldSetLite, UnknownFieldSetLite> unknownFieldSchema,
800       Registers registers)
801       throws IOException {
802     final FieldSet<GeneratedMessageLite.ExtensionDescriptor> extensions = message.extensions;
803     final int fieldNumber = tag >>> 3;
804     if (extension.descriptor.isRepeated() && extension.descriptor.isPacked()) {
805       switch (extension.getLiteType()) {
806         case DOUBLE:
807         {
808           DoubleArrayList list = new DoubleArrayList();
809           position = decodePackedDoubleList(data, position, list, registers);
810           extensions.setField(extension.descriptor, list);
811           break;
812         }
813         case FLOAT:
814         {
815           FloatArrayList list = new FloatArrayList();
816           position = decodePackedFloatList(data, position, list, registers);
817           extensions.setField(extension.descriptor, list);
818           break;
819         }
820         case INT64:
821         case UINT64:
822         {
823           LongArrayList list = new LongArrayList();
824           position = decodePackedVarint64List(data, position, list, registers);
825           extensions.setField(extension.descriptor, list);
826           break;
827         }
828         case INT32:
829         case UINT32:
830         {
831           IntArrayList list = new IntArrayList();
832           position = decodePackedVarint32List(data, position, list, registers);
833           extensions.setField(extension.descriptor, list);
834           break;
835         }
836         case FIXED64:
837         case SFIXED64:
838         {
839           LongArrayList list = new LongArrayList();
840           position = decodePackedFixed64List(data, position, list, registers);
841           extensions.setField(extension.descriptor, list);
842           break;
843         }
844         case FIXED32:
845         case SFIXED32:
846         {
847           IntArrayList list = new IntArrayList();
848           position = decodePackedFixed32List(data, position, list, registers);
849           extensions.setField(extension.descriptor, list);
850           break;
851         }
852         case BOOL:
853         {
854           BooleanArrayList list = new BooleanArrayList();
855           position = decodePackedBoolList(data, position, list, registers);
856           extensions.setField(extension.descriptor, list);
857           break;
858         }
859         case SINT32:
860         {
861           IntArrayList list = new IntArrayList();
862           position = decodePackedSInt32List(data, position, list, registers);
863           extensions.setField(extension.descriptor, list);
864           break;
865         }
866         case SINT64:
867         {
868           LongArrayList list = new LongArrayList();
869           position = decodePackedSInt64List(data, position, list, registers);
870           extensions.setField(extension.descriptor, list);
871           break;
872         }
873         case ENUM:
874           {
875             IntArrayList list = new IntArrayList();
876             position = decodePackedVarint32List(data, position, list, registers);
877             SchemaUtil.filterUnknownEnumList(
878                 message,
879                 fieldNumber,
880                 list,
881                 extension.descriptor.getEnumType(),
882                 null,
883                 unknownFieldSchema);
884             extensions.setField(extension.descriptor, list);
885             break;
886           }
887         default:
888           throw new IllegalStateException(
889               "Type cannot be packed: " + extension.descriptor.getLiteType());
890       }
891     } else {
892       Object value = null;
893       // Enum is a special case because unknown enum values will be put into UnknownFieldSetLite.
894       if (extension.getLiteType() == WireFormat.FieldType.ENUM) {
895         position = decodeVarint32(data, position, registers);
896         Object enumValue = extension.descriptor.getEnumType().findValueByNumber(registers.int1);
897         if (enumValue == null) {
898           SchemaUtil.storeUnknownEnum(
899               message, fieldNumber, registers.int1, null, unknownFieldSchema);
900           return position;
901         }
902         // Note, we store the integer value instead of the actual enum object in FieldSet.
903         // This is also different from full-runtime where we store EnumValueDescriptor.
904         value = registers.int1;
905       } else {
906         switch (extension.getLiteType()) {
907           case DOUBLE:
908             value = decodeDouble(data, position);
909             position += 8;
910             break;
911           case FLOAT:
912             value = decodeFloat(data, position);
913             position += 4;
914             break;
915           case INT64:
916           case UINT64:
917             position = decodeVarint64(data, position, registers);
918             value = registers.long1;
919             break;
920           case INT32:
921           case UINT32:
922             position = decodeVarint32(data, position, registers);
923             value = registers.int1;
924             break;
925           case FIXED64:
926           case SFIXED64:
927             value = decodeFixed64(data, position);
928             position += 8;
929             break;
930           case FIXED32:
931           case SFIXED32:
932             value = decodeFixed32(data, position);
933             position += 4;
934             break;
935           case BOOL:
936             position = decodeVarint64(data, position, registers);
937             value = (registers.long1 != 0);
938             break;
939           case BYTES:
940             position = decodeBytes(data, position, registers);
941             value = registers.object1;
942             break;
943           case SINT32:
944             position = decodeVarint32(data, position, registers);
945             value = CodedInputStream.decodeZigZag32(registers.int1);
946             break;
947           case SINT64:
948             position = decodeVarint64(data, position, registers);
949             value = CodedInputStream.decodeZigZag64(registers.long1);
950             break;
951           case STRING:
952             position = decodeString(data, position, registers);
953             value = registers.object1;
954             break;
955           case GROUP:
956             {
957               final int endTag = (fieldNumber << 3) | WireFormat.WIRETYPE_END_GROUP;
958               final Schema fieldSchema =
959                   Protobuf.getInstance()
960                       .schemaFor(extension.getMessageDefaultInstance().getClass());
961               if (extension.isRepeated()) {
962                 position = decodeGroupField(fieldSchema, data, position, limit, endTag, registers);
963                 extensions.addRepeatedField(extension.descriptor, registers.object1);
964               } else {
965                 Object oldValue = extensions.getField(extension.descriptor);
966                 if (oldValue == null) {
967                   oldValue = fieldSchema.newInstance();
968                   extensions.setField(extension.descriptor, oldValue);
969                 }
970                 position =
971                     mergeGroupField(
972                         oldValue, fieldSchema, data, position, limit, endTag, registers);
973               }
974               return position;
975             }
976           case MESSAGE:
977             {
978               final Schema fieldSchema =
979                   Protobuf.getInstance()
980                       .schemaFor(extension.getMessageDefaultInstance().getClass());
981               if (extension.isRepeated()) {
982                 position = decodeMessageField(fieldSchema, data, position, limit, registers);
983                 extensions.addRepeatedField(extension.descriptor, registers.object1);
984               } else {
985                 Object oldValue = extensions.getField(extension.descriptor);
986                 if (oldValue == null) {
987                   oldValue = fieldSchema.newInstance();
988                   extensions.setField(extension.descriptor, oldValue);
989                 }
990                 position =
991                     mergeMessageField(oldValue, fieldSchema, data, position, limit, registers);
992               }
993               return position;
994             }
995           case ENUM:
996             throw new IllegalStateException("Shouldn't reach here.");
997         }
998       }
999       if (extension.isRepeated()) {
1000         extensions.addRepeatedField(extension.descriptor, value);
1001       } else {
1002         extensions.setField(extension.descriptor, value);
1003       }
1004     }
1005     return position;
1006   }
1007 
1008   /** Decodes an unknown field. */
decodeUnknownField( int tag, byte[] data, int position, int limit, UnknownFieldSetLite unknownFields, Registers registers)1009   static int decodeUnknownField(
1010       int tag,
1011       byte[] data,
1012       int position,
1013       int limit,
1014       UnknownFieldSetLite unknownFields,
1015       Registers registers)
1016       throws InvalidProtocolBufferException {
1017     if (WireFormat.getTagFieldNumber(tag) == 0) {
1018       throw InvalidProtocolBufferException.invalidTag();
1019     }
1020     switch (WireFormat.getTagWireType(tag)) {
1021       case WireFormat.WIRETYPE_VARINT:
1022         position = decodeVarint64(data, position, registers);
1023         unknownFields.storeField(tag, registers.long1);
1024         return position;
1025       case WireFormat.WIRETYPE_FIXED32:
1026         unknownFields.storeField(tag, decodeFixed32(data, position));
1027         return position + 4;
1028       case WireFormat.WIRETYPE_FIXED64:
1029         unknownFields.storeField(tag, decodeFixed64(data, position));
1030         return position + 8;
1031       case WireFormat.WIRETYPE_LENGTH_DELIMITED:
1032         position = decodeVarint32(data, position, registers);
1033         final int length = registers.int1;
1034         if (length < 0) {
1035           throw InvalidProtocolBufferException.negativeSize();
1036         } else if (length > data.length - position) {
1037           throw InvalidProtocolBufferException.truncatedMessage();
1038         } else if (length == 0) {
1039           unknownFields.storeField(tag, ByteString.EMPTY);
1040         } else {
1041           unknownFields.storeField(tag, ByteString.copyFrom(data, position, length));
1042         }
1043         return position + length;
1044       case WireFormat.WIRETYPE_START_GROUP:
1045         final UnknownFieldSetLite child = UnknownFieldSetLite.newInstance();
1046         final int endGroup = (tag & ~0x7) | WireFormat.WIRETYPE_END_GROUP;
1047         int lastTag = 0;
1048         while (position < limit) {
1049           position = decodeVarint32(data, position, registers);
1050           lastTag = registers.int1;
1051           if (lastTag == endGroup) {
1052             break;
1053           }
1054           position = decodeUnknownField(lastTag, data, position, limit, child, registers);
1055         }
1056         if (position > limit || lastTag != endGroup) {
1057           throw InvalidProtocolBufferException.parseFailure();
1058         }
1059         unknownFields.storeField(tag, child);
1060         return position;
1061       default:
1062         throw InvalidProtocolBufferException.invalidTag();
1063     }
1064   }
1065 
1066   /** Skips an unknown field. */
skipField(int tag, byte[] data, int position, int limit, Registers registers)1067   static int skipField(int tag, byte[] data, int position, int limit, Registers registers)
1068       throws InvalidProtocolBufferException {
1069     if (WireFormat.getTagFieldNumber(tag) == 0) {
1070       throw InvalidProtocolBufferException.invalidTag();
1071     }
1072     switch (WireFormat.getTagWireType(tag)) {
1073       case WireFormat.WIRETYPE_VARINT:
1074         position = decodeVarint64(data, position, registers);
1075         return position;
1076       case WireFormat.WIRETYPE_FIXED32:
1077         return position + 4;
1078       case WireFormat.WIRETYPE_FIXED64:
1079         return position + 8;
1080       case WireFormat.WIRETYPE_LENGTH_DELIMITED:
1081         position = decodeVarint32(data, position, registers);
1082         return position + registers.int1;
1083       case WireFormat.WIRETYPE_START_GROUP:
1084         final int endGroup = (tag & ~0x7) | WireFormat.WIRETYPE_END_GROUP;
1085         int lastTag = 0;
1086         while (position < limit) {
1087           position = decodeVarint32(data, position, registers);
1088           lastTag = registers.int1;
1089           if (lastTag == endGroup) {
1090             break;
1091           }
1092           position = skipField(lastTag, data, position, limit, registers);
1093         }
1094         if (position > limit || lastTag != endGroup) {
1095           throw InvalidProtocolBufferException.parseFailure();
1096         }
1097         return position;
1098       default:
1099         throw InvalidProtocolBufferException.invalidTag();
1100     }
1101   }
1102 }
1103