• 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 com.google.protobuf.FieldSet.FieldDescriptorLite;
11 import com.google.protobuf.Internal.EnumLiteMap;
12 import com.google.protobuf.Internal.EnumVerifier;
13 import java.io.IOException;
14 import java.lang.reflect.Field;
15 import java.util.Iterator;
16 import java.util.List;
17 import java.util.RandomAccess;
18 
19 /** Helper methods used by schemas. */
20 @ExperimentalApi
21 @CheckReturnValue
22 final class SchemaUtil {
23   private static final Class<?> GENERATED_MESSAGE_CLASS = getGeneratedMessageClass();
24   private static final UnknownFieldSchema<?, ?> UNKNOWN_FIELD_SET_FULL_SCHEMA =
25       getUnknownFieldSetSchema();
26   private static final UnknownFieldSchema<?, ?> UNKNOWN_FIELD_SET_LITE_SCHEMA =
27       new UnknownFieldSetLiteSchema();
28 
29   private static final int DEFAULT_LOOK_UP_START_NUMBER = 40;
30 
SchemaUtil()31   private SchemaUtil() {}
32 
33   /**
34    * Requires that the given message extend {@link com.google.protobuf.GeneratedMessage} or {@link
35    * GeneratedMessageLite}.
36    */
requireGeneratedMessage(Class<?> messageType)37   public static void requireGeneratedMessage(Class<?> messageType) {
38     // TODO decide if we're keeping support for Full in schema classes and handle this
39     // better.
40     if (!GeneratedMessageLite.class.isAssignableFrom(messageType)
41         && !Protobuf.assumeLiteRuntime
42         && GENERATED_MESSAGE_CLASS != null
43         && !GENERATED_MESSAGE_CLASS.isAssignableFrom(messageType)) {
44       throw new IllegalArgumentException(
45           "Message classes must extend GeneratedMessage or GeneratedMessageLite");
46     }
47   }
48 
writeDouble(int fieldNumber, double value, Writer writer)49   public static void writeDouble(int fieldNumber, double value, Writer writer) throws IOException {
50     if (Double.doubleToRawLongBits(value) != 0) {
51       writer.writeDouble(fieldNumber, value);
52     }
53   }
54 
writeFloat(int fieldNumber, float value, Writer writer)55   public static void writeFloat(int fieldNumber, float value, Writer writer) throws IOException {
56     if (Float.floatToRawIntBits(value) != 0) {
57       writer.writeFloat(fieldNumber, value);
58     }
59   }
60 
writeInt64(int fieldNumber, long value, Writer writer)61   public static void writeInt64(int fieldNumber, long value, Writer writer) throws IOException {
62     if (value != 0) {
63       writer.writeInt64(fieldNumber, value);
64     }
65   }
66 
writeUInt64(int fieldNumber, long value, Writer writer)67   public static void writeUInt64(int fieldNumber, long value, Writer writer) throws IOException {
68     if (value != 0) {
69       writer.writeUInt64(fieldNumber, value);
70     }
71   }
72 
writeSInt64(int fieldNumber, long value, Writer writer)73   public static void writeSInt64(int fieldNumber, long value, Writer writer) throws IOException {
74     if (value != 0) {
75       writer.writeSInt64(fieldNumber, value);
76     }
77   }
78 
writeFixed64(int fieldNumber, long value, Writer writer)79   public static void writeFixed64(int fieldNumber, long value, Writer writer) throws IOException {
80     if (value != 0) {
81       writer.writeFixed64(fieldNumber, value);
82     }
83   }
84 
writeSFixed64(int fieldNumber, long value, Writer writer)85   public static void writeSFixed64(int fieldNumber, long value, Writer writer) throws IOException {
86     if (value != 0) {
87       writer.writeSFixed64(fieldNumber, value);
88     }
89   }
90 
writeInt32(int fieldNumber, int value, Writer writer)91   public static void writeInt32(int fieldNumber, int value, Writer writer) throws IOException {
92     if (value != 0) {
93       writer.writeInt32(fieldNumber, value);
94     }
95   }
96 
writeUInt32(int fieldNumber, int value, Writer writer)97   public static void writeUInt32(int fieldNumber, int value, Writer writer) throws IOException {
98     if (value != 0) {
99       writer.writeUInt32(fieldNumber, value);
100     }
101   }
102 
writeSInt32(int fieldNumber, int value, Writer writer)103   public static void writeSInt32(int fieldNumber, int value, Writer writer) throws IOException {
104     if (value != 0) {
105       writer.writeSInt32(fieldNumber, value);
106     }
107   }
108 
writeFixed32(int fieldNumber, int value, Writer writer)109   public static void writeFixed32(int fieldNumber, int value, Writer writer) throws IOException {
110     if (value != 0) {
111       writer.writeFixed32(fieldNumber, value);
112     }
113   }
114 
writeSFixed32(int fieldNumber, int value, Writer writer)115   public static void writeSFixed32(int fieldNumber, int value, Writer writer) throws IOException {
116     if (value != 0) {
117       writer.writeSFixed32(fieldNumber, value);
118     }
119   }
120 
writeEnum(int fieldNumber, int value, Writer writer)121   public static void writeEnum(int fieldNumber, int value, Writer writer) throws IOException {
122     if (value != 0) {
123       writer.writeEnum(fieldNumber, value);
124     }
125   }
126 
writeBool(int fieldNumber, boolean value, Writer writer)127   public static void writeBool(int fieldNumber, boolean value, Writer writer) throws IOException {
128     if (value) {
129       writer.writeBool(fieldNumber, true);
130     }
131   }
132 
writeString(int fieldNumber, Object value, Writer writer)133   public static void writeString(int fieldNumber, Object value, Writer writer) throws IOException {
134     if (value instanceof String) {
135       writeStringInternal(fieldNumber, (String) value, writer);
136     } else {
137       writeBytes(fieldNumber, (ByteString) value, writer);
138     }
139   }
140 
writeStringInternal(int fieldNumber, String value, Writer writer)141   private static void writeStringInternal(int fieldNumber, String value, Writer writer)
142       throws IOException {
143     if (value != null && !value.isEmpty()) {
144       writer.writeString(fieldNumber, value);
145     }
146   }
147 
writeBytes(int fieldNumber, ByteString value, Writer writer)148   public static void writeBytes(int fieldNumber, ByteString value, Writer writer)
149       throws IOException {
150     if (value != null && !value.isEmpty()) {
151       writer.writeBytes(fieldNumber, value);
152     }
153   }
154 
writeMessage(int fieldNumber, Object value, Writer writer)155   public static void writeMessage(int fieldNumber, Object value, Writer writer) throws IOException {
156     if (value != null) {
157       writer.writeMessage(fieldNumber, value);
158     }
159   }
160 
writeDoubleList( int fieldNumber, List<Double> value, Writer writer, boolean packed)161   public static void writeDoubleList(
162       int fieldNumber, List<Double> value, Writer writer, boolean packed) throws IOException {
163     if (value != null && !value.isEmpty()) {
164       writer.writeDoubleList(fieldNumber, value, packed);
165     }
166   }
167 
writeFloatList( int fieldNumber, List<Float> value, Writer writer, boolean packed)168   public static void writeFloatList(
169       int fieldNumber, List<Float> value, Writer writer, boolean packed) throws IOException {
170     if (value != null && !value.isEmpty()) {
171       writer.writeFloatList(fieldNumber, value, packed);
172     }
173   }
174 
writeInt64List( int fieldNumber, List<Long> value, Writer writer, boolean packed)175   public static void writeInt64List(
176       int fieldNumber, List<Long> value, Writer writer, boolean packed) throws IOException {
177     if (value != null && !value.isEmpty()) {
178       writer.writeInt64List(fieldNumber, value, packed);
179     }
180   }
181 
writeUInt64List( int fieldNumber, List<Long> value, Writer writer, boolean packed)182   public static void writeUInt64List(
183       int fieldNumber, List<Long> value, Writer writer, boolean packed) throws IOException {
184     if (value != null && !value.isEmpty()) {
185       writer.writeUInt64List(fieldNumber, value, packed);
186     }
187   }
188 
writeSInt64List( int fieldNumber, List<Long> value, Writer writer, boolean packed)189   public static void writeSInt64List(
190       int fieldNumber, List<Long> value, Writer writer, boolean packed) throws IOException {
191     if (value != null && !value.isEmpty()) {
192       writer.writeSInt64List(fieldNumber, value, packed);
193     }
194   }
195 
writeFixed64List( int fieldNumber, List<Long> value, Writer writer, boolean packed)196   public static void writeFixed64List(
197       int fieldNumber, List<Long> value, Writer writer, boolean packed) throws IOException {
198     if (value != null && !value.isEmpty()) {
199       writer.writeFixed64List(fieldNumber, value, packed);
200     }
201   }
202 
writeSFixed64List( int fieldNumber, List<Long> value, Writer writer, boolean packed)203   public static void writeSFixed64List(
204       int fieldNumber, List<Long> value, Writer writer, boolean packed) throws IOException {
205     if (value != null && !value.isEmpty()) {
206       writer.writeSFixed64List(fieldNumber, value, packed);
207     }
208   }
209 
writeInt32List( int fieldNumber, List<Integer> value, Writer writer, boolean packed)210   public static void writeInt32List(
211       int fieldNumber, List<Integer> value, Writer writer, boolean packed) throws IOException {
212     if (value != null && !value.isEmpty()) {
213       writer.writeInt32List(fieldNumber, value, packed);
214     }
215   }
216 
writeUInt32List( int fieldNumber, List<Integer> value, Writer writer, boolean packed)217   public static void writeUInt32List(
218       int fieldNumber, List<Integer> value, Writer writer, boolean packed) throws IOException {
219     if (value != null && !value.isEmpty()) {
220       writer.writeUInt32List(fieldNumber, value, packed);
221     }
222   }
223 
writeSInt32List( int fieldNumber, List<Integer> value, Writer writer, boolean packed)224   public static void writeSInt32List(
225       int fieldNumber, List<Integer> value, Writer writer, boolean packed) throws IOException {
226     if (value != null && !value.isEmpty()) {
227       writer.writeSInt32List(fieldNumber, value, packed);
228     }
229   }
230 
writeFixed32List( int fieldNumber, List<Integer> value, Writer writer, boolean packed)231   public static void writeFixed32List(
232       int fieldNumber, List<Integer> value, Writer writer, boolean packed) throws IOException {
233     if (value != null && !value.isEmpty()) {
234       writer.writeFixed32List(fieldNumber, value, packed);
235     }
236   }
237 
writeSFixed32List( int fieldNumber, List<Integer> value, Writer writer, boolean packed)238   public static void writeSFixed32List(
239       int fieldNumber, List<Integer> value, Writer writer, boolean packed) throws IOException {
240     if (value != null && !value.isEmpty()) {
241       writer.writeSFixed32List(fieldNumber, value, packed);
242     }
243   }
244 
writeEnumList( int fieldNumber, List<Integer> value, Writer writer, boolean packed)245   public static void writeEnumList(
246       int fieldNumber, List<Integer> value, Writer writer, boolean packed) throws IOException {
247     if (value != null && !value.isEmpty()) {
248       writer.writeEnumList(fieldNumber, value, packed);
249     }
250   }
251 
writeBoolList( int fieldNumber, List<Boolean> value, Writer writer, boolean packed)252   public static void writeBoolList(
253       int fieldNumber, List<Boolean> value, Writer writer, boolean packed) throws IOException {
254     if (value != null && !value.isEmpty()) {
255       writer.writeBoolList(fieldNumber, value, packed);
256     }
257   }
258 
writeStringList(int fieldNumber, List<String> value, Writer writer)259   public static void writeStringList(int fieldNumber, List<String> value, Writer writer)
260       throws IOException {
261     if (value != null && !value.isEmpty()) {
262       writer.writeStringList(fieldNumber, value);
263     }
264   }
265 
writeBytesList(int fieldNumber, List<ByteString> value, Writer writer)266   public static void writeBytesList(int fieldNumber, List<ByteString> value, Writer writer)
267       throws IOException {
268     if (value != null && !value.isEmpty()) {
269       writer.writeBytesList(fieldNumber, value);
270     }
271   }
272 
writeMessageList(int fieldNumber, List<?> value, Writer writer)273   public static void writeMessageList(int fieldNumber, List<?> value, Writer writer)
274       throws IOException {
275     if (value != null && !value.isEmpty()) {
276       writer.writeMessageList(fieldNumber, value);
277     }
278   }
279 
writeMessageList( int fieldNumber, List<?> value, Writer writer, Schema<?> schema)280   public static void writeMessageList(
281       int fieldNumber, List<?> value, Writer writer, Schema<?> schema) throws IOException {
282     if (value != null && !value.isEmpty()) {
283       writer.writeMessageList(fieldNumber, value, schema);
284     }
285   }
286 
writeLazyFieldList(int fieldNumber, List<?> value, Writer writer)287   public static void writeLazyFieldList(int fieldNumber, List<?> value, Writer writer)
288       throws IOException {
289     if (value != null && !value.isEmpty()) {
290       for (Object item : value) {
291         ((LazyFieldLite) item).writeTo(writer, fieldNumber);
292       }
293     }
294   }
295 
writeGroupList(int fieldNumber, List<?> value, Writer writer)296   public static void writeGroupList(int fieldNumber, List<?> value, Writer writer)
297       throws IOException {
298     if (value != null && !value.isEmpty()) {
299       writer.writeGroupList(fieldNumber, value);
300     }
301   }
302 
writeGroupList(int fieldNumber, List<?> value, Writer writer, Schema<?> schema)303   public static void writeGroupList(int fieldNumber, List<?> value, Writer writer, Schema<?> schema)
304       throws IOException {
305     if (value != null && !value.isEmpty()) {
306       writer.writeGroupList(fieldNumber, value, schema);
307     }
308   }
309 
computeSizeInt64ListNoTag(List<Long> list)310   static int computeSizeInt64ListNoTag(List<Long> list) {
311     final int length = list.size();
312     if (length == 0) {
313       return 0;
314     }
315 
316     int size = 0;
317 
318     if (list instanceof LongArrayList) {
319       final LongArrayList primitiveList = (LongArrayList) list;
320       for (int i = 0; i < length; i++) {
321         size += CodedOutputStream.computeInt64SizeNoTag(primitiveList.getLong(i));
322       }
323     } else {
324       for (int i = 0; i < length; i++) {
325         size += CodedOutputStream.computeInt64SizeNoTag(list.get(i));
326       }
327     }
328     return size;
329   }
330 
computeSizeInt64List(int fieldNumber, List<Long> list, boolean packed)331   static int computeSizeInt64List(int fieldNumber, List<Long> list, boolean packed) {
332     final int length = list.size();
333     if (length == 0) {
334       return 0;
335     }
336     int size = computeSizeInt64ListNoTag(list);
337 
338     if (packed) {
339       return CodedOutputStream.computeTagSize(fieldNumber)
340           + CodedOutputStream.computeLengthDelimitedFieldSize(size);
341     } else {
342       return size + (list.size() * CodedOutputStream.computeTagSize(fieldNumber));
343     }
344   }
345 
computeSizeUInt64ListNoTag(List<Long> list)346   static int computeSizeUInt64ListNoTag(List<Long> list) {
347     final int length = list.size();
348     if (length == 0) {
349       return 0;
350     }
351 
352     int size = 0;
353 
354     if (list instanceof LongArrayList) {
355       final LongArrayList primitiveList = (LongArrayList) list;
356       for (int i = 0; i < length; i++) {
357         size += CodedOutputStream.computeUInt64SizeNoTag(primitiveList.getLong(i));
358       }
359     } else {
360       for (int i = 0; i < length; i++) {
361         size += CodedOutputStream.computeUInt64SizeNoTag(list.get(i));
362       }
363     }
364     return size;
365   }
366 
computeSizeUInt64List(int fieldNumber, List<Long> list, boolean packed)367   static int computeSizeUInt64List(int fieldNumber, List<Long> list, boolean packed) {
368     final int length = list.size();
369     if (length == 0) {
370       return 0;
371     }
372     int size = computeSizeUInt64ListNoTag(list);
373 
374     if (packed) {
375       return CodedOutputStream.computeTagSize(fieldNumber)
376           + CodedOutputStream.computeLengthDelimitedFieldSize(size);
377     } else {
378       return size + (length * CodedOutputStream.computeTagSize(fieldNumber));
379     }
380   }
381 
computeSizeSInt64ListNoTag(List<Long> list)382   static int computeSizeSInt64ListNoTag(List<Long> list) {
383     final int length = list.size();
384     if (length == 0) {
385       return 0;
386     }
387 
388     int size = 0;
389 
390     if (list instanceof LongArrayList) {
391       final LongArrayList primitiveList = (LongArrayList) list;
392       for (int i = 0; i < length; i++) {
393         size += CodedOutputStream.computeSInt64SizeNoTag(primitiveList.getLong(i));
394       }
395     } else {
396       for (int i = 0; i < length; i++) {
397         size += CodedOutputStream.computeSInt64SizeNoTag(list.get(i));
398       }
399     }
400     return size;
401   }
402 
computeSizeSInt64List(int fieldNumber, List<Long> list, boolean packed)403   static int computeSizeSInt64List(int fieldNumber, List<Long> list, boolean packed) {
404     final int length = list.size();
405     if (length == 0) {
406       return 0;
407     }
408     int size = computeSizeSInt64ListNoTag(list);
409 
410     if (packed) {
411       return CodedOutputStream.computeTagSize(fieldNumber)
412           + CodedOutputStream.computeLengthDelimitedFieldSize(size);
413     } else {
414       return size + (length * CodedOutputStream.computeTagSize(fieldNumber));
415     }
416   }
417 
computeSizeEnumListNoTag(List<Integer> list)418   static int computeSizeEnumListNoTag(List<Integer> list) {
419     final int length = list.size();
420     if (length == 0) {
421       return 0;
422     }
423 
424     int size = 0;
425 
426     if (list instanceof IntArrayList) {
427       final IntArrayList primitiveList = (IntArrayList) list;
428       for (int i = 0; i < length; i++) {
429         size += CodedOutputStream.computeEnumSizeNoTag(primitiveList.getInt(i));
430       }
431     } else {
432       for (int i = 0; i < length; i++) {
433         size += CodedOutputStream.computeEnumSizeNoTag(list.get(i));
434       }
435     }
436     return size;
437   }
438 
computeSizeEnumList(int fieldNumber, List<Integer> list, boolean packed)439   static int computeSizeEnumList(int fieldNumber, List<Integer> list, boolean packed) {
440     final int length = list.size();
441     if (length == 0) {
442       return 0;
443     }
444     int size = computeSizeEnumListNoTag(list);
445 
446     if (packed) {
447       return CodedOutputStream.computeTagSize(fieldNumber)
448           + CodedOutputStream.computeLengthDelimitedFieldSize(size);
449     } else {
450       return size + (length * CodedOutputStream.computeTagSize(fieldNumber));
451     }
452   }
453 
computeSizeInt32ListNoTag(List<Integer> list)454   static int computeSizeInt32ListNoTag(List<Integer> list) {
455     final int length = list.size();
456     if (length == 0) {
457       return 0;
458     }
459 
460     int size = 0;
461 
462     if (list instanceof IntArrayList) {
463       final IntArrayList primitiveList = (IntArrayList) list;
464       for (int i = 0; i < length; i++) {
465         size += CodedOutputStream.computeInt32SizeNoTag(primitiveList.getInt(i));
466       }
467     } else {
468       for (int i = 0; i < length; i++) {
469         size += CodedOutputStream.computeInt32SizeNoTag(list.get(i));
470       }
471     }
472     return size;
473   }
474 
computeSizeInt32List(int fieldNumber, List<Integer> list, boolean packed)475   static int computeSizeInt32List(int fieldNumber, List<Integer> list, boolean packed) {
476     final int length = list.size();
477     if (length == 0) {
478       return 0;
479     }
480     int size = computeSizeInt32ListNoTag(list);
481 
482     if (packed) {
483       return CodedOutputStream.computeTagSize(fieldNumber)
484           + CodedOutputStream.computeLengthDelimitedFieldSize(size);
485     } else {
486       return size + (length * CodedOutputStream.computeTagSize(fieldNumber));
487     }
488   }
489 
computeSizeUInt32ListNoTag(List<Integer> list)490   static int computeSizeUInt32ListNoTag(List<Integer> list) {
491     final int length = list.size();
492     if (length == 0) {
493       return 0;
494     }
495 
496     int size = 0;
497 
498     if (list instanceof IntArrayList) {
499       final IntArrayList primitiveList = (IntArrayList) list;
500       for (int i = 0; i < length; i++) {
501         size += CodedOutputStream.computeUInt32SizeNoTag(primitiveList.getInt(i));
502       }
503     } else {
504       for (int i = 0; i < length; i++) {
505         size += CodedOutputStream.computeUInt32SizeNoTag(list.get(i));
506       }
507     }
508     return size;
509   }
510 
computeSizeUInt32List(int fieldNumber, List<Integer> list, boolean packed)511   static int computeSizeUInt32List(int fieldNumber, List<Integer> list, boolean packed) {
512     final int length = list.size();
513     if (length == 0) {
514       return 0;
515     }
516     int size = computeSizeUInt32ListNoTag(list);
517 
518     if (packed) {
519       return CodedOutputStream.computeTagSize(fieldNumber)
520           + CodedOutputStream.computeLengthDelimitedFieldSize(size);
521     } else {
522       return size + (length * CodedOutputStream.computeTagSize(fieldNumber));
523     }
524   }
525 
computeSizeSInt32ListNoTag(List<Integer> list)526   static int computeSizeSInt32ListNoTag(List<Integer> list) {
527     final int length = list.size();
528     if (length == 0) {
529       return 0;
530     }
531 
532     int size = 0;
533 
534     if (list instanceof IntArrayList) {
535       final IntArrayList primitiveList = (IntArrayList) list;
536       for (int i = 0; i < length; i++) {
537         size += CodedOutputStream.computeSInt32SizeNoTag(primitiveList.getInt(i));
538       }
539     } else {
540       for (int i = 0; i < length; i++) {
541         size += CodedOutputStream.computeSInt32SizeNoTag(list.get(i));
542       }
543     }
544     return size;
545   }
546 
computeSizeSInt32List(int fieldNumber, List<Integer> list, boolean packed)547   static int computeSizeSInt32List(int fieldNumber, List<Integer> list, boolean packed) {
548     final int length = list.size();
549     if (length == 0) {
550       return 0;
551     }
552 
553     int size = computeSizeSInt32ListNoTag(list);
554 
555     if (packed) {
556       return CodedOutputStream.computeTagSize(fieldNumber)
557           + CodedOutputStream.computeLengthDelimitedFieldSize(size);
558     } else {
559       return size + (length * CodedOutputStream.computeTagSize(fieldNumber));
560     }
561   }
562 
computeSizeFixed32ListNoTag(List<?> list)563   static int computeSizeFixed32ListNoTag(List<?> list) {
564     return list.size() * WireFormat.FIXED32_SIZE;
565   }
566 
computeSizeFixed32List(int fieldNumber, List<?> list, boolean packed)567   static int computeSizeFixed32List(int fieldNumber, List<?> list, boolean packed) {
568     final int length = list.size();
569     if (length == 0) {
570       return 0;
571     }
572     if (packed) {
573       int dataSize = length * WireFormat.FIXED32_SIZE;
574       return CodedOutputStream.computeTagSize(fieldNumber)
575           + CodedOutputStream.computeLengthDelimitedFieldSize(dataSize);
576     } else {
577       return length * CodedOutputStream.computeFixed32Size(fieldNumber, 0);
578     }
579   }
580 
computeSizeFixed64ListNoTag(List<?> list)581   static int computeSizeFixed64ListNoTag(List<?> list) {
582     return list.size() * WireFormat.FIXED64_SIZE;
583   }
584 
computeSizeFixed64List(int fieldNumber, List<?> list, boolean packed)585   static int computeSizeFixed64List(int fieldNumber, List<?> list, boolean packed) {
586     final int length = list.size();
587     if (length == 0) {
588       return 0;
589     }
590     if (packed) {
591       final int dataSize = length * WireFormat.FIXED64_SIZE;
592       return CodedOutputStream.computeTagSize(fieldNumber)
593           + CodedOutputStream.computeLengthDelimitedFieldSize(dataSize);
594     } else {
595       return length * CodedOutputStream.computeFixed64Size(fieldNumber, 0);
596     }
597   }
598 
computeSizeBoolListNoTag(List<?> list)599   static int computeSizeBoolListNoTag(List<?> list) {
600     // bools are 1 byte varints
601     return list.size();
602   }
603 
computeSizeBoolList(int fieldNumber, List<?> list, boolean packed)604   static int computeSizeBoolList(int fieldNumber, List<?> list, boolean packed) {
605     final int length = list.size();
606     if (length == 0) {
607       return 0;
608     }
609     if (packed) {
610       // bools are 1 byte varints
611       return CodedOutputStream.computeTagSize(fieldNumber)
612           + CodedOutputStream.computeLengthDelimitedFieldSize(length);
613     } else {
614       return length * CodedOutputStream.computeBoolSize(fieldNumber, true);
615     }
616   }
617 
computeSizeStringList(int fieldNumber, List<?> list)618   static int computeSizeStringList(int fieldNumber, List<?> list) {
619     final int length = list.size();
620     if (length == 0) {
621       return 0;
622     }
623     int size = length * CodedOutputStream.computeTagSize(fieldNumber);
624     if (list instanceof LazyStringList) {
625       LazyStringList lazyList = ((LazyStringList) list);
626       for (int i = 0; i < length; i++) {
627         Object value = lazyList.getRaw(i);
628         if (value instanceof ByteString) {
629           size += CodedOutputStream.computeBytesSizeNoTag((ByteString) value);
630         } else {
631           size += CodedOutputStream.computeStringSizeNoTag((String) value);
632         }
633       }
634     } else {
635       for (int i = 0; i < length; i++) {
636         Object value = list.get(i);
637         if (value instanceof ByteString) {
638           size += CodedOutputStream.computeBytesSizeNoTag((ByteString) value);
639         } else {
640           size += CodedOutputStream.computeStringSizeNoTag((String) value);
641         }
642       }
643     }
644     return size;
645   }
646 
computeSizeMessage(int fieldNumber, Object value, Schema<?> schema)647   static int computeSizeMessage(int fieldNumber, Object value, Schema<?> schema) {
648     if (value instanceof LazyFieldLite) {
649       return CodedOutputStream.computeLazyFieldSize(fieldNumber, (LazyFieldLite) value);
650     } else {
651       return CodedOutputStream.computeMessageSize(fieldNumber, (MessageLite) value, schema);
652     }
653   }
654 
computeSizeMessageList(int fieldNumber, List<?> list)655   static int computeSizeMessageList(int fieldNumber, List<?> list) {
656     final int length = list.size();
657     if (length == 0) {
658       return 0;
659     }
660     int size = length * CodedOutputStream.computeTagSize(fieldNumber);
661     for (int i = 0; i < length; i++) {
662       Object value = list.get(i);
663       if (value instanceof LazyFieldLite) {
664         size += CodedOutputStream.computeLazyFieldSizeNoTag((LazyFieldLite) value);
665       } else {
666         size += CodedOutputStream.computeMessageSizeNoTag((MessageLite) value);
667       }
668     }
669     return size;
670   }
671 
computeSizeMessageList(int fieldNumber, List<?> list, Schema<?> schema)672   static int computeSizeMessageList(int fieldNumber, List<?> list, Schema<?> schema) {
673     final int length = list.size();
674     if (length == 0) {
675       return 0;
676     }
677     int size = length * CodedOutputStream.computeTagSize(fieldNumber);
678     for (int i = 0; i < length; i++) {
679       Object value = list.get(i);
680       if (value instanceof LazyFieldLite) {
681         size += CodedOutputStream.computeLazyFieldSizeNoTag((LazyFieldLite) value);
682       } else {
683         size += CodedOutputStream.computeMessageSizeNoTag((MessageLite) value, schema);
684       }
685     }
686     return size;
687   }
688 
computeSizeByteStringList(int fieldNumber, List<ByteString> list)689   static int computeSizeByteStringList(int fieldNumber, List<ByteString> list) {
690     final int length = list.size();
691     if (length == 0) {
692       return 0;
693     }
694     int size = length * CodedOutputStream.computeTagSize(fieldNumber);
695     for (int i = 0; i < list.size(); i++) {
696       size += CodedOutputStream.computeBytesSizeNoTag(list.get(i));
697     }
698     return size;
699   }
700 
computeSizeGroupList(int fieldNumber, List<MessageLite> list)701   static int computeSizeGroupList(int fieldNumber, List<MessageLite> list) {
702     final int length = list.size();
703     if (length == 0) {
704       return 0;
705     }
706     int size = 0;
707     for (int i = 0; i < length; i++) {
708       size += CodedOutputStream.computeGroupSize(fieldNumber, list.get(i));
709     }
710     return size;
711   }
712 
computeSizeGroupList(int fieldNumber, List<MessageLite> list, Schema<?> schema)713   static int computeSizeGroupList(int fieldNumber, List<MessageLite> list, Schema<?> schema) {
714     final int length = list.size();
715     if (length == 0) {
716       return 0;
717     }
718     int size = 0;
719     for (int i = 0; i < length; i++) {
720       size += CodedOutputStream.computeGroupSize(fieldNumber, list.get(i), schema);
721     }
722     return size;
723   }
724 
725   /**
726    * Determines whether to issue tableswitch or lookupswitch for the mergeFrom method.
727    *
728    * @see #shouldUseTableSwitch(int, int, int)
729    */
shouldUseTableSwitch(FieldInfo[] fields)730   public static boolean shouldUseTableSwitch(FieldInfo[] fields) {
731     // Determine whether to issue a tableswitch or a lookupswitch
732     // instruction.
733     if (fields.length == 0) {
734       return false;
735     }
736 
737     int lo = fields[0].getFieldNumber();
738     int hi = fields[fields.length - 1].getFieldNumber();
739     return shouldUseTableSwitch(lo, hi, fields.length);
740   }
741 
742   /**
743    * Determines whether to issue tableswitch or lookupswitch for the mergeFrom method. This is based
744    * on the <a href=
745    * "http://hg.openjdk.java.net/jdk8/jdk8/langtools/file/30db5e0aaf83/src/share/classes/com/sun/tools/javac/jvm/Gen.java#l1159">
746    * logic in the JDK</a>.
747    *
748    * @param lo the lowest fieldNumber contained within the message.
749    * @param hi the highest fieldNumber contained within the message.
750    * @param numFields the total number of fields in the message.
751    * @return {@code true} if tableswitch should be used, rather than lookupswitch.
752    */
shouldUseTableSwitch(int lo, int hi, int numFields)753   public static boolean shouldUseTableSwitch(int lo, int hi, int numFields) {
754     if (hi < DEFAULT_LOOK_UP_START_NUMBER) {
755       return true;
756     }
757     long tableSpaceCost = ((long) hi - lo + 1); // words
758     long tableTimeCost = 3; // comparisons
759     long lookupSpaceCost = 3 + 2 * (long) numFields;
760     long lookupTimeCost = 3 + (long) numFields;
761     return tableSpaceCost + 3 * tableTimeCost <= lookupSpaceCost + 3 * lookupTimeCost;
762   }
763 
unknownFieldSetFullSchema()764   public static UnknownFieldSchema<?, ?> unknownFieldSetFullSchema() {
765     return UNKNOWN_FIELD_SET_FULL_SCHEMA;
766   }
767 
unknownFieldSetLiteSchema()768   public static UnknownFieldSchema<?, ?> unknownFieldSetLiteSchema() {
769     return UNKNOWN_FIELD_SET_LITE_SCHEMA;
770   }
771 
getUnknownFieldSetSchema()772   private static UnknownFieldSchema<?, ?> getUnknownFieldSetSchema() {
773     try {
774       Class<?> clz = getUnknownFieldSetSchemaClass();
775       if (clz == null) {
776         return null;
777       }
778       return (UnknownFieldSchema) clz.getConstructor().newInstance();
779     } catch (Throwable t) {
780       return null;
781     }
782   }
783 
getGeneratedMessageClass()784   private static Class<?> getGeneratedMessageClass() {
785     if (Protobuf.assumeLiteRuntime) {
786       return null;
787     }
788     try {
789       // TODO decide if we're keeping support for Full in schema classes and handle
790       // this better.
791       return Class.forName("com.google.protobuf.GeneratedMessage");
792     } catch (Throwable e) {
793       return null;
794     }
795   }
796 
getUnknownFieldSetSchemaClass()797   private static Class<?> getUnknownFieldSetSchemaClass() {
798     if (Protobuf.assumeLiteRuntime) {
799       return null;
800     }
801     try {
802       return Class.forName("com.google.protobuf.UnknownFieldSetSchema");
803     } catch (Throwable e) {
804       return null;
805     }
806   }
807 
getMapDefaultEntry(Class<?> clazz, String name)808   static Object getMapDefaultEntry(Class<?> clazz, String name) {
809     try {
810       Class<?> holder =
811           Class.forName(clazz.getName() + "$" + toCamelCase(name, true) + "DefaultEntryHolder");
812       Field[] fields = holder.getDeclaredFields();
813       if (fields.length != 1) {
814         throw new IllegalStateException(
815             "Unable to look up map field default entry holder class for "
816                 + name
817                 + " in "
818                 + clazz.getName());
819       }
820       return UnsafeUtil.getStaticObject(fields[0]);
821     } catch (Throwable t) {
822       throw new RuntimeException(t);
823     }
824   }
825 
toCamelCase(String name, boolean capNext)826   static String toCamelCase(String name, boolean capNext) {
827     StringBuilder sb = new StringBuilder();
828     for (int i = 0; i < name.length(); ++i) {
829       char c = name.charAt(i);
830       // Matches protoc field name function:
831       if ('a' <= c && c <= 'z') {
832         if (capNext) {
833           sb.append((char) (c + ('A' - 'a')));
834         } else {
835           sb.append(c);
836         }
837         capNext = false;
838       } else if ('A' <= c && c <= 'Z') {
839         if (i == 0 && !capNext) {
840           // Force first letter to lower-case unless explicitly told to capitalize it.
841           sb.append((char) (c - ('A' - 'a')));
842         } else {
843           sb.append(c);
844         }
845         capNext = false;
846       } else if ('0' <= c && c <= '9') {
847         sb.append(c);
848         capNext = true;
849       } else {
850         capNext = true;
851       }
852     }
853     return sb.toString();
854   }
855 
856   /** Returns true if both are null or both are {@link Object#equals}. */
safeEquals(Object a, Object b)857   static boolean safeEquals(Object a, Object b) {
858     return a == b || (a != null && a.equals(b));
859   }
860 
mergeMap(MapFieldSchema mapFieldSchema, T message, T o, long offset)861   static <T> void mergeMap(MapFieldSchema mapFieldSchema, T message, T o, long offset) {
862     Object merged =
863         mapFieldSchema.mergeFrom(
864             UnsafeUtil.getObject(message, offset), UnsafeUtil.getObject(o, offset));
865     UnsafeUtil.putObject(message, offset, merged);
866   }
867 
mergeExtensions( ExtensionSchema<FT> schema, T message, T other)868   static <T, FT extends FieldDescriptorLite<FT>> void mergeExtensions(
869       ExtensionSchema<FT> schema, T message, T other) {
870     FieldSet<FT> otherExtensions = schema.getExtensions(other);
871     if (!otherExtensions.isEmpty()) {
872       FieldSet<FT> messageExtensions = schema.getMutableExtensions(message);
873       messageExtensions.mergeFrom(otherExtensions);
874     }
875   }
876 
mergeUnknownFields( UnknownFieldSchema<UT, UB> schema, T message, T other)877   static <T, UT, UB> void mergeUnknownFields(
878       UnknownFieldSchema<UT, UB> schema, T message, T other) {
879     UT messageUnknowns = schema.getFromMessage(message);
880     UT otherUnknowns = schema.getFromMessage(other);
881     UT merged = schema.merge(messageUnknowns, otherUnknowns);
882     schema.setToMessage(message, merged);
883   }
884 
885   /** Filters unrecognized enum values in a list. */
886   @CanIgnoreReturnValue
filterUnknownEnumList( Object containerMessage, int number, List<Integer> enumList, EnumLiteMap<?> enumMap, UB unknownFields, UnknownFieldSchema<UT, UB> unknownFieldSchema)887   static <UT, UB> UB filterUnknownEnumList(
888       Object containerMessage,
889       int number,
890       List<Integer> enumList,
891       EnumLiteMap<?> enumMap,
892       UB unknownFields,
893       UnknownFieldSchema<UT, UB> unknownFieldSchema) {
894     if (enumMap == null) {
895       return unknownFields;
896     }
897     // TODO: Specialize for IntArrayList to avoid boxing.
898     if (enumList instanceof RandomAccess) {
899       int writePos = 0;
900       int size = enumList.size();
901       for (int readPos = 0; readPos < size; ++readPos) {
902         int enumValue = enumList.get(readPos);
903         if (enumMap.findValueByNumber(enumValue) != null) {
904           if (readPos != writePos) {
905             enumList.set(writePos, enumValue);
906           }
907           ++writePos;
908         } else {
909           unknownFields =
910               storeUnknownEnum(
911                   containerMessage, number, enumValue, unknownFields, unknownFieldSchema);
912         }
913       }
914       if (writePos != size) {
915         enumList.subList(writePos, size).clear();
916       }
917     } else {
918       for (Iterator<Integer> it = enumList.iterator(); it.hasNext(); ) {
919         int enumValue = it.next();
920         if (enumMap.findValueByNumber(enumValue) == null) {
921           unknownFields =
922               storeUnknownEnum(
923                   containerMessage, number, enumValue, unknownFields, unknownFieldSchema);
924           it.remove();
925         }
926       }
927     }
928     return unknownFields;
929   }
930 
931   /** Filters unrecognized enum values in a list. */
932   @CanIgnoreReturnValue
filterUnknownEnumList( Object containerMessage, int number, List<Integer> enumList, EnumVerifier enumVerifier, UB unknownFields, UnknownFieldSchema<UT, UB> unknownFieldSchema)933   static <UT, UB> UB filterUnknownEnumList(
934       Object containerMessage,
935       int number,
936       List<Integer> enumList,
937       EnumVerifier enumVerifier,
938       UB unknownFields,
939       UnknownFieldSchema<UT, UB> unknownFieldSchema) {
940     if (enumVerifier == null) {
941       return unknownFields;
942     }
943     // TODO: Specialize for IntArrayList to avoid boxing.
944     if (enumList instanceof RandomAccess) {
945       int writePos = 0;
946       int size = enumList.size();
947       for (int readPos = 0; readPos < size; ++readPos) {
948         int enumValue = enumList.get(readPos);
949         if (enumVerifier.isInRange(enumValue)) {
950           if (readPos != writePos) {
951             enumList.set(writePos, enumValue);
952           }
953           ++writePos;
954         } else {
955           unknownFields =
956               storeUnknownEnum(
957                   containerMessage, number, enumValue, unknownFields, unknownFieldSchema);
958         }
959       }
960       if (writePos != size) {
961         enumList.subList(writePos, size).clear();
962       }
963     } else {
964       for (Iterator<Integer> it = enumList.iterator(); it.hasNext(); ) {
965         int enumValue = it.next();
966         if (!enumVerifier.isInRange(enumValue)) {
967           unknownFields =
968               storeUnknownEnum(
969                   containerMessage, number, enumValue, unknownFields, unknownFieldSchema);
970           it.remove();
971         }
972       }
973     }
974     return unknownFields;
975   }
976 
977   /** Stores an unrecognized enum value as an unknown value. */
978   @CanIgnoreReturnValue
storeUnknownEnum( Object containerMessage, int number, int enumValue, UB unknownFields, UnknownFieldSchema<UT, UB> unknownFieldSchema)979   static <UT, UB> UB storeUnknownEnum(
980       Object containerMessage,
981       int number,
982       int enumValue,
983       UB unknownFields,
984       UnknownFieldSchema<UT, UB> unknownFieldSchema) {
985     if (unknownFields == null) {
986       unknownFields = unknownFieldSchema.getBuilderFromMessage(containerMessage);
987     }
988     unknownFieldSchema.addVarint(unknownFields, number, enumValue);
989     return unknownFields;
990   }
991 }
992