• 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.ArrayDecoders.decodeBoolList;
34 import static com.google.protobuf.ArrayDecoders.decodeBytes;
35 import static com.google.protobuf.ArrayDecoders.decodeBytesList;
36 import static com.google.protobuf.ArrayDecoders.decodeDouble;
37 import static com.google.protobuf.ArrayDecoders.decodeDoubleList;
38 import static com.google.protobuf.ArrayDecoders.decodeExtensionOrUnknownField;
39 import static com.google.protobuf.ArrayDecoders.decodeFixed32;
40 import static com.google.protobuf.ArrayDecoders.decodeFixed32List;
41 import static com.google.protobuf.ArrayDecoders.decodeFixed64;
42 import static com.google.protobuf.ArrayDecoders.decodeFixed64List;
43 import static com.google.protobuf.ArrayDecoders.decodeFloat;
44 import static com.google.protobuf.ArrayDecoders.decodeFloatList;
45 import static com.google.protobuf.ArrayDecoders.decodeGroupField;
46 import static com.google.protobuf.ArrayDecoders.decodeGroupList;
47 import static com.google.protobuf.ArrayDecoders.decodeMessageField;
48 import static com.google.protobuf.ArrayDecoders.decodeMessageList;
49 import static com.google.protobuf.ArrayDecoders.decodePackedBoolList;
50 import static com.google.protobuf.ArrayDecoders.decodePackedDoubleList;
51 import static com.google.protobuf.ArrayDecoders.decodePackedFixed32List;
52 import static com.google.protobuf.ArrayDecoders.decodePackedFixed64List;
53 import static com.google.protobuf.ArrayDecoders.decodePackedFloatList;
54 import static com.google.protobuf.ArrayDecoders.decodePackedSInt32List;
55 import static com.google.protobuf.ArrayDecoders.decodePackedSInt64List;
56 import static com.google.protobuf.ArrayDecoders.decodePackedVarint32List;
57 import static com.google.protobuf.ArrayDecoders.decodePackedVarint64List;
58 import static com.google.protobuf.ArrayDecoders.decodeSInt32List;
59 import static com.google.protobuf.ArrayDecoders.decodeSInt64List;
60 import static com.google.protobuf.ArrayDecoders.decodeString;
61 import static com.google.protobuf.ArrayDecoders.decodeStringList;
62 import static com.google.protobuf.ArrayDecoders.decodeStringListRequireUtf8;
63 import static com.google.protobuf.ArrayDecoders.decodeStringRequireUtf8;
64 import static com.google.protobuf.ArrayDecoders.decodeUnknownField;
65 import static com.google.protobuf.ArrayDecoders.decodeVarint32;
66 import static com.google.protobuf.ArrayDecoders.decodeVarint32List;
67 import static com.google.protobuf.ArrayDecoders.decodeVarint64;
68 import static com.google.protobuf.ArrayDecoders.decodeVarint64List;
69 import static com.google.protobuf.ArrayDecoders.skipField;
70 
71 import com.google.protobuf.ArrayDecoders.Registers;
72 import com.google.protobuf.ByteString.CodedBuilder;
73 import com.google.protobuf.FieldSet.FieldDescriptorLite;
74 import com.google.protobuf.Internal.EnumVerifier;
75 import com.google.protobuf.Internal.ProtobufList;
76 import com.google.protobuf.MapEntryLite.Metadata;
77 import java.io.IOException;
78 import java.lang.reflect.Field;
79 import java.util.Arrays;
80 import java.util.Iterator;
81 import java.util.List;
82 import java.util.Map;
83 
84 /** Schema used for standard messages. */
85 final class MessageSchema<T> implements Schema<T> {
86   private static final int INTS_PER_FIELD = 3;
87   private static final int OFFSET_BITS = 20;
88   private static final int OFFSET_MASK = 0XFFFFF;
89   private static final int FIELD_TYPE_MASK = 0x0FF00000;
90   private static final int REQUIRED_MASK = 0x10000000;
91   private static final int ENFORCE_UTF8_MASK = 0x20000000;
92   private static final int NO_PRESENCE_SENTINEL = -1 & OFFSET_MASK;
93   private static final int[] EMPTY_INT_ARRAY = new int[0];
94 
95   /** An offset applied to the field type ID for scalar fields that are a member of a oneof. */
96   static final int ONEOF_TYPE_OFFSET = 51 /* FieldType.MAP + 1 */;
97 
98   /**
99    * Keep a direct reference to the unsafe object so we don't need to go through the UnsafeUtil
100    * wrapper for every call.
101    */
102   private static final sun.misc.Unsafe UNSAFE = UnsafeUtil.getUnsafe();
103 
104   /**
105    * Holds all information for accessing the message fields. The layout is as follows (field
106    * positions are relative to the offset of the start of the field in the buffer):
107    *
108    * <p>
109    *
110    * <pre>
111    * [ 0 -    3] unused
112    * [ 4 -   31] field number
113    * [32 -   33] unused
114    * [34 -   34] whether UTF-8 enforcement should be applied to a string field.
115    * [35 -   35] whether the field is required
116    * [36 -   43] field type / for oneof: field type + {@link #ONEOF_TYPE_OFFSET}
117    * [44 -   63] field offset / oneof value field offset
118    * [64 -   69] unused
119    * [70 -   75] field presence mask shift (unused for oneof/repeated fields)
120    * [76 -   95] presence field offset / oneof case field offset / cached size field offset
121    * </pre>
122    *
123    * Note that presence field offset can only use 20 bits - 1. All bits set to 1 is the sentinel
124    * value for non-presence. This is not validated at runtime, we simply assume message layouts
125    * will not exceed 1MB (assuming ~10 bytes per field, that implies 100k fields which should hit
126    * other javac limits first).
127    */
128   private final int[] buffer;
129 
130   /**
131    * Holds object references for fields. For each field entry in {@code buffer}, there are two
132    * corresponding entries in this array. The content is different from different field types:
133    *
134    * <pre>
135    *   Map fields:
136    *     objects[pos] = map default entry instance
137    *     objects[pos + 1] = EnumVerifier if map value is enum, or message class reference if map
138    *                        value is message.
139    *   Message fields:
140    *     objects[pos] = null or cached message schema
141    *     objects[pos + 1] = message class reference
142    *   Enum fields:
143    *     objects[pos] = null
144    *     objects[pos + 1] = EnumVerifier
145    * </pre>
146    */
147   private final Object[] objects;
148 
149   private final int minFieldNumber;
150   private final int maxFieldNumber;
151 
152   private final MessageLite defaultInstance;
153   private final boolean hasExtensions;
154   private final boolean lite;
155   private final boolean proto3;
156   // TODO(xiaofeng): Make both full-runtime and lite-runtime support cached field size.
157   private final boolean useCachedSizeField;
158 
159   /** Represents [checkInitialized positions, map field positions, repeated field offsets]. */
160   private final int[] intArray;
161 
162   /**
163    * Values at indices 0 -> checkInitializedCount in intArray are positions to check for
164    * initialization.
165    */
166   private final int checkInitializedCount;
167 
168   /**
169    * Values at indices checkInitializedCount -> repeatedFieldOffsetStart are map positions.
170    * Everything after that are repeated field offsets.
171    */
172   private final int repeatedFieldOffsetStart;
173 
174   private final NewInstanceSchema newInstanceSchema;
175   private final ListFieldSchema listFieldSchema;
176   private final UnknownFieldSchema<?, ?> unknownFieldSchema;
177   private final ExtensionSchema<?> extensionSchema;
178   private final MapFieldSchema mapFieldSchema;
179 
MessageSchema( int[] buffer, Object[] objects, int minFieldNumber, int maxFieldNumber, MessageLite defaultInstance, boolean proto3, boolean useCachedSizeField, int[] intArray, int checkInitialized, int mapFieldPositions, NewInstanceSchema newInstanceSchema, ListFieldSchema listFieldSchema, UnknownFieldSchema<?, ?> unknownFieldSchema, ExtensionSchema<?> extensionSchema, MapFieldSchema mapFieldSchema)180   private MessageSchema(
181       int[] buffer,
182       Object[] objects,
183       int minFieldNumber,
184       int maxFieldNumber,
185       MessageLite defaultInstance,
186       boolean proto3,
187       boolean useCachedSizeField,
188       int[] intArray,
189       int checkInitialized,
190       int mapFieldPositions,
191       NewInstanceSchema newInstanceSchema,
192       ListFieldSchema listFieldSchema,
193       UnknownFieldSchema<?, ?> unknownFieldSchema,
194       ExtensionSchema<?> extensionSchema,
195       MapFieldSchema mapFieldSchema) {
196     this.buffer = buffer;
197     this.objects = objects;
198     this.minFieldNumber = minFieldNumber;
199     this.maxFieldNumber = maxFieldNumber;
200 
201     this.lite = defaultInstance instanceof GeneratedMessageLite;
202     this.proto3 = proto3;
203     this.hasExtensions = extensionSchema != null && extensionSchema.hasExtensions(defaultInstance);
204     this.useCachedSizeField = useCachedSizeField;
205 
206     this.intArray = intArray;
207     this.checkInitializedCount = checkInitialized;
208     this.repeatedFieldOffsetStart = mapFieldPositions;
209 
210     this.newInstanceSchema = newInstanceSchema;
211     this.listFieldSchema = listFieldSchema;
212     this.unknownFieldSchema = unknownFieldSchema;
213     this.extensionSchema = extensionSchema;
214     this.defaultInstance = defaultInstance;
215     this.mapFieldSchema = mapFieldSchema;
216   }
217 
newSchema( Class<T> messageClass, MessageInfo messageInfo, NewInstanceSchema newInstanceSchema, ListFieldSchema listFieldSchema, UnknownFieldSchema<?, ?> unknownFieldSchema, ExtensionSchema<?> extensionSchema, MapFieldSchema mapFieldSchema)218   static <T> MessageSchema<T> newSchema(
219       Class<T> messageClass,
220       MessageInfo messageInfo,
221       NewInstanceSchema newInstanceSchema,
222       ListFieldSchema listFieldSchema,
223       UnknownFieldSchema<?, ?> unknownFieldSchema,
224       ExtensionSchema<?> extensionSchema,
225       MapFieldSchema mapFieldSchema) {
226     if (messageInfo instanceof RawMessageInfo) {
227       return newSchemaForRawMessageInfo(
228           (RawMessageInfo) messageInfo,
229           newInstanceSchema,
230           listFieldSchema,
231           unknownFieldSchema,
232           extensionSchema,
233           mapFieldSchema);
234 
235     } else {
236       return newSchemaForMessageInfo(
237           (StructuralMessageInfo) messageInfo,
238           newInstanceSchema,
239           listFieldSchema,
240           unknownFieldSchema,
241           extensionSchema,
242           mapFieldSchema);
243     }
244   }
245 
newSchemaForRawMessageInfo( RawMessageInfo messageInfo, NewInstanceSchema newInstanceSchema, ListFieldSchema listFieldSchema, UnknownFieldSchema<?, ?> unknownFieldSchema, ExtensionSchema<?> extensionSchema, MapFieldSchema mapFieldSchema)246   static <T> MessageSchema<T> newSchemaForRawMessageInfo(
247       RawMessageInfo messageInfo,
248       NewInstanceSchema newInstanceSchema,
249       ListFieldSchema listFieldSchema,
250       UnknownFieldSchema<?, ?> unknownFieldSchema,
251       ExtensionSchema<?> extensionSchema,
252       MapFieldSchema mapFieldSchema) {
253     final boolean isProto3 = messageInfo.getSyntax() == ProtoSyntax.PROTO3;
254 
255     String info = messageInfo.getStringInfo();
256     final int length = info.length();
257     int i = 0;
258 
259     int next = info.charAt(i++);
260     if (next >= 0xD800) {
261       int result = next & 0x1FFF;
262       int shift = 13;
263       while ((next = info.charAt(i++)) >= 0xD800) {
264         result |= (next & 0x1FFF) << shift;
265         shift += 13;
266       }
267       next = result | (next << shift);
268     }
269     final int unusedFlags = next;
270 
271     next = info.charAt(i++);
272     if (next >= 0xD800) {
273       int result = next & 0x1FFF;
274       int shift = 13;
275       while ((next = info.charAt(i++)) >= 0xD800) {
276         result |= (next & 0x1FFF) << shift;
277         shift += 13;
278       }
279       next = result | (next << shift);
280     }
281     final int fieldCount = next;
282 
283     final int oneofCount;
284     final int hasBitsCount;
285     final int minFieldNumber;
286     final int maxFieldNumber;
287     final int numEntries;
288     final int mapFieldCount;
289     final int repeatedFieldCount;
290     final int checkInitialized;
291     final int[] intArray;
292     int objectsPosition;
293     if (fieldCount == 0) {
294       oneofCount = 0;
295       hasBitsCount = 0;
296       minFieldNumber = 0;
297       maxFieldNumber = 0;
298       numEntries = 0;
299       mapFieldCount = 0;
300       repeatedFieldCount = 0;
301       checkInitialized = 0;
302       intArray = EMPTY_INT_ARRAY;
303       objectsPosition = 0;
304     } else {
305       next = info.charAt(i++);
306       if (next >= 0xD800) {
307         int result = next & 0x1FFF;
308         int shift = 13;
309         while ((next = info.charAt(i++)) >= 0xD800) {
310           result |= (next & 0x1FFF) << shift;
311           shift += 13;
312         }
313         next = result | (next << shift);
314       }
315       oneofCount = next;
316 
317       next = info.charAt(i++);
318       if (next >= 0xD800) {
319         int result = next & 0x1FFF;
320         int shift = 13;
321         while ((next = info.charAt(i++)) >= 0xD800) {
322           result |= (next & 0x1FFF) << shift;
323           shift += 13;
324         }
325         next = result | (next << shift);
326       }
327       hasBitsCount = next;
328 
329       next = info.charAt(i++);
330       if (next >= 0xD800) {
331         int result = next & 0x1FFF;
332         int shift = 13;
333         while ((next = info.charAt(i++)) >= 0xD800) {
334           result |= (next & 0x1FFF) << shift;
335           shift += 13;
336         }
337         next = result | (next << shift);
338       }
339       minFieldNumber = next;
340 
341       next = info.charAt(i++);
342       if (next >= 0xD800) {
343         int result = next & 0x1FFF;
344         int shift = 13;
345         while ((next = info.charAt(i++)) >= 0xD800) {
346           result |= (next & 0x1FFF) << shift;
347           shift += 13;
348         }
349         next = result | (next << shift);
350       }
351       maxFieldNumber = next;
352 
353       next = info.charAt(i++);
354       if (next >= 0xD800) {
355         int result = next & 0x1FFF;
356         int shift = 13;
357         while ((next = info.charAt(i++)) >= 0xD800) {
358           result |= (next & 0x1FFF) << shift;
359           shift += 13;
360         }
361         next = result | (next << shift);
362       }
363       numEntries = next;
364 
365       next = info.charAt(i++);
366       if (next >= 0xD800) {
367         int result = next & 0x1FFF;
368         int shift = 13;
369         while ((next = info.charAt(i++)) >= 0xD800) {
370           result |= (next & 0x1FFF) << shift;
371           shift += 13;
372         }
373         next = result | (next << shift);
374       }
375       mapFieldCount = next;
376 
377       next = info.charAt(i++);
378       if (next >= 0xD800) {
379         int result = next & 0x1FFF;
380         int shift = 13;
381         while ((next = info.charAt(i++)) >= 0xD800) {
382           result |= (next & 0x1FFF) << shift;
383           shift += 13;
384         }
385         next = result | (next << shift);
386       }
387       repeatedFieldCount = next;
388 
389       next = info.charAt(i++);
390       if (next >= 0xD800) {
391         int result = next & 0x1FFF;
392         int shift = 13;
393         while ((next = info.charAt(i++)) >= 0xD800) {
394           result |= (next & 0x1FFF) << shift;
395           shift += 13;
396         }
397         next = result | (next << shift);
398       }
399       checkInitialized = next;
400       intArray = new int[checkInitialized + mapFieldCount + repeatedFieldCount];
401       // Field objects are after a list of (oneof, oneofCase) pairs  + a list of hasbits fields.
402       objectsPosition = oneofCount * 2 + hasBitsCount;
403     }
404 
405     final sun.misc.Unsafe unsafe = UNSAFE;
406     final Object[] messageInfoObjects = messageInfo.getObjects();
407     int checkInitializedPosition = 0;
408     final Class<?> messageClass = messageInfo.getDefaultInstance().getClass();
409     int[] buffer = new int[numEntries * INTS_PER_FIELD];
410     Object[] objects = new Object[numEntries * 2];
411 
412     int mapFieldIndex = checkInitialized;
413     int repeatedFieldIndex = checkInitialized + mapFieldCount;
414 
415     int bufferIndex = 0;
416     while (i < length) {
417       final int fieldNumber;
418       final int fieldTypeWithExtraBits;
419       final int fieldType;
420 
421       next = info.charAt(i++);
422       if (next >= 0xD800) {
423         int result = next & 0x1FFF;
424         int shift = 13;
425         while ((next = info.charAt(i++)) >= 0xD800) {
426           result |= (next & 0x1FFF) << shift;
427           shift += 13;
428         }
429         next = result | (next << shift);
430       }
431       fieldNumber = next;
432 
433       next = info.charAt(i++);
434       if (next >= 0xD800) {
435         int result = next & 0x1FFF;
436         int shift = 13;
437         while ((next = info.charAt(i++)) >= 0xD800) {
438           result |= (next & 0x1FFF) << shift;
439           shift += 13;
440         }
441         next = result | (next << shift);
442       }
443       fieldTypeWithExtraBits = next;
444       fieldType = fieldTypeWithExtraBits & 0xFF;
445 
446       if ((fieldTypeWithExtraBits & 0x400) != 0) {
447         intArray[checkInitializedPosition++] = bufferIndex;
448       }
449 
450       final int fieldOffset;
451       final int presenceMaskShift;
452       final int presenceFieldOffset;
453 
454       // Oneof
455       if (fieldType >= ONEOF_TYPE_OFFSET) {
456         next = info.charAt(i++);
457         if (next >= 0xD800) {
458           int result = next & 0x1FFF;
459           int shift = 13;
460           while ((next = info.charAt(i++)) >= 0xD800) {
461             result |= (next & 0x1FFF) << shift;
462             shift += 13;
463           }
464           next = result | (next << shift);
465         }
466         int oneofIndex = next;
467 
468         final int oneofFieldType = fieldType - ONEOF_TYPE_OFFSET;
469         if (oneofFieldType == 9 /* FieldType.MESSAGE */
470             || oneofFieldType == 17 /* FieldType.GROUP */) {
471           objects[bufferIndex / INTS_PER_FIELD * 2 + 1] = messageInfoObjects[objectsPosition++];
472         } else if (oneofFieldType == 12 /* FieldType.ENUM */) {
473           if (!isProto3) {
474             objects[bufferIndex / INTS_PER_FIELD * 2 + 1] = messageInfoObjects[objectsPosition++];
475           }
476         }
477 
478         final java.lang.reflect.Field oneofField;
479         int index = oneofIndex * 2;
480         Object o = messageInfoObjects[index];
481         if (o instanceof java.lang.reflect.Field) {
482           oneofField = (java.lang.reflect.Field) o;
483         } else {
484           oneofField = reflectField(messageClass, (String) o);
485           // Memoize java.lang.reflect.Field instances for oneof/hasbits fields, since they're
486           // potentially used for many Protobuf fields.  Since there's a 1-1 mapping from the
487           // Protobuf field to the Java Field for non-oneofs, there's no benefit for memoizing
488           // those.
489           messageInfoObjects[index] = oneofField;
490         }
491 
492         fieldOffset = (int) unsafe.objectFieldOffset(oneofField);
493 
494         final java.lang.reflect.Field oneofCaseField;
495         index++;
496         o = messageInfoObjects[index];
497         if (o instanceof java.lang.reflect.Field) {
498           oneofCaseField = (java.lang.reflect.Field) o;
499         } else {
500           oneofCaseField = reflectField(messageClass, (String) o);
501           messageInfoObjects[index] = oneofCaseField;
502         }
503 
504         presenceFieldOffset = (int) unsafe.objectFieldOffset(oneofCaseField);
505         presenceMaskShift = 0;
506       } else {
507         Field field = reflectField(messageClass, (String) messageInfoObjects[objectsPosition++]);
508         if (fieldType == 9 /* FieldType.MESSAGE */ || fieldType == 17 /* FieldType.GROUP */) {
509           objects[bufferIndex / INTS_PER_FIELD * 2 + 1] = field.getType();
510         } else if (fieldType == 27 /* FieldType.MESSAGE_LIST */
511             || fieldType == 49 /* FieldType.GROUP_LIST */) {
512           objects[bufferIndex / INTS_PER_FIELD * 2 + 1] = messageInfoObjects[objectsPosition++];
513         } else if (fieldType == 12 /* FieldType.ENUM */
514             || fieldType == 30 /* FieldType.ENUM_LIST */
515             || fieldType == 44 /* FieldType.ENUM_LIST_PACKED */) {
516           if (!isProto3) {
517             objects[bufferIndex / INTS_PER_FIELD * 2 + 1] = messageInfoObjects[objectsPosition++];
518           }
519         } else if (fieldType == 50 /* FieldType.MAP */) {
520           intArray[mapFieldIndex++] = bufferIndex;
521           objects[bufferIndex / INTS_PER_FIELD * 2] = messageInfoObjects[objectsPosition++];
522           if ((fieldTypeWithExtraBits & 0x800) != 0) {
523             objects[bufferIndex / INTS_PER_FIELD * 2 + 1] = messageInfoObjects[objectsPosition++];
524           }
525         }
526 
527         fieldOffset = (int) unsafe.objectFieldOffset(field);
528         boolean hasHasBit = (fieldTypeWithExtraBits & 0x1000) == 0x1000;
529         if (hasHasBit && fieldType <= 17 /* FieldType.GROUP */) {
530           next = info.charAt(i++);
531           if (next >= 0xD800) {
532             int result = next & 0x1FFF;
533             int shift = 13;
534             while ((next = info.charAt(i++)) >= 0xD800) {
535               result |= (next & 0x1FFF) << shift;
536               shift += 13;
537             }
538             next = result | (next << shift);
539           }
540           int hasBitsIndex = next;
541 
542           final java.lang.reflect.Field hasBitsField;
543           int index = oneofCount * 2 + hasBitsIndex / 32;
544           Object o = messageInfoObjects[index];
545           if (o instanceof java.lang.reflect.Field) {
546             hasBitsField = (java.lang.reflect.Field) o;
547           } else {
548             hasBitsField = reflectField(messageClass, (String) o);
549             messageInfoObjects[index] = hasBitsField;
550           }
551 
552           presenceFieldOffset = (int) unsafe.objectFieldOffset(hasBitsField);
553           presenceMaskShift = hasBitsIndex % 32;
554         } else {
555           presenceFieldOffset = NO_PRESENCE_SENTINEL;
556           presenceMaskShift = 0;
557         }
558 
559         if (fieldType >= 18 && fieldType <= 49) {
560           // Field types of repeated fields are in a consecutive range from 18 (DOUBLE_LIST) to
561           // 49 (GROUP_LIST).
562           intArray[repeatedFieldIndex++] = fieldOffset;
563         }
564       }
565 
566       buffer[bufferIndex++] = fieldNumber;
567       buffer[bufferIndex++] =
568           ((fieldTypeWithExtraBits & 0x200) != 0 ? ENFORCE_UTF8_MASK : 0)
569               | ((fieldTypeWithExtraBits & 0x100) != 0 ? REQUIRED_MASK : 0)
570               | (fieldType << OFFSET_BITS)
571               | fieldOffset;
572       buffer[bufferIndex++] = (presenceMaskShift << OFFSET_BITS) | presenceFieldOffset;
573     }
574 
575     return new MessageSchema<T>(
576         buffer,
577         objects,
578         minFieldNumber,
579         maxFieldNumber,
580         messageInfo.getDefaultInstance(),
581         isProto3,
582         /* useCachedSizeField= */ false,
583         intArray,
584         checkInitialized,
585         checkInitialized + mapFieldCount,
586         newInstanceSchema,
587         listFieldSchema,
588         unknownFieldSchema,
589         extensionSchema,
590         mapFieldSchema);
591   }
592 
reflectField(Class<?> messageClass, String fieldName)593   private static java.lang.reflect.Field reflectField(Class<?> messageClass, String fieldName) {
594     try {
595       return messageClass.getDeclaredField(fieldName);
596     } catch (NoSuchFieldException e) {
597       // Some Samsung devices lie about what fields are present via the getDeclaredField API so
598       // we do the for loop properly that they seem to have messed up...
599       java.lang.reflect.Field[] fields = messageClass.getDeclaredFields();
600       for (java.lang.reflect.Field field : fields) {
601         if (fieldName.equals(field.getName())) {
602           return field;
603         }
604       }
605 
606       // If we make it here, the runtime still lies about what we know to be true at compile
607       // time. We throw to alert server monitoring for further remediation.
608       throw new RuntimeException(
609           "Field "
610               + fieldName
611               + " for "
612               + messageClass.getName()
613               + " not found. Known fields are "
614               + Arrays.toString(fields));
615     }
616   }
617 
newSchemaForMessageInfo( StructuralMessageInfo messageInfo, NewInstanceSchema newInstanceSchema, ListFieldSchema listFieldSchema, UnknownFieldSchema<?, ?> unknownFieldSchema, ExtensionSchema<?> extensionSchema, MapFieldSchema mapFieldSchema)618   static <T> MessageSchema<T> newSchemaForMessageInfo(
619       StructuralMessageInfo messageInfo,
620       NewInstanceSchema newInstanceSchema,
621       ListFieldSchema listFieldSchema,
622       UnknownFieldSchema<?, ?> unknownFieldSchema,
623       ExtensionSchema<?> extensionSchema,
624       MapFieldSchema mapFieldSchema) {
625     final boolean isProto3 = messageInfo.getSyntax() == ProtoSyntax.PROTO3;
626     FieldInfo[] fis = messageInfo.getFields();
627     final int minFieldNumber;
628     final int maxFieldNumber;
629     if (fis.length == 0) {
630       minFieldNumber = 0;
631       maxFieldNumber = 0;
632     } else {
633       minFieldNumber = fis[0].getFieldNumber();
634       maxFieldNumber = fis[fis.length - 1].getFieldNumber();
635     }
636 
637     final int numEntries = fis.length;
638 
639     int[] buffer = new int[numEntries * INTS_PER_FIELD];
640     Object[] objects = new Object[numEntries * 2];
641 
642     int mapFieldCount = 0;
643     int repeatedFieldCount = 0;
644     for (FieldInfo fi : fis) {
645       if (fi.getType() == FieldType.MAP) {
646         mapFieldCount++;
647       } else if (fi.getType().id() >= 18 && fi.getType().id() <= 49) {
648         // Field types of repeated fields are in a consecutive range from 18 (DOUBLE_LIST) to
649         // 49 (GROUP_LIST).
650         repeatedFieldCount++;
651       }
652     }
653     int[] mapFieldPositions = mapFieldCount > 0 ? new int[mapFieldCount] : null;
654     int[] repeatedFieldOffsets = repeatedFieldCount > 0 ? new int[repeatedFieldCount] : null;
655     mapFieldCount = 0;
656     repeatedFieldCount = 0;
657 
658     int[] checkInitialized = messageInfo.getCheckInitialized();
659     if (checkInitialized == null) {
660       checkInitialized = EMPTY_INT_ARRAY;
661     }
662     int checkInitializedIndex = 0;
663     // Fill in the manifest data from the descriptors.
664     int fieldIndex = 0;
665     for (int bufferIndex = 0; fieldIndex < fis.length; bufferIndex += INTS_PER_FIELD) {
666       final FieldInfo fi = fis[fieldIndex];
667       final int fieldNumber = fi.getFieldNumber();
668 
669       // We found the entry for the next field. Store the entry in the manifest for
670       // this field and increment the field index.
671       storeFieldData(fi, buffer, bufferIndex, objects);
672 
673       // Convert field number to index
674       if (checkInitializedIndex < checkInitialized.length
675           && checkInitialized[checkInitializedIndex] == fieldNumber) {
676         checkInitialized[checkInitializedIndex++] = bufferIndex;
677       }
678 
679       if (fi.getType() == FieldType.MAP) {
680         mapFieldPositions[mapFieldCount++] = bufferIndex;
681       } else if (fi.getType().id() >= 18 && fi.getType().id() <= 49) {
682         // Field types of repeated fields are in a consecutive range from 18 (DOUBLE_LIST) to
683         // 49 (GROUP_LIST).
684         repeatedFieldOffsets[repeatedFieldCount++] =
685             (int) UnsafeUtil.objectFieldOffset(fi.getField());
686       }
687 
688       fieldIndex++;
689     }
690 
691     if (mapFieldPositions == null) {
692       mapFieldPositions = EMPTY_INT_ARRAY;
693     }
694     if (repeatedFieldOffsets == null) {
695       repeatedFieldOffsets = EMPTY_INT_ARRAY;
696     }
697     int[] combined =
698         new int[checkInitialized.length + mapFieldPositions.length + repeatedFieldOffsets.length];
699     System.arraycopy(checkInitialized, 0, combined, 0, checkInitialized.length);
700     System.arraycopy(
701         mapFieldPositions, 0, combined, checkInitialized.length, mapFieldPositions.length);
702     System.arraycopy(
703         repeatedFieldOffsets,
704         0,
705         combined,
706         checkInitialized.length + mapFieldPositions.length,
707         repeatedFieldOffsets.length);
708 
709     return new MessageSchema<T>(
710         buffer,
711         objects,
712         minFieldNumber,
713         maxFieldNumber,
714         messageInfo.getDefaultInstance(),
715         isProto3,
716         /* useCachedSizeField= */ true,
717         combined,
718         checkInitialized.length,
719         checkInitialized.length + mapFieldPositions.length,
720         newInstanceSchema,
721         listFieldSchema,
722         unknownFieldSchema,
723         extensionSchema,
724         mapFieldSchema);
725   }
726 
storeFieldData( FieldInfo fi, int[] buffer, int bufferIndex, Object[] objects)727   private static void storeFieldData(
728       FieldInfo fi, int[] buffer, int bufferIndex, Object[] objects) {
729     final int fieldOffset;
730     final int typeId;
731     final int presenceMaskShift;
732     final int presenceFieldOffset;
733 
734     OneofInfo oneof = fi.getOneof();
735     if (oneof != null) {
736       typeId = fi.getType().id() + ONEOF_TYPE_OFFSET;
737       fieldOffset = (int) UnsafeUtil.objectFieldOffset(oneof.getValueField());
738       presenceFieldOffset = (int) UnsafeUtil.objectFieldOffset(oneof.getCaseField());
739       presenceMaskShift = 0;
740     } else {
741       FieldType type = fi.getType();
742       fieldOffset = (int) UnsafeUtil.objectFieldOffset(fi.getField());
743       typeId = type.id();
744       if (!type.isList() && !type.isMap()) {
745         Field presenceField = fi.getPresenceField();
746         if (presenceField == null) {
747           presenceFieldOffset = NO_PRESENCE_SENTINEL;
748         } else {
749           presenceFieldOffset = (int) UnsafeUtil.objectFieldOffset(presenceField);
750         }
751         presenceMaskShift = Integer.numberOfTrailingZeros(fi.getPresenceMask());
752       } else {
753         if (fi.getCachedSizeField() == null) {
754           presenceFieldOffset = 0;
755           presenceMaskShift = 0;
756         } else {
757           presenceFieldOffset = (int) UnsafeUtil.objectFieldOffset(fi.getCachedSizeField());
758           presenceMaskShift = 0;
759         }
760       }
761     }
762 
763     buffer[bufferIndex] = fi.getFieldNumber();
764     buffer[bufferIndex + 1] =
765         (fi.isEnforceUtf8() ? ENFORCE_UTF8_MASK : 0)
766             | (fi.isRequired() ? REQUIRED_MASK : 0)
767             | (typeId << OFFSET_BITS)
768             | fieldOffset;
769     buffer[bufferIndex + 2] = (presenceMaskShift << OFFSET_BITS) | presenceFieldOffset;
770 
771     Object messageFieldClass = fi.getMessageFieldClass();
772     if (fi.getMapDefaultEntry() != null) {
773       objects[bufferIndex / INTS_PER_FIELD * 2] = fi.getMapDefaultEntry();
774       if (messageFieldClass != null) {
775         objects[bufferIndex / INTS_PER_FIELD * 2 + 1] = messageFieldClass;
776       } else if (fi.getEnumVerifier() != null) {
777         objects[bufferIndex / INTS_PER_FIELD * 2 + 1] = fi.getEnumVerifier();
778       }
779     } else {
780       if (messageFieldClass != null) {
781         objects[bufferIndex / INTS_PER_FIELD * 2 + 1] = messageFieldClass;
782       } else if (fi.getEnumVerifier() != null) {
783         objects[bufferIndex / INTS_PER_FIELD * 2 + 1] = fi.getEnumVerifier();
784       }
785     }
786   }
787 
788   @SuppressWarnings("unchecked")
789   @Override
newInstance()790   public T newInstance() {
791     return (T) newInstanceSchema.newInstance(defaultInstance);
792   }
793 
794   @Override
equals(T message, T other)795   public boolean equals(T message, T other) {
796     final int bufferLength = buffer.length;
797     for (int pos = 0; pos < bufferLength; pos += INTS_PER_FIELD) {
798       if (!equals(message, other, pos)) {
799         return false;
800       }
801     }
802 
803     Object messageUnknown = unknownFieldSchema.getFromMessage(message);
804     Object otherUnknown = unknownFieldSchema.getFromMessage(other);
805     if (!messageUnknown.equals(otherUnknown)) {
806       return false;
807     }
808 
809     if (hasExtensions) {
810       FieldSet<?> messageExtensions = extensionSchema.getExtensions(message);
811       FieldSet<?> otherExtensions = extensionSchema.getExtensions(other);
812       return messageExtensions.equals(otherExtensions);
813     }
814     return true;
815   }
816 
equals(T message, T other, int pos)817   private boolean equals(T message, T other, int pos) {
818     final int typeAndOffset = typeAndOffsetAt(pos);
819     final long offset = offset(typeAndOffset);
820 
821     switch (type(typeAndOffset)) {
822       case 0: // DOUBLE:
823         return arePresentForEquals(message, other, pos)
824             && Double.doubleToLongBits(UnsafeUtil.getDouble(message, offset))
825                 == Double.doubleToLongBits(UnsafeUtil.getDouble(other, offset));
826       case 1: // FLOAT:
827         return arePresentForEquals(message, other, pos)
828             && Float.floatToIntBits(UnsafeUtil.getFloat(message, offset))
829                 == Float.floatToIntBits(UnsafeUtil.getFloat(other, offset));
830       case 2: // INT64:
831         return arePresentForEquals(message, other, pos)
832             && UnsafeUtil.getLong(message, offset) == UnsafeUtil.getLong(other, offset);
833       case 3: // UINT64:
834         return arePresentForEquals(message, other, pos)
835             && UnsafeUtil.getLong(message, offset) == UnsafeUtil.getLong(other, offset);
836       case 4: // INT32:
837         return arePresentForEquals(message, other, pos)
838             && UnsafeUtil.getInt(message, offset) == UnsafeUtil.getInt(other, offset);
839       case 5: // FIXED64:
840         return arePresentForEquals(message, other, pos)
841             && UnsafeUtil.getLong(message, offset) == UnsafeUtil.getLong(other, offset);
842       case 6: // FIXED32:
843         return arePresentForEquals(message, other, pos)
844             && UnsafeUtil.getInt(message, offset) == UnsafeUtil.getInt(other, offset);
845       case 7: // BOOL:
846         return arePresentForEquals(message, other, pos)
847             && UnsafeUtil.getBoolean(message, offset) == UnsafeUtil.getBoolean(other, offset);
848       case 8: // STRING:
849         return arePresentForEquals(message, other, pos)
850             && SchemaUtil.safeEquals(
851                 UnsafeUtil.getObject(message, offset), UnsafeUtil.getObject(other, offset));
852       case 9: // MESSAGE:
853         return arePresentForEquals(message, other, pos)
854             && SchemaUtil.safeEquals(
855                 UnsafeUtil.getObject(message, offset), UnsafeUtil.getObject(other, offset));
856       case 10: // BYTES:
857         return arePresentForEquals(message, other, pos)
858             && SchemaUtil.safeEquals(
859                 UnsafeUtil.getObject(message, offset), UnsafeUtil.getObject(other, offset));
860       case 11: // UINT32:
861         return arePresentForEquals(message, other, pos)
862             && UnsafeUtil.getInt(message, offset) == UnsafeUtil.getInt(other, offset);
863       case 12: // ENUM:
864         return arePresentForEquals(message, other, pos)
865             && UnsafeUtil.getInt(message, offset) == UnsafeUtil.getInt(other, offset);
866       case 13: // SFIXED32:
867         return arePresentForEquals(message, other, pos)
868             && UnsafeUtil.getInt(message, offset) == UnsafeUtil.getInt(other, offset);
869       case 14: // SFIXED64:
870         return arePresentForEquals(message, other, pos)
871             && UnsafeUtil.getLong(message, offset) == UnsafeUtil.getLong(other, offset);
872       case 15: // SINT32:
873         return arePresentForEquals(message, other, pos)
874             && UnsafeUtil.getInt(message, offset) == UnsafeUtil.getInt(other, offset);
875       case 16: // SINT64:
876         return arePresentForEquals(message, other, pos)
877             && UnsafeUtil.getLong(message, offset) == UnsafeUtil.getLong(other, offset);
878       case 17: // GROUP:
879         return arePresentForEquals(message, other, pos)
880             && SchemaUtil.safeEquals(
881                 UnsafeUtil.getObject(message, offset), UnsafeUtil.getObject(other, offset));
882 
883       case 18: // DOUBLE_LIST:
884       case 19: // FLOAT_LIST:
885       case 20: // INT64_LIST:
886       case 21: // UINT64_LIST:
887       case 22: // INT32_LIST:
888       case 23: // FIXED64_LIST:
889       case 24: // FIXED32_LIST:
890       case 25: // BOOL_LIST:
891       case 26: // STRING_LIST:
892       case 27: // MESSAGE_LIST:
893       case 28: // BYTES_LIST:
894       case 29: // UINT32_LIST:
895       case 30: // ENUM_LIST:
896       case 31: // SFIXED32_LIST:
897       case 32: // SFIXED64_LIST:
898       case 33: // SINT32_LIST:
899       case 34: // SINT64_LIST:
900       case 35: // DOUBLE_LIST_PACKED:
901       case 36: // FLOAT_LIST_PACKED:
902       case 37: // INT64_LIST_PACKED:
903       case 38: // UINT64_LIST_PACKED:
904       case 39: // INT32_LIST_PACKED:
905       case 40: // FIXED64_LIST_PACKED:
906       case 41: // FIXED32_LIST_PACKED:
907       case 42: // BOOL_LIST_PACKED:
908       case 43: // UINT32_LIST_PACKED:
909       case 44: // ENUM_LIST_PACKED:
910       case 45: // SFIXED32_LIST_PACKED:
911       case 46: // SFIXED64_LIST_PACKED:
912       case 47: // SINT32_LIST_PACKED:
913       case 48: // SINT64_LIST_PACKED:
914       case 49: // GROUP_LIST:
915         return SchemaUtil.safeEquals(
916             UnsafeUtil.getObject(message, offset), UnsafeUtil.getObject(other, offset));
917       case 50: // MAP:
918         return SchemaUtil.safeEquals(
919             UnsafeUtil.getObject(message, offset), UnsafeUtil.getObject(other, offset));
920       case 51: // ONEOF_DOUBLE:
921       case 52: // ONEOF_FLOAT:
922       case 53: // ONEOF_INT64:
923       case 54: // ONEOF_UINT64:
924       case 55: // ONEOF_INT32:
925       case 56: // ONEOF_FIXED64:
926       case 57: // ONEOF_FIXED32:
927       case 58: // ONEOF_BOOL:
928       case 59: // ONEOF_STRING:
929       case 60: // ONEOF_MESSAGE:
930       case 61: // ONEOF_BYTES:
931       case 62: // ONEOF_UINT32:
932       case 63: // ONEOF_ENUM:
933       case 64: // ONEOF_SFIXED32:
934       case 65: // ONEOF_SFIXED64:
935       case 66: // ONEOF_SINT32:
936       case 67: // ONEOF_SINT64:
937       case 68: // ONEOF_GROUP:
938         return isOneofCaseEqual(message, other, pos)
939             && SchemaUtil.safeEquals(
940                 UnsafeUtil.getObject(message, offset), UnsafeUtil.getObject(other, offset));
941       default:
942         // Assume it's an empty entry - just go to the next entry.
943         return true;
944     }
945   }
946 
947   @Override
hashCode(T message)948   public int hashCode(T message) {
949     int hashCode = 0;
950     final int bufferLength = buffer.length;
951     for (int pos = 0; pos < bufferLength; pos += INTS_PER_FIELD) {
952       final int typeAndOffset = typeAndOffsetAt(pos);
953       final int entryNumber = numberAt(pos);
954 
955       final long offset = offset(typeAndOffset);
956 
957       switch (type(typeAndOffset)) {
958         case 0: // DOUBLE:
959           hashCode =
960               (hashCode * 53)
961                   + Internal.hashLong(
962                       Double.doubleToLongBits(UnsafeUtil.getDouble(message, offset)));
963           break;
964         case 1: // FLOAT:
965           hashCode = (hashCode * 53) + Float.floatToIntBits(UnsafeUtil.getFloat(message, offset));
966           break;
967         case 2: // INT64:
968           hashCode = (hashCode * 53) + Internal.hashLong(UnsafeUtil.getLong(message, offset));
969           break;
970         case 3: // UINT64:
971           hashCode = (hashCode * 53) + Internal.hashLong(UnsafeUtil.getLong(message, offset));
972           break;
973         case 4: // INT32:
974           hashCode = (hashCode * 53) + (UnsafeUtil.getInt(message, offset));
975           break;
976         case 5: // FIXED64:
977           hashCode = (hashCode * 53) + Internal.hashLong(UnsafeUtil.getLong(message, offset));
978           break;
979         case 6: // FIXED32:
980           hashCode = (hashCode * 53) + (UnsafeUtil.getInt(message, offset));
981           break;
982         case 7: // BOOL:
983           hashCode = (hashCode * 53) + Internal.hashBoolean(UnsafeUtil.getBoolean(message, offset));
984           break;
985         case 8: // STRING:
986           hashCode = (hashCode * 53) + ((String) UnsafeUtil.getObject(message, offset)).hashCode();
987           break;
988         case 9: // MESSAGE:
989           {
990             int protoHash = 37;
991             Object submessage = UnsafeUtil.getObject(message, offset);
992             if (submessage != null) {
993               protoHash = submessage.hashCode();
994             }
995             hashCode = (53 * hashCode) + protoHash;
996             break;
997           }
998         case 10: // BYTES:
999           hashCode = (hashCode * 53) + UnsafeUtil.getObject(message, offset).hashCode();
1000           break;
1001         case 11: // UINT32:
1002           hashCode = (hashCode * 53) + (UnsafeUtil.getInt(message, offset));
1003           break;
1004         case 12: // ENUM:
1005           hashCode = (hashCode * 53) + (UnsafeUtil.getInt(message, offset));
1006           break;
1007         case 13: // SFIXED32:
1008           hashCode = (hashCode * 53) + (UnsafeUtil.getInt(message, offset));
1009           break;
1010         case 14: // SFIXED64:
1011           hashCode = (hashCode * 53) + Internal.hashLong(UnsafeUtil.getLong(message, offset));
1012           break;
1013         case 15: // SINT32:
1014           hashCode = (hashCode * 53) + (UnsafeUtil.getInt(message, offset));
1015           break;
1016         case 16: // SINT64:
1017           hashCode = (hashCode * 53) + Internal.hashLong(UnsafeUtil.getLong(message, offset));
1018           break;
1019 
1020         case 17: // GROUP:
1021           {
1022             int protoHash = 37;
1023             Object submessage = UnsafeUtil.getObject(message, offset);
1024             if (submessage != null) {
1025               protoHash = submessage.hashCode();
1026             }
1027             hashCode = (53 * hashCode) + protoHash;
1028             break;
1029           }
1030         case 18: // DOUBLE_LIST:
1031         case 19: // FLOAT_LIST:
1032         case 20: // INT64_LIST:
1033         case 21: // UINT64_LIST:
1034         case 22: // INT32_LIST:
1035         case 23: // FIXED64_LIST:
1036         case 24: // FIXED32_LIST:
1037         case 25: // BOOL_LIST:
1038         case 26: // STRING_LIST:
1039         case 27: // MESSAGE_LIST:
1040         case 28: // BYTES_LIST:
1041         case 29: // UINT32_LIST:
1042         case 30: // ENUM_LIST:
1043         case 31: // SFIXED32_LIST:
1044         case 32: // SFIXED64_LIST:
1045         case 33: // SINT32_LIST:
1046         case 34: // SINT64_LIST:
1047         case 35: // DOUBLE_LIST_PACKED:
1048         case 36: // FLOAT_LIST_PACKED:
1049         case 37: // INT64_LIST_PACKED:
1050         case 38: // UINT64_LIST_PACKED:
1051         case 39: // INT32_LIST_PACKED:
1052         case 40: // FIXED64_LIST_PACKED:
1053         case 41: // FIXED32_LIST_PACKED:
1054         case 42: // BOOL_LIST_PACKED:
1055         case 43: // UINT32_LIST_PACKED:
1056         case 44: // ENUM_LIST_PACKED:
1057         case 45: // SFIXED32_LIST_PACKED:
1058         case 46: // SFIXED64_LIST_PACKED:
1059         case 47: // SINT32_LIST_PACKED:
1060         case 48: // SINT64_LIST_PACKED:
1061         case 49: // GROUP_LIST:
1062           hashCode = (hashCode * 53) + UnsafeUtil.getObject(message, offset).hashCode();
1063           break;
1064         case 50: // MAP:
1065           hashCode = (hashCode * 53) + UnsafeUtil.getObject(message, offset).hashCode();
1066           break;
1067         case 51: // ONEOF_DOUBLE:
1068           if (isOneofPresent(message, entryNumber, pos)) {
1069             hashCode =
1070                 (hashCode * 53)
1071                     + Internal.hashLong(Double.doubleToLongBits(oneofDoubleAt(message, offset)));
1072           }
1073           break;
1074         case 52: // ONEOF_FLOAT:
1075           if (isOneofPresent(message, entryNumber, pos)) {
1076             hashCode = (hashCode * 53) + Float.floatToIntBits(oneofFloatAt(message, offset));
1077           }
1078           break;
1079         case 53: // ONEOF_INT64:
1080           if (isOneofPresent(message, entryNumber, pos)) {
1081             hashCode = (hashCode * 53) + Internal.hashLong(oneofLongAt(message, offset));
1082           }
1083           break;
1084         case 54: // ONEOF_UINT64:
1085           if (isOneofPresent(message, entryNumber, pos)) {
1086             hashCode = (hashCode * 53) + Internal.hashLong(oneofLongAt(message, offset));
1087           }
1088           break;
1089         case 55: // ONEOF_INT32:
1090           if (isOneofPresent(message, entryNumber, pos)) {
1091             hashCode = (hashCode * 53) + (oneofIntAt(message, offset));
1092           }
1093           break;
1094         case 56: // ONEOF_FIXED64:
1095           if (isOneofPresent(message, entryNumber, pos)) {
1096             hashCode = (hashCode * 53) + Internal.hashLong(oneofLongAt(message, offset));
1097           }
1098           break;
1099         case 57: // ONEOF_FIXED32:
1100           if (isOneofPresent(message, entryNumber, pos)) {
1101             hashCode = (hashCode * 53) + (oneofIntAt(message, offset));
1102           }
1103           break;
1104         case 58: // ONEOF_BOOL:
1105           if (isOneofPresent(message, entryNumber, pos)) {
1106             hashCode = (hashCode * 53) + Internal.hashBoolean(oneofBooleanAt(message, offset));
1107           }
1108           break;
1109         case 59: // ONEOF_STRING:
1110           if (isOneofPresent(message, entryNumber, pos)) {
1111             hashCode =
1112                 (hashCode * 53) + ((String) UnsafeUtil.getObject(message, offset)).hashCode();
1113           }
1114           break;
1115         case 60: // ONEOF_MESSAGE:
1116           if (isOneofPresent(message, entryNumber, pos)) {
1117             Object submessage = UnsafeUtil.getObject(message, offset);
1118             hashCode = (53 * hashCode) + submessage.hashCode();
1119           }
1120           break;
1121         case 61: // ONEOF_BYTES:
1122           if (isOneofPresent(message, entryNumber, pos)) {
1123             hashCode = (hashCode * 53) + UnsafeUtil.getObject(message, offset).hashCode();
1124           }
1125           break;
1126         case 62: // ONEOF_UINT32:
1127           if (isOneofPresent(message, entryNumber, pos)) {
1128             hashCode = (hashCode * 53) + (oneofIntAt(message, offset));
1129           }
1130           break;
1131         case 63: // ONEOF_ENUM:
1132           if (isOneofPresent(message, entryNumber, pos)) {
1133             hashCode = (hashCode * 53) + (oneofIntAt(message, offset));
1134           }
1135           break;
1136         case 64: // ONEOF_SFIXED32:
1137           if (isOneofPresent(message, entryNumber, pos)) {
1138             hashCode = (hashCode * 53) + (oneofIntAt(message, offset));
1139           }
1140           break;
1141         case 65: // ONEOF_SFIXED64:
1142           if (isOneofPresent(message, entryNumber, pos)) {
1143             hashCode = (hashCode * 53) + Internal.hashLong(oneofLongAt(message, offset));
1144           }
1145           break;
1146         case 66: // ONEOF_SINT32:
1147           if (isOneofPresent(message, entryNumber, pos)) {
1148             hashCode = (hashCode * 53) + (oneofIntAt(message, offset));
1149           }
1150           break;
1151         case 67: // ONEOF_SINT64:
1152           if (isOneofPresent(message, entryNumber, pos)) {
1153             hashCode = (hashCode * 53) + Internal.hashLong(oneofLongAt(message, offset));
1154           }
1155           break;
1156         case 68: // ONEOF_GROUP:
1157           if (isOneofPresent(message, entryNumber, pos)) {
1158             Object submessage = UnsafeUtil.getObject(message, offset);
1159             hashCode = (53 * hashCode) + submessage.hashCode();
1160           }
1161           break;
1162         default:
1163           // Assume it's an empty entry - just go to the next entry.
1164           break;
1165       }
1166     }
1167 
1168     hashCode = (hashCode * 53) + unknownFieldSchema.getFromMessage(message).hashCode();
1169 
1170     if (hasExtensions) {
1171       hashCode = (hashCode * 53) + extensionSchema.getExtensions(message).hashCode();
1172     }
1173 
1174     return hashCode;
1175   }
1176 
1177   @Override
mergeFrom(T message, T other)1178   public void mergeFrom(T message, T other) {
1179     if (other == null) {
1180       throw new NullPointerException();
1181     }
1182     for (int i = 0; i < buffer.length; i += INTS_PER_FIELD) {
1183       // A separate method allows for better JIT optimizations
1184       mergeSingleField(message, other, i);
1185     }
1186 
1187     SchemaUtil.mergeUnknownFields(unknownFieldSchema, message, other);
1188 
1189     if (hasExtensions) {
1190       SchemaUtil.mergeExtensions(extensionSchema, message, other);
1191     }
1192   }
1193 
mergeSingleField(T message, T other, int pos)1194   private void mergeSingleField(T message, T other, int pos) {
1195     final int typeAndOffset = typeAndOffsetAt(pos);
1196     final long offset = offset(typeAndOffset);
1197     final int number = numberAt(pos);
1198 
1199     switch (type(typeAndOffset)) {
1200       case 0: // DOUBLE:
1201         if (isFieldPresent(other, pos)) {
1202           UnsafeUtil.putDouble(message, offset, UnsafeUtil.getDouble(other, offset));
1203           setFieldPresent(message, pos);
1204         }
1205         break;
1206       case 1: // FLOAT:
1207         if (isFieldPresent(other, pos)) {
1208           UnsafeUtil.putFloat(message, offset, UnsafeUtil.getFloat(other, offset));
1209           setFieldPresent(message, pos);
1210         }
1211         break;
1212       case 2: // INT64:
1213         if (isFieldPresent(other, pos)) {
1214           UnsafeUtil.putLong(message, offset, UnsafeUtil.getLong(other, offset));
1215           setFieldPresent(message, pos);
1216         }
1217         break;
1218       case 3: // UINT64:
1219         if (isFieldPresent(other, pos)) {
1220           UnsafeUtil.putLong(message, offset, UnsafeUtil.getLong(other, offset));
1221           setFieldPresent(message, pos);
1222         }
1223         break;
1224       case 4: // INT32:
1225         if (isFieldPresent(other, pos)) {
1226           UnsafeUtil.putInt(message, offset, UnsafeUtil.getInt(other, offset));
1227           setFieldPresent(message, pos);
1228         }
1229         break;
1230       case 5: // FIXED64:
1231         if (isFieldPresent(other, pos)) {
1232           UnsafeUtil.putLong(message, offset, UnsafeUtil.getLong(other, offset));
1233           setFieldPresent(message, pos);
1234         }
1235         break;
1236       case 6: // FIXED32:
1237         if (isFieldPresent(other, pos)) {
1238           UnsafeUtil.putInt(message, offset, UnsafeUtil.getInt(other, offset));
1239           setFieldPresent(message, pos);
1240         }
1241         break;
1242       case 7: // BOOL:
1243         if (isFieldPresent(other, pos)) {
1244           UnsafeUtil.putBoolean(message, offset, UnsafeUtil.getBoolean(other, offset));
1245           setFieldPresent(message, pos);
1246         }
1247         break;
1248       case 8: // STRING:
1249         if (isFieldPresent(other, pos)) {
1250           UnsafeUtil.putObject(message, offset, UnsafeUtil.getObject(other, offset));
1251           setFieldPresent(message, pos);
1252         }
1253         break;
1254       case 9: // MESSAGE:
1255         mergeMessage(message, other, pos);
1256         break;
1257       case 10: // BYTES:
1258         if (isFieldPresent(other, pos)) {
1259           UnsafeUtil.putObject(message, offset, UnsafeUtil.getObject(other, offset));
1260           setFieldPresent(message, pos);
1261         }
1262         break;
1263       case 11: // UINT32:
1264         if (isFieldPresent(other, pos)) {
1265           UnsafeUtil.putInt(message, offset, UnsafeUtil.getInt(other, offset));
1266           setFieldPresent(message, pos);
1267         }
1268         break;
1269       case 12: // ENUM:
1270         if (isFieldPresent(other, pos)) {
1271           UnsafeUtil.putInt(message, offset, UnsafeUtil.getInt(other, offset));
1272           setFieldPresent(message, pos);
1273         }
1274         break;
1275       case 13: // SFIXED32:
1276         if (isFieldPresent(other, pos)) {
1277           UnsafeUtil.putInt(message, offset, UnsafeUtil.getInt(other, offset));
1278           setFieldPresent(message, pos);
1279         }
1280         break;
1281       case 14: // SFIXED64:
1282         if (isFieldPresent(other, pos)) {
1283           UnsafeUtil.putLong(message, offset, UnsafeUtil.getLong(other, offset));
1284           setFieldPresent(message, pos);
1285         }
1286         break;
1287       case 15: // SINT32:
1288         if (isFieldPresent(other, pos)) {
1289           UnsafeUtil.putInt(message, offset, UnsafeUtil.getInt(other, offset));
1290           setFieldPresent(message, pos);
1291         }
1292         break;
1293       case 16: // SINT64:
1294         if (isFieldPresent(other, pos)) {
1295           UnsafeUtil.putLong(message, offset, UnsafeUtil.getLong(other, offset));
1296           setFieldPresent(message, pos);
1297         }
1298         break;
1299       case 17: // GROUP:
1300         mergeMessage(message, other, pos);
1301         break;
1302       case 18: // DOUBLE_LIST:
1303       case 19: // FLOAT_LIST:
1304       case 20: // INT64_LIST:
1305       case 21: // UINT64_LIST:
1306       case 22: // INT32_LIST:
1307       case 23: // FIXED64_LIST:
1308       case 24: // FIXED32_LIST:
1309       case 25: // BOOL_LIST:
1310       case 26: // STRING_LIST:
1311       case 27: // MESSAGE_LIST:
1312       case 28: // BYTES_LIST:
1313       case 29: // UINT32_LIST:
1314       case 30: // ENUM_LIST:
1315       case 31: // SFIXED32_LIST:
1316       case 32: // SFIXED64_LIST:
1317       case 33: // SINT32_LIST:
1318       case 34: // SINT64_LIST:
1319       case 35: // DOUBLE_LIST_PACKED:
1320       case 36: // FLOAT_LIST_PACKED:
1321       case 37: // INT64_LIST_PACKED:
1322       case 38: // UINT64_LIST_PACKED:
1323       case 39: // INT32_LIST_PACKED:
1324       case 40: // FIXED64_LIST_PACKED:
1325       case 41: // FIXED32_LIST_PACKED:
1326       case 42: // BOOL_LIST_PACKED:
1327       case 43: // UINT32_LIST_PACKED:
1328       case 44: // ENUM_LIST_PACKED:
1329       case 45: // SFIXED32_LIST_PACKED:
1330       case 46: // SFIXED64_LIST_PACKED:
1331       case 47: // SINT32_LIST_PACKED:
1332       case 48: // SINT64_LIST_PACKED:
1333       case 49: // GROUP_LIST:
1334         listFieldSchema.mergeListsAt(message, other, offset);
1335         break;
1336       case 50: // MAP:
1337         SchemaUtil.mergeMap(mapFieldSchema, message, other, offset);
1338         break;
1339       case 51: // ONEOF_DOUBLE:
1340       case 52: // ONEOF_FLOAT:
1341       case 53: // ONEOF_INT64:
1342       case 54: // ONEOF_UINT64:
1343       case 55: // ONEOF_INT32:
1344       case 56: // ONEOF_FIXED64:
1345       case 57: // ONEOF_FIXED32:
1346       case 58: // ONEOF_BOOL:
1347       case 59: // ONEOF_STRING:
1348         if (isOneofPresent(other, number, pos)) {
1349           UnsafeUtil.putObject(message, offset, UnsafeUtil.getObject(other, offset));
1350           setOneofPresent(message, number, pos);
1351         }
1352         break;
1353 
1354       case 60: // ONEOF_MESSAGE:
1355         mergeOneofMessage(message, other, pos);
1356         break;
1357       case 61: // ONEOF_BYTES:
1358       case 62: // ONEOF_UINT32:
1359       case 63: // ONEOF_ENUM:
1360       case 64: // ONEOF_SFIXED32:
1361       case 65: // ONEOF_SFIXED64:
1362       case 66: // ONEOF_SINT32:
1363       case 67: // ONEOF_SINT64:
1364         if (isOneofPresent(other, number, pos)) {
1365           UnsafeUtil.putObject(message, offset, UnsafeUtil.getObject(other, offset));
1366           setOneofPresent(message, number, pos);
1367         }
1368         break;
1369       case 68: // ONEOF_GROUP:
1370         mergeOneofMessage(message, other, pos);
1371         break;
1372       default:
1373         break;
1374     }
1375   }
1376 
mergeMessage(T message, T other, int pos)1377   private void mergeMessage(T message, T other, int pos) {
1378     final int typeAndOffset = typeAndOffsetAt(pos);
1379     final long offset = offset(typeAndOffset);
1380 
1381     if (!isFieldPresent(other, pos)) {
1382       return;
1383     }
1384 
1385     Object mine = UnsafeUtil.getObject(message, offset);
1386     Object theirs = UnsafeUtil.getObject(other, offset);
1387     if (mine != null && theirs != null) {
1388       Object merged = Internal.mergeMessage(mine, theirs);
1389       UnsafeUtil.putObject(message, offset, merged);
1390       setFieldPresent(message, pos);
1391     } else if (theirs != null) {
1392       UnsafeUtil.putObject(message, offset, theirs);
1393       setFieldPresent(message, pos);
1394     }
1395   }
1396 
mergeOneofMessage(T message, T other, int pos)1397   private void mergeOneofMessage(T message, T other, int pos) {
1398     int typeAndOffset = typeAndOffsetAt(pos);
1399     int number = numberAt(pos);
1400     long offset = offset(typeAndOffset);
1401 
1402     if (!isOneofPresent(other, number, pos)) {
1403       return;
1404     }
1405 
1406     Object mine = UnsafeUtil.getObject(message, offset);
1407     Object theirs = UnsafeUtil.getObject(other, offset);
1408     if (mine != null && theirs != null) {
1409       Object merged = Internal.mergeMessage(mine, theirs);
1410       UnsafeUtil.putObject(message, offset, merged);
1411       setOneofPresent(message, number, pos);
1412     } else if (theirs != null) {
1413       UnsafeUtil.putObject(message, offset, theirs);
1414       setOneofPresent(message, number, pos);
1415     }
1416   }
1417 
1418   @Override
getSerializedSize(T message)1419   public int getSerializedSize(T message) {
1420     return proto3 ? getSerializedSizeProto3(message) : getSerializedSizeProto2(message);
1421   }
1422 
1423   @SuppressWarnings("unchecked")
getSerializedSizeProto2(T message)1424   private int getSerializedSizeProto2(T message) {
1425     int size = 0;
1426 
1427     final sun.misc.Unsafe unsafe = UNSAFE;
1428     int currentPresenceFieldOffset = NO_PRESENCE_SENTINEL;
1429     int currentPresenceField = 0;
1430     for (int i = 0; i < buffer.length; i += INTS_PER_FIELD) {
1431       final int typeAndOffset = typeAndOffsetAt(i);
1432       final int number = numberAt(i);
1433 
1434       int fieldType = type(typeAndOffset);
1435       int presenceMaskAndOffset = 0;
1436       int presenceMask = 0;
1437       if (fieldType <= 17) {
1438         presenceMaskAndOffset = buffer[i + 2];
1439         final int presenceFieldOffset = presenceMaskAndOffset & OFFSET_MASK;
1440         presenceMask = 1 << (presenceMaskAndOffset >>> OFFSET_BITS);
1441         if (presenceFieldOffset != currentPresenceFieldOffset) {
1442           currentPresenceFieldOffset = presenceFieldOffset;
1443           currentPresenceField = unsafe.getInt(message, (long) presenceFieldOffset);
1444         }
1445       } else if (useCachedSizeField
1446           && fieldType >= FieldType.DOUBLE_LIST_PACKED.id()
1447           && fieldType <= FieldType.SINT64_LIST_PACKED.id()) {
1448         presenceMaskAndOffset = buffer[i + 2] & OFFSET_MASK;
1449       }
1450 
1451       final long offset = offset(typeAndOffset);
1452 
1453       switch (fieldType) {
1454         case 0: // DOUBLE:
1455           if ((currentPresenceField & presenceMask) != 0) {
1456             size += CodedOutputStream.computeDoubleSize(number, 0);
1457           }
1458           break;
1459         case 1: // FLOAT:
1460           if ((currentPresenceField & presenceMask) != 0) {
1461             size += CodedOutputStream.computeFloatSize(number, 0);
1462           }
1463           break;
1464         case 2: // INT64:
1465           if ((currentPresenceField & presenceMask) != 0) {
1466             size += CodedOutputStream.computeInt64Size(number, unsafe.getLong(message, offset));
1467           }
1468           break;
1469         case 3: // UINT64:
1470           if ((currentPresenceField & presenceMask) != 0) {
1471             size += CodedOutputStream.computeUInt64Size(number, unsafe.getLong(message, offset));
1472           }
1473           break;
1474         case 4: // INT32:
1475           if ((currentPresenceField & presenceMask) != 0) {
1476             size += CodedOutputStream.computeInt32Size(number, unsafe.getInt(message, offset));
1477           }
1478           break;
1479         case 5: // FIXED64:
1480           if ((currentPresenceField & presenceMask) != 0) {
1481             size += CodedOutputStream.computeFixed64Size(number, 0);
1482           }
1483           break;
1484         case 6: // FIXED32:
1485           if ((currentPresenceField & presenceMask) != 0) {
1486             size += CodedOutputStream.computeFixed32Size(number, 0);
1487           }
1488           break;
1489         case 7: // BOOL:
1490           if ((currentPresenceField & presenceMask) != 0) {
1491             size += CodedOutputStream.computeBoolSize(number, true);
1492           }
1493           break;
1494         case 8: // STRING:
1495           if ((currentPresenceField & presenceMask) != 0) {
1496             Object value = unsafe.getObject(message, offset);
1497             if (value instanceof ByteString) {
1498               size += CodedOutputStream.computeBytesSize(number, (ByteString) value);
1499             } else {
1500               size += CodedOutputStream.computeStringSize(number, (String) value);
1501             }
1502           }
1503           break;
1504         case 9: // MESSAGE:
1505           if ((currentPresenceField & presenceMask) != 0) {
1506             Object value = unsafe.getObject(message, offset);
1507             size += SchemaUtil.computeSizeMessage(number, value, getMessageFieldSchema(i));
1508           }
1509           break;
1510         case 10: // BYTES:
1511           if ((currentPresenceField & presenceMask) != 0) {
1512             ByteString value = (ByteString) unsafe.getObject(message, offset);
1513             size += CodedOutputStream.computeBytesSize(number, value);
1514           }
1515           break;
1516         case 11: // UINT32:
1517           if ((currentPresenceField & presenceMask) != 0) {
1518             size += CodedOutputStream.computeUInt32Size(number, unsafe.getInt(message, offset));
1519           }
1520           break;
1521         case 12: // ENUM:
1522           if ((currentPresenceField & presenceMask) != 0) {
1523             size += CodedOutputStream.computeEnumSize(number, unsafe.getInt(message, offset));
1524           }
1525           break;
1526         case 13: // SFIXED32:
1527           if ((currentPresenceField & presenceMask) != 0) {
1528             size += CodedOutputStream.computeSFixed32Size(number, 0);
1529           }
1530           break;
1531         case 14: // SFIXED64:
1532           if ((currentPresenceField & presenceMask) != 0) {
1533             size += CodedOutputStream.computeSFixed64Size(number, 0);
1534           }
1535           break;
1536         case 15: // SINT32:
1537           if ((currentPresenceField & presenceMask) != 0) {
1538             size += CodedOutputStream.computeSInt32Size(number, unsafe.getInt(message, offset));
1539           }
1540           break;
1541         case 16: // SINT64:
1542           if ((currentPresenceField & presenceMask) != 0) {
1543             size += CodedOutputStream.computeSInt64Size(number, unsafe.getLong(message, offset));
1544           }
1545           break;
1546         case 17: // GROUP:
1547           if ((currentPresenceField & presenceMask) != 0) {
1548             size +=
1549                 CodedOutputStream.computeGroupSize(
1550                     number,
1551                     (MessageLite) unsafe.getObject(message, offset),
1552                     getMessageFieldSchema(i));
1553           }
1554           break;
1555         case 18: // DOUBLE_LIST:
1556           size +=
1557               SchemaUtil.computeSizeFixed64List(
1558                   number, (List<?>) unsafe.getObject(message, offset), false);
1559           break;
1560         case 19: // FLOAT_LIST:
1561           size +=
1562               SchemaUtil.computeSizeFixed32List(
1563                   number, (List<?>) unsafe.getObject(message, offset), false);
1564           break;
1565         case 20: // INT64_LIST:
1566           size +=
1567               SchemaUtil.computeSizeInt64List(
1568                   number, (List<Long>) unsafe.getObject(message, offset), false);
1569           break;
1570         case 21: // UINT64_LIST:
1571           size +=
1572               SchemaUtil.computeSizeUInt64List(
1573                   number, (List<Long>) unsafe.getObject(message, offset), false);
1574           break;
1575         case 22: // INT32_LIST:
1576           size +=
1577               SchemaUtil.computeSizeInt32List(
1578                   number, (List<Integer>) unsafe.getObject(message, offset), false);
1579           break;
1580         case 23: // FIXED64_LIST:
1581           size +=
1582               SchemaUtil.computeSizeFixed64List(
1583                   number, (List<?>) unsafe.getObject(message, offset), false);
1584           break;
1585         case 24: // FIXED32_LIST:
1586           size +=
1587               SchemaUtil.computeSizeFixed32List(
1588                   number, (List<?>) unsafe.getObject(message, offset), false);
1589           break;
1590         case 25: // BOOL_LIST:
1591           size +=
1592               SchemaUtil.computeSizeBoolList(
1593                   number, (List<?>) unsafe.getObject(message, offset), false);
1594           break;
1595         case 26: // STRING_LIST:
1596           size +=
1597               SchemaUtil.computeSizeStringList(number, (List<?>) unsafe.getObject(message, offset));
1598           break;
1599         case 27: // MESSAGE_LIST:
1600           size +=
1601               SchemaUtil.computeSizeMessageList(
1602                   number, (List<?>) unsafe.getObject(message, offset), getMessageFieldSchema(i));
1603           break;
1604         case 28: // BYTES_LIST:
1605           size +=
1606               SchemaUtil.computeSizeByteStringList(
1607                   number, (List<ByteString>) unsafe.getObject(message, offset));
1608           break;
1609         case 29: // UINT32_LIST:
1610           size +=
1611               SchemaUtil.computeSizeUInt32List(
1612                   number, (List<Integer>) unsafe.getObject(message, offset), false);
1613           break;
1614         case 30: // ENUM_LIST:
1615           size +=
1616               SchemaUtil.computeSizeEnumList(
1617                   number, (List<Integer>) unsafe.getObject(message, offset), false);
1618           break;
1619         case 31: // SFIXED32_LIST:
1620           size +=
1621               SchemaUtil.computeSizeFixed32List(
1622                   number, (List<Integer>) unsafe.getObject(message, offset), false);
1623           break;
1624         case 32: // SFIXED64_LIST:
1625           size +=
1626               SchemaUtil.computeSizeFixed64List(
1627                   number, (List<Long>) unsafe.getObject(message, offset), false);
1628           break;
1629         case 33: // SINT32_LIST:
1630           size +=
1631               SchemaUtil.computeSizeSInt32List(
1632                   number, (List<Integer>) unsafe.getObject(message, offset), false);
1633           break;
1634         case 34: // SINT64_LIST:
1635           size +=
1636               SchemaUtil.computeSizeSInt64List(
1637                   number, (List<Long>) unsafe.getObject(message, offset), false);
1638           break;
1639         case 35:
1640           { // DOUBLE_LIST_PACKED:
1641             int fieldSize =
1642                 SchemaUtil.computeSizeFixed64ListNoTag(
1643                     (List<Double>) unsafe.getObject(message, offset));
1644             if (fieldSize > 0) {
1645               if (useCachedSizeField) {
1646                 unsafe.putInt(message, (long) presenceMaskAndOffset, fieldSize);
1647               }
1648               size +=
1649                   CodedOutputStream.computeTagSize(number)
1650                       + CodedOutputStream.computeUInt32SizeNoTag(fieldSize)
1651                       + fieldSize;
1652             }
1653             break;
1654           }
1655         case 36:
1656           { // FLOAT_LIST_PACKED:
1657             int fieldSize =
1658                 SchemaUtil.computeSizeFixed32ListNoTag(
1659                     (List<Float>) unsafe.getObject(message, offset));
1660             if (fieldSize > 0) {
1661               if (useCachedSizeField) {
1662                 unsafe.putInt(message, (long) presenceMaskAndOffset, fieldSize);
1663               }
1664               size +=
1665                   CodedOutputStream.computeTagSize(number)
1666                       + CodedOutputStream.computeUInt32SizeNoTag(fieldSize)
1667                       + fieldSize;
1668             }
1669             break;
1670           }
1671         case 37:
1672           { // INT64_LIST_PACKED:
1673             int fieldSize =
1674                 SchemaUtil.computeSizeInt64ListNoTag(
1675                     (List<Long>) unsafe.getObject(message, offset));
1676             if (fieldSize > 0) {
1677               if (useCachedSizeField) {
1678                 unsafe.putInt(message, (long) presenceMaskAndOffset, fieldSize);
1679               }
1680               size +=
1681                   CodedOutputStream.computeTagSize(number)
1682                       + CodedOutputStream.computeUInt32SizeNoTag(fieldSize)
1683                       + fieldSize;
1684             }
1685             break;
1686           }
1687         case 38:
1688           { // UINT64_LIST_PACKED:
1689             int fieldSize =
1690                 SchemaUtil.computeSizeUInt64ListNoTag(
1691                     (List<Long>) unsafe.getObject(message, offset));
1692             if (fieldSize > 0) {
1693               if (useCachedSizeField) {
1694                 unsafe.putInt(message, (long) presenceMaskAndOffset, fieldSize);
1695               }
1696               size +=
1697                   CodedOutputStream.computeTagSize(number)
1698                       + CodedOutputStream.computeUInt32SizeNoTag(fieldSize)
1699                       + fieldSize;
1700             }
1701             break;
1702           }
1703         case 39:
1704           { // INT32_LIST_PACKED:
1705             int fieldSize =
1706                 SchemaUtil.computeSizeInt32ListNoTag(
1707                     (List<Integer>) unsafe.getObject(message, offset));
1708             if (fieldSize > 0) {
1709               if (useCachedSizeField) {
1710                 unsafe.putInt(message, (long) presenceMaskAndOffset, fieldSize);
1711               }
1712               size +=
1713                   CodedOutputStream.computeTagSize(number)
1714                       + CodedOutputStream.computeUInt32SizeNoTag(fieldSize)
1715                       + fieldSize;
1716             }
1717             break;
1718           }
1719         case 40:
1720           { // FIXED64_LIST_PACKED:
1721             int fieldSize =
1722                 SchemaUtil.computeSizeFixed64ListNoTag(
1723                     (List<Long>) unsafe.getObject(message, offset));
1724             if (fieldSize > 0) {
1725               if (useCachedSizeField) {
1726                 unsafe.putInt(message, (long) presenceMaskAndOffset, fieldSize);
1727               }
1728               size +=
1729                   CodedOutputStream.computeTagSize(number)
1730                       + CodedOutputStream.computeUInt32SizeNoTag(fieldSize)
1731                       + fieldSize;
1732             }
1733             break;
1734           }
1735         case 41:
1736           { // FIXED32_LIST_PACKED:
1737             int fieldSize =
1738                 SchemaUtil.computeSizeFixed32ListNoTag(
1739                     (List<Integer>) unsafe.getObject(message, offset));
1740             if (fieldSize > 0) {
1741               if (useCachedSizeField) {
1742                 unsafe.putInt(message, (long) presenceMaskAndOffset, fieldSize);
1743               }
1744               size +=
1745                   CodedOutputStream.computeTagSize(number)
1746                       + CodedOutputStream.computeUInt32SizeNoTag(fieldSize)
1747                       + fieldSize;
1748             }
1749             break;
1750           }
1751         case 42:
1752           { // BOOL_LIST_PACKED:
1753             int fieldSize =
1754                 SchemaUtil.computeSizeBoolListNoTag(
1755                     (List<Boolean>) unsafe.getObject(message, offset));
1756             if (fieldSize > 0) {
1757               if (useCachedSizeField) {
1758                 unsafe.putInt(message, (long) presenceMaskAndOffset, fieldSize);
1759               }
1760               size +=
1761                   CodedOutputStream.computeTagSize(number)
1762                       + CodedOutputStream.computeUInt32SizeNoTag(fieldSize)
1763                       + fieldSize;
1764             }
1765             break;
1766           }
1767         case 43:
1768           { // UINT32_LIST_PACKED:
1769             int fieldSize =
1770                 SchemaUtil.computeSizeUInt32ListNoTag(
1771                     (List<Integer>) unsafe.getObject(message, offset));
1772             if (fieldSize > 0) {
1773               if (useCachedSizeField) {
1774                 unsafe.putInt(message, (long) presenceMaskAndOffset, fieldSize);
1775               }
1776               size +=
1777                   CodedOutputStream.computeTagSize(number)
1778                       + CodedOutputStream.computeUInt32SizeNoTag(fieldSize)
1779                       + fieldSize;
1780             }
1781             break;
1782           }
1783         case 44:
1784           { // ENUM_LIST_PACKED:
1785             int fieldSize =
1786                 SchemaUtil.computeSizeEnumListNoTag(
1787                     (List<Integer>) unsafe.getObject(message, offset));
1788             if (fieldSize > 0) {
1789               if (useCachedSizeField) {
1790                 unsafe.putInt(message, (long) presenceMaskAndOffset, fieldSize);
1791               }
1792               size +=
1793                   CodedOutputStream.computeTagSize(number)
1794                       + CodedOutputStream.computeUInt32SizeNoTag(fieldSize)
1795                       + fieldSize;
1796             }
1797             break;
1798           }
1799         case 45:
1800           { // SFIXED32_LIST_PACKED:
1801             int fieldSize =
1802                 SchemaUtil.computeSizeFixed32ListNoTag(
1803                     (List<Integer>) unsafe.getObject(message, offset));
1804             if (fieldSize > 0) {
1805               if (useCachedSizeField) {
1806                 unsafe.putInt(message, (long) presenceMaskAndOffset, fieldSize);
1807               }
1808               size +=
1809                   CodedOutputStream.computeTagSize(number)
1810                       + CodedOutputStream.computeUInt32SizeNoTag(fieldSize)
1811                       + fieldSize;
1812             }
1813             break;
1814           }
1815         case 46:
1816           { // SFIXED64_LIST_PACKED:
1817             int fieldSize =
1818                 SchemaUtil.computeSizeFixed64ListNoTag(
1819                     (List<Long>) unsafe.getObject(message, offset));
1820             if (fieldSize > 0) {
1821               if (useCachedSizeField) {
1822                 unsafe.putInt(message, (long) presenceMaskAndOffset, fieldSize);
1823               }
1824               size +=
1825                   CodedOutputStream.computeTagSize(number)
1826                       + CodedOutputStream.computeUInt32SizeNoTag(fieldSize)
1827                       + fieldSize;
1828             }
1829             break;
1830           }
1831         case 47:
1832           { // SINT32_LIST_PACKED:
1833             int fieldSize =
1834                 SchemaUtil.computeSizeSInt32ListNoTag(
1835                     (List<Integer>) unsafe.getObject(message, offset));
1836             if (fieldSize > 0) {
1837               if (useCachedSizeField) {
1838                 unsafe.putInt(message, (long) presenceMaskAndOffset, fieldSize);
1839               }
1840               size +=
1841                   CodedOutputStream.computeTagSize(number)
1842                       + CodedOutputStream.computeUInt32SizeNoTag(fieldSize)
1843                       + fieldSize;
1844             }
1845             break;
1846           }
1847         case 48:
1848           { // SINT64_LIST_PACKED:
1849             int fieldSize =
1850                 SchemaUtil.computeSizeSInt64ListNoTag(
1851                     (List<Long>) unsafe.getObject(message, offset));
1852             if (fieldSize > 0) {
1853               if (useCachedSizeField) {
1854                 unsafe.putInt(message, (long) presenceMaskAndOffset, fieldSize);
1855               }
1856               size +=
1857                   CodedOutputStream.computeTagSize(number)
1858                       + CodedOutputStream.computeUInt32SizeNoTag(fieldSize)
1859                       + fieldSize;
1860             }
1861             break;
1862           }
1863         case 49: // GROUP_LIST:
1864           size +=
1865               SchemaUtil.computeSizeGroupList(
1866                   number,
1867                   (List<MessageLite>) unsafe.getObject(message, offset),
1868                   getMessageFieldSchema(i));
1869           break;
1870         case 50: // MAP:
1871           // TODO(dweis): Use schema cache.
1872           size +=
1873               mapFieldSchema.getSerializedSize(
1874                   number, unsafe.getObject(message, offset), getMapFieldDefaultEntry(i));
1875           break;
1876         case 51: // ONEOF_DOUBLE:
1877           if (isOneofPresent(message, number, i)) {
1878             size += CodedOutputStream.computeDoubleSize(number, 0);
1879           }
1880           break;
1881         case 52: // ONEOF_FLOAT:
1882           if (isOneofPresent(message, number, i)) {
1883             size += CodedOutputStream.computeFloatSize(number, 0);
1884           }
1885           break;
1886         case 53: // ONEOF_INT64:
1887           if (isOneofPresent(message, number, i)) {
1888             size += CodedOutputStream.computeInt64Size(number, oneofLongAt(message, offset));
1889           }
1890           break;
1891         case 54: // ONEOF_UINT64:
1892           if (isOneofPresent(message, number, i)) {
1893             size += CodedOutputStream.computeUInt64Size(number, oneofLongAt(message, offset));
1894           }
1895           break;
1896         case 55: // ONEOF_INT32:
1897           if (isOneofPresent(message, number, i)) {
1898             size += CodedOutputStream.computeInt32Size(number, oneofIntAt(message, offset));
1899           }
1900           break;
1901         case 56: // ONEOF_FIXED64:
1902           if (isOneofPresent(message, number, i)) {
1903             size += CodedOutputStream.computeFixed64Size(number, 0);
1904           }
1905           break;
1906         case 57: // ONEOF_FIXED32:
1907           if (isOneofPresent(message, number, i)) {
1908             size += CodedOutputStream.computeFixed32Size(number, 0);
1909           }
1910           break;
1911         case 58: // ONEOF_BOOL:
1912           if (isOneofPresent(message, number, i)) {
1913             size += CodedOutputStream.computeBoolSize(number, true);
1914           }
1915           break;
1916         case 59: // ONEOF_STRING:
1917           if (isOneofPresent(message, number, i)) {
1918             Object value = unsafe.getObject(message, offset);
1919             if (value instanceof ByteString) {
1920               size += CodedOutputStream.computeBytesSize(number, (ByteString) value);
1921             } else {
1922               size += CodedOutputStream.computeStringSize(number, (String) value);
1923             }
1924           }
1925           break;
1926         case 60: // ONEOF_MESSAGE:
1927           if (isOneofPresent(message, number, i)) {
1928             Object value = unsafe.getObject(message, offset);
1929             size += SchemaUtil.computeSizeMessage(number, value, getMessageFieldSchema(i));
1930           }
1931           break;
1932         case 61: // ONEOF_BYTES:
1933           if (isOneofPresent(message, number, i)) {
1934             size +=
1935                 CodedOutputStream.computeBytesSize(
1936                     number, (ByteString) unsafe.getObject(message, offset));
1937           }
1938           break;
1939         case 62: // ONEOF_UINT32:
1940           if (isOneofPresent(message, number, i)) {
1941             size += CodedOutputStream.computeUInt32Size(number, oneofIntAt(message, offset));
1942           }
1943           break;
1944         case 63: // ONEOF_ENUM:
1945           if (isOneofPresent(message, number, i)) {
1946             size += CodedOutputStream.computeEnumSize(number, oneofIntAt(message, offset));
1947           }
1948           break;
1949         case 64: // ONEOF_SFIXED32:
1950           if (isOneofPresent(message, number, i)) {
1951             size += CodedOutputStream.computeSFixed32Size(number, 0);
1952           }
1953           break;
1954         case 65: // ONEOF_SFIXED64:
1955           if (isOneofPresent(message, number, i)) {
1956             size += CodedOutputStream.computeSFixed64Size(number, 0);
1957           }
1958           break;
1959         case 66: // ONEOF_SINT32:
1960           if (isOneofPresent(message, number, i)) {
1961             size += CodedOutputStream.computeSInt32Size(number, oneofIntAt(message, offset));
1962           }
1963           break;
1964         case 67: // ONEOF_SINT64:
1965           if (isOneofPresent(message, number, i)) {
1966             size += CodedOutputStream.computeSInt64Size(number, oneofLongAt(message, offset));
1967           }
1968           break;
1969         case 68: // ONEOF_GROUP:
1970           if (isOneofPresent(message, number, i)) {
1971             size +=
1972                 CodedOutputStream.computeGroupSize(
1973                     number,
1974                     (MessageLite) unsafe.getObject(message, offset),
1975                     getMessageFieldSchema(i));
1976           }
1977           break;
1978         default:
1979           // Assume it's an empty entry.
1980       }
1981     }
1982 
1983     size += getUnknownFieldsSerializedSize(unknownFieldSchema, message);
1984 
1985     if (hasExtensions) {
1986       size += extensionSchema.getExtensions(message).getSerializedSize();
1987     }
1988 
1989     return size;
1990   }
1991 
getSerializedSizeProto3(T message)1992   private int getSerializedSizeProto3(T message) {
1993     final sun.misc.Unsafe unsafe = UNSAFE;
1994     int size = 0;
1995     for (int i = 0; i < buffer.length; i += INTS_PER_FIELD) {
1996       final int typeAndOffset = typeAndOffsetAt(i);
1997       final int fieldType = type(typeAndOffset);
1998       final int number = numberAt(i);
1999 
2000       final long offset = offset(typeAndOffset);
2001       final int cachedSizeOffset =
2002           fieldType >= FieldType.DOUBLE_LIST_PACKED.id()
2003                   && fieldType <= FieldType.SINT64_LIST_PACKED.id()
2004               ? buffer[i + 2] & OFFSET_MASK
2005               : 0;
2006 
2007       switch (fieldType) {
2008         case 0: // DOUBLE:
2009           if (isFieldPresent(message, i)) {
2010             size += CodedOutputStream.computeDoubleSize(number, 0);
2011           }
2012           break;
2013         case 1: // FLOAT:
2014           if (isFieldPresent(message, i)) {
2015             size += CodedOutputStream.computeFloatSize(number, 0);
2016           }
2017           break;
2018         case 2: // INT64:
2019           if (isFieldPresent(message, i)) {
2020             size += CodedOutputStream.computeInt64Size(number, UnsafeUtil.getLong(message, offset));
2021           }
2022           break;
2023         case 3: // UINT64:
2024           if (isFieldPresent(message, i)) {
2025             size +=
2026                 CodedOutputStream.computeUInt64Size(number, UnsafeUtil.getLong(message, offset));
2027           }
2028           break;
2029         case 4: // INT32:
2030           if (isFieldPresent(message, i)) {
2031             size += CodedOutputStream.computeInt32Size(number, UnsafeUtil.getInt(message, offset));
2032           }
2033           break;
2034         case 5: // FIXED64:
2035           if (isFieldPresent(message, i)) {
2036             size += CodedOutputStream.computeFixed64Size(number, 0);
2037           }
2038           break;
2039         case 6: // FIXED32:
2040           if (isFieldPresent(message, i)) {
2041             size += CodedOutputStream.computeFixed32Size(number, 0);
2042           }
2043           break;
2044         case 7: // BOOL:
2045           if (isFieldPresent(message, i)) {
2046             size += CodedOutputStream.computeBoolSize(number, true);
2047           }
2048           break;
2049         case 8: // STRING:
2050           if (isFieldPresent(message, i)) {
2051             Object value = UnsafeUtil.getObject(message, offset);
2052             if (value instanceof ByteString) {
2053               size += CodedOutputStream.computeBytesSize(number, (ByteString) value);
2054             } else {
2055               size += CodedOutputStream.computeStringSize(number, (String) value);
2056             }
2057           }
2058           break;
2059         case 9: // MESSAGE:
2060           if (isFieldPresent(message, i)) {
2061             Object value = UnsafeUtil.getObject(message, offset);
2062             size += SchemaUtil.computeSizeMessage(number, value, getMessageFieldSchema(i));
2063           }
2064           break;
2065         case 10: // BYTES:
2066           if (isFieldPresent(message, i)) {
2067             ByteString value = (ByteString) UnsafeUtil.getObject(message, offset);
2068             size += CodedOutputStream.computeBytesSize(number, value);
2069           }
2070           break;
2071         case 11: // UINT32:
2072           if (isFieldPresent(message, i)) {
2073             size += CodedOutputStream.computeUInt32Size(number, UnsafeUtil.getInt(message, offset));
2074           }
2075           break;
2076         case 12: // ENUM:
2077           if (isFieldPresent(message, i)) {
2078             size += CodedOutputStream.computeEnumSize(number, UnsafeUtil.getInt(message, offset));
2079           }
2080           break;
2081         case 13: // SFIXED32:
2082           if (isFieldPresent(message, i)) {
2083             size += CodedOutputStream.computeSFixed32Size(number, 0);
2084           }
2085           break;
2086         case 14: // SFIXED64:
2087           if (isFieldPresent(message, i)) {
2088             size += CodedOutputStream.computeSFixed64Size(number, 0);
2089           }
2090           break;
2091         case 15: // SINT32:
2092           if (isFieldPresent(message, i)) {
2093             size += CodedOutputStream.computeSInt32Size(number, UnsafeUtil.getInt(message, offset));
2094           }
2095           break;
2096         case 16: // SINT64:
2097           if (isFieldPresent(message, i)) {
2098             size +=
2099                 CodedOutputStream.computeSInt64Size(number, UnsafeUtil.getLong(message, offset));
2100           }
2101           break;
2102         case 17: // GROUP:
2103           if (isFieldPresent(message, i)) {
2104             size +=
2105                 CodedOutputStream.computeGroupSize(
2106                     number,
2107                     (MessageLite) UnsafeUtil.getObject(message, offset),
2108                     getMessageFieldSchema(i));
2109           }
2110           break;
2111         case 18: // DOUBLE_LIST:
2112           size += SchemaUtil.computeSizeFixed64List(number, listAt(message, offset), false);
2113           break;
2114         case 19: // FLOAT_LIST:
2115           size += SchemaUtil.computeSizeFixed32List(number, listAt(message, offset), false);
2116           break;
2117         case 20: // INT64_LIST:
2118           size +=
2119               SchemaUtil.computeSizeInt64List(number, (List<Long>) listAt(message, offset), false);
2120           break;
2121         case 21: // UINT64_LIST:
2122           size +=
2123               SchemaUtil.computeSizeUInt64List(number, (List<Long>) listAt(message, offset), false);
2124           break;
2125         case 22: // INT32_LIST:
2126           size +=
2127               SchemaUtil.computeSizeInt32List(
2128                   number, (List<Integer>) listAt(message, offset), false);
2129           break;
2130         case 23: // FIXED64_LIST:
2131           size += SchemaUtil.computeSizeFixed64List(number, listAt(message, offset), false);
2132           break;
2133         case 24: // FIXED32_LIST:
2134           size += SchemaUtil.computeSizeFixed32List(number, listAt(message, offset), false);
2135           break;
2136         case 25: // BOOL_LIST:
2137           size += SchemaUtil.computeSizeBoolList(number, listAt(message, offset), false);
2138           break;
2139         case 26: // STRING_LIST:
2140           size += SchemaUtil.computeSizeStringList(number, listAt(message, offset));
2141           break;
2142         case 27: // MESSAGE_LIST:
2143           size +=
2144               SchemaUtil.computeSizeMessageList(
2145                   number, listAt(message, offset), getMessageFieldSchema(i));
2146           break;
2147         case 28: // BYTES_LIST:
2148           size +=
2149               SchemaUtil.computeSizeByteStringList(
2150                   number, (List<ByteString>) listAt(message, offset));
2151           break;
2152         case 29: // UINT32_LIST:
2153           size +=
2154               SchemaUtil.computeSizeUInt32List(
2155                   number, (List<Integer>) listAt(message, offset), false);
2156           break;
2157         case 30: // ENUM_LIST:
2158           size +=
2159               SchemaUtil.computeSizeEnumList(
2160                   number, (List<Integer>) listAt(message, offset), false);
2161           break;
2162         case 31: // SFIXED32_LIST:
2163           size += SchemaUtil.computeSizeFixed32List(number, listAt(message, offset), false);
2164           break;
2165         case 32: // SFIXED64_LIST:
2166           size += SchemaUtil.computeSizeFixed64List(number, listAt(message, offset), false);
2167           break;
2168         case 33: // SINT32_LIST:
2169           size +=
2170               SchemaUtil.computeSizeSInt32List(
2171                   number, (List<Integer>) listAt(message, offset), false);
2172           break;
2173         case 34: // SINT64_LIST:
2174           size +=
2175               SchemaUtil.computeSizeSInt64List(number, (List<Long>) listAt(message, offset), false);
2176           break;
2177         case 35:
2178           { // DOUBLE_LIST_PACKED:
2179             int fieldSize =
2180                 SchemaUtil.computeSizeFixed64ListNoTag(
2181                     (List<Double>) unsafe.getObject(message, offset));
2182             if (fieldSize > 0) {
2183               if (useCachedSizeField) {
2184                 unsafe.putInt(message, (long) cachedSizeOffset, fieldSize);
2185               }
2186               size +=
2187                   CodedOutputStream.computeTagSize(number)
2188                       + CodedOutputStream.computeUInt32SizeNoTag(fieldSize)
2189                       + fieldSize;
2190             }
2191             break;
2192           }
2193         case 36:
2194           { // FLOAT_LIST_PACKED:
2195             int fieldSize =
2196                 SchemaUtil.computeSizeFixed32ListNoTag(
2197                     (List<Float>) unsafe.getObject(message, offset));
2198             if (fieldSize > 0) {
2199               if (useCachedSizeField) {
2200                 unsafe.putInt(message, (long) cachedSizeOffset, fieldSize);
2201               }
2202               size +=
2203                   CodedOutputStream.computeTagSize(number)
2204                       + CodedOutputStream.computeUInt32SizeNoTag(fieldSize)
2205                       + fieldSize;
2206             }
2207             break;
2208           }
2209         case 37:
2210           { // INT64_LIST_PACKED:
2211             int fieldSize =
2212                 SchemaUtil.computeSizeInt64ListNoTag(
2213                     (List<Long>) unsafe.getObject(message, offset));
2214             if (fieldSize > 0) {
2215               if (useCachedSizeField) {
2216                 unsafe.putInt(message, (long) cachedSizeOffset, fieldSize);
2217               }
2218               size +=
2219                   CodedOutputStream.computeTagSize(number)
2220                       + CodedOutputStream.computeUInt32SizeNoTag(fieldSize)
2221                       + fieldSize;
2222             }
2223             break;
2224           }
2225         case 38:
2226           { // UINT64_LIST_PACKED:
2227             int fieldSize =
2228                 SchemaUtil.computeSizeUInt64ListNoTag(
2229                     (List<Long>) unsafe.getObject(message, offset));
2230             if (fieldSize > 0) {
2231               if (useCachedSizeField) {
2232                 unsafe.putInt(message, (long) cachedSizeOffset, fieldSize);
2233               }
2234               size +=
2235                   CodedOutputStream.computeTagSize(number)
2236                       + CodedOutputStream.computeUInt32SizeNoTag(fieldSize)
2237                       + fieldSize;
2238             }
2239             break;
2240           }
2241         case 39:
2242           { // INT32_LIST_PACKED:
2243             int fieldSize =
2244                 SchemaUtil.computeSizeInt32ListNoTag(
2245                     (List<Integer>) unsafe.getObject(message, offset));
2246             if (fieldSize > 0) {
2247               if (useCachedSizeField) {
2248                 unsafe.putInt(message, (long) cachedSizeOffset, fieldSize);
2249               }
2250               size +=
2251                   CodedOutputStream.computeTagSize(number)
2252                       + CodedOutputStream.computeUInt32SizeNoTag(fieldSize)
2253                       + fieldSize;
2254             }
2255             break;
2256           }
2257         case 40:
2258           { // FIXED64_LIST_PACKED:
2259             int fieldSize =
2260                 SchemaUtil.computeSizeFixed64ListNoTag(
2261                     (List<Long>) unsafe.getObject(message, offset));
2262             if (fieldSize > 0) {
2263               if (useCachedSizeField) {
2264                 unsafe.putInt(message, (long) cachedSizeOffset, fieldSize);
2265               }
2266               size +=
2267                   CodedOutputStream.computeTagSize(number)
2268                       + CodedOutputStream.computeUInt32SizeNoTag(fieldSize)
2269                       + fieldSize;
2270             }
2271             break;
2272           }
2273         case 41:
2274           { // FIXED32_LIST_PACKED:
2275             int fieldSize =
2276                 SchemaUtil.computeSizeFixed32ListNoTag(
2277                     (List<Integer>) unsafe.getObject(message, offset));
2278             if (fieldSize > 0) {
2279               if (useCachedSizeField) {
2280                 unsafe.putInt(message, (long) cachedSizeOffset, fieldSize);
2281               }
2282               size +=
2283                   CodedOutputStream.computeTagSize(number)
2284                       + CodedOutputStream.computeUInt32SizeNoTag(fieldSize)
2285                       + fieldSize;
2286             }
2287             break;
2288           }
2289         case 42:
2290           { // BOOL_LIST_PACKED:
2291             int fieldSize =
2292                 SchemaUtil.computeSizeBoolListNoTag(
2293                     (List<Boolean>) unsafe.getObject(message, offset));
2294             if (fieldSize > 0) {
2295               if (useCachedSizeField) {
2296                 unsafe.putInt(message, (long) cachedSizeOffset, fieldSize);
2297               }
2298               size +=
2299                   CodedOutputStream.computeTagSize(number)
2300                       + CodedOutputStream.computeUInt32SizeNoTag(fieldSize)
2301                       + fieldSize;
2302             }
2303             break;
2304           }
2305         case 43:
2306           { // UINT32_LIST_PACKED:
2307             int fieldSize =
2308                 SchemaUtil.computeSizeUInt32ListNoTag(
2309                     (List<Integer>) unsafe.getObject(message, offset));
2310             if (fieldSize > 0) {
2311               if (useCachedSizeField) {
2312                 unsafe.putInt(message, (long) cachedSizeOffset, fieldSize);
2313               }
2314               size +=
2315                   CodedOutputStream.computeTagSize(number)
2316                       + CodedOutputStream.computeUInt32SizeNoTag(fieldSize)
2317                       + fieldSize;
2318             }
2319             break;
2320           }
2321         case 44:
2322           { // ENUM_LIST_PACKED:
2323             int fieldSize =
2324                 SchemaUtil.computeSizeEnumListNoTag(
2325                     (List<Integer>) unsafe.getObject(message, offset));
2326             if (fieldSize > 0) {
2327               if (useCachedSizeField) {
2328                 unsafe.putInt(message, (long) cachedSizeOffset, fieldSize);
2329               }
2330               size +=
2331                   CodedOutputStream.computeTagSize(number)
2332                       + CodedOutputStream.computeUInt32SizeNoTag(fieldSize)
2333                       + fieldSize;
2334             }
2335             break;
2336           }
2337         case 45:
2338           { // SFIXED32_LIST_PACKED:
2339             int fieldSize =
2340                 SchemaUtil.computeSizeFixed32ListNoTag(
2341                     (List<Integer>) unsafe.getObject(message, offset));
2342             if (fieldSize > 0) {
2343               if (useCachedSizeField) {
2344                 unsafe.putInt(message, (long) cachedSizeOffset, fieldSize);
2345               }
2346               size +=
2347                   CodedOutputStream.computeTagSize(number)
2348                       + CodedOutputStream.computeUInt32SizeNoTag(fieldSize)
2349                       + fieldSize;
2350             }
2351             break;
2352           }
2353         case 46:
2354           { // SFIXED64_LIST_PACKED:
2355             int fieldSize =
2356                 SchemaUtil.computeSizeFixed64ListNoTag(
2357                     (List<Long>) unsafe.getObject(message, offset));
2358             if (fieldSize > 0) {
2359               if (useCachedSizeField) {
2360                 unsafe.putInt(message, (long) cachedSizeOffset, fieldSize);
2361               }
2362               size +=
2363                   CodedOutputStream.computeTagSize(number)
2364                       + CodedOutputStream.computeUInt32SizeNoTag(fieldSize)
2365                       + fieldSize;
2366             }
2367             break;
2368           }
2369         case 47:
2370           { // SINT32_LIST_PACKED:
2371             int fieldSize =
2372                 SchemaUtil.computeSizeSInt32ListNoTag(
2373                     (List<Integer>) unsafe.getObject(message, offset));
2374             if (fieldSize > 0) {
2375               if (useCachedSizeField) {
2376                 unsafe.putInt(message, (long) cachedSizeOffset, fieldSize);
2377               }
2378               size +=
2379                   CodedOutputStream.computeTagSize(number)
2380                       + CodedOutputStream.computeUInt32SizeNoTag(fieldSize)
2381                       + fieldSize;
2382             }
2383             break;
2384           }
2385         case 48:
2386           { // SINT64_LIST_PACKED:
2387             int fieldSize =
2388                 SchemaUtil.computeSizeSInt64ListNoTag(
2389                     (List<Long>) unsafe.getObject(message, offset));
2390             if (fieldSize > 0) {
2391               if (useCachedSizeField) {
2392                 unsafe.putInt(message, (long) cachedSizeOffset, fieldSize);
2393               }
2394               size +=
2395                   CodedOutputStream.computeTagSize(number)
2396                       + CodedOutputStream.computeUInt32SizeNoTag(fieldSize)
2397                       + fieldSize;
2398             }
2399             break;
2400           }
2401         case 49: // GROUP_LIST:
2402           size +=
2403               SchemaUtil.computeSizeGroupList(
2404                   number, (List<MessageLite>) listAt(message, offset), getMessageFieldSchema(i));
2405           break;
2406         case 50: // MAP:
2407           // TODO(dweis): Use schema cache.
2408           size +=
2409               mapFieldSchema.getSerializedSize(
2410                   number, UnsafeUtil.getObject(message, offset), getMapFieldDefaultEntry(i));
2411           break;
2412         case 51: // ONEOF_DOUBLE:
2413           if (isOneofPresent(message, number, i)) {
2414             size += CodedOutputStream.computeDoubleSize(number, 0);
2415           }
2416           break;
2417         case 52: // ONEOF_FLOAT:
2418           if (isOneofPresent(message, number, i)) {
2419             size += CodedOutputStream.computeFloatSize(number, 0);
2420           }
2421           break;
2422         case 53: // ONEOF_INT64:
2423           if (isOneofPresent(message, number, i)) {
2424             size += CodedOutputStream.computeInt64Size(number, oneofLongAt(message, offset));
2425           }
2426           break;
2427         case 54: // ONEOF_UINT64:
2428           if (isOneofPresent(message, number, i)) {
2429             size += CodedOutputStream.computeUInt64Size(number, oneofLongAt(message, offset));
2430           }
2431           break;
2432         case 55: // ONEOF_INT32:
2433           if (isOneofPresent(message, number, i)) {
2434             size += CodedOutputStream.computeInt32Size(number, oneofIntAt(message, offset));
2435           }
2436           break;
2437         case 56: // ONEOF_FIXED64:
2438           if (isOneofPresent(message, number, i)) {
2439             size += CodedOutputStream.computeFixed64Size(number, 0);
2440           }
2441           break;
2442         case 57: // ONEOF_FIXED32:
2443           if (isOneofPresent(message, number, i)) {
2444             size += CodedOutputStream.computeFixed32Size(number, 0);
2445           }
2446           break;
2447         case 58: // ONEOF_BOOL:
2448           if (isOneofPresent(message, number, i)) {
2449             size += CodedOutputStream.computeBoolSize(number, true);
2450           }
2451           break;
2452         case 59: // ONEOF_STRING:
2453           if (isOneofPresent(message, number, i)) {
2454             Object value = UnsafeUtil.getObject(message, offset);
2455             if (value instanceof ByteString) {
2456               size += CodedOutputStream.computeBytesSize(number, (ByteString) value);
2457             } else {
2458               size += CodedOutputStream.computeStringSize(number, (String) value);
2459             }
2460           }
2461           break;
2462         case 60: // ONEOF_MESSAGE:
2463           if (isOneofPresent(message, number, i)) {
2464             Object value = UnsafeUtil.getObject(message, offset);
2465             size += SchemaUtil.computeSizeMessage(number, value, getMessageFieldSchema(i));
2466           }
2467           break;
2468         case 61: // ONEOF_BYTES:
2469           if (isOneofPresent(message, number, i)) {
2470             size +=
2471                 CodedOutputStream.computeBytesSize(
2472                     number, (ByteString) UnsafeUtil.getObject(message, offset));
2473           }
2474           break;
2475         case 62: // ONEOF_UINT32:
2476           if (isOneofPresent(message, number, i)) {
2477             size += CodedOutputStream.computeUInt32Size(number, oneofIntAt(message, offset));
2478           }
2479           break;
2480         case 63: // ONEOF_ENUM:
2481           if (isOneofPresent(message, number, i)) {
2482             size += CodedOutputStream.computeEnumSize(number, oneofIntAt(message, offset));
2483           }
2484           break;
2485         case 64: // ONEOF_SFIXED32:
2486           if (isOneofPresent(message, number, i)) {
2487             size += CodedOutputStream.computeSFixed32Size(number, 0);
2488           }
2489           break;
2490         case 65: // ONEOF_SFIXED64:
2491           if (isOneofPresent(message, number, i)) {
2492             size += CodedOutputStream.computeSFixed64Size(number, 0);
2493           }
2494           break;
2495         case 66: // ONEOF_SINT32:
2496           if (isOneofPresent(message, number, i)) {
2497             size += CodedOutputStream.computeSInt32Size(number, oneofIntAt(message, offset));
2498           }
2499           break;
2500         case 67: // ONEOF_SINT64:
2501           if (isOneofPresent(message, number, i)) {
2502             size += CodedOutputStream.computeSInt64Size(number, oneofLongAt(message, offset));
2503           }
2504           break;
2505         case 68: // ONEOF_GROUP:
2506           if (isOneofPresent(message, number, i)) {
2507             size +=
2508                 CodedOutputStream.computeGroupSize(
2509                     number,
2510                     (MessageLite) UnsafeUtil.getObject(message, offset),
2511                     getMessageFieldSchema(i));
2512           }
2513           break;
2514         default:
2515           // Assume it's an empty entry.
2516       }
2517     }
2518 
2519     size += getUnknownFieldsSerializedSize(unknownFieldSchema, message);
2520 
2521     return size;
2522   }
2523 
getUnknownFieldsSerializedSize( UnknownFieldSchema<UT, UB> schema, T message)2524   private <UT, UB> int getUnknownFieldsSerializedSize(
2525       UnknownFieldSchema<UT, UB> schema, T message) {
2526     UT unknowns = schema.getFromMessage(message);
2527     return schema.getSerializedSize(unknowns);
2528   }
2529 
listAt(Object message, long offset)2530   private static List<?> listAt(Object message, long offset) {
2531     return (List<?>) UnsafeUtil.getObject(message, offset);
2532   }
2533 
2534   @SuppressWarnings("unchecked")
2535   @Override
2536   // TODO(nathanmittler): Consider serializing oneof fields last so that only one entry per
2537   // oneof is actually serialized. This would mean that we would violate the serialization order
2538   // contract. It should also be noted that Go currently does this.
writeTo(T message, Writer writer)2539   public void writeTo(T message, Writer writer) throws IOException {
2540     if (writer.fieldOrder() == Writer.FieldOrder.DESCENDING) {
2541       writeFieldsInDescendingOrder(message, writer);
2542     } else {
2543       if (proto3) {
2544         writeFieldsInAscendingOrderProto3(message, writer);
2545       } else {
2546         writeFieldsInAscendingOrderProto2(message, writer);
2547       }
2548     }
2549   }
2550 
2551   @SuppressWarnings("unchecked")
writeFieldsInAscendingOrderProto2(T message, Writer writer)2552   private void writeFieldsInAscendingOrderProto2(T message, Writer writer) throws IOException {
2553     Iterator<? extends Map.Entry<?, ?>> extensionIterator = null;
2554     Map.Entry nextExtension = null;
2555     if (hasExtensions) {
2556       FieldSet<?> extensions = extensionSchema.getExtensions(message);
2557       if (!extensions.isEmpty()) {
2558         extensionIterator = extensions.iterator();
2559         nextExtension = extensionIterator.next();
2560       }
2561     }
2562     int currentPresenceFieldOffset = NO_PRESENCE_SENTINEL;
2563     int currentPresenceField = 0;
2564     final int bufferLength = buffer.length;
2565     final sun.misc.Unsafe unsafe = UNSAFE;
2566     for (int pos = 0; pos < bufferLength; pos += INTS_PER_FIELD) {
2567       final int typeAndOffset = typeAndOffsetAt(pos);
2568       final int number = numberAt(pos);
2569       final int fieldType = type(typeAndOffset);
2570 
2571       int presenceMaskAndOffset = 0;
2572       int presenceMask = 0;
2573       if (!proto3 && fieldType <= 17) {
2574         presenceMaskAndOffset = buffer[pos + 2];
2575         final int presenceFieldOffset = presenceMaskAndOffset & OFFSET_MASK;
2576         if (presenceFieldOffset != currentPresenceFieldOffset) {
2577           currentPresenceFieldOffset = presenceFieldOffset;
2578           currentPresenceField = unsafe.getInt(message, (long) presenceFieldOffset);
2579         }
2580         presenceMask = 1 << (presenceMaskAndOffset >>> OFFSET_BITS);
2581       }
2582 
2583       // Write any extensions that need to be written before the current field.
2584       while (nextExtension != null && extensionSchema.extensionNumber(nextExtension) <= number) {
2585         extensionSchema.serializeExtension(writer, nextExtension);
2586         nextExtension = extensionIterator.hasNext() ? extensionIterator.next() : null;
2587       }
2588       final long offset = offset(typeAndOffset);
2589 
2590       switch (fieldType) {
2591         case 0: // DOUBLE:
2592           if ((currentPresenceField & presenceMask) != 0) {
2593             writer.writeDouble(number, doubleAt(message, offset));
2594           }
2595           break;
2596         case 1: // FLOAT:
2597           if ((currentPresenceField & presenceMask) != 0) {
2598             writer.writeFloat(number, floatAt(message, offset));
2599           }
2600           break;
2601         case 2: // INT64:
2602           if ((currentPresenceField & presenceMask) != 0) {
2603             writer.writeInt64(number, unsafe.getLong(message, offset));
2604           }
2605           break;
2606         case 3: // UINT64:
2607           if ((currentPresenceField & presenceMask) != 0) {
2608             writer.writeUInt64(number, unsafe.getLong(message, offset));
2609           }
2610           break;
2611         case 4: // INT32:
2612           if ((currentPresenceField & presenceMask) != 0) {
2613             writer.writeInt32(number, unsafe.getInt(message, offset));
2614           }
2615           break;
2616         case 5: // FIXED64:
2617           if ((currentPresenceField & presenceMask) != 0) {
2618             writer.writeFixed64(number, unsafe.getLong(message, offset));
2619           }
2620           break;
2621         case 6: // FIXED32:
2622           if ((currentPresenceField & presenceMask) != 0) {
2623             writer.writeFixed32(number, unsafe.getInt(message, offset));
2624           }
2625           break;
2626         case 7: // BOOL:
2627           if ((currentPresenceField & presenceMask) != 0) {
2628             writer.writeBool(number, booleanAt(message, offset));
2629           }
2630           break;
2631         case 8: // STRING:
2632           if ((currentPresenceField & presenceMask) != 0) {
2633             writeString(number, unsafe.getObject(message, offset), writer);
2634           }
2635           break;
2636         case 9: // MESSAGE:
2637           if ((currentPresenceField & presenceMask) != 0) {
2638             Object value = unsafe.getObject(message, offset);
2639             writer.writeMessage(number, value, getMessageFieldSchema(pos));
2640           }
2641           break;
2642         case 10: // BYTES:
2643           if ((currentPresenceField & presenceMask) != 0) {
2644             writer.writeBytes(number, (ByteString) unsafe.getObject(message, offset));
2645           }
2646           break;
2647         case 11: // UINT32:
2648           if ((currentPresenceField & presenceMask) != 0) {
2649             writer.writeUInt32(number, unsafe.getInt(message, offset));
2650           }
2651           break;
2652         case 12: // ENUM:
2653           if ((currentPresenceField & presenceMask) != 0) {
2654             writer.writeEnum(number, unsafe.getInt(message, offset));
2655           }
2656           break;
2657         case 13: // SFIXED32:
2658           if ((currentPresenceField & presenceMask) != 0) {
2659             writer.writeSFixed32(number, unsafe.getInt(message, offset));
2660           }
2661           break;
2662         case 14: // SFIXED64:
2663           if ((currentPresenceField & presenceMask) != 0) {
2664             writer.writeSFixed64(number, unsafe.getLong(message, offset));
2665           }
2666           break;
2667         case 15: // SINT32:
2668           if ((currentPresenceField & presenceMask) != 0) {
2669             writer.writeSInt32(number, unsafe.getInt(message, offset));
2670           }
2671           break;
2672         case 16: // SINT64:
2673           if ((currentPresenceField & presenceMask) != 0) {
2674             writer.writeSInt64(number, unsafe.getLong(message, offset));
2675           }
2676           break;
2677         case 17: // GROUP:
2678           if ((currentPresenceField & presenceMask) != 0) {
2679             writer.writeGroup(
2680                 number, unsafe.getObject(message, offset), getMessageFieldSchema(pos));
2681           }
2682           break;
2683         case 18: // DOUBLE_LIST:
2684           SchemaUtil.writeDoubleList(
2685               numberAt(pos), (List<Double>) unsafe.getObject(message, offset), writer, false);
2686           break;
2687         case 19: // FLOAT_LIST:
2688           SchemaUtil.writeFloatList(
2689               numberAt(pos), (List<Float>) unsafe.getObject(message, offset), writer, false);
2690           break;
2691         case 20: // INT64_LIST:
2692           SchemaUtil.writeInt64List(
2693               numberAt(pos), (List<Long>) unsafe.getObject(message, offset), writer, false);
2694           break;
2695         case 21: // UINT64_LIST:
2696           SchemaUtil.writeUInt64List(
2697               numberAt(pos), (List<Long>) unsafe.getObject(message, offset), writer, false);
2698           break;
2699         case 22: // INT32_LIST:
2700           SchemaUtil.writeInt32List(
2701               numberAt(pos), (List<Integer>) unsafe.getObject(message, offset), writer, false);
2702           break;
2703         case 23: // FIXED64_LIST:
2704           SchemaUtil.writeFixed64List(
2705               numberAt(pos), (List<Long>) unsafe.getObject(message, offset), writer, false);
2706           break;
2707         case 24: // FIXED32_LIST:
2708           SchemaUtil.writeFixed32List(
2709               numberAt(pos), (List<Integer>) unsafe.getObject(message, offset), writer, false);
2710           break;
2711         case 25: // BOOL_LIST:
2712           SchemaUtil.writeBoolList(
2713               numberAt(pos), (List<Boolean>) unsafe.getObject(message, offset), writer, false);
2714           break;
2715         case 26: // STRING_LIST:
2716           SchemaUtil.writeStringList(
2717               numberAt(pos), (List<String>) unsafe.getObject(message, offset), writer);
2718           break;
2719         case 27: // MESSAGE_LIST:
2720           SchemaUtil.writeMessageList(
2721               numberAt(pos),
2722               (List<?>) unsafe.getObject(message, offset),
2723               writer,
2724               getMessageFieldSchema(pos));
2725           break;
2726         case 28: // BYTES_LIST:
2727           SchemaUtil.writeBytesList(
2728               numberAt(pos), (List<ByteString>) unsafe.getObject(message, offset), writer);
2729           break;
2730         case 29: // UINT32_LIST:
2731           SchemaUtil.writeUInt32List(
2732               numberAt(pos), (List<Integer>) unsafe.getObject(message, offset), writer, false);
2733           break;
2734         case 30: // ENUM_LIST:
2735           SchemaUtil.writeEnumList(
2736               numberAt(pos), (List<Integer>) unsafe.getObject(message, offset), writer, false);
2737           break;
2738         case 31: // SFIXED32_LIST:
2739           SchemaUtil.writeSFixed32List(
2740               numberAt(pos), (List<Integer>) unsafe.getObject(message, offset), writer, false);
2741           break;
2742         case 32: // SFIXED64_LIST:
2743           SchemaUtil.writeSFixed64List(
2744               numberAt(pos), (List<Long>) unsafe.getObject(message, offset), writer, false);
2745           break;
2746         case 33: // SINT32_LIST:
2747           SchemaUtil.writeSInt32List(
2748               numberAt(pos), (List<Integer>) unsafe.getObject(message, offset), writer, false);
2749           break;
2750         case 34: // SINT64_LIST:
2751           SchemaUtil.writeSInt64List(
2752               numberAt(pos), (List<Long>) unsafe.getObject(message, offset), writer, false);
2753           break;
2754         case 35: // DOUBLE_LIST_PACKED:
2755           // TODO(xiaofeng): Make use of cached field size to speed up serialization.
2756           SchemaUtil.writeDoubleList(
2757               numberAt(pos), (List<Double>) unsafe.getObject(message, offset), writer, true);
2758           break;
2759         case 36: // FLOAT_LIST_PACKED:
2760           SchemaUtil.writeFloatList(
2761               numberAt(pos), (List<Float>) unsafe.getObject(message, offset), writer, true);
2762           break;
2763         case 37: // INT64_LIST_PACKED:
2764           SchemaUtil.writeInt64List(
2765               numberAt(pos), (List<Long>) unsafe.getObject(message, offset), writer, true);
2766           break;
2767         case 38: // UINT64_LIST_PACKED:
2768           SchemaUtil.writeUInt64List(
2769               numberAt(pos), (List<Long>) unsafe.getObject(message, offset), writer, true);
2770           break;
2771         case 39: // INT32_LIST_PACKED:
2772           SchemaUtil.writeInt32List(
2773               numberAt(pos), (List<Integer>) unsafe.getObject(message, offset), writer, true);
2774           break;
2775         case 40: // FIXED64_LIST_PACKED:
2776           SchemaUtil.writeFixed64List(
2777               numberAt(pos), (List<Long>) unsafe.getObject(message, offset), writer, true);
2778           break;
2779         case 41: // FIXED32_LIST_PACKED:
2780           SchemaUtil.writeFixed32List(
2781               numberAt(pos), (List<Integer>) unsafe.getObject(message, offset), writer, true);
2782 
2783           break;
2784         case 42: // BOOL_LIST_PACKED:
2785           SchemaUtil.writeBoolList(
2786               numberAt(pos), (List<Boolean>) unsafe.getObject(message, offset), writer, true);
2787           break;
2788         case 43: // UINT32_LIST_PACKED:
2789           SchemaUtil.writeUInt32List(
2790               numberAt(pos), (List<Integer>) unsafe.getObject(message, offset), writer, true);
2791           break;
2792         case 44: // ENUM_LIST_PACKED:
2793           SchemaUtil.writeEnumList(
2794               numberAt(pos), (List<Integer>) unsafe.getObject(message, offset), writer, true);
2795           break;
2796         case 45: // SFIXED32_LIST_PACKED:
2797           SchemaUtil.writeSFixed32List(
2798               numberAt(pos), (List<Integer>) unsafe.getObject(message, offset), writer, true);
2799           break;
2800         case 46: // SFIXED64_LIST_PACKED:
2801           SchemaUtil.writeSFixed64List(
2802               numberAt(pos), (List<Long>) unsafe.getObject(message, offset), writer, true);
2803           break;
2804         case 47: // SINT32_LIST_PACKED:
2805           SchemaUtil.writeSInt32List(
2806               numberAt(pos), (List<Integer>) unsafe.getObject(message, offset), writer, true);
2807           break;
2808         case 48: // SINT64_LIST_PACKED:
2809           SchemaUtil.writeSInt64List(
2810               numberAt(pos), (List<Long>) unsafe.getObject(message, offset), writer, true);
2811           break;
2812         case 49: // GROUP_LIST:
2813           SchemaUtil.writeGroupList(
2814               numberAt(pos),
2815               (List<?>) unsafe.getObject(message, offset),
2816               writer,
2817               getMessageFieldSchema(pos));
2818           break;
2819         case 50: // MAP:
2820           // TODO(dweis): Use schema cache.
2821           writeMapHelper(writer, number, unsafe.getObject(message, offset), pos);
2822           break;
2823         case 51: // ONEOF_DOUBLE:
2824           if (isOneofPresent(message, number, pos)) {
2825             writer.writeDouble(number, oneofDoubleAt(message, offset));
2826           }
2827           break;
2828         case 52: // ONEOF_FLOAT:
2829           if (isOneofPresent(message, number, pos)) {
2830             writer.writeFloat(number, oneofFloatAt(message, offset));
2831           }
2832           break;
2833         case 53: // ONEOF_INT64:
2834           if (isOneofPresent(message, number, pos)) {
2835             writer.writeInt64(number, oneofLongAt(message, offset));
2836           }
2837           break;
2838         case 54: // ONEOF_UINT64:
2839           if (isOneofPresent(message, number, pos)) {
2840             writer.writeUInt64(number, oneofLongAt(message, offset));
2841           }
2842           break;
2843         case 55: // ONEOF_INT32:
2844           if (isOneofPresent(message, number, pos)) {
2845             writer.writeInt32(number, oneofIntAt(message, offset));
2846           }
2847           break;
2848         case 56: // ONEOF_FIXED64:
2849           if (isOneofPresent(message, number, pos)) {
2850             writer.writeFixed64(number, oneofLongAt(message, offset));
2851           }
2852           break;
2853         case 57: // ONEOF_FIXED32:
2854           if (isOneofPresent(message, number, pos)) {
2855             writer.writeFixed32(number, oneofIntAt(message, offset));
2856           }
2857           break;
2858         case 58: // ONEOF_BOOL:
2859           if (isOneofPresent(message, number, pos)) {
2860             writer.writeBool(number, oneofBooleanAt(message, offset));
2861           }
2862           break;
2863         case 59: // ONEOF_STRING:
2864           if (isOneofPresent(message, number, pos)) {
2865             writeString(number, unsafe.getObject(message, offset), writer);
2866           }
2867           break;
2868         case 60: // ONEOF_MESSAGE:
2869           if (isOneofPresent(message, number, pos)) {
2870             Object value = unsafe.getObject(message, offset);
2871             writer.writeMessage(number, value, getMessageFieldSchema(pos));
2872           }
2873           break;
2874         case 61: // ONEOF_BYTES:
2875           if (isOneofPresent(message, number, pos)) {
2876             writer.writeBytes(number, (ByteString) unsafe.getObject(message, offset));
2877           }
2878           break;
2879         case 62: // ONEOF_UINT32:
2880           if (isOneofPresent(message, number, pos)) {
2881             writer.writeUInt32(number, oneofIntAt(message, offset));
2882           }
2883           break;
2884         case 63: // ONEOF_ENUM:
2885           if (isOneofPresent(message, number, pos)) {
2886             writer.writeEnum(number, oneofIntAt(message, offset));
2887           }
2888           break;
2889         case 64: // ONEOF_SFIXED32:
2890           if (isOneofPresent(message, number, pos)) {
2891             writer.writeSFixed32(number, oneofIntAt(message, offset));
2892           }
2893           break;
2894         case 65: // ONEOF_SFIXED64:
2895           if (isOneofPresent(message, number, pos)) {
2896             writer.writeSFixed64(number, oneofLongAt(message, offset));
2897           }
2898           break;
2899         case 66: // ONEOF_SINT32:
2900           if (isOneofPresent(message, number, pos)) {
2901             writer.writeSInt32(number, oneofIntAt(message, offset));
2902           }
2903           break;
2904         case 67: // ONEOF_SINT64:
2905           if (isOneofPresent(message, number, pos)) {
2906             writer.writeSInt64(number, oneofLongAt(message, offset));
2907           }
2908           break;
2909         case 68: // ONEOF_GROUP:
2910           if (isOneofPresent(message, number, pos)) {
2911             writer.writeGroup(
2912                 number, unsafe.getObject(message, offset), getMessageFieldSchema(pos));
2913           }
2914           break;
2915         default:
2916           // Assume it's an empty entry - just go to the next entry.
2917           break;
2918       }
2919     }
2920     while (nextExtension != null) {
2921       extensionSchema.serializeExtension(writer, nextExtension);
2922       nextExtension = extensionIterator.hasNext() ? extensionIterator.next() : null;
2923     }
2924     writeUnknownInMessageTo(unknownFieldSchema, message, writer);
2925   }
2926 
2927   @SuppressWarnings("unchecked")
writeFieldsInAscendingOrderProto3(T message, Writer writer)2928   private void writeFieldsInAscendingOrderProto3(T message, Writer writer) throws IOException {
2929     Iterator<? extends Map.Entry<?, ?>> extensionIterator = null;
2930     Map.Entry nextExtension = null;
2931     if (hasExtensions) {
2932       FieldSet<?> extensions = extensionSchema.getExtensions(message);
2933       if (!extensions.isEmpty()) {
2934         extensionIterator = extensions.iterator();
2935         nextExtension = extensionIterator.next();
2936       }
2937     }
2938     final int bufferLength = buffer.length;
2939     for (int pos = 0; pos < bufferLength; pos += INTS_PER_FIELD) {
2940       final int typeAndOffset = typeAndOffsetAt(pos);
2941       final int number = numberAt(pos);
2942 
2943       // Write any extensions that need to be written before the current field.
2944       while (nextExtension != null && extensionSchema.extensionNumber(nextExtension) <= number) {
2945         extensionSchema.serializeExtension(writer, nextExtension);
2946         nextExtension = extensionIterator.hasNext() ? extensionIterator.next() : null;
2947       }
2948 
2949       switch (type(typeAndOffset)) {
2950         case 0: // DOUBLE:
2951           if (isFieldPresent(message, pos)) {
2952             writer.writeDouble(number, doubleAt(message, offset(typeAndOffset)));
2953           }
2954           break;
2955         case 1: // FLOAT:
2956           if (isFieldPresent(message, pos)) {
2957             writer.writeFloat(number, floatAt(message, offset(typeAndOffset)));
2958           }
2959           break;
2960         case 2: // INT64:
2961           if (isFieldPresent(message, pos)) {
2962             writer.writeInt64(number, longAt(message, offset(typeAndOffset)));
2963           }
2964           break;
2965         case 3: // UINT64:
2966           if (isFieldPresent(message, pos)) {
2967             writer.writeUInt64(number, longAt(message, offset(typeAndOffset)));
2968           }
2969           break;
2970         case 4: // INT32:
2971           if (isFieldPresent(message, pos)) {
2972             writer.writeInt32(number, intAt(message, offset(typeAndOffset)));
2973           }
2974           break;
2975         case 5: // FIXED64:
2976           if (isFieldPresent(message, pos)) {
2977             writer.writeFixed64(number, longAt(message, offset(typeAndOffset)));
2978           }
2979           break;
2980         case 6: // FIXED32:
2981           if (isFieldPresent(message, pos)) {
2982             writer.writeFixed32(number, intAt(message, offset(typeAndOffset)));
2983           }
2984           break;
2985         case 7: // BOOL:
2986           if (isFieldPresent(message, pos)) {
2987             writer.writeBool(number, booleanAt(message, offset(typeAndOffset)));
2988           }
2989           break;
2990         case 8: // STRING:
2991           if (isFieldPresent(message, pos)) {
2992             writeString(number, UnsafeUtil.getObject(message, offset(typeAndOffset)), writer);
2993           }
2994           break;
2995         case 9: // MESSAGE:
2996           if (isFieldPresent(message, pos)) {
2997             Object value = UnsafeUtil.getObject(message, offset(typeAndOffset));
2998             writer.writeMessage(number, value, getMessageFieldSchema(pos));
2999           }
3000           break;
3001         case 10: // BYTES:
3002           if (isFieldPresent(message, pos)) {
3003             writer.writeBytes(
3004                 number, (ByteString) UnsafeUtil.getObject(message, offset(typeAndOffset)));
3005           }
3006           break;
3007         case 11: // UINT32:
3008           if (isFieldPresent(message, pos)) {
3009             writer.writeUInt32(number, intAt(message, offset(typeAndOffset)));
3010           }
3011           break;
3012         case 12: // ENUM:
3013           if (isFieldPresent(message, pos)) {
3014             writer.writeEnum(number, intAt(message, offset(typeAndOffset)));
3015           }
3016           break;
3017         case 13: // SFIXED32:
3018           if (isFieldPresent(message, pos)) {
3019             writer.writeSFixed32(number, intAt(message, offset(typeAndOffset)));
3020           }
3021           break;
3022         case 14: // SFIXED64:
3023           if (isFieldPresent(message, pos)) {
3024             writer.writeSFixed64(number, longAt(message, offset(typeAndOffset)));
3025           }
3026           break;
3027         case 15: // SINT32:
3028           if (isFieldPresent(message, pos)) {
3029             writer.writeSInt32(number, intAt(message, offset(typeAndOffset)));
3030           }
3031           break;
3032         case 16: // SINT64:
3033           if (isFieldPresent(message, pos)) {
3034             writer.writeSInt64(number, longAt(message, offset(typeAndOffset)));
3035           }
3036           break;
3037         case 17: // GROUP:
3038           if (isFieldPresent(message, pos)) {
3039             writer.writeGroup(
3040                 number,
3041                 UnsafeUtil.getObject(message, offset(typeAndOffset)),
3042                 getMessageFieldSchema(pos));
3043           }
3044           break;
3045         case 18: // DOUBLE_LIST:
3046           SchemaUtil.writeDoubleList(
3047               numberAt(pos),
3048               (List<Double>) UnsafeUtil.getObject(message, offset(typeAndOffset)),
3049               writer,
3050               false);
3051           break;
3052         case 19: // FLOAT_LIST:
3053           SchemaUtil.writeFloatList(
3054               numberAt(pos),
3055               (List<Float>) UnsafeUtil.getObject(message, offset(typeAndOffset)),
3056               writer,
3057               false);
3058           break;
3059         case 20: // INT64_LIST:
3060           SchemaUtil.writeInt64List(
3061               numberAt(pos),
3062               (List<Long>) UnsafeUtil.getObject(message, offset(typeAndOffset)),
3063               writer,
3064               false);
3065           break;
3066         case 21: // UINT64_LIST:
3067           SchemaUtil.writeUInt64List(
3068               numberAt(pos),
3069               (List<Long>) UnsafeUtil.getObject(message, offset(typeAndOffset)),
3070               writer,
3071               false);
3072           break;
3073         case 22: // INT32_LIST:
3074           SchemaUtil.writeInt32List(
3075               numberAt(pos),
3076               (List<Integer>) UnsafeUtil.getObject(message, offset(typeAndOffset)),
3077               writer,
3078               false);
3079           break;
3080         case 23: // FIXED64_LIST:
3081           SchemaUtil.writeFixed64List(
3082               numberAt(pos),
3083               (List<Long>) UnsafeUtil.getObject(message, offset(typeAndOffset)),
3084               writer,
3085               false);
3086           break;
3087         case 24: // FIXED32_LIST:
3088           SchemaUtil.writeFixed32List(
3089               numberAt(pos),
3090               (List<Integer>) UnsafeUtil.getObject(message, offset(typeAndOffset)),
3091               writer,
3092               false);
3093           break;
3094         case 25: // BOOL_LIST:
3095           SchemaUtil.writeBoolList(
3096               numberAt(pos),
3097               (List<Boolean>) UnsafeUtil.getObject(message, offset(typeAndOffset)),
3098               writer,
3099               false);
3100           break;
3101         case 26: // STRING_LIST:
3102           SchemaUtil.writeStringList(
3103               numberAt(pos),
3104               (List<String>) UnsafeUtil.getObject(message, offset(typeAndOffset)),
3105               writer);
3106           break;
3107         case 27: // MESSAGE_LIST:
3108           SchemaUtil.writeMessageList(
3109               numberAt(pos),
3110               (List<?>) UnsafeUtil.getObject(message, offset(typeAndOffset)),
3111               writer,
3112               getMessageFieldSchema(pos));
3113           break;
3114         case 28: // BYTES_LIST:
3115           SchemaUtil.writeBytesList(
3116               numberAt(pos),
3117               (List<ByteString>) UnsafeUtil.getObject(message, offset(typeAndOffset)),
3118               writer);
3119           break;
3120         case 29: // UINT32_LIST:
3121           SchemaUtil.writeUInt32List(
3122               numberAt(pos),
3123               (List<Integer>) UnsafeUtil.getObject(message, offset(typeAndOffset)),
3124               writer,
3125               false);
3126           break;
3127         case 30: // ENUM_LIST:
3128           SchemaUtil.writeEnumList(
3129               numberAt(pos),
3130               (List<Integer>) UnsafeUtil.getObject(message, offset(typeAndOffset)),
3131               writer,
3132               false);
3133           break;
3134         case 31: // SFIXED32_LIST:
3135           SchemaUtil.writeSFixed32List(
3136               numberAt(pos),
3137               (List<Integer>) UnsafeUtil.getObject(message, offset(typeAndOffset)),
3138               writer,
3139               false);
3140           break;
3141         case 32: // SFIXED64_LIST:
3142           SchemaUtil.writeSFixed64List(
3143               numberAt(pos),
3144               (List<Long>) UnsafeUtil.getObject(message, offset(typeAndOffset)),
3145               writer,
3146               false);
3147           break;
3148         case 33: // SINT32_LIST:
3149           SchemaUtil.writeSInt32List(
3150               numberAt(pos),
3151               (List<Integer>) UnsafeUtil.getObject(message, offset(typeAndOffset)),
3152               writer,
3153               false);
3154           break;
3155         case 34: // SINT64_LIST:
3156           SchemaUtil.writeSInt64List(
3157               numberAt(pos),
3158               (List<Long>) UnsafeUtil.getObject(message, offset(typeAndOffset)),
3159               writer,
3160               false);
3161           break;
3162         case 35: // DOUBLE_LIST_PACKED:
3163           // TODO(xiaofeng): Make use of cached field size to speed up serialization.
3164           SchemaUtil.writeDoubleList(
3165               numberAt(pos),
3166               (List<Double>) UnsafeUtil.getObject(message, offset(typeAndOffset)),
3167               writer,
3168               true);
3169           break;
3170         case 36: // FLOAT_LIST_PACKED:
3171           SchemaUtil.writeFloatList(
3172               numberAt(pos),
3173               (List<Float>) UnsafeUtil.getObject(message, offset(typeAndOffset)),
3174               writer,
3175               true);
3176           break;
3177         case 37: // INT64_LIST_PACKED:
3178           SchemaUtil.writeInt64List(
3179               numberAt(pos),
3180               (List<Long>) UnsafeUtil.getObject(message, offset(typeAndOffset)),
3181               writer,
3182               true);
3183           break;
3184         case 38: // UINT64_LIST_PACKED:
3185           SchemaUtil.writeUInt64List(
3186               numberAt(pos),
3187               (List<Long>) UnsafeUtil.getObject(message, offset(typeAndOffset)),
3188               writer,
3189               true);
3190           break;
3191         case 39: // INT32_LIST_PACKED:
3192           SchemaUtil.writeInt32List(
3193               numberAt(pos),
3194               (List<Integer>) UnsafeUtil.getObject(message, offset(typeAndOffset)),
3195               writer,
3196               true);
3197           break;
3198         case 40: // FIXED64_LIST_PACKED:
3199           SchemaUtil.writeFixed64List(
3200               numberAt(pos),
3201               (List<Long>) UnsafeUtil.getObject(message, offset(typeAndOffset)),
3202               writer,
3203               true);
3204           break;
3205         case 41: // FIXED32_LIST_PACKED:
3206           SchemaUtil.writeFixed32List(
3207               numberAt(pos),
3208               (List<Integer>) UnsafeUtil.getObject(message, offset(typeAndOffset)),
3209               writer,
3210               true);
3211 
3212           break;
3213         case 42: // BOOL_LIST_PACKED:
3214           SchemaUtil.writeBoolList(
3215               numberAt(pos),
3216               (List<Boolean>) UnsafeUtil.getObject(message, offset(typeAndOffset)),
3217               writer,
3218               true);
3219           break;
3220         case 43: // UINT32_LIST_PACKED:
3221           SchemaUtil.writeUInt32List(
3222               numberAt(pos),
3223               (List<Integer>) UnsafeUtil.getObject(message, offset(typeAndOffset)),
3224               writer,
3225               true);
3226           break;
3227         case 44: // ENUM_LIST_PACKED:
3228           SchemaUtil.writeEnumList(
3229               numberAt(pos),
3230               (List<Integer>) UnsafeUtil.getObject(message, offset(typeAndOffset)),
3231               writer,
3232               true);
3233           break;
3234         case 45: // SFIXED32_LIST_PACKED:
3235           SchemaUtil.writeSFixed32List(
3236               numberAt(pos),
3237               (List<Integer>) UnsafeUtil.getObject(message, offset(typeAndOffset)),
3238               writer,
3239               true);
3240           break;
3241         case 46: // SFIXED64_LIST_PACKED:
3242           SchemaUtil.writeSFixed64List(
3243               numberAt(pos),
3244               (List<Long>) UnsafeUtil.getObject(message, offset(typeAndOffset)),
3245               writer,
3246               true);
3247           break;
3248         case 47: // SINT32_LIST_PACKED:
3249           SchemaUtil.writeSInt32List(
3250               numberAt(pos),
3251               (List<Integer>) UnsafeUtil.getObject(message, offset(typeAndOffset)),
3252               writer,
3253               true);
3254           break;
3255         case 48: // SINT64_LIST_PACKED:
3256           SchemaUtil.writeSInt64List(
3257               numberAt(pos),
3258               (List<Long>) UnsafeUtil.getObject(message, offset(typeAndOffset)),
3259               writer,
3260               true);
3261           break;
3262         case 49: // GROUP_LIST:
3263           SchemaUtil.writeGroupList(
3264               numberAt(pos),
3265               (List<?>) UnsafeUtil.getObject(message, offset(typeAndOffset)),
3266               writer,
3267               getMessageFieldSchema(pos));
3268           break;
3269         case 50: // MAP:
3270           // TODO(dweis): Use schema cache.
3271           writeMapHelper(writer, number, UnsafeUtil.getObject(message, offset(typeAndOffset)), pos);
3272           break;
3273         case 51: // ONEOF_DOUBLE:
3274           if (isOneofPresent(message, number, pos)) {
3275             writer.writeDouble(number, oneofDoubleAt(message, offset(typeAndOffset)));
3276           }
3277           break;
3278         case 52: // ONEOF_FLOAT:
3279           if (isOneofPresent(message, number, pos)) {
3280             writer.writeFloat(number, oneofFloatAt(message, offset(typeAndOffset)));
3281           }
3282           break;
3283         case 53: // ONEOF_INT64:
3284           if (isOneofPresent(message, number, pos)) {
3285             writer.writeInt64(number, oneofLongAt(message, offset(typeAndOffset)));
3286           }
3287           break;
3288         case 54: // ONEOF_UINT64:
3289           if (isOneofPresent(message, number, pos)) {
3290             writer.writeUInt64(number, oneofLongAt(message, offset(typeAndOffset)));
3291           }
3292           break;
3293         case 55: // ONEOF_INT32:
3294           if (isOneofPresent(message, number, pos)) {
3295             writer.writeInt32(number, oneofIntAt(message, offset(typeAndOffset)));
3296           }
3297           break;
3298         case 56: // ONEOF_FIXED64:
3299           if (isOneofPresent(message, number, pos)) {
3300             writer.writeFixed64(number, oneofLongAt(message, offset(typeAndOffset)));
3301           }
3302           break;
3303         case 57: // ONEOF_FIXED32:
3304           if (isOneofPresent(message, number, pos)) {
3305             writer.writeFixed32(number, oneofIntAt(message, offset(typeAndOffset)));
3306           }
3307           break;
3308         case 58: // ONEOF_BOOL:
3309           if (isOneofPresent(message, number, pos)) {
3310             writer.writeBool(number, oneofBooleanAt(message, offset(typeAndOffset)));
3311           }
3312           break;
3313         case 59: // ONEOF_STRING:
3314           if (isOneofPresent(message, number, pos)) {
3315             writeString(number, UnsafeUtil.getObject(message, offset(typeAndOffset)), writer);
3316           }
3317           break;
3318         case 60: // ONEOF_MESSAGE:
3319           if (isOneofPresent(message, number, pos)) {
3320             Object value = UnsafeUtil.getObject(message, offset(typeAndOffset));
3321             writer.writeMessage(number, value, getMessageFieldSchema(pos));
3322           }
3323           break;
3324         case 61: // ONEOF_BYTES:
3325           if (isOneofPresent(message, number, pos)) {
3326             writer.writeBytes(
3327                 number, (ByteString) UnsafeUtil.getObject(message, offset(typeAndOffset)));
3328           }
3329           break;
3330         case 62: // ONEOF_UINT32:
3331           if (isOneofPresent(message, number, pos)) {
3332             writer.writeUInt32(number, oneofIntAt(message, offset(typeAndOffset)));
3333           }
3334           break;
3335         case 63: // ONEOF_ENUM:
3336           if (isOneofPresent(message, number, pos)) {
3337             writer.writeEnum(number, oneofIntAt(message, offset(typeAndOffset)));
3338           }
3339           break;
3340         case 64: // ONEOF_SFIXED32:
3341           if (isOneofPresent(message, number, pos)) {
3342             writer.writeSFixed32(number, oneofIntAt(message, offset(typeAndOffset)));
3343           }
3344           break;
3345         case 65: // ONEOF_SFIXED64:
3346           if (isOneofPresent(message, number, pos)) {
3347             writer.writeSFixed64(number, oneofLongAt(message, offset(typeAndOffset)));
3348           }
3349           break;
3350         case 66: // ONEOF_SINT32:
3351           if (isOneofPresent(message, number, pos)) {
3352             writer.writeSInt32(number, oneofIntAt(message, offset(typeAndOffset)));
3353           }
3354           break;
3355         case 67: // ONEOF_SINT64:
3356           if (isOneofPresent(message, number, pos)) {
3357             writer.writeSInt64(number, oneofLongAt(message, offset(typeAndOffset)));
3358           }
3359           break;
3360         case 68: // ONEOF_GROUP:
3361           if (isOneofPresent(message, number, pos)) {
3362             writer.writeGroup(
3363                 number,
3364                 UnsafeUtil.getObject(message, offset(typeAndOffset)),
3365                 getMessageFieldSchema(pos));
3366           }
3367           break;
3368         default:
3369           // Assume it's an empty entry - just go to the next entry.
3370           break;
3371       }
3372     }
3373     while (nextExtension != null) {
3374       extensionSchema.serializeExtension(writer, nextExtension);
3375       nextExtension = extensionIterator.hasNext() ? extensionIterator.next() : null;
3376     }
3377     writeUnknownInMessageTo(unknownFieldSchema, message, writer);
3378   }
3379 
3380   @SuppressWarnings("unchecked")
writeFieldsInDescendingOrder(T message, Writer writer)3381   private void writeFieldsInDescendingOrder(T message, Writer writer) throws IOException {
3382     writeUnknownInMessageTo(unknownFieldSchema, message, writer);
3383 
3384     Iterator<? extends Map.Entry<?, ?>> extensionIterator = null;
3385     Map.Entry nextExtension = null;
3386     if (hasExtensions) {
3387       FieldSet<?> extensions = extensionSchema.getExtensions(message);
3388       if (!extensions.isEmpty()) {
3389         extensionIterator = extensions.descendingIterator();
3390         nextExtension = extensionIterator.next();
3391       }
3392     }
3393 
3394     for (int pos = buffer.length - INTS_PER_FIELD; pos >= 0; pos -= INTS_PER_FIELD) {
3395       final int typeAndOffset = typeAndOffsetAt(pos);
3396       final int number = numberAt(pos);
3397 
3398       // Write any extensions that need to be written before the current field.
3399       while (nextExtension != null && extensionSchema.extensionNumber(nextExtension) > number) {
3400         extensionSchema.serializeExtension(writer, nextExtension);
3401         nextExtension = extensionIterator.hasNext() ? extensionIterator.next() : null;
3402       }
3403 
3404       switch (type(typeAndOffset)) {
3405         case 0: // DOUBLE:
3406           if (isFieldPresent(message, pos)) {
3407             writer.writeDouble(number, doubleAt(message, offset(typeAndOffset)));
3408           }
3409           break;
3410         case 1: // FLOAT:
3411           if (isFieldPresent(message, pos)) {
3412             writer.writeFloat(number, floatAt(message, offset(typeAndOffset)));
3413           }
3414           break;
3415         case 2: // INT64:
3416           if (isFieldPresent(message, pos)) {
3417             writer.writeInt64(number, longAt(message, offset(typeAndOffset)));
3418           }
3419           break;
3420         case 3: // UINT64:
3421           if (isFieldPresent(message, pos)) {
3422             writer.writeUInt64(number, longAt(message, offset(typeAndOffset)));
3423           }
3424           break;
3425         case 4: // INT32:
3426           if (isFieldPresent(message, pos)) {
3427             writer.writeInt32(number, intAt(message, offset(typeAndOffset)));
3428           }
3429           break;
3430         case 5: // FIXED64:
3431           if (isFieldPresent(message, pos)) {
3432             writer.writeFixed64(number, longAt(message, offset(typeAndOffset)));
3433           }
3434           break;
3435         case 6: // FIXED32:
3436           if (isFieldPresent(message, pos)) {
3437             writer.writeFixed32(number, intAt(message, offset(typeAndOffset)));
3438           }
3439           break;
3440         case 7: // BOOL:
3441           if (isFieldPresent(message, pos)) {
3442             writer.writeBool(number, booleanAt(message, offset(typeAndOffset)));
3443           }
3444           break;
3445         case 8: // STRING:
3446           if (isFieldPresent(message, pos)) {
3447             writeString(number, UnsafeUtil.getObject(message, offset(typeAndOffset)), writer);
3448           }
3449           break;
3450         case 9: // MESSAGE:
3451           if (isFieldPresent(message, pos)) {
3452             Object value = UnsafeUtil.getObject(message, offset(typeAndOffset));
3453             writer.writeMessage(number, value, getMessageFieldSchema(pos));
3454           }
3455           break;
3456         case 10: // BYTES:
3457           if (isFieldPresent(message, pos)) {
3458             writer.writeBytes(
3459                 number, (ByteString) UnsafeUtil.getObject(message, offset(typeAndOffset)));
3460           }
3461           break;
3462         case 11: // UINT32:
3463           if (isFieldPresent(message, pos)) {
3464             writer.writeUInt32(number, intAt(message, offset(typeAndOffset)));
3465           }
3466           break;
3467         case 12: // ENUM:
3468           if (isFieldPresent(message, pos)) {
3469             writer.writeEnum(number, intAt(message, offset(typeAndOffset)));
3470           }
3471           break;
3472         case 13: // SFIXED32:
3473           if (isFieldPresent(message, pos)) {
3474             writer.writeSFixed32(number, intAt(message, offset(typeAndOffset)));
3475           }
3476           break;
3477         case 14: // SFIXED64:
3478           if (isFieldPresent(message, pos)) {
3479             writer.writeSFixed64(number, longAt(message, offset(typeAndOffset)));
3480           }
3481           break;
3482         case 15: // SINT32:
3483           if (isFieldPresent(message, pos)) {
3484             writer.writeSInt32(number, intAt(message, offset(typeAndOffset)));
3485           }
3486           break;
3487         case 16: // SINT64:
3488           if (isFieldPresent(message, pos)) {
3489             writer.writeSInt64(number, longAt(message, offset(typeAndOffset)));
3490           }
3491           break;
3492         case 17: // GROUP:
3493           if (isFieldPresent(message, pos)) {
3494             writer.writeGroup(
3495                 number,
3496                 UnsafeUtil.getObject(message, offset(typeAndOffset)),
3497                 getMessageFieldSchema(pos));
3498           }
3499           break;
3500         case 18: // DOUBLE_LIST:
3501           SchemaUtil.writeDoubleList(
3502               numberAt(pos),
3503               (List<Double>) UnsafeUtil.getObject(message, offset(typeAndOffset)),
3504               writer,
3505               false);
3506           break;
3507         case 19: // FLOAT_LIST:
3508           SchemaUtil.writeFloatList(
3509               numberAt(pos),
3510               (List<Float>) UnsafeUtil.getObject(message, offset(typeAndOffset)),
3511               writer,
3512               false);
3513           break;
3514         case 20: // INT64_LIST:
3515           SchemaUtil.writeInt64List(
3516               numberAt(pos),
3517               (List<Long>) UnsafeUtil.getObject(message, offset(typeAndOffset)),
3518               writer,
3519               false);
3520           break;
3521         case 21: // UINT64_LIST:
3522           SchemaUtil.writeUInt64List(
3523               numberAt(pos),
3524               (List<Long>) UnsafeUtil.getObject(message, offset(typeAndOffset)),
3525               writer,
3526               false);
3527           break;
3528         case 22: // INT32_LIST:
3529           SchemaUtil.writeInt32List(
3530               numberAt(pos),
3531               (List<Integer>) UnsafeUtil.getObject(message, offset(typeAndOffset)),
3532               writer,
3533               false);
3534           break;
3535         case 23: // FIXED64_LIST:
3536           SchemaUtil.writeFixed64List(
3537               numberAt(pos),
3538               (List<Long>) UnsafeUtil.getObject(message, offset(typeAndOffset)),
3539               writer,
3540               false);
3541           break;
3542         case 24: // FIXED32_LIST:
3543           SchemaUtil.writeFixed32List(
3544               numberAt(pos),
3545               (List<Integer>) UnsafeUtil.getObject(message, offset(typeAndOffset)),
3546               writer,
3547               false);
3548           break;
3549         case 25: // BOOL_LIST:
3550           SchemaUtil.writeBoolList(
3551               numberAt(pos),
3552               (List<Boolean>) UnsafeUtil.getObject(message, offset(typeAndOffset)),
3553               writer,
3554               false);
3555           break;
3556         case 26: // STRING_LIST:
3557           SchemaUtil.writeStringList(
3558               numberAt(pos),
3559               (List<String>) UnsafeUtil.getObject(message, offset(typeAndOffset)),
3560               writer);
3561           break;
3562         case 27: // MESSAGE_LIST:
3563           SchemaUtil.writeMessageList(
3564               numberAt(pos),
3565               (List<?>) UnsafeUtil.getObject(message, offset(typeAndOffset)),
3566               writer,
3567               getMessageFieldSchema(pos));
3568           break;
3569         case 28: // BYTES_LIST:
3570           SchemaUtil.writeBytesList(
3571               numberAt(pos),
3572               (List<ByteString>) UnsafeUtil.getObject(message, offset(typeAndOffset)),
3573               writer);
3574           break;
3575         case 29: // UINT32_LIST:
3576           SchemaUtil.writeUInt32List(
3577               numberAt(pos),
3578               (List<Integer>) UnsafeUtil.getObject(message, offset(typeAndOffset)),
3579               writer,
3580               false);
3581           break;
3582         case 30: // ENUM_LIST:
3583           SchemaUtil.writeEnumList(
3584               numberAt(pos),
3585               (List<Integer>) UnsafeUtil.getObject(message, offset(typeAndOffset)),
3586               writer,
3587               false);
3588           break;
3589         case 31: // SFIXED32_LIST:
3590           SchemaUtil.writeSFixed32List(
3591               numberAt(pos),
3592               (List<Integer>) UnsafeUtil.getObject(message, offset(typeAndOffset)),
3593               writer,
3594               false);
3595           break;
3596         case 32: // SFIXED64_LIST:
3597           SchemaUtil.writeSFixed64List(
3598               numberAt(pos),
3599               (List<Long>) UnsafeUtil.getObject(message, offset(typeAndOffset)),
3600               writer,
3601               false);
3602           break;
3603         case 33: // SINT32_LIST:
3604           SchemaUtil.writeSInt32List(
3605               numberAt(pos),
3606               (List<Integer>) UnsafeUtil.getObject(message, offset(typeAndOffset)),
3607               writer,
3608               false);
3609           break;
3610         case 34: // SINT64_LIST:
3611           SchemaUtil.writeSInt64List(
3612               numberAt(pos),
3613               (List<Long>) UnsafeUtil.getObject(message, offset(typeAndOffset)),
3614               writer,
3615               false);
3616           break;
3617         case 35: // DOUBLE_LIST_PACKED:
3618           SchemaUtil.writeDoubleList(
3619               numberAt(pos),
3620               (List<Double>) UnsafeUtil.getObject(message, offset(typeAndOffset)),
3621               writer,
3622               true);
3623           break;
3624         case 36: // FLOAT_LIST_PACKED:
3625           SchemaUtil.writeFloatList(
3626               numberAt(pos),
3627               (List<Float>) UnsafeUtil.getObject(message, offset(typeAndOffset)),
3628               writer,
3629               true);
3630           break;
3631         case 37: // INT64_LIST_PACKED:
3632           SchemaUtil.writeInt64List(
3633               numberAt(pos),
3634               (List<Long>) UnsafeUtil.getObject(message, offset(typeAndOffset)),
3635               writer,
3636               true);
3637           break;
3638         case 38: // UINT64_LIST_PACKED:
3639           SchemaUtil.writeUInt64List(
3640               numberAt(pos),
3641               (List<Long>) UnsafeUtil.getObject(message, offset(typeAndOffset)),
3642               writer,
3643               true);
3644           break;
3645         case 39: // INT32_LIST_PACKED:
3646           SchemaUtil.writeInt32List(
3647               numberAt(pos),
3648               (List<Integer>) UnsafeUtil.getObject(message, offset(typeAndOffset)),
3649               writer,
3650               true);
3651           break;
3652         case 40: // FIXED64_LIST_PACKED:
3653           SchemaUtil.writeFixed64List(
3654               numberAt(pos),
3655               (List<Long>) UnsafeUtil.getObject(message, offset(typeAndOffset)),
3656               writer,
3657               true);
3658           break;
3659         case 41: // FIXED32_LIST_PACKED:
3660           SchemaUtil.writeFixed32List(
3661               numberAt(pos),
3662               (List<Integer>) UnsafeUtil.getObject(message, offset(typeAndOffset)),
3663               writer,
3664               true);
3665 
3666           break;
3667         case 42: // BOOL_LIST_PACKED:
3668           SchemaUtil.writeBoolList(
3669               numberAt(pos),
3670               (List<Boolean>) UnsafeUtil.getObject(message, offset(typeAndOffset)),
3671               writer,
3672               true);
3673           break;
3674         case 43: // UINT32_LIST_PACKED:
3675           SchemaUtil.writeUInt32List(
3676               numberAt(pos),
3677               (List<Integer>) UnsafeUtil.getObject(message, offset(typeAndOffset)),
3678               writer,
3679               true);
3680           break;
3681         case 44: // ENUM_LIST_PACKED:
3682           SchemaUtil.writeEnumList(
3683               numberAt(pos),
3684               (List<Integer>) UnsafeUtil.getObject(message, offset(typeAndOffset)),
3685               writer,
3686               true);
3687           break;
3688         case 45: // SFIXED32_LIST_PACKED:
3689           SchemaUtil.writeSFixed32List(
3690               numberAt(pos),
3691               (List<Integer>) UnsafeUtil.getObject(message, offset(typeAndOffset)),
3692               writer,
3693               true);
3694           break;
3695         case 46: // SFIXED64_LIST_PACKED:
3696           SchemaUtil.writeSFixed64List(
3697               numberAt(pos),
3698               (List<Long>) UnsafeUtil.getObject(message, offset(typeAndOffset)),
3699               writer,
3700               true);
3701           break;
3702         case 47: // SINT32_LIST_PACKED:
3703           SchemaUtil.writeSInt32List(
3704               numberAt(pos),
3705               (List<Integer>) UnsafeUtil.getObject(message, offset(typeAndOffset)),
3706               writer,
3707               true);
3708           break;
3709         case 48: // SINT64_LIST_PACKED:
3710           SchemaUtil.writeSInt64List(
3711               numberAt(pos),
3712               (List<Long>) UnsafeUtil.getObject(message, offset(typeAndOffset)),
3713               writer,
3714               true);
3715           break;
3716         case 49: // GROUP_LIST:
3717           SchemaUtil.writeGroupList(
3718               numberAt(pos),
3719               (List<?>) UnsafeUtil.getObject(message, offset(typeAndOffset)),
3720               writer,
3721               getMessageFieldSchema(pos));
3722           break;
3723         case 50: // MAP:
3724           // TODO(dweis): Use schema cache.
3725           writeMapHelper(writer, number, UnsafeUtil.getObject(message, offset(typeAndOffset)), pos);
3726           break;
3727         case 51: // ONEOF_DOUBLE:
3728           if (isOneofPresent(message, number, pos)) {
3729             writer.writeDouble(number, oneofDoubleAt(message, offset(typeAndOffset)));
3730           }
3731           break;
3732         case 52: // ONEOF_FLOAT:
3733           if (isOneofPresent(message, number, pos)) {
3734             writer.writeFloat(number, oneofFloatAt(message, offset(typeAndOffset)));
3735           }
3736           break;
3737         case 53: // ONEOF_INT64:
3738           if (isOneofPresent(message, number, pos)) {
3739             writer.writeInt64(number, oneofLongAt(message, offset(typeAndOffset)));
3740           }
3741           break;
3742         case 54: // ONEOF_UINT64:
3743           if (isOneofPresent(message, number, pos)) {
3744             writer.writeUInt64(number, oneofLongAt(message, offset(typeAndOffset)));
3745           }
3746           break;
3747         case 55: // ONEOF_INT32:
3748           if (isOneofPresent(message, number, pos)) {
3749             writer.writeInt32(number, oneofIntAt(message, offset(typeAndOffset)));
3750           }
3751           break;
3752         case 56: // ONEOF_FIXED64:
3753           if (isOneofPresent(message, number, pos)) {
3754             writer.writeFixed64(number, oneofLongAt(message, offset(typeAndOffset)));
3755           }
3756           break;
3757         case 57: // ONEOF_FIXED32:
3758           if (isOneofPresent(message, number, pos)) {
3759             writer.writeFixed32(number, oneofIntAt(message, offset(typeAndOffset)));
3760           }
3761           break;
3762         case 58: // ONEOF_BOOL:
3763           if (isOneofPresent(message, number, pos)) {
3764             writer.writeBool(number, oneofBooleanAt(message, offset(typeAndOffset)));
3765           }
3766           break;
3767         case 59: // ONEOF_STRING:
3768           if (isOneofPresent(message, number, pos)) {
3769             writeString(number, UnsafeUtil.getObject(message, offset(typeAndOffset)), writer);
3770           }
3771           break;
3772         case 60: // ONEOF_MESSAGE:
3773           if (isOneofPresent(message, number, pos)) {
3774             Object value = UnsafeUtil.getObject(message, offset(typeAndOffset));
3775             writer.writeMessage(number, value, getMessageFieldSchema(pos));
3776           }
3777           break;
3778         case 61: // ONEOF_BYTES:
3779           if (isOneofPresent(message, number, pos)) {
3780             writer.writeBytes(
3781                 number, (ByteString) UnsafeUtil.getObject(message, offset(typeAndOffset)));
3782           }
3783           break;
3784         case 62: // ONEOF_UINT32:
3785           if (isOneofPresent(message, number, pos)) {
3786             writer.writeUInt32(number, oneofIntAt(message, offset(typeAndOffset)));
3787           }
3788           break;
3789         case 63: // ONEOF_ENUM:
3790           if (isOneofPresent(message, number, pos)) {
3791             writer.writeEnum(number, oneofIntAt(message, offset(typeAndOffset)));
3792           }
3793           break;
3794         case 64: // ONEOF_SFIXED32:
3795           if (isOneofPresent(message, number, pos)) {
3796             writer.writeSFixed32(number, oneofIntAt(message, offset(typeAndOffset)));
3797           }
3798           break;
3799         case 65: // ONEOF_SFIXED64:
3800           if (isOneofPresent(message, number, pos)) {
3801             writer.writeSFixed64(number, oneofLongAt(message, offset(typeAndOffset)));
3802           }
3803           break;
3804         case 66: // ONEOF_SINT32:
3805           if (isOneofPresent(message, number, pos)) {
3806             writer.writeSInt32(number, oneofIntAt(message, offset(typeAndOffset)));
3807           }
3808           break;
3809         case 67: // ONEOF_SINT64:
3810           if (isOneofPresent(message, number, pos)) {
3811             writer.writeSInt64(number, oneofLongAt(message, offset(typeAndOffset)));
3812           }
3813           break;
3814         case 68: // ONEOF_GROUP:
3815           if (isOneofPresent(message, number, pos)) {
3816             writer.writeGroup(
3817                 number,
3818                 UnsafeUtil.getObject(message, offset(typeAndOffset)),
3819                 getMessageFieldSchema(pos));
3820           }
3821           break;
3822         default:
3823           break;
3824       }
3825     }
3826     while (nextExtension != null) {
3827       extensionSchema.serializeExtension(writer, nextExtension);
3828       nextExtension = extensionIterator.hasNext() ? extensionIterator.next() : null;
3829     }
3830   }
3831 
3832   @SuppressWarnings("unchecked")
writeMapHelper(Writer writer, int number, Object mapField, int pos)3833   private <K, V> void writeMapHelper(Writer writer, int number, Object mapField, int pos)
3834       throws IOException {
3835     if (mapField != null) {
3836       writer.writeMap(
3837           number,
3838           (MapEntryLite.Metadata<K, V>) mapFieldSchema.forMapMetadata(getMapFieldDefaultEntry(pos)),
3839           (Map<K, V>) mapFieldSchema.forMapData(mapField));
3840     }
3841   }
3842 
writeUnknownInMessageTo( UnknownFieldSchema<UT, UB> schema, T message, Writer writer)3843   private <UT, UB> void writeUnknownInMessageTo(
3844       UnknownFieldSchema<UT, UB> schema, T message, Writer writer) throws IOException {
3845     schema.writeTo(schema.getFromMessage(message), writer);
3846   }
3847 
3848   @Override
mergeFrom(T message, Reader reader, ExtensionRegistryLite extensionRegistry)3849   public void mergeFrom(T message, Reader reader, ExtensionRegistryLite extensionRegistry)
3850       throws IOException {
3851     if (extensionRegistry == null) {
3852       throw new NullPointerException();
3853     }
3854     mergeFromHelper(unknownFieldSchema, extensionSchema, message, reader, extensionRegistry);
3855   }
3856 
3857   /**
3858    * A helper method for wildcard capture of {@code unknownFieldSchema}. See:
3859    * https://docs.oracle.com/javase/tutorial/java/generics/capture.html
3860    */
mergeFromHelper( UnknownFieldSchema<UT, UB> unknownFieldSchema, ExtensionSchema<ET> extensionSchema, T message, Reader reader, ExtensionRegistryLite extensionRegistry)3861   private <UT, UB, ET extends FieldDescriptorLite<ET>> void mergeFromHelper(
3862       UnknownFieldSchema<UT, UB> unknownFieldSchema,
3863       ExtensionSchema<ET> extensionSchema,
3864       T message,
3865       Reader reader,
3866       ExtensionRegistryLite extensionRegistry)
3867       throws IOException {
3868     UB unknownFields = null;
3869     FieldSet<ET> extensions = null;
3870     try {
3871       while (true) {
3872         final int number = reader.getFieldNumber();
3873         final int pos = positionForFieldNumber(number);
3874         if (pos < 0) {
3875           if (number == Reader.READ_DONE) {
3876             return;
3877           }
3878           // Check if it's an extension.
3879           Object extension =
3880               !hasExtensions
3881                   ? null
3882                   : extensionSchema.findExtensionByNumber(
3883                       extensionRegistry, defaultInstance, number);
3884           if (extension != null) {
3885             if (extensions == null) {
3886               extensions = extensionSchema.getMutableExtensions(message);
3887             }
3888             unknownFields =
3889                 extensionSchema.parseExtension(
3890                     reader,
3891                     extension,
3892                     extensionRegistry,
3893                     extensions,
3894                     unknownFields,
3895                     unknownFieldSchema);
3896             continue;
3897           }
3898           if (unknownFieldSchema.shouldDiscardUnknownFields(reader)) {
3899             if (reader.skipField()) {
3900               continue;
3901             }
3902           } else {
3903             if (unknownFields == null) {
3904               unknownFields = unknownFieldSchema.getBuilderFromMessage(message);
3905             }
3906             // Unknown field.
3907             if (unknownFieldSchema.mergeOneFieldFrom(unknownFields, reader)) {
3908               continue;
3909             }
3910           }
3911           // Done reading.
3912           return;
3913         }
3914         final int typeAndOffset = typeAndOffsetAt(pos);
3915 
3916         try {
3917           switch (type(typeAndOffset)) {
3918             case 0: // DOUBLE:
3919               UnsafeUtil.putDouble(message, offset(typeAndOffset), reader.readDouble());
3920               setFieldPresent(message, pos);
3921               break;
3922             case 1: // FLOAT:
3923               UnsafeUtil.putFloat(message, offset(typeAndOffset), reader.readFloat());
3924               setFieldPresent(message, pos);
3925               break;
3926             case 2: // INT64:
3927               UnsafeUtil.putLong(message, offset(typeAndOffset), reader.readInt64());
3928               setFieldPresent(message, pos);
3929               break;
3930             case 3: // UINT64:
3931               UnsafeUtil.putLong(message, offset(typeAndOffset), reader.readUInt64());
3932               setFieldPresent(message, pos);
3933               break;
3934             case 4: // INT32:
3935               UnsafeUtil.putInt(message, offset(typeAndOffset), reader.readInt32());
3936               setFieldPresent(message, pos);
3937               break;
3938             case 5: // FIXED64:
3939               UnsafeUtil.putLong(message, offset(typeAndOffset), reader.readFixed64());
3940               setFieldPresent(message, pos);
3941               break;
3942             case 6: // FIXED32:
3943               UnsafeUtil.putInt(message, offset(typeAndOffset), reader.readFixed32());
3944               setFieldPresent(message, pos);
3945               break;
3946             case 7: // BOOL:
3947               UnsafeUtil.putBoolean(message, offset(typeAndOffset), reader.readBool());
3948               setFieldPresent(message, pos);
3949               break;
3950             case 8: // STRING:
3951               readString(message, typeAndOffset, reader);
3952               setFieldPresent(message, pos);
3953               break;
3954             case 9:
3955               { // MESSAGE:
3956                 if (isFieldPresent(message, pos)) {
3957                   Object mergedResult =
3958                       Internal.mergeMessage(
3959                           UnsafeUtil.getObject(message, offset(typeAndOffset)),
3960                           reader.readMessageBySchemaWithCheck(
3961                               (Schema<T>) getMessageFieldSchema(pos), extensionRegistry));
3962                   UnsafeUtil.putObject(message, offset(typeAndOffset), mergedResult);
3963                 } else {
3964                   UnsafeUtil.putObject(
3965                       message,
3966                       offset(typeAndOffset),
3967                       reader.readMessageBySchemaWithCheck(
3968                           (Schema<T>) getMessageFieldSchema(pos), extensionRegistry));
3969                   setFieldPresent(message, pos);
3970                 }
3971                 break;
3972               }
3973             case 10: // BYTES:
3974               UnsafeUtil.putObject(message, offset(typeAndOffset), reader.readBytes());
3975               setFieldPresent(message, pos);
3976               break;
3977             case 11: // UINT32:
3978               UnsafeUtil.putInt(message, offset(typeAndOffset), reader.readUInt32());
3979               setFieldPresent(message, pos);
3980               break;
3981             case 12: // ENUM:
3982               {
3983                 int enumValue = reader.readEnum();
3984                 EnumVerifier enumVerifier = getEnumFieldVerifier(pos);
3985                 if (enumVerifier == null || enumVerifier.isInRange(enumValue)) {
3986                   UnsafeUtil.putInt(message, offset(typeAndOffset), enumValue);
3987                   setFieldPresent(message, pos);
3988                 } else {
3989                   unknownFields =
3990                       SchemaUtil.storeUnknownEnum(
3991                           number, enumValue, unknownFields, unknownFieldSchema);
3992                 }
3993                 break;
3994               }
3995             case 13: // SFIXED32:
3996               UnsafeUtil.putInt(message, offset(typeAndOffset), reader.readSFixed32());
3997               setFieldPresent(message, pos);
3998               break;
3999             case 14: // SFIXED64:
4000               UnsafeUtil.putLong(message, offset(typeAndOffset), reader.readSFixed64());
4001               setFieldPresent(message, pos);
4002               break;
4003             case 15: // SINT32:
4004               UnsafeUtil.putInt(message, offset(typeAndOffset), reader.readSInt32());
4005               setFieldPresent(message, pos);
4006               break;
4007             case 16: // SINT64:
4008               UnsafeUtil.putLong(message, offset(typeAndOffset), reader.readSInt64());
4009               setFieldPresent(message, pos);
4010               break;
4011             case 17:
4012               { // GROUP:
4013                 if (isFieldPresent(message, pos)) {
4014                   Object mergedResult =
4015                       Internal.mergeMessage(
4016                           UnsafeUtil.getObject(message, offset(typeAndOffset)),
4017                           reader.readGroupBySchemaWithCheck(
4018                               (Schema<T>) getMessageFieldSchema(pos), extensionRegistry));
4019                   UnsafeUtil.putObject(message, offset(typeAndOffset), mergedResult);
4020                 } else {
4021                   UnsafeUtil.putObject(
4022                       message,
4023                       offset(typeAndOffset),
4024                       reader.readGroupBySchemaWithCheck(
4025                           (Schema<T>) getMessageFieldSchema(pos), extensionRegistry));
4026                   setFieldPresent(message, pos);
4027                 }
4028                 break;
4029               }
4030             case 18: // DOUBLE_LIST:
4031               reader.readDoubleList(
4032                   listFieldSchema.<Double>mutableListAt(message, offset(typeAndOffset)));
4033               break;
4034             case 19: // FLOAT_LIST:
4035               reader.readFloatList(
4036                   listFieldSchema.<Float>mutableListAt(message, offset(typeAndOffset)));
4037               break;
4038             case 20: // INT64_LIST:
4039               reader.readInt64List(
4040                   listFieldSchema.<Long>mutableListAt(message, offset(typeAndOffset)));
4041               break;
4042             case 21: // UINT64_LIST:
4043               reader.readUInt64List(
4044                   listFieldSchema.<Long>mutableListAt(message, offset(typeAndOffset)));
4045               break;
4046             case 22: // INT32_LIST:
4047               reader.readInt32List(
4048                   listFieldSchema.<Integer>mutableListAt(message, offset(typeAndOffset)));
4049               break;
4050             case 23: // FIXED64_LIST:
4051               reader.readFixed64List(
4052                   listFieldSchema.<Long>mutableListAt(message, offset(typeAndOffset)));
4053               break;
4054             case 24: // FIXED32_LIST:
4055               reader.readFixed32List(
4056                   listFieldSchema.<Integer>mutableListAt(message, offset(typeAndOffset)));
4057               break;
4058             case 25: // BOOL_LIST:
4059               reader.readBoolList(
4060                   listFieldSchema.<Boolean>mutableListAt(message, offset(typeAndOffset)));
4061               break;
4062             case 26: // STRING_LIST:
4063               readStringList(message, typeAndOffset, reader);
4064               break;
4065             case 27:
4066               { // MESSAGE_LIST:
4067                 readMessageList(
4068                     message,
4069                     typeAndOffset,
4070                     reader,
4071                     (Schema<T>) getMessageFieldSchema(pos),
4072                     extensionRegistry);
4073                 break;
4074               }
4075             case 28: // BYTES_LIST:
4076               reader.readBytesList(
4077                   listFieldSchema.<ByteString>mutableListAt(message, offset(typeAndOffset)));
4078               break;
4079             case 29: // UINT32_LIST:
4080               reader.readUInt32List(
4081                   listFieldSchema.<Integer>mutableListAt(message, offset(typeAndOffset)));
4082               break;
4083             case 30: // ENUM_LIST:
4084               {
4085                 List<Integer> enumList =
4086                     listFieldSchema.<Integer>mutableListAt(message, offset(typeAndOffset));
4087                 reader.readEnumList(enumList);
4088                 unknownFields =
4089                     SchemaUtil.filterUnknownEnumList(
4090                         number,
4091                         enumList,
4092                         getEnumFieldVerifier(pos),
4093                         unknownFields,
4094                         unknownFieldSchema);
4095                 break;
4096               }
4097             case 31: // SFIXED32_LIST:
4098               reader.readSFixed32List(
4099                   listFieldSchema.<Integer>mutableListAt(message, offset(typeAndOffset)));
4100               break;
4101             case 32: // SFIXED64_LIST:
4102               reader.readSFixed64List(
4103                   listFieldSchema.<Long>mutableListAt(message, offset(typeAndOffset)));
4104               break;
4105             case 33: // SINT32_LIST:
4106               reader.readSInt32List(
4107                   listFieldSchema.<Integer>mutableListAt(message, offset(typeAndOffset)));
4108               break;
4109             case 34: // SINT64_LIST:
4110               reader.readSInt64List(
4111                   listFieldSchema.<Long>mutableListAt(message, offset(typeAndOffset)));
4112               break;
4113             case 35: // DOUBLE_LIST_PACKED:
4114               reader.readDoubleList(
4115                   listFieldSchema.<Double>mutableListAt(message, offset(typeAndOffset)));
4116               break;
4117             case 36: // FLOAT_LIST_PACKED:
4118               reader.readFloatList(
4119                   listFieldSchema.<Float>mutableListAt(message, offset(typeAndOffset)));
4120               break;
4121             case 37: // INT64_LIST_PACKED:
4122               reader.readInt64List(
4123                   listFieldSchema.<Long>mutableListAt(message, offset(typeAndOffset)));
4124               break;
4125             case 38: // UINT64_LIST_PACKED:
4126               reader.readUInt64List(
4127                   listFieldSchema.<Long>mutableListAt(message, offset(typeAndOffset)));
4128               break;
4129             case 39: // INT32_LIST_PACKED:
4130               reader.readInt32List(
4131                   listFieldSchema.<Integer>mutableListAt(message, offset(typeAndOffset)));
4132               break;
4133             case 40: // FIXED64_LIST_PACKED:
4134               reader.readFixed64List(
4135                   listFieldSchema.<Long>mutableListAt(message, offset(typeAndOffset)));
4136               break;
4137             case 41: // FIXED32_LIST_PACKED:
4138               reader.readFixed32List(
4139                   listFieldSchema.<Integer>mutableListAt(message, offset(typeAndOffset)));
4140               break;
4141             case 42: // BOOL_LIST_PACKED:
4142               reader.readBoolList(
4143                   listFieldSchema.<Boolean>mutableListAt(message, offset(typeAndOffset)));
4144               break;
4145             case 43: // UINT32_LIST_PACKED:
4146               reader.readUInt32List(
4147                   listFieldSchema.<Integer>mutableListAt(message, offset(typeAndOffset)));
4148               break;
4149             case 44: // ENUM_LIST_PACKED:
4150               {
4151                 List<Integer> enumList =
4152                     listFieldSchema.<Integer>mutableListAt(message, offset(typeAndOffset));
4153                 reader.readEnumList(enumList);
4154                 unknownFields =
4155                     SchemaUtil.filterUnknownEnumList(
4156                         number,
4157                         enumList,
4158                         getEnumFieldVerifier(pos),
4159                         unknownFields,
4160                         unknownFieldSchema);
4161                 break;
4162               }
4163             case 45: // SFIXED32_LIST_PACKED:
4164               reader.readSFixed32List(
4165                   listFieldSchema.<Integer>mutableListAt(message, offset(typeAndOffset)));
4166               break;
4167             case 46: // SFIXED64_LIST_PACKED:
4168               reader.readSFixed64List(
4169                   listFieldSchema.<Long>mutableListAt(message, offset(typeAndOffset)));
4170               break;
4171             case 47: // SINT32_LIST_PACKED:
4172               reader.readSInt32List(
4173                   listFieldSchema.<Integer>mutableListAt(message, offset(typeAndOffset)));
4174               break;
4175             case 48: // SINT64_LIST_PACKED:
4176               reader.readSInt64List(
4177                   listFieldSchema.<Long>mutableListAt(message, offset(typeAndOffset)));
4178               break;
4179             case 49:
4180               { // GROUP_LIST:
4181                 readGroupList(
4182                     message,
4183                     offset(typeAndOffset),
4184                     reader,
4185                     (Schema<T>) getMessageFieldSchema(pos),
4186                     extensionRegistry);
4187                 break;
4188               }
4189             case 50: // MAP:
4190               mergeMap(message, pos, getMapFieldDefaultEntry(pos), extensionRegistry, reader);
4191               break;
4192             case 51: // ONEOF_DOUBLE:
4193               UnsafeUtil.putObject(
4194                   message, offset(typeAndOffset), Double.valueOf(reader.readDouble()));
4195               setOneofPresent(message, number, pos);
4196               break;
4197             case 52: // ONEOF_FLOAT:
4198               UnsafeUtil.putObject(
4199                   message, offset(typeAndOffset), Float.valueOf(reader.readFloat()));
4200               setOneofPresent(message, number, pos);
4201               break;
4202             case 53: // ONEOF_INT64:
4203               UnsafeUtil.putObject(
4204                   message, offset(typeAndOffset), Long.valueOf(reader.readInt64()));
4205               setOneofPresent(message, number, pos);
4206               break;
4207             case 54: // ONEOF_UINT64:
4208               UnsafeUtil.putObject(
4209                   message, offset(typeAndOffset), Long.valueOf(reader.readUInt64()));
4210               setOneofPresent(message, number, pos);
4211               break;
4212             case 55: // ONEOF_INT32:
4213               UnsafeUtil.putObject(
4214                   message, offset(typeAndOffset), Integer.valueOf(reader.readInt32()));
4215               setOneofPresent(message, number, pos);
4216               break;
4217             case 56: // ONEOF_FIXED64:
4218               UnsafeUtil.putObject(
4219                   message, offset(typeAndOffset), Long.valueOf(reader.readFixed64()));
4220               setOneofPresent(message, number, pos);
4221               break;
4222             case 57: // ONEOF_FIXED32:
4223               UnsafeUtil.putObject(
4224                   message, offset(typeAndOffset), Integer.valueOf(reader.readFixed32()));
4225               setOneofPresent(message, number, pos);
4226               break;
4227             case 58: // ONEOF_BOOL:
4228               UnsafeUtil.putObject(
4229                   message, offset(typeAndOffset), Boolean.valueOf(reader.readBool()));
4230               setOneofPresent(message, number, pos);
4231               break;
4232             case 59: // ONEOF_STRING:
4233               readString(message, typeAndOffset, reader);
4234               setOneofPresent(message, number, pos);
4235               break;
4236             case 60: // ONEOF_MESSAGE:
4237               if (isOneofPresent(message, number, pos)) {
4238                 Object mergedResult =
4239                     Internal.mergeMessage(
4240                         UnsafeUtil.getObject(message, offset(typeAndOffset)),
4241                         reader.readMessageBySchemaWithCheck(
4242                             getMessageFieldSchema(pos), extensionRegistry));
4243                 UnsafeUtil.putObject(message, offset(typeAndOffset), mergedResult);
4244               } else {
4245                 UnsafeUtil.putObject(
4246                     message,
4247                     offset(typeAndOffset),
4248                     reader.readMessageBySchemaWithCheck(
4249                         getMessageFieldSchema(pos), extensionRegistry));
4250                 setFieldPresent(message, pos);
4251               }
4252               setOneofPresent(message, number, pos);
4253               break;
4254             case 61: // ONEOF_BYTES:
4255               UnsafeUtil.putObject(message, offset(typeAndOffset), reader.readBytes());
4256               setOneofPresent(message, number, pos);
4257               break;
4258             case 62: // ONEOF_UINT32:
4259               UnsafeUtil.putObject(
4260                   message, offset(typeAndOffset), Integer.valueOf(reader.readUInt32()));
4261               setOneofPresent(message, number, pos);
4262               break;
4263             case 63: // ONEOF_ENUM:
4264               {
4265                 int enumValue = reader.readEnum();
4266                 EnumVerifier enumVerifier = getEnumFieldVerifier(pos);
4267                 if (enumVerifier == null || enumVerifier.isInRange(enumValue)) {
4268                   UnsafeUtil.putObject(message, offset(typeAndOffset), enumValue);
4269                   setOneofPresent(message, number, pos);
4270                 } else {
4271                   unknownFields =
4272                       SchemaUtil.storeUnknownEnum(
4273                           number, enumValue, unknownFields, unknownFieldSchema);
4274                 }
4275                 break;
4276               }
4277             case 64: // ONEOF_SFIXED32:
4278               UnsafeUtil.putObject(
4279                   message, offset(typeAndOffset), Integer.valueOf(reader.readSFixed32()));
4280               setOneofPresent(message, number, pos);
4281               break;
4282             case 65: // ONEOF_SFIXED64:
4283               UnsafeUtil.putObject(
4284                   message, offset(typeAndOffset), Long.valueOf(reader.readSFixed64()));
4285               setOneofPresent(message, number, pos);
4286               break;
4287             case 66: // ONEOF_SINT32:
4288               UnsafeUtil.putObject(
4289                   message, offset(typeAndOffset), Integer.valueOf(reader.readSInt32()));
4290               setOneofPresent(message, number, pos);
4291               break;
4292             case 67: // ONEOF_SINT64:
4293               UnsafeUtil.putObject(
4294                   message, offset(typeAndOffset), Long.valueOf(reader.readSInt64()));
4295               setOneofPresent(message, number, pos);
4296               break;
4297             case 68: // ONEOF_GROUP:
4298               UnsafeUtil.putObject(
4299                   message,
4300                   offset(typeAndOffset),
4301                   reader.readGroupBySchemaWithCheck(getMessageFieldSchema(pos), extensionRegistry));
4302               setOneofPresent(message, number, pos);
4303               break;
4304             default:
4305               // Assume we've landed on an empty entry. Treat it as an unknown field.
4306               if (unknownFields == null) {
4307                 unknownFields = unknownFieldSchema.newBuilder();
4308               }
4309               if (!unknownFieldSchema.mergeOneFieldFrom(unknownFields, reader)) {
4310                 return;
4311               }
4312               break;
4313           }
4314         } catch (InvalidProtocolBufferException.InvalidWireTypeException e) {
4315           // Treat fields with an invalid wire type as unknown fields
4316           // (i.e. same as the default case).
4317           if (unknownFieldSchema.shouldDiscardUnknownFields(reader)) {
4318             if (!reader.skipField()) {
4319               return;
4320             }
4321           } else {
4322             if (unknownFields == null) {
4323               unknownFields = unknownFieldSchema.getBuilderFromMessage(message);
4324             }
4325             if (!unknownFieldSchema.mergeOneFieldFrom(unknownFields, reader)) {
4326               return;
4327             }
4328           }
4329         }
4330       }
4331     } finally {
4332       for (int i = checkInitializedCount; i < repeatedFieldOffsetStart; i++) {
4333         unknownFields =
4334             filterMapUnknownEnumValues(message, intArray[i], unknownFields, unknownFieldSchema);
4335       }
4336       if (unknownFields != null) {
4337         unknownFieldSchema.setBuilderToMessage(message, unknownFields);
4338       }
4339     }
4340   }
4341 
4342   @SuppressWarnings("ReferenceEquality")
getMutableUnknownFields(Object message)4343   static UnknownFieldSetLite getMutableUnknownFields(Object message) {
4344     UnknownFieldSetLite unknownFields = ((GeneratedMessageLite) message).unknownFields;
4345     if (unknownFields == UnknownFieldSetLite.getDefaultInstance()) {
4346       unknownFields = UnknownFieldSetLite.newInstance();
4347       ((GeneratedMessageLite) message).unknownFields = unknownFields;
4348     }
4349     return unknownFields;
4350   }
4351 
4352   /** Decodes a map entry key or value. Stores result in registers.object1. */
decodeMapEntryValue( byte[] data, int position, int limit, WireFormat.FieldType fieldType, Class<?> messageType, Registers registers)4353   private int decodeMapEntryValue(
4354       byte[] data,
4355       int position,
4356       int limit,
4357       WireFormat.FieldType fieldType,
4358       Class<?> messageType,
4359       Registers registers)
4360       throws IOException {
4361     switch (fieldType) {
4362       case BOOL:
4363         position = decodeVarint64(data, position, registers);
4364         registers.object1 = registers.long1 != 0;
4365         break;
4366       case BYTES:
4367         position = decodeBytes(data, position, registers);
4368         break;
4369       case DOUBLE:
4370         registers.object1 = decodeDouble(data, position);
4371         position += 8;
4372         break;
4373       case FIXED32:
4374       case SFIXED32:
4375         registers.object1 = decodeFixed32(data, position);
4376         position += 4;
4377         break;
4378       case FIXED64:
4379       case SFIXED64:
4380         registers.object1 = decodeFixed64(data, position);
4381         position += 8;
4382         break;
4383       case FLOAT:
4384         registers.object1 = decodeFloat(data, position);
4385         position += 4;
4386         break;
4387       case ENUM:
4388       case INT32:
4389       case UINT32:
4390         position = decodeVarint32(data, position, registers);
4391         registers.object1 = registers.int1;
4392         break;
4393       case INT64:
4394       case UINT64:
4395         position = decodeVarint64(data, position, registers);
4396         registers.object1 = registers.long1;
4397         break;
4398       case MESSAGE:
4399         position =
4400             decodeMessageField(
4401                 Protobuf.getInstance().schemaFor(messageType), data, position, limit, registers);
4402         break;
4403       case SINT32:
4404         position = decodeVarint32(data, position, registers);
4405         registers.object1 = CodedInputStream.decodeZigZag32(registers.int1);
4406         break;
4407       case SINT64:
4408         position = decodeVarint64(data, position, registers);
4409         registers.object1 = CodedInputStream.decodeZigZag64(registers.long1);
4410         break;
4411       case STRING:
4412         position = decodeStringRequireUtf8(data, position, registers);
4413         break;
4414       default:
4415         throw new RuntimeException("unsupported field type.");
4416     }
4417     return position;
4418   }
4419 
4420   /** Decodes a map entry. */
decodeMapEntry( byte[] data, int position, int limit, MapEntryLite.Metadata<K, V> metadata, Map<K, V> target, Registers registers)4421   private <K, V> int decodeMapEntry(
4422       byte[] data,
4423       int position,
4424       int limit,
4425       MapEntryLite.Metadata<K, V> metadata,
4426       Map<K, V> target,
4427       Registers registers)
4428       throws IOException {
4429     position = decodeVarint32(data, position, registers);
4430     final int length = registers.int1;
4431     if (length < 0 || length > limit - position) {
4432       throw InvalidProtocolBufferException.truncatedMessage();
4433     }
4434     final int end = position + length;
4435     K key = metadata.defaultKey;
4436     V value = metadata.defaultValue;
4437     while (position < end) {
4438       int tag = data[position++];
4439       if (tag < 0) {
4440         position = decodeVarint32(tag, data, position, registers);
4441         tag = registers.int1;
4442       }
4443       final int fieldNumber = tag >>> 3;
4444       final int wireType = tag & 0x7;
4445       switch (fieldNumber) {
4446         case 1:
4447           if (wireType == metadata.keyType.getWireType()) {
4448             position =
4449                 decodeMapEntryValue(data, position, limit, metadata.keyType, null, registers);
4450             key = (K) registers.object1;
4451             continue;
4452           }
4453           break;
4454         case 2:
4455           if (wireType == metadata.valueType.getWireType()) {
4456             position =
4457                 decodeMapEntryValue(
4458                     data,
4459                     position,
4460                     limit,
4461                     metadata.valueType,
4462                     metadata.defaultValue.getClass(),
4463                     registers);
4464             value = (V) registers.object1;
4465             continue;
4466           }
4467           break;
4468         default:
4469           break;
4470       }
4471       position = skipField(tag, data, position, limit, registers);
4472     }
4473     if (position != end) {
4474       throw InvalidProtocolBufferException.parseFailure();
4475     }
4476     target.put(key, value);
4477     return end;
4478   }
4479 
4480   @SuppressWarnings("ReferenceEquality")
parseRepeatedField( T message, byte[] data, int position, int limit, int tag, int number, int wireType, int bufferPosition, long typeAndOffset, int fieldType, long fieldOffset, Registers registers)4481   private int parseRepeatedField(
4482       T message,
4483       byte[] data,
4484       int position,
4485       int limit,
4486       int tag,
4487       int number,
4488       int wireType,
4489       int bufferPosition,
4490       long typeAndOffset,
4491       int fieldType,
4492       long fieldOffset,
4493       Registers registers)
4494       throws IOException {
4495     ProtobufList<?> list = (ProtobufList<?>) UNSAFE.getObject(message, fieldOffset);
4496     if (!list.isModifiable()) {
4497       final int size = list.size();
4498       list =
4499           list.mutableCopyWithCapacity(
4500               size == 0 ? AbstractProtobufList.DEFAULT_CAPACITY : size * 2);
4501       UNSAFE.putObject(message, fieldOffset, list);
4502     }
4503     switch (fieldType) {
4504       case 18: // DOUBLE_LIST:
4505       case 35: // DOUBLE_LIST_PACKED:
4506         if (wireType == WireFormat.WIRETYPE_LENGTH_DELIMITED) {
4507           position = decodePackedDoubleList(data, position, list, registers);
4508         } else if (wireType == WireFormat.WIRETYPE_FIXED64) {
4509           position = decodeDoubleList(tag, data, position, limit, list, registers);
4510         }
4511         break;
4512       case 19: // FLOAT_LIST:
4513       case 36: // FLOAT_LIST_PACKED:
4514         if (wireType == WireFormat.WIRETYPE_LENGTH_DELIMITED) {
4515           position = decodePackedFloatList(data, position, list, registers);
4516         } else if (wireType == WireFormat.WIRETYPE_FIXED32) {
4517           position = decodeFloatList(tag, data, position, limit, list, registers);
4518         }
4519         break;
4520       case 20: // INT64_LIST:
4521       case 21: // UINT64_LIST:
4522       case 37: // INT64_LIST_PACKED:
4523       case 38: // UINT64_LIST_PACKED:
4524         if (wireType == WireFormat.WIRETYPE_LENGTH_DELIMITED) {
4525           position = decodePackedVarint64List(data, position, list, registers);
4526         } else if (wireType == WireFormat.WIRETYPE_VARINT) {
4527           position = decodeVarint64List(tag, data, position, limit, list, registers);
4528         }
4529         break;
4530       case 22: // INT32_LIST:
4531       case 29: // UINT32_LIST:
4532       case 39: // INT32_LIST_PACKED:
4533       case 43: // UINT32_LIST_PACKED:
4534         if (wireType == WireFormat.WIRETYPE_LENGTH_DELIMITED) {
4535           position = decodePackedVarint32List(data, position, list, registers);
4536         } else if (wireType == WireFormat.WIRETYPE_VARINT) {
4537           position = decodeVarint32List(tag, data, position, limit, list, registers);
4538         }
4539         break;
4540       case 23: // FIXED64_LIST:
4541       case 32: // SFIXED64_LIST:
4542       case 40: // FIXED64_LIST_PACKED:
4543       case 46: // SFIXED64_LIST_PACKED:
4544         if (wireType == WireFormat.WIRETYPE_LENGTH_DELIMITED) {
4545           position = decodePackedFixed64List(data, position, list, registers);
4546         } else if (wireType == WireFormat.WIRETYPE_FIXED64) {
4547           position = decodeFixed64List(tag, data, position, limit, list, registers);
4548         }
4549         break;
4550       case 24: // FIXED32_LIST:
4551       case 31: // SFIXED32_LIST:
4552       case 41: // FIXED32_LIST_PACKED:
4553       case 45: // SFIXED32_LIST_PACKED:
4554         if (wireType == WireFormat.WIRETYPE_LENGTH_DELIMITED) {
4555           position = decodePackedFixed32List(data, position, list, registers);
4556         } else if (wireType == WireFormat.WIRETYPE_FIXED32) {
4557           position = decodeFixed32List(tag, data, position, limit, list, registers);
4558         }
4559         break;
4560       case 25: // BOOL_LIST:
4561       case 42: // BOOL_LIST_PACKED:
4562         if (wireType == WireFormat.WIRETYPE_LENGTH_DELIMITED) {
4563           position = decodePackedBoolList(data, position, list, registers);
4564         } else if (wireType == WireFormat.WIRETYPE_VARINT) {
4565           position = decodeBoolList(tag, data, position, limit, list, registers);
4566         }
4567         break;
4568       case 26: // STRING_LIST:
4569         if (wireType == WireFormat.WIRETYPE_LENGTH_DELIMITED) {
4570           if ((typeAndOffset & ENFORCE_UTF8_MASK) == 0) {
4571             position = decodeStringList(tag, data, position, limit, list, registers);
4572           } else {
4573             position = decodeStringListRequireUtf8(tag, data, position, limit, list, registers);
4574           }
4575         }
4576         break;
4577       case 27: // MESSAGE_LIST:
4578         if (wireType == WireFormat.WIRETYPE_LENGTH_DELIMITED) {
4579           position =
4580               decodeMessageList(
4581                   getMessageFieldSchema(bufferPosition),
4582                   tag,
4583                   data,
4584                   position,
4585                   limit,
4586                   list,
4587                   registers);
4588         }
4589         break;
4590       case 28: // BYTES_LIST:
4591         if (wireType == WireFormat.WIRETYPE_LENGTH_DELIMITED) {
4592           position = decodeBytesList(tag, data, position, limit, list, registers);
4593         }
4594         break;
4595       case 30: // ENUM_LIST:
4596       case 44: // ENUM_LIST_PACKED:
4597         if (wireType == WireFormat.WIRETYPE_LENGTH_DELIMITED) {
4598           position = decodePackedVarint32List(data, position, list, registers);
4599         } else if (wireType == WireFormat.WIRETYPE_VARINT) {
4600           position = decodeVarint32List(tag, data, position, limit, list, registers);
4601         } else {
4602           break;
4603         }
4604         UnknownFieldSetLite unknownFields = ((GeneratedMessageLite) message).unknownFields;
4605         if (unknownFields == UnknownFieldSetLite.getDefaultInstance()) {
4606           // filterUnknownEnumList() expects the unknownFields parameter to be mutable or null.
4607           // Since we don't know yet whether there exist unknown enum values, we'd better pass
4608           // null to it instead of allocating a mutable instance. This is also needed to be
4609           // consistent with the behavior of generated parser/builder.
4610           unknownFields = null;
4611         }
4612         unknownFields =
4613             SchemaUtil.filterUnknownEnumList(
4614                 number,
4615                 (ProtobufList<Integer>) list,
4616                 getEnumFieldVerifier(bufferPosition),
4617                 unknownFields,
4618                 (UnknownFieldSchema<UnknownFieldSetLite, UnknownFieldSetLite>) unknownFieldSchema);
4619         if (unknownFields != null) {
4620           ((GeneratedMessageLite) message).unknownFields = unknownFields;
4621         }
4622         break;
4623       case 33: // SINT32_LIST:
4624       case 47: // SINT32_LIST_PACKED:
4625         if (wireType == WireFormat.WIRETYPE_LENGTH_DELIMITED) {
4626           position = decodePackedSInt32List(data, position, list, registers);
4627         } else if (wireType == WireFormat.WIRETYPE_VARINT) {
4628           position = decodeSInt32List(tag, data, position, limit, list, registers);
4629         }
4630         break;
4631       case 34: // SINT64_LIST:
4632       case 48: // SINT64_LIST_PACKED:
4633         if (wireType == WireFormat.WIRETYPE_LENGTH_DELIMITED) {
4634           position = decodePackedSInt64List(data, position, list, registers);
4635         } else if (wireType == WireFormat.WIRETYPE_VARINT) {
4636           position = decodeSInt64List(tag, data, position, limit, list, registers);
4637         }
4638         break;
4639       case 49: // GROUP_LIST:
4640         if (wireType == WireFormat.WIRETYPE_START_GROUP) {
4641           position =
4642               decodeGroupList(
4643                   getMessageFieldSchema(bufferPosition),
4644                   tag,
4645                   data,
4646                   position,
4647                   limit,
4648                   list,
4649                   registers);
4650         }
4651         break;
4652       default:
4653         break;
4654     }
4655     return position;
4656   }
4657 
parseMapField( T message, byte[] data, int position, int limit, int bufferPosition, long fieldOffset, Registers registers)4658   private <K, V> int parseMapField(
4659       T message,
4660       byte[] data,
4661       int position,
4662       int limit,
4663       int bufferPosition,
4664       long fieldOffset,
4665       Registers registers)
4666       throws IOException {
4667     final sun.misc.Unsafe unsafe = UNSAFE;
4668     Object mapDefaultEntry = getMapFieldDefaultEntry(bufferPosition);
4669     Object mapField = unsafe.getObject(message, fieldOffset);
4670     if (mapFieldSchema.isImmutable(mapField)) {
4671       Object oldMapField = mapField;
4672       mapField = mapFieldSchema.newMapField(mapDefaultEntry);
4673       mapFieldSchema.mergeFrom(mapField, oldMapField);
4674       unsafe.putObject(message, fieldOffset, mapField);
4675     }
4676     return decodeMapEntry(
4677         data,
4678         position,
4679         limit,
4680         (Metadata<K, V>) mapFieldSchema.forMapMetadata(mapDefaultEntry),
4681         (Map<K, V>) mapFieldSchema.forMutableMapData(mapField),
4682         registers);
4683   }
4684 
parseOneofField( T message, byte[] data, int position, int limit, int tag, int number, int wireType, int typeAndOffset, int fieldType, long fieldOffset, int bufferPosition, Registers registers)4685   private int parseOneofField(
4686       T message,
4687       byte[] data,
4688       int position,
4689       int limit,
4690       int tag,
4691       int number,
4692       int wireType,
4693       int typeAndOffset,
4694       int fieldType,
4695       long fieldOffset,
4696       int bufferPosition,
4697       Registers registers)
4698       throws IOException {
4699     final sun.misc.Unsafe unsafe = UNSAFE;
4700     final long oneofCaseOffset = buffer[bufferPosition + 2] & OFFSET_MASK;
4701     switch (fieldType) {
4702       case 51: // ONEOF_DOUBLE:
4703         if (wireType == WireFormat.WIRETYPE_FIXED64) {
4704           unsafe.putObject(message, fieldOffset, decodeDouble(data, position));
4705           position += 8;
4706           unsafe.putInt(message, oneofCaseOffset, number);
4707         }
4708         break;
4709       case 52: // ONEOF_FLOAT:
4710         if (wireType == WireFormat.WIRETYPE_FIXED32) {
4711           unsafe.putObject(message, fieldOffset, decodeFloat(data, position));
4712           position += 4;
4713           unsafe.putInt(message, oneofCaseOffset, number);
4714         }
4715         break;
4716       case 53: // ONEOF_INT64:
4717       case 54: // ONEOF_UINT64:
4718         if (wireType == WireFormat.WIRETYPE_VARINT) {
4719           position = decodeVarint64(data, position, registers);
4720           unsafe.putObject(message, fieldOffset, registers.long1);
4721           unsafe.putInt(message, oneofCaseOffset, number);
4722         }
4723         break;
4724       case 55: // ONEOF_INT32:
4725       case 62: // ONEOF_UINT32:
4726         if (wireType == WireFormat.WIRETYPE_VARINT) {
4727           position = decodeVarint32(data, position, registers);
4728           unsafe.putObject(message, fieldOffset, registers.int1);
4729           unsafe.putInt(message, oneofCaseOffset, number);
4730         }
4731         break;
4732       case 56: // ONEOF_FIXED64:
4733       case 65: // ONEOF_SFIXED64:
4734         if (wireType == WireFormat.WIRETYPE_FIXED64) {
4735           unsafe.putObject(message, fieldOffset, decodeFixed64(data, position));
4736           position += 8;
4737           unsafe.putInt(message, oneofCaseOffset, number);
4738         }
4739         break;
4740       case 57: // ONEOF_FIXED32:
4741       case 64: // ONEOF_SFIXED32:
4742         if (wireType == WireFormat.WIRETYPE_FIXED32) {
4743           unsafe.putObject(message, fieldOffset, decodeFixed32(data, position));
4744           position += 4;
4745           unsafe.putInt(message, oneofCaseOffset, number);
4746         }
4747         break;
4748       case 58: // ONEOF_BOOL:
4749         if (wireType == WireFormat.WIRETYPE_VARINT) {
4750           position = decodeVarint64(data, position, registers);
4751           unsafe.putObject(message, fieldOffset, registers.long1 != 0);
4752           unsafe.putInt(message, oneofCaseOffset, number);
4753         }
4754         break;
4755       case 59: // ONEOF_STRING:
4756         if (wireType == WireFormat.WIRETYPE_LENGTH_DELIMITED) {
4757           position = decodeVarint32(data, position, registers);
4758           final int length = registers.int1;
4759           if (length == 0) {
4760             unsafe.putObject(message, fieldOffset, "");
4761           } else {
4762             if ((typeAndOffset & ENFORCE_UTF8_MASK) != 0
4763                 && !Utf8.isValidUtf8(data, position, position + length)) {
4764               throw InvalidProtocolBufferException.invalidUtf8();
4765             }
4766             final String value = new String(data, position, length, Internal.UTF_8);
4767             unsafe.putObject(message, fieldOffset, value);
4768             position += length;
4769           }
4770           unsafe.putInt(message, oneofCaseOffset, number);
4771         }
4772         break;
4773       case 60: // ONEOF_MESSAGE:
4774         if (wireType == WireFormat.WIRETYPE_LENGTH_DELIMITED) {
4775           position =
4776               decodeMessageField(
4777                   getMessageFieldSchema(bufferPosition), data, position, limit, registers);
4778           final Object oldValue =
4779               unsafe.getInt(message, oneofCaseOffset) == number
4780                   ? unsafe.getObject(message, fieldOffset)
4781                   : null;
4782           if (oldValue == null) {
4783             unsafe.putObject(message, fieldOffset, registers.object1);
4784           } else {
4785             unsafe.putObject(
4786                 message, fieldOffset, Internal.mergeMessage(oldValue, registers.object1));
4787           }
4788           unsafe.putInt(message, oneofCaseOffset, number);
4789         }
4790         break;
4791       case 61: // ONEOF_BYTES:
4792         if (wireType == WireFormat.WIRETYPE_LENGTH_DELIMITED) {
4793           position = decodeBytes(data, position, registers);
4794           unsafe.putObject(message, fieldOffset, registers.object1);
4795           unsafe.putInt(message, oneofCaseOffset, number);
4796         }
4797         break;
4798       case 63: // ONEOF_ENUM:
4799         if (wireType == WireFormat.WIRETYPE_VARINT) {
4800           position = decodeVarint32(data, position, registers);
4801           final int enumValue = registers.int1;
4802           EnumVerifier enumVerifier = getEnumFieldVerifier(bufferPosition);
4803           if (enumVerifier == null || enumVerifier.isInRange(enumValue)) {
4804             unsafe.putObject(message, fieldOffset, enumValue);
4805             unsafe.putInt(message, oneofCaseOffset, number);
4806           } else {
4807             // UnknownFieldSetLite requires varint to be represented as Long.
4808             getMutableUnknownFields(message).storeField(tag, (long) enumValue);
4809           }
4810         }
4811         break;
4812       case 66: // ONEOF_SINT32:
4813         if (wireType == WireFormat.WIRETYPE_VARINT) {
4814           position = decodeVarint32(data, position, registers);
4815           unsafe.putObject(message, fieldOffset, CodedInputStream.decodeZigZag32(registers.int1));
4816           unsafe.putInt(message, oneofCaseOffset, number);
4817         }
4818         break;
4819       case 67: // ONEOF_SINT64:
4820         if (wireType == WireFormat.WIRETYPE_VARINT) {
4821           position = decodeVarint64(data, position, registers);
4822           unsafe.putObject(message, fieldOffset, CodedInputStream.decodeZigZag64(registers.long1));
4823           unsafe.putInt(message, oneofCaseOffset, number);
4824         }
4825         break;
4826       case 68: // ONEOF_GROUP:
4827         if (wireType == WireFormat.WIRETYPE_START_GROUP) {
4828           final int endTag = (tag & ~0x7) | WireFormat.WIRETYPE_END_GROUP;
4829           position =
4830               decodeGroupField(
4831                   getMessageFieldSchema(bufferPosition), data, position, limit, endTag, registers);
4832           final Object oldValue =
4833               unsafe.getInt(message, oneofCaseOffset) == number
4834                   ? unsafe.getObject(message, fieldOffset)
4835                   : null;
4836           if (oldValue == null) {
4837             unsafe.putObject(message, fieldOffset, registers.object1);
4838           } else {
4839             unsafe.putObject(
4840                 message, fieldOffset, Internal.mergeMessage(oldValue, registers.object1));
4841           }
4842           unsafe.putInt(message, oneofCaseOffset, number);
4843         }
4844         break;
4845       default:
4846         break;
4847     }
4848     return position;
4849   }
4850 
getMessageFieldSchema(int pos)4851   private Schema getMessageFieldSchema(int pos) {
4852     final int index = pos / INTS_PER_FIELD * 2;
4853     Schema schema = (Schema) objects[index];
4854     if (schema != null) {
4855       return schema;
4856     }
4857     schema = Protobuf.getInstance().schemaFor((Class) objects[index + 1]);
4858     objects[index] = schema;
4859     return schema;
4860   }
4861 
getMapFieldDefaultEntry(int pos)4862   private Object getMapFieldDefaultEntry(int pos) {
4863     return objects[pos / INTS_PER_FIELD * 2];
4864   }
4865 
getEnumFieldVerifier(int pos)4866   private EnumVerifier getEnumFieldVerifier(int pos) {
4867     return (EnumVerifier) objects[pos / INTS_PER_FIELD * 2 + 1];
4868   }
4869 
4870   /**
4871    * Parses a proto2 message or group and returns the position after the message/group. If it's
4872    * parsing a message (endGroup == 0), returns limit if parsing is successful; It it's parsing a
4873    * group (endGroup != 0), parsing ends when a tag == endGroup is encountered and the position
4874    * after that tag is returned.
4875    */
parseProto2Message( T message, byte[] data, int position, int limit, int endGroup, Registers registers)4876   int parseProto2Message(
4877       T message, byte[] data, int position, int limit, int endGroup, Registers registers)
4878       throws IOException {
4879     final sun.misc.Unsafe unsafe = UNSAFE;
4880     int currentPresenceFieldOffset = NO_PRESENCE_SENTINEL;
4881     int currentPresenceField = 0;
4882     int tag = 0;
4883     int oldNumber = -1;
4884     int pos = 0;
4885     while (position < limit) {
4886       tag = data[position++];
4887       if (tag < 0) {
4888         position = decodeVarint32(tag, data, position, registers);
4889         tag = registers.int1;
4890       }
4891       final int number = tag >>> 3;
4892       final int wireType = tag & 0x7;
4893       if (number > oldNumber) {
4894         pos = positionForFieldNumber(number, pos / INTS_PER_FIELD);
4895       } else {
4896         pos = positionForFieldNumber(number);
4897       }
4898       oldNumber = number;
4899       if (pos == -1) {
4900         // need to reset
4901         pos = 0;
4902       } else {
4903         final int typeAndOffset = buffer[pos + 1];
4904         final int fieldType = type(typeAndOffset);
4905         final long fieldOffset = offset(typeAndOffset);
4906         if (fieldType <= 17) {
4907           // Proto2 optional fields have has-bits.
4908           final int presenceMaskAndOffset = buffer[pos + 2];
4909           final int presenceMask = 1 << (presenceMaskAndOffset >>> OFFSET_BITS);
4910           final int presenceFieldOffset = presenceMaskAndOffset & OFFSET_MASK;
4911           // We cache the 32-bit has-bits integer value and only write it back when parsing a field
4912           // using a different has-bits integer.
4913           if (presenceFieldOffset != currentPresenceFieldOffset) {
4914             if (currentPresenceFieldOffset != NO_PRESENCE_SENTINEL) {
4915               unsafe.putInt(message, (long) currentPresenceFieldOffset, currentPresenceField);
4916             }
4917             currentPresenceFieldOffset = presenceFieldOffset;
4918             currentPresenceField = unsafe.getInt(message, (long) presenceFieldOffset);
4919           }
4920           switch (fieldType) {
4921             case 0: // DOUBLE
4922               if (wireType == WireFormat.WIRETYPE_FIXED64) {
4923                 UnsafeUtil.putDouble(message, fieldOffset, decodeDouble(data, position));
4924                 position += 8;
4925                 currentPresenceField |= presenceMask;
4926                 continue;
4927               }
4928               break;
4929             case 1: // FLOAT
4930               if (wireType == WireFormat.WIRETYPE_FIXED32) {
4931                 UnsafeUtil.putFloat(message, fieldOffset, decodeFloat(data, position));
4932                 position += 4;
4933                 currentPresenceField |= presenceMask;
4934                 continue;
4935               }
4936               break;
4937             case 2: // INT64
4938             case 3: // UINT64
4939               if (wireType == WireFormat.WIRETYPE_VARINT) {
4940                 position = decodeVarint64(data, position, registers);
4941                 unsafe.putLong(message, fieldOffset, registers.long1);
4942                 currentPresenceField |= presenceMask;
4943                 continue;
4944               }
4945               break;
4946             case 4: // INT32
4947             case 11: // UINT32
4948               if (wireType == WireFormat.WIRETYPE_VARINT) {
4949                 position = decodeVarint32(data, position, registers);
4950                 unsafe.putInt(message, fieldOffset, registers.int1);
4951                 currentPresenceField |= presenceMask;
4952                 continue;
4953               }
4954               break;
4955             case 5: // FIXED64
4956             case 14: // SFIXED64
4957               if (wireType == WireFormat.WIRETYPE_FIXED64) {
4958                 unsafe.putLong(message, fieldOffset, decodeFixed64(data, position));
4959                 position += 8;
4960                 currentPresenceField |= presenceMask;
4961                 continue;
4962               }
4963               break;
4964             case 6: // FIXED32
4965             case 13: // SFIXED32
4966               if (wireType == WireFormat.WIRETYPE_FIXED32) {
4967                 unsafe.putInt(message, fieldOffset, decodeFixed32(data, position));
4968                 position += 4;
4969                 currentPresenceField |= presenceMask;
4970                 continue;
4971               }
4972               break;
4973             case 7: // BOOL
4974               if (wireType == WireFormat.WIRETYPE_VARINT) {
4975                 position = decodeVarint64(data, position, registers);
4976                 UnsafeUtil.putBoolean(message, fieldOffset, registers.long1 != 0);
4977                 currentPresenceField |= presenceMask;
4978                 continue;
4979               }
4980               break;
4981             case 8: // STRING
4982               if (wireType == WireFormat.WIRETYPE_LENGTH_DELIMITED) {
4983                 if ((typeAndOffset & ENFORCE_UTF8_MASK) == 0) {
4984                   position = decodeString(data, position, registers);
4985                 } else {
4986                   position = decodeStringRequireUtf8(data, position, registers);
4987                 }
4988                 unsafe.putObject(message, fieldOffset, registers.object1);
4989                 currentPresenceField |= presenceMask;
4990                 continue;
4991               }
4992               break;
4993             case 9: // MESSAGE
4994               if (wireType == WireFormat.WIRETYPE_LENGTH_DELIMITED) {
4995                 position =
4996                     decodeMessageField(
4997                         getMessageFieldSchema(pos), data, position, limit, registers);
4998                 if ((currentPresenceField & presenceMask) == 0) {
4999                   unsafe.putObject(message, fieldOffset, registers.object1);
5000                 } else {
5001                   unsafe.putObject(
5002                       message,
5003                       fieldOffset,
5004                       Internal.mergeMessage(
5005                           unsafe.getObject(message, fieldOffset), registers.object1));
5006                 }
5007                 currentPresenceField |= presenceMask;
5008                 continue;
5009               }
5010               break;
5011             case 10: // BYTES
5012               if (wireType == WireFormat.WIRETYPE_LENGTH_DELIMITED) {
5013                 position = decodeBytes(data, position, registers);
5014                 unsafe.putObject(message, fieldOffset, registers.object1);
5015                 currentPresenceField |= presenceMask;
5016                 continue;
5017               }
5018               break;
5019             case 12: // ENUM
5020               if (wireType == WireFormat.WIRETYPE_VARINT) {
5021                 position = decodeVarint32(data, position, registers);
5022                 final int enumValue = registers.int1;
5023                 EnumVerifier enumVerifier = getEnumFieldVerifier(pos);
5024                 if (enumVerifier == null || enumVerifier.isInRange(enumValue)) {
5025                   unsafe.putInt(message, fieldOffset, enumValue);
5026                   currentPresenceField |= presenceMask;
5027                 } else {
5028                   // UnknownFieldSetLite requires varint to be represented as Long.
5029                   getMutableUnknownFields(message).storeField(tag, (long) enumValue);
5030                 }
5031                 continue;
5032               }
5033               break;
5034             case 15: // SINT32
5035               if (wireType == WireFormat.WIRETYPE_VARINT) {
5036                 position = decodeVarint32(data, position, registers);
5037                 unsafe.putInt(
5038                     message, fieldOffset, CodedInputStream.decodeZigZag32(registers.int1));
5039                 currentPresenceField |= presenceMask;
5040                 continue;
5041               }
5042               break;
5043             case 16: // SINT64
5044               if (wireType == WireFormat.WIRETYPE_VARINT) {
5045                 position = decodeVarint64(data, position, registers);
5046                 unsafe.putLong(
5047                     message, fieldOffset, CodedInputStream.decodeZigZag64(registers.long1));
5048 
5049                 currentPresenceField |= presenceMask;
5050                 continue;
5051               }
5052               break;
5053             case 17: // GROUP
5054               if (wireType == WireFormat.WIRETYPE_START_GROUP) {
5055                 final int endTag = (number << 3) | WireFormat.WIRETYPE_END_GROUP;
5056                 position =
5057                     decodeGroupField(
5058                         getMessageFieldSchema(pos), data, position, limit, endTag, registers);
5059                 if ((currentPresenceField & presenceMask) == 0) {
5060                   unsafe.putObject(message, fieldOffset, registers.object1);
5061                 } else {
5062                   unsafe.putObject(
5063                       message,
5064                       fieldOffset,
5065                       Internal.mergeMessage(
5066                           unsafe.getObject(message, fieldOffset), registers.object1));
5067                 }
5068 
5069                 currentPresenceField |= presenceMask;
5070                 continue;
5071               }
5072               break;
5073             default:
5074               break;
5075           }
5076         } else if (fieldType == 27) {
5077           // Handle repeated message fields.
5078           if (wireType == WireFormat.WIRETYPE_LENGTH_DELIMITED) {
5079             ProtobufList<?> list = (ProtobufList<?>) unsafe.getObject(message, fieldOffset);
5080             if (!list.isModifiable()) {
5081               final int size = list.size();
5082               list =
5083                   list.mutableCopyWithCapacity(
5084                       size == 0 ? AbstractProtobufList.DEFAULT_CAPACITY : size * 2);
5085               unsafe.putObject(message, fieldOffset, list);
5086             }
5087             position =
5088                 decodeMessageList(
5089                     getMessageFieldSchema(pos), tag, data, position, limit, list, registers);
5090             continue;
5091           }
5092         } else if (fieldType <= 49) {
5093           // Handle all other repeated fields.
5094           final int oldPosition = position;
5095           position =
5096               parseRepeatedField(
5097                   message,
5098                   data,
5099                   position,
5100                   limit,
5101                   tag,
5102                   number,
5103                   wireType,
5104                   pos,
5105                   typeAndOffset,
5106                   fieldType,
5107                   fieldOffset,
5108                   registers);
5109           if (position != oldPosition) {
5110             continue;
5111           }
5112         } else if (fieldType == 50) {
5113           if (wireType == WireFormat.WIRETYPE_LENGTH_DELIMITED) {
5114             final int oldPosition = position;
5115             position = parseMapField(message, data, position, limit, pos, fieldOffset, registers);
5116             if (position != oldPosition) {
5117               continue;
5118             }
5119           }
5120         } else {
5121           final int oldPosition = position;
5122           position =
5123               parseOneofField(
5124                   message,
5125                   data,
5126                   position,
5127                   limit,
5128                   tag,
5129                   number,
5130                   wireType,
5131                   typeAndOffset,
5132                   fieldType,
5133                   fieldOffset,
5134                   pos,
5135                   registers);
5136           if (position != oldPosition) {
5137             continue;
5138           }
5139         }
5140       }
5141       if (tag == endGroup && endGroup != 0) {
5142         break;
5143       }
5144 
5145       if (hasExtensions
5146           && registers.extensionRegistry != ExtensionRegistryLite.getEmptyRegistry()) {
5147         position = decodeExtensionOrUnknownField(
5148             tag, data, position, limit, message, defaultInstance,
5149             (UnknownFieldSchema<UnknownFieldSetLite, UnknownFieldSetLite>) unknownFieldSchema,
5150             registers);
5151       } else {
5152         position = decodeUnknownField(
5153             tag, data, position, limit, getMutableUnknownFields(message), registers);
5154       }
5155     }
5156     if (currentPresenceFieldOffset != NO_PRESENCE_SENTINEL) {
5157       unsafe.putInt(message, (long) currentPresenceFieldOffset, currentPresenceField);
5158     }
5159     UnknownFieldSetLite unknownFields = null;
5160     for (int i = checkInitializedCount; i < repeatedFieldOffsetStart; i++) {
5161       unknownFields =
5162           filterMapUnknownEnumValues(
5163               message,
5164               intArray[i],
5165               unknownFields,
5166               (UnknownFieldSchema<UnknownFieldSetLite, UnknownFieldSetLite>) unknownFieldSchema);
5167     }
5168     if (unknownFields != null) {
5169       ((UnknownFieldSchema<UnknownFieldSetLite, UnknownFieldSetLite>) unknownFieldSchema)
5170           .setBuilderToMessage(message, unknownFields);
5171     }
5172     if (endGroup == 0) {
5173       if (position != limit) {
5174         throw InvalidProtocolBufferException.parseFailure();
5175       }
5176     } else {
5177       if (position > limit || tag != endGroup) {
5178         throw InvalidProtocolBufferException.parseFailure();
5179       }
5180     }
5181     return position;
5182   }
5183 
5184   /** Parses a proto3 message and returns the limit if parsing is successful. */
parseProto3Message( T message, byte[] data, int position, int limit, Registers registers)5185   private int parseProto3Message(
5186       T message, byte[] data, int position, int limit, Registers registers) throws IOException {
5187     final sun.misc.Unsafe unsafe = UNSAFE;
5188     int currentPresenceFieldOffset = NO_PRESENCE_SENTINEL;
5189     int currentPresenceField = 0;
5190     int tag = 0;
5191     int oldNumber = -1;
5192     int pos = 0;
5193     while (position < limit) {
5194       tag = data[position++];
5195       if (tag < 0) {
5196         position = decodeVarint32(tag, data, position, registers);
5197         tag = registers.int1;
5198       }
5199       final int number = tag >>> 3;
5200       final int wireType = tag & 0x7;
5201       if (number > oldNumber) {
5202         pos = positionForFieldNumber(number, pos / INTS_PER_FIELD);
5203       } else {
5204         pos = positionForFieldNumber(number);
5205       }
5206       oldNumber = number;
5207       if (pos == -1) {
5208         // need to reset
5209         pos = 0;
5210       } else {
5211         final int typeAndOffset = buffer[pos + 1];
5212         final int fieldType = type(typeAndOffset);
5213         final long fieldOffset = offset(typeAndOffset);
5214         if (fieldType <= 17) {
5215           // Proto3 optional fields have has-bits.
5216           final int presenceMaskAndOffset = buffer[pos + 2];
5217           final int presenceMask = 1 << (presenceMaskAndOffset >>> OFFSET_BITS);
5218           final int presenceFieldOffset = presenceMaskAndOffset & OFFSET_MASK;
5219           // We cache the 32-bit has-bits integer value and only write it back when parsing a field
5220           // using a different has-bits integer.
5221           //
5222           // Note that for fields that do not have hasbits, we unconditionally write and discard
5223           // the data.
5224           if (presenceFieldOffset != currentPresenceFieldOffset) {
5225             if (currentPresenceFieldOffset != NO_PRESENCE_SENTINEL) {
5226               unsafe.putInt(message, (long) currentPresenceFieldOffset, currentPresenceField);
5227             }
5228             if (presenceFieldOffset != NO_PRESENCE_SENTINEL) {
5229               currentPresenceField = unsafe.getInt(message, (long) presenceFieldOffset);
5230             }
5231             currentPresenceFieldOffset = presenceFieldOffset;
5232           }
5233           switch (fieldType) {
5234             case 0: // DOUBLE:
5235               if (wireType == WireFormat.WIRETYPE_FIXED64) {
5236                 UnsafeUtil.putDouble(message, fieldOffset, decodeDouble(data, position));
5237                 position += 8;
5238                 currentPresenceField |= presenceMask;
5239                 continue;
5240               }
5241               break;
5242             case 1: // FLOAT:
5243               if (wireType == WireFormat.WIRETYPE_FIXED32) {
5244                 UnsafeUtil.putFloat(message, fieldOffset, decodeFloat(data, position));
5245                 position += 4;
5246                 currentPresenceField |= presenceMask;
5247                 continue;
5248               }
5249               break;
5250             case 2: // INT64:
5251             case 3: // UINT64:
5252               if (wireType == WireFormat.WIRETYPE_VARINT) {
5253                 position = decodeVarint64(data, position, registers);
5254                 unsafe.putLong(message, fieldOffset, registers.long1);
5255                 currentPresenceField |= presenceMask;
5256                 continue;
5257               }
5258               break;
5259             case 4: // INT32:
5260             case 11: // UINT32:
5261               if (wireType == WireFormat.WIRETYPE_VARINT) {
5262                 position = decodeVarint32(data, position, registers);
5263                 unsafe.putInt(message, fieldOffset, registers.int1);
5264                 currentPresenceField |= presenceMask;
5265                 continue;
5266               }
5267               break;
5268             case 5: // FIXED64:
5269             case 14: // SFIXED64:
5270               if (wireType == WireFormat.WIRETYPE_FIXED64) {
5271                 unsafe.putLong(message, fieldOffset, decodeFixed64(data, position));
5272                 position += 8;
5273                 currentPresenceField |= presenceMask;
5274                 continue;
5275               }
5276               break;
5277             case 6: // FIXED32:
5278             case 13: // SFIXED32:
5279               if (wireType == WireFormat.WIRETYPE_FIXED32) {
5280                 unsafe.putInt(message, fieldOffset, decodeFixed32(data, position));
5281                 position += 4;
5282                 currentPresenceField |= presenceMask;
5283                 continue;
5284               }
5285               break;
5286             case 7: // BOOL:
5287               if (wireType == WireFormat.WIRETYPE_VARINT) {
5288                 position = decodeVarint64(data, position, registers);
5289                 UnsafeUtil.putBoolean(message, fieldOffset, registers.long1 != 0);
5290                 currentPresenceField |= presenceMask;
5291                 continue;
5292               }
5293               break;
5294             case 8: // STRING:
5295               if (wireType == WireFormat.WIRETYPE_LENGTH_DELIMITED) {
5296                 if ((typeAndOffset & ENFORCE_UTF8_MASK) == 0) {
5297                   position = decodeString(data, position, registers);
5298                 } else {
5299                   position = decodeStringRequireUtf8(data, position, registers);
5300                 }
5301                 unsafe.putObject(message, fieldOffset, registers.object1);
5302                 currentPresenceField |= presenceMask;
5303                 continue;
5304               }
5305               break;
5306             case 9: // MESSAGE:
5307               if (wireType == WireFormat.WIRETYPE_LENGTH_DELIMITED) {
5308                 position =
5309                     decodeMessageField(
5310                         getMessageFieldSchema(pos), data, position, limit, registers);
5311                 final Object oldValue = unsafe.getObject(message, fieldOffset);
5312                 if (oldValue == null) {
5313                   unsafe.putObject(message, fieldOffset, registers.object1);
5314                 } else {
5315                   unsafe.putObject(
5316                       message, fieldOffset, Internal.mergeMessage(oldValue, registers.object1));
5317                 }
5318                 currentPresenceField |= presenceMask;
5319                 continue;
5320               }
5321               break;
5322             case 10: // BYTES:
5323               if (wireType == WireFormat.WIRETYPE_LENGTH_DELIMITED) {
5324                 position = decodeBytes(data, position, registers);
5325                 unsafe.putObject(message, fieldOffset, registers.object1);
5326                 currentPresenceField |= presenceMask;
5327                 continue;
5328               }
5329               break;
5330             case 12: // ENUM:
5331               if (wireType == WireFormat.WIRETYPE_VARINT) {
5332                 position = decodeVarint32(data, position, registers);
5333                 unsafe.putInt(message, fieldOffset, registers.int1);
5334                 currentPresenceField |= presenceMask;
5335                 continue;
5336               }
5337               break;
5338             case 15: // SINT32:
5339               if (wireType == WireFormat.WIRETYPE_VARINT) {
5340                 position = decodeVarint32(data, position, registers);
5341                 unsafe.putInt(
5342                     message, fieldOffset, CodedInputStream.decodeZigZag32(registers.int1));
5343                 currentPresenceField |= presenceMask;
5344                 continue;
5345               }
5346               break;
5347             case 16: // SINT64:
5348               if (wireType == WireFormat.WIRETYPE_VARINT) {
5349                 position = decodeVarint64(data, position, registers);
5350                 unsafe.putLong(
5351                     message, fieldOffset, CodedInputStream.decodeZigZag64(registers.long1));
5352                 currentPresenceField |= presenceMask;
5353                 continue;
5354               }
5355               break;
5356             default:
5357               break;
5358           }
5359         } else if (fieldType == 27) {
5360           // Handle repeated message field.
5361           if (wireType == WireFormat.WIRETYPE_LENGTH_DELIMITED) {
5362             ProtobufList<?> list = (ProtobufList<?>) unsafe.getObject(message, fieldOffset);
5363             if (!list.isModifiable()) {
5364               final int size = list.size();
5365               list =
5366                   list.mutableCopyWithCapacity(
5367                       size == 0 ? AbstractProtobufList.DEFAULT_CAPACITY : size * 2);
5368               unsafe.putObject(message, fieldOffset, list);
5369             }
5370             position =
5371                 decodeMessageList(
5372                     getMessageFieldSchema(pos), tag, data, position, limit, list, registers);
5373             continue;
5374           }
5375         } else if (fieldType <= 49) {
5376           // Handle all other repeated fields.
5377           final int oldPosition = position;
5378           position =
5379               parseRepeatedField(
5380                   message,
5381                   data,
5382                   position,
5383                   limit,
5384                   tag,
5385                   number,
5386                   wireType,
5387                   pos,
5388                   typeAndOffset,
5389                   fieldType,
5390                   fieldOffset,
5391                   registers);
5392           if (position != oldPosition) {
5393             continue;
5394           }
5395         } else if (fieldType == 50) {
5396           if (wireType == WireFormat.WIRETYPE_LENGTH_DELIMITED) {
5397             final int oldPosition = position;
5398             position = parseMapField(message, data, position, limit, pos, fieldOffset, registers);
5399             if (position != oldPosition) {
5400               continue;
5401             }
5402           }
5403         } else {
5404           final int oldPosition = position;
5405           position =
5406               parseOneofField(
5407                   message,
5408                   data,
5409                   position,
5410                   limit,
5411                   tag,
5412                   number,
5413                   wireType,
5414                   typeAndOffset,
5415                   fieldType,
5416                   fieldOffset,
5417                   pos,
5418                   registers);
5419           if (position != oldPosition) {
5420             continue;
5421           }
5422         }
5423       }
5424       position = decodeUnknownField(
5425           tag, data, position, limit, getMutableUnknownFields(message), registers);
5426     }
5427     if (currentPresenceFieldOffset != NO_PRESENCE_SENTINEL) {
5428       unsafe.putInt(message, (long) currentPresenceFieldOffset, currentPresenceField);
5429     }
5430     if (position != limit) {
5431       throw InvalidProtocolBufferException.parseFailure();
5432     }
5433     return position;
5434   }
5435 
5436   @Override
mergeFrom(T message, byte[] data, int position, int limit, Registers registers)5437   public void mergeFrom(T message, byte[] data, int position, int limit, Registers registers)
5438       throws IOException {
5439     if (proto3) {
5440       parseProto3Message(message, data, position, limit, registers);
5441     } else {
5442       parseProto2Message(message, data, position, limit, 0, registers);
5443     }
5444   }
5445 
5446   @Override
makeImmutable(T message)5447   public void makeImmutable(T message) {
5448     // Make all repeated/map fields immutable.
5449     for (int i = checkInitializedCount; i < repeatedFieldOffsetStart; i++) {
5450       long offset = offset(typeAndOffsetAt(intArray[i]));
5451       Object mapField = UnsafeUtil.getObject(message, offset);
5452       if (mapField == null) {
5453         continue;
5454       }
5455       UnsafeUtil.putObject(message, offset, mapFieldSchema.toImmutable(mapField));
5456     }
5457     final int length = intArray.length;
5458     for (int i = repeatedFieldOffsetStart; i < length; i++) {
5459       listFieldSchema.makeImmutableListAt(message, intArray[i]);
5460     }
5461     unknownFieldSchema.makeImmutable(message);
5462     if (hasExtensions) {
5463       extensionSchema.makeImmutable(message);
5464     }
5465   }
5466 
5467   @SuppressWarnings("unchecked")
mergeMap( Object message, int pos, Object mapDefaultEntry, ExtensionRegistryLite extensionRegistry, Reader reader)5468   private final <K, V> void mergeMap(
5469       Object message,
5470       int pos,
5471       Object mapDefaultEntry,
5472       ExtensionRegistryLite extensionRegistry,
5473       Reader reader)
5474       throws IOException {
5475     long offset = offset(typeAndOffsetAt(pos));
5476     Object mapField = UnsafeUtil.getObject(message, offset);
5477     // TODO(xiaofeng): Consider creating separate implementations for full and lite. In lite
5478     // runtime map field will never be null but here we still need to check null because the
5479     // code is shared by both full and lite. It might be better if full/lite uses different
5480     // schema implementations.
5481     if (mapField == null) {
5482       mapField = mapFieldSchema.newMapField(mapDefaultEntry);
5483       UnsafeUtil.putObject(message, offset, mapField);
5484     } else if (mapFieldSchema.isImmutable(mapField)) {
5485       Object oldMapField = mapField;
5486       mapField = mapFieldSchema.newMapField(mapDefaultEntry);
5487       mapFieldSchema.mergeFrom(mapField, oldMapField);
5488       UnsafeUtil.putObject(message, offset, mapField);
5489     }
5490     reader.readMap(
5491         (Map<K, V>) mapFieldSchema.forMutableMapData(mapField),
5492         (Metadata<K, V>) mapFieldSchema.forMapMetadata(mapDefaultEntry),
5493         extensionRegistry);
5494   }
5495 
filterMapUnknownEnumValues( Object message, int pos, UB unknownFields, UnknownFieldSchema<UT, UB> unknownFieldSchema)5496   private final <UT, UB> UB filterMapUnknownEnumValues(
5497       Object message, int pos, UB unknownFields, UnknownFieldSchema<UT, UB> unknownFieldSchema) {
5498     int fieldNumber = numberAt(pos);
5499     long offset = offset(typeAndOffsetAt(pos));
5500     Object mapField = UnsafeUtil.getObject(message, offset);
5501     if (mapField == null) {
5502       return unknownFields;
5503     }
5504     EnumVerifier enumVerifier = getEnumFieldVerifier(pos);
5505     if (enumVerifier == null) {
5506       return unknownFields;
5507     }
5508     Map<?, ?> mapData = mapFieldSchema.forMutableMapData(mapField);
5509     // Filter unknown enum values.
5510     unknownFields =
5511         filterUnknownEnumMap(
5512             pos, fieldNumber, mapData, enumVerifier, unknownFields, unknownFieldSchema);
5513     return unknownFields;
5514   }
5515 
5516   @SuppressWarnings("unchecked")
filterUnknownEnumMap( int pos, int number, Map<K, V> mapData, EnumVerifier enumVerifier, UB unknownFields, UnknownFieldSchema<UT, UB> unknownFieldSchema)5517   private final <K, V, UT, UB> UB filterUnknownEnumMap(
5518       int pos,
5519       int number,
5520       Map<K, V> mapData,
5521       EnumVerifier enumVerifier,
5522       UB unknownFields,
5523       UnknownFieldSchema<UT, UB> unknownFieldSchema) {
5524     Metadata<K, V> metadata =
5525         (Metadata<K, V>) mapFieldSchema.forMapMetadata(getMapFieldDefaultEntry(pos));
5526     for (Iterator<Map.Entry<K, V>> it = mapData.entrySet().iterator(); it.hasNext(); ) {
5527       Map.Entry<K, V> entry = it.next();
5528       if (!enumVerifier.isInRange((Integer) entry.getValue())) {
5529         if (unknownFields == null) {
5530           unknownFields = unknownFieldSchema.newBuilder();
5531         }
5532         int entrySize =
5533             MapEntryLite.computeSerializedSize(metadata, entry.getKey(), entry.getValue());
5534         CodedBuilder codedBuilder = ByteString.newCodedBuilder(entrySize);
5535         CodedOutputStream codedOutput = codedBuilder.getCodedOutput();
5536         try {
5537           MapEntryLite.writeTo(codedOutput, metadata, entry.getKey(), entry.getValue());
5538         } catch (IOException e) {
5539           // Writing to ByteString CodedOutputStream should not throw IOException.
5540           throw new RuntimeException(e);
5541         }
5542         unknownFieldSchema.addLengthDelimited(unknownFields, number, codedBuilder.build());
5543         it.remove();
5544       }
5545     }
5546     return unknownFields;
5547   }
5548 
5549   @Override
isInitialized(T message)5550   public final boolean isInitialized(T message) {
5551     int currentPresenceFieldOffset = NO_PRESENCE_SENTINEL;
5552     int currentPresenceField = 0;
5553     for (int i = 0; i < checkInitializedCount; i++) {
5554       final int pos = intArray[i];
5555       final int number = numberAt(pos);
5556       final int typeAndOffset = typeAndOffsetAt(pos);
5557 
5558       int presenceMaskAndOffset = buffer[pos + 2];
5559       final int presenceFieldOffset = presenceMaskAndOffset & OFFSET_MASK;
5560       int presenceMask = 1 << (presenceMaskAndOffset >>> OFFSET_BITS);
5561       if (presenceFieldOffset != currentPresenceFieldOffset) {
5562         currentPresenceFieldOffset = presenceFieldOffset;
5563         if (currentPresenceFieldOffset != NO_PRESENCE_SENTINEL) {
5564           currentPresenceField = UNSAFE.getInt(message, (long) presenceFieldOffset);
5565         }
5566       }
5567 
5568       if (isRequired(typeAndOffset)) {
5569         if (!isFieldPresent(
5570             message, pos, currentPresenceFieldOffset, currentPresenceField, presenceMask)) {
5571           return false;
5572         }
5573         // If a required message field is set but has no required fields of it's own, we still
5574         // proceed and check the message is initialized. It should be fairly cheap to check these
5575         // messages but is worth documenting.
5576       }
5577       // Check nested message and groups.
5578       switch (type(typeAndOffset)) {
5579         case 9: // MESSAGE
5580         case 17: // GROUP
5581           if (isFieldPresent(
5582                   message, pos, currentPresenceFieldOffset, currentPresenceField, presenceMask)
5583               && !isInitialized(message, typeAndOffset, getMessageFieldSchema(pos))) {
5584             return false;
5585           }
5586           break;
5587         case 27: // MESSAGE_LIST
5588         case 49: // GROUP_LIST
5589           if (!isListInitialized(message, typeAndOffset, pos)) {
5590             return false;
5591           }
5592           break;
5593         case 60: // ONEOF_MESSAGE
5594         case 68: // ONEOF_GROUP
5595           if (isOneofPresent(message, number, pos)
5596               && !isInitialized(message, typeAndOffset, getMessageFieldSchema(pos))) {
5597             return false;
5598           }
5599           break;
5600         case 50: // MAP
5601           if (!isMapInitialized(message, typeAndOffset, pos)) {
5602             return false;
5603           }
5604           break;
5605         default:
5606           break;
5607       }
5608     }
5609 
5610     if (hasExtensions) {
5611       if (!extensionSchema.getExtensions(message).isInitialized()) {
5612         return false;
5613       }
5614     }
5615 
5616     return true;
5617   }
5618 
isInitialized(Object message, int typeAndOffset, Schema schema)5619   private static boolean isInitialized(Object message, int typeAndOffset, Schema schema) {
5620     Object nested = UnsafeUtil.getObject(message, offset(typeAndOffset));
5621     return schema.isInitialized(nested);
5622   }
5623 
isListInitialized(Object message, int typeAndOffset, int pos)5624   private <N> boolean isListInitialized(Object message, int typeAndOffset, int pos) {
5625     @SuppressWarnings("unchecked")
5626     List<N> list = (List<N>) UnsafeUtil.getObject(message, offset(typeAndOffset));
5627     if (list.isEmpty()) {
5628       return true;
5629     }
5630 
5631     Schema schema = getMessageFieldSchema(pos);
5632     for (int i = 0; i < list.size(); i++) {
5633       N nested = list.get(i);
5634       if (!schema.isInitialized(nested)) {
5635         return false;
5636       }
5637     }
5638     return true;
5639   }
5640 
isMapInitialized(T message, int typeAndOffset, int pos)5641   private boolean isMapInitialized(T message, int typeAndOffset, int pos) {
5642     Map<?, ?> map = mapFieldSchema.forMapData(UnsafeUtil.getObject(message, offset(typeAndOffset)));
5643     if (map.isEmpty()) {
5644       return true;
5645     }
5646     Object mapDefaultEntry = getMapFieldDefaultEntry(pos);
5647     MapEntryLite.Metadata<?, ?> metadata = mapFieldSchema.forMapMetadata(mapDefaultEntry);
5648     if (metadata.valueType.getJavaType() != WireFormat.JavaType.MESSAGE) {
5649       return true;
5650     }
5651     // TODO(dweis): Use schema cache.
5652     Schema schema = null;
5653     for (Object nested : map.values()) {
5654       if (schema == null) {
5655         schema = Protobuf.getInstance().schemaFor(nested.getClass());
5656       }
5657       if (!schema.isInitialized(nested)) {
5658         return false;
5659       }
5660     }
5661     return true;
5662   }
5663 
writeString(int fieldNumber, Object value, Writer writer)5664   private void writeString(int fieldNumber, Object value, Writer writer) throws IOException {
5665     if (value instanceof String) {
5666       writer.writeString(fieldNumber, (String) value);
5667     } else {
5668       writer.writeBytes(fieldNumber, (ByteString) value);
5669     }
5670   }
5671 
readString(Object message, int typeAndOffset, Reader reader)5672   private void readString(Object message, int typeAndOffset, Reader reader) throws IOException {
5673     if (isEnforceUtf8(typeAndOffset)) {
5674       // Enforce valid UTF-8 on the read.
5675       UnsafeUtil.putObject(message, offset(typeAndOffset), reader.readStringRequireUtf8());
5676     } else if (lite) {
5677       // Lite messages use String fields to store strings. Read a string but do not
5678       // enforce UTF-8
5679       UnsafeUtil.putObject(message, offset(typeAndOffset), reader.readString());
5680     } else {
5681       // Full runtime messages use Objects to store either a String or ByteString. Read
5682       // the string as a ByteString and do not enforce UTF-8.
5683       UnsafeUtil.putObject(message, offset(typeAndOffset), reader.readBytes());
5684     }
5685   }
5686 
readStringList(Object message, int typeAndOffset, Reader reader)5687   private void readStringList(Object message, int typeAndOffset, Reader reader) throws IOException {
5688     if (isEnforceUtf8(typeAndOffset)) {
5689       reader.readStringListRequireUtf8(
5690           listFieldSchema.<String>mutableListAt(message, offset(typeAndOffset)));
5691     } else {
5692       reader.readStringList(listFieldSchema.<String>mutableListAt(message, offset(typeAndOffset)));
5693     }
5694   }
5695 
readMessageList( Object message, int typeAndOffset, Reader reader, Schema<E> schema, ExtensionRegistryLite extensionRegistry)5696   private <E> void readMessageList(
5697       Object message,
5698       int typeAndOffset,
5699       Reader reader,
5700       Schema<E> schema,
5701       ExtensionRegistryLite extensionRegistry)
5702       throws IOException {
5703     long offset = offset(typeAndOffset);
5704     reader.readMessageList(
5705         listFieldSchema.<E>mutableListAt(message, offset), schema, extensionRegistry);
5706   }
5707 
readGroupList( Object message, long offset, Reader reader, Schema<E> schema, ExtensionRegistryLite extensionRegistry)5708   private <E> void readGroupList(
5709       Object message,
5710       long offset,
5711       Reader reader,
5712       Schema<E> schema,
5713       ExtensionRegistryLite extensionRegistry)
5714       throws IOException {
5715     reader.readGroupList(
5716         listFieldSchema.<E>mutableListAt(message, offset), schema, extensionRegistry);
5717   }
5718 
numberAt(int pos)5719   private int numberAt(int pos) {
5720     return buffer[pos];
5721   }
5722 
typeAndOffsetAt(int pos)5723   private int typeAndOffsetAt(int pos) {
5724     return buffer[pos + 1];
5725   }
5726 
presenceMaskAndOffsetAt(int pos)5727   private int presenceMaskAndOffsetAt(int pos) {
5728     return buffer[pos + 2];
5729   }
5730 
type(int value)5731   private static int type(int value) {
5732     return (value & FIELD_TYPE_MASK) >>> OFFSET_BITS;
5733   }
5734 
isRequired(int value)5735   private static boolean isRequired(int value) {
5736     return (value & REQUIRED_MASK) != 0;
5737   }
5738 
isEnforceUtf8(int value)5739   private static boolean isEnforceUtf8(int value) {
5740     return (value & ENFORCE_UTF8_MASK) != 0;
5741   }
5742 
offset(int value)5743   private static long offset(int value) {
5744     return value & OFFSET_MASK;
5745   }
5746 
doubleAt(T message, long offset)5747   private static <T> double doubleAt(T message, long offset) {
5748     return UnsafeUtil.getDouble(message, offset);
5749   }
5750 
floatAt(T message, long offset)5751   private static <T> float floatAt(T message, long offset) {
5752     return UnsafeUtil.getFloat(message, offset);
5753   }
5754 
intAt(T message, long offset)5755   private static <T> int intAt(T message, long offset) {
5756     return UnsafeUtil.getInt(message, offset);
5757   }
5758 
longAt(T message, long offset)5759   private static <T> long longAt(T message, long offset) {
5760     return UnsafeUtil.getLong(message, offset);
5761   }
5762 
booleanAt(T message, long offset)5763   private static <T> boolean booleanAt(T message, long offset) {
5764     return UnsafeUtil.getBoolean(message, offset);
5765   }
5766 
oneofDoubleAt(T message, long offset)5767   private static <T> double oneofDoubleAt(T message, long offset) {
5768     return ((Double) UnsafeUtil.getObject(message, offset)).doubleValue();
5769   }
5770 
oneofFloatAt(T message, long offset)5771   private static <T> float oneofFloatAt(T message, long offset) {
5772     return ((Float) UnsafeUtil.getObject(message, offset)).floatValue();
5773   }
5774 
oneofIntAt(T message, long offset)5775   private static <T> int oneofIntAt(T message, long offset) {
5776     return ((Integer) UnsafeUtil.getObject(message, offset)).intValue();
5777   }
5778 
oneofLongAt(T message, long offset)5779   private static <T> long oneofLongAt(T message, long offset) {
5780     return ((Long) UnsafeUtil.getObject(message, offset)).longValue();
5781   }
5782 
oneofBooleanAt(T message, long offset)5783   private static <T> boolean oneofBooleanAt(T message, long offset) {
5784     return ((Boolean) UnsafeUtil.getObject(message, offset)).booleanValue();
5785   }
5786 
5787   /** Returns true the field is present in both messages, or neither. */
arePresentForEquals(T message, T other, int pos)5788   private boolean arePresentForEquals(T message, T other, int pos) {
5789     return isFieldPresent(message, pos) == isFieldPresent(other, pos);
5790   }
5791 
isFieldPresent( T message, int pos, int presenceFieldOffset, int presenceField, int presenceMask)5792   private boolean isFieldPresent(
5793       T message, int pos, int presenceFieldOffset, int presenceField, int presenceMask) {
5794     if (presenceFieldOffset == NO_PRESENCE_SENTINEL) {
5795       return isFieldPresent(message, pos);
5796     } else {
5797       return (presenceField & presenceMask) != 0;
5798     }
5799   }
5800 
isFieldPresent(T message, int pos)5801   private boolean isFieldPresent(T message, int pos) {
5802     final int presenceMaskAndOffset = presenceMaskAndOffsetAt(pos);
5803     final long presenceFieldOffset = presenceMaskAndOffset & OFFSET_MASK;
5804     if (presenceFieldOffset == NO_PRESENCE_SENTINEL) {
5805       final int typeAndOffset = typeAndOffsetAt(pos);
5806       final long offset = offset(typeAndOffset);
5807       switch (type(typeAndOffset)) {
5808         case 0: // DOUBLE:
5809           return UnsafeUtil.getDouble(message, offset) != 0D;
5810         case 1: // FLOAT:
5811           return UnsafeUtil.getFloat(message, offset) != 0F;
5812         case 2: // INT64:
5813           return UnsafeUtil.getLong(message, offset) != 0L;
5814         case 3: // UINT64:
5815           return UnsafeUtil.getLong(message, offset) != 0L;
5816         case 4: // INT32:
5817           return UnsafeUtil.getInt(message, offset) != 0;
5818         case 5: // FIXED64:
5819           return UnsafeUtil.getLong(message, offset) != 0L;
5820         case 6: // FIXED32:
5821           return UnsafeUtil.getInt(message, offset) != 0;
5822         case 7: // BOOL:
5823           return UnsafeUtil.getBoolean(message, offset);
5824         case 8: // STRING:
5825           Object value = UnsafeUtil.getObject(message, offset);
5826           if (value instanceof String) {
5827             return !((String) value).isEmpty();
5828           } else if (value instanceof ByteString) {
5829             return !ByteString.EMPTY.equals(value);
5830           } else {
5831             throw new IllegalArgumentException();
5832           }
5833         case 9: // MESSAGE:
5834           return UnsafeUtil.getObject(message, offset) != null;
5835         case 10: // BYTES:
5836           return !ByteString.EMPTY.equals(UnsafeUtil.getObject(message, offset));
5837         case 11: // UINT32:
5838           return UnsafeUtil.getInt(message, offset) != 0;
5839         case 12: // ENUM:
5840           return UnsafeUtil.getInt(message, offset) != 0;
5841         case 13: // SFIXED32:
5842           return UnsafeUtil.getInt(message, offset) != 0;
5843         case 14: // SFIXED64:
5844           return UnsafeUtil.getLong(message, offset) != 0L;
5845         case 15: // SINT32:
5846           return UnsafeUtil.getInt(message, offset) != 0;
5847         case 16: // SINT64:
5848           return UnsafeUtil.getLong(message, offset) != 0L;
5849         case 17: // GROUP:
5850           return UnsafeUtil.getObject(message, offset) != null;
5851         default:
5852           throw new IllegalArgumentException();
5853       }
5854     } else {
5855       final int presenceMask = 1 << (presenceMaskAndOffset >>> OFFSET_BITS);
5856       return (UnsafeUtil.getInt(message, presenceMaskAndOffset & OFFSET_MASK) & presenceMask) != 0;
5857     }
5858   }
5859 
setFieldPresent(T message, int pos)5860   private void setFieldPresent(T message, int pos) {
5861     int presenceMaskAndOffset = presenceMaskAndOffsetAt(pos);
5862     final long presenceFieldOffset = presenceMaskAndOffset & OFFSET_MASK;
5863     if (presenceFieldOffset == NO_PRESENCE_SENTINEL) {
5864       return;
5865     }
5866     final int presenceMask = 1 << (presenceMaskAndOffset >>> OFFSET_BITS);
5867     UnsafeUtil.putInt(
5868         message,
5869         presenceFieldOffset,
5870         UnsafeUtil.getInt(message, presenceFieldOffset) | presenceMask);
5871   }
5872 
isOneofPresent(T message, int fieldNumber, int pos)5873   private boolean isOneofPresent(T message, int fieldNumber, int pos) {
5874     int presenceMaskAndOffset = presenceMaskAndOffsetAt(pos);
5875     return UnsafeUtil.getInt(message, presenceMaskAndOffset & OFFSET_MASK) == fieldNumber;
5876   }
5877 
isOneofCaseEqual(T message, T other, int pos)5878   private boolean isOneofCaseEqual(T message, T other, int pos) {
5879     int presenceMaskAndOffset = presenceMaskAndOffsetAt(pos);
5880     return UnsafeUtil.getInt(message, presenceMaskAndOffset & OFFSET_MASK)
5881         == UnsafeUtil.getInt(other, presenceMaskAndOffset & OFFSET_MASK);
5882   }
5883 
setOneofPresent(T message, int fieldNumber, int pos)5884   private void setOneofPresent(T message, int fieldNumber, int pos) {
5885     int presenceMaskAndOffset = presenceMaskAndOffsetAt(pos);
5886     UnsafeUtil.putInt(message, presenceMaskAndOffset & OFFSET_MASK, fieldNumber);
5887   }
5888 
positionForFieldNumber(final int number)5889   private int positionForFieldNumber(final int number) {
5890     if (number >= minFieldNumber && number <= maxFieldNumber) {
5891       return slowPositionForFieldNumber(number, 0);
5892     }
5893     return -1;
5894   }
5895 
positionForFieldNumber(final int number, final int min)5896   private int positionForFieldNumber(final int number, final int min) {
5897     if (number >= minFieldNumber && number <= maxFieldNumber) {
5898       return slowPositionForFieldNumber(number, min);
5899     }
5900     return -1;
5901   }
5902 
slowPositionForFieldNumber(final int number, int min)5903   private int slowPositionForFieldNumber(final int number, int min) {
5904     int max = buffer.length / INTS_PER_FIELD - 1;
5905     while (min <= max) {
5906       // Find the midpoint address.
5907       final int mid = (max + min) >>> 1;
5908       final int pos = mid * INTS_PER_FIELD;
5909       final int midFieldNumber = numberAt(pos);
5910       if (number == midFieldNumber) {
5911         // Found the field.
5912         return pos;
5913       }
5914       if (number < midFieldNumber) {
5915         // Search the lower half.
5916         max = mid - 1;
5917       } else {
5918         // Search the upper half.
5919         min = mid + 1;
5920       }
5921     }
5922     return -1;
5923   }
5924 
getSchemaSize()5925   int getSchemaSize() {
5926     return buffer.length * 3;
5927   }
5928 }
5929