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