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