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// Author: kenton@google.com (Kenton Varda)
32//  Based on original Protocol Buffers design by
33//  Sanjay Ghemawat, Jeff Dean, and others.
34
35#include <algorithm>
36#include <google/protobuf/stubs/hash.h>
37#include <limits>
38#include <vector>
39
40#include <google/protobuf/compiler/java/java_helpers.h>
41#include <google/protobuf/compiler/java/java_name_resolver.h>
42#include <google/protobuf/descriptor.pb.h>
43#include <google/protobuf/wire_format.h>
44#include <google/protobuf/stubs/strutil.h>
45#include <google/protobuf/stubs/substitute.h>
46
47namespace google {
48namespace protobuf {
49namespace compiler {
50namespace java {
51
52using internal::WireFormat;
53using internal::WireFormatLite;
54
55const char kThickSeparator[] =
56  "// ===================================================================\n";
57const char kThinSeparator[] =
58  "// -------------------------------------------------------------------\n";
59
60namespace {
61
62const char* kDefaultPackage = "";
63
64// Names that should be avoided as field names.
65// Using them will cause the compiler to generate accessors whose names are
66// colliding with methods defined in base classes.
67const char* kForbiddenWordList[] = {
68  // message base class:
69  "cached_size", "serialized_size",
70  // java.lang.Object:
71  "class",
72};
73
74bool IsForbidden(const string& field_name) {
75  for (int i = 0; i < GOOGLE_ARRAYSIZE(kForbiddenWordList); ++i) {
76    if (field_name == kForbiddenWordList[i]) {
77      return true;
78    }
79  }
80  return false;
81}
82
83string FieldName(const FieldDescriptor* field) {
84  string field_name;
85  // Groups are hacky:  The name of the field is just the lower-cased name
86  // of the group type.  In Java, though, we would like to retain the original
87  // capitalization of the type name.
88  if (GetType(field) == FieldDescriptor::TYPE_GROUP) {
89    field_name = field->message_type()->name();
90  } else {
91    field_name = field->name();
92  }
93  if (IsForbidden(field_name)) {
94    // Append a trailing "#" to indicate that the name should be decorated to
95    // avoid collision with other names.
96    field_name += "#";
97  }
98  return field_name;
99}
100
101
102}  // namespace
103
104string UnderscoresToCamelCase(const string& input, bool cap_next_letter) {
105  string result;
106  // Note:  I distrust ctype.h due to locales.
107  for (int i = 0; i < input.size(); i++) {
108    if ('a' <= input[i] && input[i] <= 'z') {
109      if (cap_next_letter) {
110        result += input[i] + ('A' - 'a');
111      } else {
112        result += input[i];
113      }
114      cap_next_letter = false;
115    } else if ('A' <= input[i] && input[i] <= 'Z') {
116      if (i == 0 && !cap_next_letter) {
117        // Force first letter to lower-case unless explicitly told to
118        // capitalize it.
119        result += input[i] + ('a' - 'A');
120      } else {
121        // Capital letters after the first are left as-is.
122        result += input[i];
123      }
124      cap_next_letter = false;
125    } else if ('0' <= input[i] && input[i] <= '9') {
126      result += input[i];
127      cap_next_letter = true;
128    } else {
129      cap_next_letter = true;
130    }
131  }
132  // Add a trailing "_" if the name should be altered.
133  if (input[input.size() - 1] == '#') {
134    result += '_';
135  }
136  return result;
137}
138
139string UnderscoresToCamelCase(const FieldDescriptor* field) {
140  return UnderscoresToCamelCase(FieldName(field), false);
141}
142
143string UnderscoresToCapitalizedCamelCase(const FieldDescriptor* field) {
144  return UnderscoresToCamelCase(FieldName(field), true);
145}
146
147string UnderscoresToCamelCase(const MethodDescriptor* method) {
148  return UnderscoresToCamelCase(method->name(), false);
149}
150
151string UniqueFileScopeIdentifier(const Descriptor* descriptor) {
152  return "static_" + StringReplace(descriptor->full_name(), ".", "_", true);
153}
154
155string StripProto(const string& filename) {
156  if (HasSuffixString(filename, ".protodevel")) {
157    return StripSuffixString(filename, ".protodevel");
158  } else {
159    return StripSuffixString(filename, ".proto");
160  }
161}
162
163string FileClassName(const FileDescriptor* file, bool immutable) {
164  ClassNameResolver name_resolver;
165  return name_resolver.GetFileClassName(file, immutable);
166}
167
168string FileJavaPackage(const FileDescriptor* file, bool immutable) {
169  string result;
170
171  if (file->options().has_java_package()) {
172    result = file->options().java_package();
173  } else {
174    result = kDefaultPackage;
175    if (!file->package().empty()) {
176      if (!result.empty()) result += '.';
177      result += file->package();
178    }
179  }
180
181  return result;
182}
183
184string JavaPackageToDir(string package_name) {
185  string package_dir =
186    StringReplace(package_name, ".", "/", true);
187  if (!package_dir.empty()) package_dir += "/";
188  return package_dir;
189}
190
191// TODO(xiaofeng): This function is only kept for it's publicly referenced.
192// It should be removed after mutable API up-integration.
193string ToJavaName(const string& full_name,
194                  const FileDescriptor* file) {
195  string result;
196  if (file->options().java_multiple_files()) {
197    result = FileJavaPackage(file);
198  } else {
199    result = ClassName(file);
200  }
201  if (!result.empty()) {
202    result += '.';
203  }
204  if (file->package().empty()) {
205    result += full_name;
206  } else {
207    // Strip the proto package from full_name since we've replaced it with
208    // the Java package.
209    result += full_name.substr(file->package().size() + 1);
210  }
211  return result;
212}
213
214string ClassName(const Descriptor* descriptor) {
215  ClassNameResolver name_resolver;
216  return name_resolver.GetClassName(descriptor, true);
217}
218
219string ClassName(const EnumDescriptor* descriptor) {
220  ClassNameResolver name_resolver;
221  return name_resolver.GetClassName(descriptor, true);
222}
223
224string ClassName(const ServiceDescriptor* descriptor) {
225  ClassNameResolver name_resolver;
226  return name_resolver.GetClassName(descriptor, true);
227}
228
229string ClassName(const FileDescriptor* descriptor) {
230  ClassNameResolver name_resolver;
231  return name_resolver.GetClassName(descriptor, true);
232}
233
234string ExtraMessageInterfaces(const Descriptor* descriptor) {
235  string interfaces = "// @@protoc_insertion_point(message_implements:"
236      + descriptor->full_name() + ")";
237  return interfaces;
238}
239
240
241string ExtraBuilderInterfaces(const Descriptor* descriptor) {
242  string interfaces = "// @@protoc_insertion_point(builder_implements:"
243      + descriptor->full_name() + ")";
244  return interfaces;
245}
246
247string ExtraMessageOrBuilderInterfaces(const Descriptor* descriptor) {
248  string interfaces = "// @@protoc_insertion_point(interface_extends:"
249      + descriptor->full_name() + ")";
250  return interfaces;
251}
252
253string FieldConstantName(const FieldDescriptor *field) {
254  string name = field->name() + "_FIELD_NUMBER";
255  UpperString(&name);
256  return name;
257}
258
259FieldDescriptor::Type GetType(const FieldDescriptor* field) {
260  return field->type();
261}
262
263JavaType GetJavaType(const FieldDescriptor* field) {
264  switch (GetType(field)) {
265    case FieldDescriptor::TYPE_INT32:
266    case FieldDescriptor::TYPE_UINT32:
267    case FieldDescriptor::TYPE_SINT32:
268    case FieldDescriptor::TYPE_FIXED32:
269    case FieldDescriptor::TYPE_SFIXED32:
270      return JAVATYPE_INT;
271
272    case FieldDescriptor::TYPE_INT64:
273    case FieldDescriptor::TYPE_UINT64:
274    case FieldDescriptor::TYPE_SINT64:
275    case FieldDescriptor::TYPE_FIXED64:
276    case FieldDescriptor::TYPE_SFIXED64:
277      return JAVATYPE_LONG;
278
279    case FieldDescriptor::TYPE_FLOAT:
280      return JAVATYPE_FLOAT;
281
282    case FieldDescriptor::TYPE_DOUBLE:
283      return JAVATYPE_DOUBLE;
284
285    case FieldDescriptor::TYPE_BOOL:
286      return JAVATYPE_BOOLEAN;
287
288    case FieldDescriptor::TYPE_STRING:
289      return JAVATYPE_STRING;
290
291    case FieldDescriptor::TYPE_BYTES:
292      return JAVATYPE_BYTES;
293
294    case FieldDescriptor::TYPE_ENUM:
295      return JAVATYPE_ENUM;
296
297    case FieldDescriptor::TYPE_GROUP:
298    case FieldDescriptor::TYPE_MESSAGE:
299      return JAVATYPE_MESSAGE;
300
301    // No default because we want the compiler to complain if any new
302    // types are added.
303  }
304
305  GOOGLE_LOG(FATAL) << "Can't get here.";
306  return JAVATYPE_INT;
307}
308
309const char* PrimitiveTypeName(JavaType type) {
310  switch (type) {
311    case JAVATYPE_INT    : return "int";
312    case JAVATYPE_LONG   : return "long";
313    case JAVATYPE_FLOAT  : return "float";
314    case JAVATYPE_DOUBLE : return "double";
315    case JAVATYPE_BOOLEAN: return "boolean";
316    case JAVATYPE_STRING : return "java.lang.String";
317    case JAVATYPE_BYTES  : return "com.google.protobuf.ByteString";
318    case JAVATYPE_ENUM   : return NULL;
319    case JAVATYPE_MESSAGE: return NULL;
320
321    // No default because we want the compiler to complain if any new
322    // JavaTypes are added.
323  }
324
325  GOOGLE_LOG(FATAL) << "Can't get here.";
326  return NULL;
327}
328
329const char* BoxedPrimitiveTypeName(JavaType type) {
330  switch (type) {
331    case JAVATYPE_INT    : return "java.lang.Integer";
332    case JAVATYPE_LONG   : return "java.lang.Long";
333    case JAVATYPE_FLOAT  : return "java.lang.Float";
334    case JAVATYPE_DOUBLE : return "java.lang.Double";
335    case JAVATYPE_BOOLEAN: return "java.lang.Boolean";
336    case JAVATYPE_STRING : return "java.lang.String";
337    case JAVATYPE_BYTES  : return "com.google.protobuf.ByteString";
338    case JAVATYPE_ENUM   : return NULL;
339    case JAVATYPE_MESSAGE: return NULL;
340
341    // No default because we want the compiler to complain if any new
342    // JavaTypes are added.
343  }
344
345  GOOGLE_LOG(FATAL) << "Can't get here.";
346  return NULL;
347}
348
349const char* FieldTypeName(FieldDescriptor::Type field_type) {
350  switch (field_type) {
351    case FieldDescriptor::TYPE_INT32   : return "INT32";
352    case FieldDescriptor::TYPE_UINT32  : return "UINT32";
353    case FieldDescriptor::TYPE_SINT32  : return "SINT32";
354    case FieldDescriptor::TYPE_FIXED32 : return "FIXED32";
355    case FieldDescriptor::TYPE_SFIXED32: return "SFIXED32";
356    case FieldDescriptor::TYPE_INT64   : return "INT64";
357    case FieldDescriptor::TYPE_UINT64  : return "UINT64";
358    case FieldDescriptor::TYPE_SINT64  : return "SINT64";
359    case FieldDescriptor::TYPE_FIXED64 : return "FIXED64";
360    case FieldDescriptor::TYPE_SFIXED64: return "SFIXED64";
361    case FieldDescriptor::TYPE_FLOAT   : return "FLOAT";
362    case FieldDescriptor::TYPE_DOUBLE  : return "DOUBLE";
363    case FieldDescriptor::TYPE_BOOL    : return "BOOL";
364    case FieldDescriptor::TYPE_STRING  : return "STRING";
365    case FieldDescriptor::TYPE_BYTES   : return "BYTES";
366    case FieldDescriptor::TYPE_ENUM    : return "ENUM";
367    case FieldDescriptor::TYPE_GROUP   : return "GROUP";
368    case FieldDescriptor::TYPE_MESSAGE : return "MESSAGE";
369
370    // No default because we want the compiler to complain if any new
371    // types are added.
372  }
373
374  GOOGLE_LOG(FATAL) << "Can't get here.";
375  return NULL;
376}
377
378bool AllAscii(const string& text) {
379  for (int i = 0; i < text.size(); i++) {
380    if ((text[i] & 0x80) != 0) {
381      return false;
382    }
383  }
384  return true;
385}
386
387string DefaultValue(const FieldDescriptor* field, bool immutable,
388                    ClassNameResolver* name_resolver) {
389  // Switch on CppType since we need to know which default_value_* method
390  // of FieldDescriptor to call.
391  switch (field->cpp_type()) {
392    case FieldDescriptor::CPPTYPE_INT32:
393      return SimpleItoa(field->default_value_int32());
394    case FieldDescriptor::CPPTYPE_UINT32:
395      // Need to print as a signed int since Java has no unsigned.
396      return SimpleItoa(static_cast<int32>(field->default_value_uint32()));
397    case FieldDescriptor::CPPTYPE_INT64:
398      return SimpleItoa(field->default_value_int64()) + "L";
399    case FieldDescriptor::CPPTYPE_UINT64:
400      return SimpleItoa(static_cast<int64>(field->default_value_uint64())) +
401             "L";
402    case FieldDescriptor::CPPTYPE_DOUBLE: {
403      double value = field->default_value_double();
404      if (value == numeric_limits<double>::infinity()) {
405        return "Double.POSITIVE_INFINITY";
406      } else if (value == -numeric_limits<double>::infinity()) {
407        return "Double.NEGATIVE_INFINITY";
408      } else if (value != value) {
409        return "Double.NaN";
410      } else {
411        return SimpleDtoa(value) + "D";
412      }
413    }
414    case FieldDescriptor::CPPTYPE_FLOAT: {
415      float value = field->default_value_float();
416      if (value == numeric_limits<float>::infinity()) {
417        return "Float.POSITIVE_INFINITY";
418      } else if (value == -numeric_limits<float>::infinity()) {
419        return "Float.NEGATIVE_INFINITY";
420      } else if (value != value) {
421        return "Float.NaN";
422      } else {
423        return SimpleFtoa(value) + "F";
424      }
425    }
426    case FieldDescriptor::CPPTYPE_BOOL:
427      return field->default_value_bool() ? "true" : "false";
428    case FieldDescriptor::CPPTYPE_STRING:
429      if (GetType(field) == FieldDescriptor::TYPE_BYTES) {
430        if (field->has_default_value()) {
431          // See comments in Internal.java for gory details.
432          return strings::Substitute(
433            "com.google.protobuf.Internal.bytesDefaultValue(\"$0\")",
434            CEscape(field->default_value_string()));
435        } else {
436          return "com.google.protobuf.ByteString.EMPTY";
437        }
438      } else {
439        if (AllAscii(field->default_value_string())) {
440          // All chars are ASCII.  In this case CEscape() works fine.
441          return "\"" + CEscape(field->default_value_string()) + "\"";
442        } else {
443          // See comments in Internal.java for gory details.
444          return strings::Substitute(
445              "com.google.protobuf.Internal.stringDefaultValue(\"$0\")",
446              CEscape(field->default_value_string()));
447        }
448      }
449
450    case FieldDescriptor::CPPTYPE_ENUM:
451      return name_resolver->GetClassName(field->enum_type(), immutable) + "." +
452          field->default_value_enum()->name();
453
454    case FieldDescriptor::CPPTYPE_MESSAGE:
455      return name_resolver->GetClassName(field->message_type(), immutable) +
456          ".getDefaultInstance()";
457
458    // No default because we want the compiler to complain if any new
459    // types are added.
460  }
461
462  GOOGLE_LOG(FATAL) << "Can't get here.";
463  return "";
464}
465
466bool IsDefaultValueJavaDefault(const FieldDescriptor* field) {
467  // Switch on CppType since we need to know which default_value_* method
468  // of FieldDescriptor to call.
469  switch (field->cpp_type()) {
470    case FieldDescriptor::CPPTYPE_INT32:
471      return field->default_value_int32() == 0;
472    case FieldDescriptor::CPPTYPE_UINT32:
473      return field->default_value_uint32() == 0;
474    case FieldDescriptor::CPPTYPE_INT64:
475      return field->default_value_int64() == 0L;
476    case FieldDescriptor::CPPTYPE_UINT64:
477      return field->default_value_uint64() == 0L;
478    case FieldDescriptor::CPPTYPE_DOUBLE:
479      return field->default_value_double() == 0.0;
480    case FieldDescriptor::CPPTYPE_FLOAT:
481      return field->default_value_float() == 0.0;
482    case FieldDescriptor::CPPTYPE_BOOL:
483      return field->default_value_bool() == false;
484
485    case FieldDescriptor::CPPTYPE_STRING:
486    case FieldDescriptor::CPPTYPE_ENUM:
487    case FieldDescriptor::CPPTYPE_MESSAGE:
488      return false;
489
490    // No default because we want the compiler to complain if any new
491    // types are added.
492  }
493
494  GOOGLE_LOG(FATAL) << "Can't get here.";
495  return false;
496}
497
498const char* bit_masks[] = {
499  "0x00000001",
500  "0x00000002",
501  "0x00000004",
502  "0x00000008",
503  "0x00000010",
504  "0x00000020",
505  "0x00000040",
506  "0x00000080",
507
508  "0x00000100",
509  "0x00000200",
510  "0x00000400",
511  "0x00000800",
512  "0x00001000",
513  "0x00002000",
514  "0x00004000",
515  "0x00008000",
516
517  "0x00010000",
518  "0x00020000",
519  "0x00040000",
520  "0x00080000",
521  "0x00100000",
522  "0x00200000",
523  "0x00400000",
524  "0x00800000",
525
526  "0x01000000",
527  "0x02000000",
528  "0x04000000",
529  "0x08000000",
530  "0x10000000",
531  "0x20000000",
532  "0x40000000",
533  "0x80000000",
534};
535
536string GetBitFieldName(int index) {
537  string varName = "bitField";
538  varName += SimpleItoa(index);
539  varName += "_";
540  return varName;
541}
542
543string GetBitFieldNameForBit(int bitIndex) {
544  return GetBitFieldName(bitIndex / 32);
545}
546
547namespace {
548
549string GenerateGetBitInternal(const string& prefix, int bitIndex) {
550  string varName = prefix + GetBitFieldNameForBit(bitIndex);
551  int bitInVarIndex = bitIndex % 32;
552
553  string mask = bit_masks[bitInVarIndex];
554  string result = "((" + varName + " & " + mask + ") == " + mask + ")";
555  return result;
556}
557
558string GenerateSetBitInternal(const string& prefix, int bitIndex) {
559  string varName = prefix + GetBitFieldNameForBit(bitIndex);
560  int bitInVarIndex = bitIndex % 32;
561
562  string mask = bit_masks[bitInVarIndex];
563  string result = varName + " |= " + mask;
564  return result;
565}
566
567}  // namespace
568
569string GenerateGetBit(int bitIndex) {
570  return GenerateGetBitInternal("", bitIndex);
571}
572
573string GenerateSetBit(int bitIndex) {
574  return GenerateSetBitInternal("", bitIndex);
575}
576
577string GenerateClearBit(int bitIndex) {
578  string varName = GetBitFieldNameForBit(bitIndex);
579  int bitInVarIndex = bitIndex % 32;
580
581  string mask = bit_masks[bitInVarIndex];
582  string result = varName + " = (" + varName + " & ~" + mask + ")";
583  return result;
584}
585
586string GenerateGetBitFromLocal(int bitIndex) {
587  return GenerateGetBitInternal("from_", bitIndex);
588}
589
590string GenerateSetBitToLocal(int bitIndex) {
591  return GenerateSetBitInternal("to_", bitIndex);
592}
593
594string GenerateGetBitMutableLocal(int bitIndex) {
595  return GenerateGetBitInternal("mutable_", bitIndex);
596}
597
598string GenerateSetBitMutableLocal(int bitIndex) {
599  return GenerateSetBitInternal("mutable_", bitIndex);
600}
601
602bool IsReferenceType(JavaType type) {
603  switch (type) {
604    case JAVATYPE_INT    : return false;
605    case JAVATYPE_LONG   : return false;
606    case JAVATYPE_FLOAT  : return false;
607    case JAVATYPE_DOUBLE : return false;
608    case JAVATYPE_BOOLEAN: return false;
609    case JAVATYPE_STRING : return true;
610    case JAVATYPE_BYTES  : return true;
611    case JAVATYPE_ENUM   : return true;
612    case JAVATYPE_MESSAGE: return true;
613
614    // No default because we want the compiler to complain if any new
615    // JavaTypes are added.
616  }
617
618  GOOGLE_LOG(FATAL) << "Can't get here.";
619  return false;
620}
621
622const char* GetCapitalizedType(const FieldDescriptor* field, bool immutable) {
623  switch (GetType(field)) {
624    case FieldDescriptor::TYPE_INT32   : return "Int32";
625    case FieldDescriptor::TYPE_UINT32  : return "UInt32";
626    case FieldDescriptor::TYPE_SINT32  : return "SInt32";
627    case FieldDescriptor::TYPE_FIXED32 : return "Fixed32";
628    case FieldDescriptor::TYPE_SFIXED32: return "SFixed32";
629    case FieldDescriptor::TYPE_INT64   : return "Int64";
630    case FieldDescriptor::TYPE_UINT64  : return "UInt64";
631    case FieldDescriptor::TYPE_SINT64  : return "SInt64";
632    case FieldDescriptor::TYPE_FIXED64 : return "Fixed64";
633    case FieldDescriptor::TYPE_SFIXED64: return "SFixed64";
634    case FieldDescriptor::TYPE_FLOAT   : return "Float";
635    case FieldDescriptor::TYPE_DOUBLE  : return "Double";
636    case FieldDescriptor::TYPE_BOOL    : return "Bool";
637    case FieldDescriptor::TYPE_STRING  : return "String";
638    case FieldDescriptor::TYPE_BYTES   : {
639      return "Bytes";
640    }
641    case FieldDescriptor::TYPE_ENUM    : return "Enum";
642    case FieldDescriptor::TYPE_GROUP   : return "Group";
643    case FieldDescriptor::TYPE_MESSAGE : return "Message";
644
645    // No default because we want the compiler to complain if any new
646    // types are added.
647  }
648
649  GOOGLE_LOG(FATAL) << "Can't get here.";
650  return NULL;
651}
652
653// For encodings with fixed sizes, returns that size in bytes.  Otherwise
654// returns -1.
655int FixedSize(FieldDescriptor::Type type) {
656  switch (type) {
657    case FieldDescriptor::TYPE_INT32   : return -1;
658    case FieldDescriptor::TYPE_INT64   : return -1;
659    case FieldDescriptor::TYPE_UINT32  : return -1;
660    case FieldDescriptor::TYPE_UINT64  : return -1;
661    case FieldDescriptor::TYPE_SINT32  : return -1;
662    case FieldDescriptor::TYPE_SINT64  : return -1;
663    case FieldDescriptor::TYPE_FIXED32 : return WireFormatLite::kFixed32Size;
664    case FieldDescriptor::TYPE_FIXED64 : return WireFormatLite::kFixed64Size;
665    case FieldDescriptor::TYPE_SFIXED32: return WireFormatLite::kSFixed32Size;
666    case FieldDescriptor::TYPE_SFIXED64: return WireFormatLite::kSFixed64Size;
667    case FieldDescriptor::TYPE_FLOAT   : return WireFormatLite::kFloatSize;
668    case FieldDescriptor::TYPE_DOUBLE  : return WireFormatLite::kDoubleSize;
669
670    case FieldDescriptor::TYPE_BOOL    : return WireFormatLite::kBoolSize;
671    case FieldDescriptor::TYPE_ENUM    : return -1;
672
673    case FieldDescriptor::TYPE_STRING  : return -1;
674    case FieldDescriptor::TYPE_BYTES   : return -1;
675    case FieldDescriptor::TYPE_GROUP   : return -1;
676    case FieldDescriptor::TYPE_MESSAGE : return -1;
677
678    // No default because we want the compiler to complain if any new
679    // types are added.
680  }
681  GOOGLE_LOG(FATAL) << "Can't get here.";
682  return -1;
683}
684
685// Sort the fields of the given Descriptor by number into a new[]'d array
686// and return it. The caller should delete the returned array.
687const FieldDescriptor** SortFieldsByNumber(const Descriptor* descriptor) {
688  const FieldDescriptor** fields =
689    new const FieldDescriptor*[descriptor->field_count()];
690  for (int i = 0; i < descriptor->field_count(); i++) {
691    fields[i] = descriptor->field(i);
692  }
693  std::sort(fields, fields + descriptor->field_count(),
694            FieldOrderingByNumber());
695  return fields;
696}
697
698// Returns true if the message type has any required fields.  If it doesn't,
699// we can optimize out calls to its isInitialized() method.
700//
701// already_seen is used to avoid checking the same type multiple times
702// (and also to protect against recursion).
703bool HasRequiredFields(
704    const Descriptor* type,
705    hash_set<const Descriptor*>* already_seen) {
706  if (already_seen->count(type) > 0) {
707    // The type is already in cache.  This means that either:
708    // a. The type has no required fields.
709    // b. We are in the midst of checking if the type has required fields,
710    //    somewhere up the stack.  In this case, we know that if the type
711    //    has any required fields, they'll be found when we return to it,
712    //    and the whole call to HasRequiredFields() will return true.
713    //    Therefore, we don't have to check if this type has required fields
714    //    here.
715    return false;
716  }
717  already_seen->insert(type);
718
719  // If the type has extensions, an extension with message type could contain
720  // required fields, so we have to be conservative and assume such an
721  // extension exists.
722  if (type->extension_range_count() > 0) return true;
723
724  for (int i = 0; i < type->field_count(); i++) {
725    const FieldDescriptor* field = type->field(i);
726    if (field->is_required()) {
727      return true;
728    }
729    if (GetJavaType(field) == JAVATYPE_MESSAGE) {
730      if (HasRequiredFields(field->message_type(), already_seen)) {
731        return true;
732      }
733    }
734  }
735
736  return false;
737}
738
739bool HasRequiredFields(const Descriptor* type) {
740  hash_set<const Descriptor*> already_seen;
741  return HasRequiredFields(type, &already_seen);
742}
743
744bool HasRepeatedFields(const Descriptor* descriptor) {
745  for (int i = 0; i < descriptor->field_count(); ++i) {
746    const FieldDescriptor* field = descriptor->field(i);
747    if (field->is_repeated()) {
748      return true;
749    }
750  }
751  return false;
752}
753
754}  // namespace java
755}  // namespace compiler
756}  // namespace protobuf
757}  // namespace google
758