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