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