• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc.  All rights reserved.
3 // https://developers.google.com/protocol-buffers/
4 //
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are
7 // met:
8 //
9 //     * Redistributions of source code must retain the above copyright
10 // notice, this list of conditions and the following disclaimer.
11 //     * Redistributions in binary form must reproduce the above
12 // copyright notice, this list of conditions and the following disclaimer
13 // in the documentation and/or other materials provided with the
14 // distribution.
15 //     * Neither the name of Google Inc. nor the names of its
16 // contributors may be used to endorse or promote products derived from
17 // this software without specific prior written permission.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 
31 // Author: kenton@google.com (Kenton Varda)
32 //  Based on original Protocol Buffers design by
33 //  Sanjay Ghemawat, Jeff Dean, and others.
34 
35 #include <google/protobuf/compiler/java/java_primitive_field.h>
36 
37 #include <cstdint>
38 #include <map>
39 #include <string>
40 
41 #include <google/protobuf/stubs/logging.h>
42 #include <google/protobuf/stubs/common.h>
43 #include <google/protobuf/io/printer.h>
44 #include <google/protobuf/wire_format.h>
45 #include <google/protobuf/stubs/strutil.h>
46 #include <google/protobuf/compiler/java/java_context.h>
47 #include <google/protobuf/compiler/java/java_doc_comment.h>
48 #include <google/protobuf/compiler/java/java_helpers.h>
49 #include <google/protobuf/compiler/java/java_name_resolver.h>
50 
51 namespace google {
52 namespace protobuf {
53 namespace compiler {
54 namespace java {
55 
56 using internal::WireFormat;
57 
58 namespace {
59 
SetPrimitiveVariables(const FieldDescriptor * descriptor,int messageBitIndex,int builderBitIndex,const FieldGeneratorInfo * info,ClassNameResolver * name_resolver,std::map<std::string,std::string> * variables)60 void SetPrimitiveVariables(const FieldDescriptor* descriptor,
61                            int messageBitIndex, int builderBitIndex,
62                            const FieldGeneratorInfo* info,
63                            ClassNameResolver* name_resolver,
64                            std::map<std::string, std::string>* variables) {
65   SetCommonFieldVariables(descriptor, info, variables);
66   JavaType javaType = GetJavaType(descriptor);
67 
68   (*variables)["type"] = PrimitiveTypeName(javaType);
69   (*variables)["boxed_type"] = BoxedPrimitiveTypeName(javaType);
70   (*variables)["kt_type"] = KotlinTypeName(javaType);
71   (*variables)["field_type"] = (*variables)["type"];
72 
73   if (javaType == JAVATYPE_BOOLEAN || javaType == JAVATYPE_DOUBLE ||
74       javaType == JAVATYPE_FLOAT || javaType == JAVATYPE_INT ||
75       javaType == JAVATYPE_LONG) {
76     std::string capitalized_type = UnderscoresToCamelCase(
77         PrimitiveTypeName(javaType), /*cap_first_letter=*/true);
78     (*variables)["field_list_type"] =
79         "com.google.protobuf.Internal." + capitalized_type + "List";
80     (*variables)["empty_list"] = "empty" + capitalized_type + "List()";
81     (*variables)["create_list"] = "new" + capitalized_type + "List()";
82     (*variables)["mutable_copy_list"] =
83         "mutableCopy(" + (*variables)["name"] + "_)";
84     (*variables)["name_make_immutable"] =
85         (*variables)["name"] + "_.makeImmutable()";
86     (*variables)["repeated_get"] =
87         (*variables)["name"] + "_.get" + capitalized_type;
88     (*variables)["repeated_add"] =
89         (*variables)["name"] + "_.add" + capitalized_type;
90     (*variables)["repeated_set"] =
91         (*variables)["name"] + "_.set" + capitalized_type;
92   } else {
93     (*variables)["field_list_type"] =
94         "java.util.List<" + (*variables)["boxed_type"] + ">";
95     (*variables)["create_list"] =
96         "new java.util.ArrayList<" + (*variables)["boxed_type"] + ">()";
97     (*variables)["mutable_copy_list"] = "new java.util.ArrayList<" +
98                                         (*variables)["boxed_type"] + ">(" +
99                                         (*variables)["name"] + "_)";
100     (*variables)["empty_list"] = "java.util.Collections.emptyList()";
101     (*variables)["name_make_immutable"] =
102         (*variables)["name"] + "_ = java.util.Collections.unmodifiableList(" +
103         (*variables)["name"] + "_)";
104     (*variables)["repeated_get"] = (*variables)["name"] + "_.get";
105     (*variables)["repeated_add"] = (*variables)["name"] + "_.add";
106     (*variables)["repeated_set"] = (*variables)["name"] + "_.set";
107   }
108 
109   (*variables)["default"] = ImmutableDefaultValue(descriptor, name_resolver);
110   (*variables)["default_init"] =
111       IsDefaultValueJavaDefault(descriptor)
112           ? ""
113           : ("= " + ImmutableDefaultValue(descriptor, name_resolver));
114   (*variables)["capitalized_type"] =
115       GetCapitalizedType(descriptor, /* immutable = */ true);
116   (*variables)["tag"] =
117       StrCat(static_cast<int32_t>(WireFormat::MakeTag(descriptor)));
118   (*variables)["tag_size"] = StrCat(
119       WireFormat::TagSize(descriptor->number(), GetType(descriptor)));
120   if (IsReferenceType(GetJavaType(descriptor))) {
121     (*variables)["null_check"] =
122         "  if (value == null) {\n"
123         "    throw new NullPointerException();\n"
124         "  }\n";
125   } else {
126     (*variables)["null_check"] = "";
127   }
128   // TODO(birdo): Add @deprecated javadoc when generating javadoc is supported
129   // by the proto compiler
130   (*variables)["deprecation"] =
131       descriptor->options().deprecated() ? "@java.lang.Deprecated " : "";
132   (*variables)["kt_deprecation"] =
133       descriptor->options().deprecated()
134           ? "@kotlin.Deprecated(message = \"Field " + (*variables)["name"] +
135                 " is deprecated\") "
136           : "";
137   int fixed_size = FixedSize(GetType(descriptor));
138   if (fixed_size != -1) {
139     (*variables)["fixed_size"] = StrCat(fixed_size);
140   }
141   (*variables)["on_changed"] = "onChanged();";
142 
143   if (HasHasbit(descriptor)) {
144     // For singular messages and builders, one bit is used for the hasField bit.
145     (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex);
146     (*variables)["get_has_field_bit_builder"] = GenerateGetBit(builderBitIndex);
147 
148     // Note that these have a trailing ";".
149     (*variables)["set_has_field_bit_message"] =
150         GenerateSetBit(messageBitIndex) + ";";
151     (*variables)["set_has_field_bit_builder"] =
152         GenerateSetBit(builderBitIndex) + ";";
153     (*variables)["clear_has_field_bit_builder"] =
154         GenerateClearBit(builderBitIndex) + ";";
155 
156     (*variables)["is_field_present_message"] = GenerateGetBit(messageBitIndex);
157   } else {
158     (*variables)["set_has_field_bit_message"] = "";
159     (*variables)["set_has_field_bit_builder"] = "";
160     (*variables)["clear_has_field_bit_builder"] = "";
161 
162     switch (descriptor->type()) {
163       case FieldDescriptor::TYPE_BYTES:
164         (*variables)["is_field_present_message"] =
165             "!" + (*variables)["name"] + "_.isEmpty()";
166         break;
167       case FieldDescriptor::TYPE_FLOAT:
168         (*variables)["is_field_present_message"] =
169             "java.lang.Float.floatToRawIntBits(" + (*variables)["name"] +
170             "_) != 0";
171         break;
172       case FieldDescriptor::TYPE_DOUBLE:
173         (*variables)["is_field_present_message"] =
174             "java.lang.Double.doubleToRawLongBits(" + (*variables)["name"] +
175             "_) != 0";
176         break;
177       default:
178         (*variables)["is_field_present_message"] =
179             (*variables)["name"] + "_ != " + (*variables)["default"];
180         break;
181     }
182   }
183 
184   // For repeated builders, one bit is used for whether the array is immutable.
185   (*variables)["get_mutable_bit_builder"] = GenerateGetBit(builderBitIndex);
186   (*variables)["set_mutable_bit_builder"] = GenerateSetBit(builderBitIndex);
187   (*variables)["clear_mutable_bit_builder"] = GenerateClearBit(builderBitIndex);
188 
189   (*variables)["get_has_field_bit_from_local"] =
190       GenerateGetBitFromLocal(builderBitIndex);
191   (*variables)["set_has_field_bit_to_local"] =
192       GenerateSetBitToLocal(messageBitIndex);
193 }
194 
195 }  // namespace
196 
197 // ===================================================================
198 
ImmutablePrimitiveFieldGenerator(const FieldDescriptor * descriptor,int messageBitIndex,int builderBitIndex,Context * context)199 ImmutablePrimitiveFieldGenerator::ImmutablePrimitiveFieldGenerator(
200     const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex,
201     Context* context)
202     : descriptor_(descriptor), name_resolver_(context->GetNameResolver()) {
203   SetPrimitiveVariables(descriptor, messageBitIndex, builderBitIndex,
204                         context->GetFieldGeneratorInfo(descriptor),
205                         name_resolver_, &variables_);
206 }
207 
~ImmutablePrimitiveFieldGenerator()208 ImmutablePrimitiveFieldGenerator::~ImmutablePrimitiveFieldGenerator() {}
209 
GetNumBitsForMessage() const210 int ImmutablePrimitiveFieldGenerator::GetNumBitsForMessage() const {
211   return HasHasbit(descriptor_) ? 1 : 0;
212 }
213 
GetNumBitsForBuilder() const214 int ImmutablePrimitiveFieldGenerator::GetNumBitsForBuilder() const {
215   return GetNumBitsForMessage();
216 }
217 
GenerateInterfaceMembers(io::Printer * printer) const218 void ImmutablePrimitiveFieldGenerator::GenerateInterfaceMembers(
219     io::Printer* printer) const {
220   if (HasHazzer(descriptor_)) {
221     WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
222     printer->Print(variables_,
223                    "$deprecation$boolean has$capitalized_name$();\n");
224   }
225   WriteFieldAccessorDocComment(printer, descriptor_, GETTER);
226   printer->Print(variables_, "$deprecation$$type$ get$capitalized_name$();\n");
227 }
228 
GenerateMembers(io::Printer * printer) const229 void ImmutablePrimitiveFieldGenerator::GenerateMembers(
230     io::Printer* printer) const {
231   printer->Print(variables_, "private $field_type$ $name$_;\n");
232   PrintExtraFieldInfo(variables_, printer);
233   if (HasHazzer(descriptor_)) {
234     WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
235     printer->Print(
236         variables_,
237         "@java.lang.Override\n"
238         "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
239         "  return $get_has_field_bit_message$;\n"
240         "}\n");
241     printer->Annotate("{", "}", descriptor_);
242   }
243 
244   WriteFieldAccessorDocComment(printer, descriptor_, GETTER);
245   printer->Print(variables_,
246                  "@java.lang.Override\n"
247                  "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
248                  "  return $name$_;\n"
249                  "}\n");
250   printer->Annotate("{", "}", descriptor_);
251 }
252 
GenerateBuilderMembers(io::Printer * printer) const253 void ImmutablePrimitiveFieldGenerator::GenerateBuilderMembers(
254     io::Printer* printer) const {
255   printer->Print(variables_, "private $field_type$ $name$_ $default_init$;\n");
256 
257   if (HasHazzer(descriptor_)) {
258     WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
259     printer->Print(
260         variables_,
261         "@java.lang.Override\n"
262         "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
263         "  return $get_has_field_bit_builder$;\n"
264         "}\n");
265     printer->Annotate("{", "}", descriptor_);
266   }
267 
268   WriteFieldAccessorDocComment(printer, descriptor_, GETTER);
269   printer->Print(variables_,
270                  "@java.lang.Override\n"
271                  "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
272                  "  return $name$_;\n"
273                  "}\n");
274   printer->Annotate("{", "}", descriptor_);
275 
276   WriteFieldAccessorDocComment(printer, descriptor_, SETTER,
277                                /* builder */ true);
278   printer->Print(variables_,
279                  "$deprecation$public Builder "
280                  "${$set$capitalized_name$$}$($type$ value) {\n"
281                  "$null_check$"
282                  "  $set_has_field_bit_builder$\n"
283                  "  $name$_ = value;\n"
284                  "  $on_changed$\n"
285                  "  return this;\n"
286                  "}\n");
287   printer->Annotate("{", "}", descriptor_);
288 
289   WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
290                                /* builder */ true);
291   printer->Print(
292       variables_,
293       "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n"
294       "  $clear_has_field_bit_builder$\n");
295   printer->Annotate("{", "}", descriptor_);
296   JavaType type = GetJavaType(descriptor_);
297   if (type == JAVATYPE_STRING || type == JAVATYPE_BYTES) {
298     // The default value is not a simple literal so we want to avoid executing
299     // it multiple times.  Instead, get the default out of the default instance.
300     printer->Print(
301         variables_,
302         "  $name$_ = getDefaultInstance().get$capitalized_name$();\n");
303   } else {
304     printer->Print(variables_, "  $name$_ = $default$;\n");
305   }
306   printer->Print(variables_,
307                  "  $on_changed$\n"
308                  "  return this;\n"
309                  "}\n");
310 }
311 
GenerateKotlinDslMembers(io::Printer * printer) const312 void ImmutablePrimitiveFieldGenerator::GenerateKotlinDslMembers(
313     io::Printer* printer) const {
314   WriteFieldDocComment(printer, descriptor_);
315   printer->Print(variables_,
316                  "$kt_deprecation$public var $kt_name$: $kt_type$\n"
317                  "  @JvmName(\"${$get$kt_capitalized_name$$}$\")\n"
318                  "  get() = $kt_dsl_builder$.${$get$capitalized_name$$}$()\n"
319                  "  @JvmName(\"${$set$kt_capitalized_name$$}$\")\n"
320                  "  set(value) {\n"
321                  "    $kt_dsl_builder$.${$set$capitalized_name$$}$(value)\n"
322                  "  }\n");
323 
324   WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
325                                /* builder */ false);
326   printer->Print(variables_,
327                  "public fun ${$clear$kt_capitalized_name$$}$() {\n"
328                  "  $kt_dsl_builder$.${$clear$capitalized_name$$}$()\n"
329                  "}\n");
330 
331   if (HasHazzer(descriptor_)) {
332     WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
333     printer->Print(
334         variables_,
335         "public fun ${$has$kt_capitalized_name$$}$(): kotlin.Boolean {\n"
336         "  return $kt_dsl_builder$.${$has$capitalized_name$$}$()\n"
337         "}\n");
338   }
339 }
340 
GenerateFieldBuilderInitializationCode(io::Printer * printer) const341 void ImmutablePrimitiveFieldGenerator::GenerateFieldBuilderInitializationCode(
342     io::Printer* printer) const {
343   // noop for primitives
344 }
345 
GenerateInitializationCode(io::Printer * printer) const346 void ImmutablePrimitiveFieldGenerator::GenerateInitializationCode(
347     io::Printer* printer) const {
348   if (!IsDefaultValueJavaDefault(descriptor_)) {
349     printer->Print(variables_, "$name$_ = $default$;\n");
350   }
351 }
352 
GenerateBuilderClearCode(io::Printer * printer) const353 void ImmutablePrimitiveFieldGenerator::GenerateBuilderClearCode(
354     io::Printer* printer) const {
355   printer->Print(variables_,
356                  "$name$_ = $default$;\n"
357                  "$clear_has_field_bit_builder$\n");
358 }
359 
GenerateMergingCode(io::Printer * printer) const360 void ImmutablePrimitiveFieldGenerator::GenerateMergingCode(
361     io::Printer* printer) const {
362   if (HasHazzer(descriptor_)) {
363     printer->Print(variables_,
364                    "if (other.has$capitalized_name$()) {\n"
365                    "  set$capitalized_name$(other.get$capitalized_name$());\n"
366                    "}\n");
367   } else {
368     printer->Print(variables_,
369                    "if (other.get$capitalized_name$() != $default$) {\n"
370                    "  set$capitalized_name$(other.get$capitalized_name$());\n"
371                    "}\n");
372   }
373 }
374 
GenerateBuildingCode(io::Printer * printer) const375 void ImmutablePrimitiveFieldGenerator::GenerateBuildingCode(
376     io::Printer* printer) const {
377   if (HasHazzer(descriptor_)) {
378     if (IsDefaultValueJavaDefault(descriptor_)) {
379       printer->Print(variables_,
380                      "if ($get_has_field_bit_from_local$) {\n"
381                      "  result.$name$_ = $name$_;\n"
382                      "  $set_has_field_bit_to_local$;\n"
383                      "}\n");
384     } else {
385       printer->Print(variables_,
386                      "if ($get_has_field_bit_from_local$) {\n"
387                      "  $set_has_field_bit_to_local$;\n"
388                      "}\n"
389                      "result.$name$_ = $name$_;\n");
390     }
391   } else {
392     printer->Print(variables_, "result.$name$_ = $name$_;\n");
393   }
394 }
395 
GenerateBuilderParsingCode(io::Printer * printer) const396 void ImmutablePrimitiveFieldGenerator::GenerateBuilderParsingCode(
397     io::Printer* printer) const {
398   printer->Print(variables_,
399                  "$name$_ = input.read$capitalized_type$();\n"
400                  "$set_has_field_bit_builder$\n");
401 }
402 
GenerateSerializationCode(io::Printer * printer) const403 void ImmutablePrimitiveFieldGenerator::GenerateSerializationCode(
404     io::Printer* printer) const {
405   printer->Print(variables_,
406                  "if ($is_field_present_message$) {\n"
407                  "  output.write$capitalized_type$($number$, $name$_);\n"
408                  "}\n");
409 }
410 
GenerateSerializedSizeCode(io::Printer * printer) const411 void ImmutablePrimitiveFieldGenerator::GenerateSerializedSizeCode(
412     io::Printer* printer) const {
413   printer->Print(variables_,
414                  "if ($is_field_present_message$) {\n"
415                  "  size += com.google.protobuf.CodedOutputStream\n"
416                  "    .compute$capitalized_type$Size($number$, $name$_);\n"
417                  "}\n");
418 }
419 
GenerateEqualsCode(io::Printer * printer) const420 void ImmutablePrimitiveFieldGenerator::GenerateEqualsCode(
421     io::Printer* printer) const {
422   switch (GetJavaType(descriptor_)) {
423     case JAVATYPE_INT:
424     case JAVATYPE_LONG:
425     case JAVATYPE_BOOLEAN:
426       printer->Print(variables_,
427                      "if (get$capitalized_name$()\n"
428                      "    != other.get$capitalized_name$()) return false;\n");
429       break;
430 
431     case JAVATYPE_FLOAT:
432       printer->Print(
433           variables_,
434           "if (java.lang.Float.floatToIntBits(get$capitalized_name$())\n"
435           "    != java.lang.Float.floatToIntBits(\n"
436           "        other.get$capitalized_name$())) return false;\n");
437       break;
438 
439     case JAVATYPE_DOUBLE:
440       printer->Print(
441           variables_,
442           "if (java.lang.Double.doubleToLongBits(get$capitalized_name$())\n"
443           "    != java.lang.Double.doubleToLongBits(\n"
444           "        other.get$capitalized_name$())) return false;\n");
445       break;
446 
447     case JAVATYPE_STRING:
448     case JAVATYPE_BYTES:
449       printer->Print(
450           variables_,
451           "if (!get$capitalized_name$()\n"
452           "    .equals(other.get$capitalized_name$())) return false;\n");
453       break;
454 
455     case JAVATYPE_ENUM:
456     case JAVATYPE_MESSAGE:
457     default:
458       GOOGLE_LOG(FATAL) << "Can't get here.";
459       break;
460   }
461 }
462 
GenerateHashCode(io::Printer * printer) const463 void ImmutablePrimitiveFieldGenerator::GenerateHashCode(
464     io::Printer* printer) const {
465   printer->Print(variables_, "hash = (37 * hash) + $constant_name$;\n");
466   switch (GetJavaType(descriptor_)) {
467     case JAVATYPE_INT:
468       printer->Print(variables_,
469                      "hash = (53 * hash) + get$capitalized_name$();\n");
470       break;
471 
472     case JAVATYPE_LONG:
473       printer->Print(
474           variables_,
475           "hash = (53 * hash) + com.google.protobuf.Internal.hashLong(\n"
476           "    get$capitalized_name$());\n");
477       break;
478 
479     case JAVATYPE_BOOLEAN:
480       printer->Print(
481           variables_,
482           "hash = (53 * hash) + com.google.protobuf.Internal.hashBoolean(\n"
483           "    get$capitalized_name$());\n");
484       break;
485 
486     case JAVATYPE_FLOAT:
487       printer->Print(variables_,
488                      "hash = (53 * hash) + java.lang.Float.floatToIntBits(\n"
489                      "    get$capitalized_name$());\n");
490       break;
491 
492     case JAVATYPE_DOUBLE:
493       printer->Print(
494           variables_,
495           "hash = (53 * hash) + com.google.protobuf.Internal.hashLong(\n"
496           "    java.lang.Double.doubleToLongBits(get$capitalized_name$()));\n");
497       break;
498 
499     case JAVATYPE_STRING:
500     case JAVATYPE_BYTES:
501       printer->Print(
502           variables_,
503           "hash = (53 * hash) + get$capitalized_name$().hashCode();\n");
504       break;
505 
506     case JAVATYPE_ENUM:
507     case JAVATYPE_MESSAGE:
508     default:
509       GOOGLE_LOG(FATAL) << "Can't get here.";
510       break;
511   }
512 }
513 
GetBoxedType() const514 std::string ImmutablePrimitiveFieldGenerator::GetBoxedType() const {
515   return BoxedPrimitiveTypeName(GetJavaType(descriptor_));
516 }
517 
518 // ===================================================================
519 
ImmutablePrimitiveOneofFieldGenerator(const FieldDescriptor * descriptor,int messageBitIndex,int builderBitIndex,Context * context)520 ImmutablePrimitiveOneofFieldGenerator::ImmutablePrimitiveOneofFieldGenerator(
521     const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex,
522     Context* context)
523     : ImmutablePrimitiveFieldGenerator(descriptor, messageBitIndex,
524                                        builderBitIndex, context) {
525   const OneofGeneratorInfo* info =
526       context->GetOneofGeneratorInfo(descriptor->containing_oneof());
527   SetCommonOneofVariables(descriptor, info, &variables_);
528 }
529 
530 ImmutablePrimitiveOneofFieldGenerator::
~ImmutablePrimitiveOneofFieldGenerator()531     ~ImmutablePrimitiveOneofFieldGenerator() {}
532 
GenerateMembers(io::Printer * printer) const533 void ImmutablePrimitiveOneofFieldGenerator::GenerateMembers(
534     io::Printer* printer) const {
535   PrintExtraFieldInfo(variables_, printer);
536   GOOGLE_DCHECK(HasHazzer(descriptor_));
537   WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
538   printer->Print(variables_,
539                  "@java.lang.Override\n"
540                  "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
541                  "  return $has_oneof_case_message$;\n"
542                  "}\n");
543   printer->Annotate("{", "}", descriptor_);
544 
545   WriteFieldAccessorDocComment(printer, descriptor_, GETTER);
546   printer->Print(variables_,
547                  "@java.lang.Override\n"
548                  "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
549                  "  if ($has_oneof_case_message$) {\n"
550                  "    return ($boxed_type$) $oneof_name$_;\n"
551                  "  }\n"
552                  "  return $default$;\n"
553                  "}\n");
554   printer->Annotate("{", "}", descriptor_);
555 }
556 
GenerateBuilderMembers(io::Printer * printer) const557 void ImmutablePrimitiveOneofFieldGenerator::GenerateBuilderMembers(
558     io::Printer* printer) const {
559   GOOGLE_DCHECK(HasHazzer(descriptor_));
560   WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
561   printer->Print(variables_,
562                  "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
563                  "  return $has_oneof_case_message$;\n"
564                  "}\n");
565   printer->Annotate("{", "}", descriptor_);
566 
567   WriteFieldAccessorDocComment(printer, descriptor_, GETTER);
568   printer->Print(variables_,
569                  "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
570                  "  if ($has_oneof_case_message$) {\n"
571                  "    return ($boxed_type$) $oneof_name$_;\n"
572                  "  }\n"
573                  "  return $default$;\n"
574                  "}\n");
575   printer->Annotate("{", "}", descriptor_);
576 
577   WriteFieldAccessorDocComment(printer, descriptor_, SETTER,
578                                /* builder */ true);
579   printer->Print(variables_,
580                  "$deprecation$public Builder "
581                  "${$set$capitalized_name$$}$($type$ value) {\n"
582                  "$null_check$"
583                  "  $set_oneof_case_message$;\n"
584                  "  $oneof_name$_ = value;\n"
585                  "  $on_changed$\n"
586                  "  return this;\n"
587                  "}\n");
588   printer->Annotate("{", "}", descriptor_);
589 
590   WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
591                                /* builder */ true);
592   printer->Print(
593       variables_,
594       "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n"
595       "  if ($has_oneof_case_message$) {\n"
596       "    $clear_oneof_case_message$;\n"
597       "    $oneof_name$_ = null;\n"
598       "    $on_changed$\n"
599       "  }\n"
600       "  return this;\n"
601       "}\n");
602   printer->Annotate("{", "}", descriptor_);
603 }
604 
GenerateBuilderClearCode(io::Printer * printer) const605 void ImmutablePrimitiveOneofFieldGenerator::GenerateBuilderClearCode(
606     io::Printer* printer) const {
607   // No-Op: When a primitive field is in a oneof, clearing the oneof clears that
608   // field.
609 }
610 
GenerateBuildingCode(io::Printer * printer) const611 void ImmutablePrimitiveOneofFieldGenerator::GenerateBuildingCode(
612     io::Printer* printer) const {
613   printer->Print(variables_,
614                  "if ($has_oneof_case_message$) {\n"
615                  "  result.$oneof_name$_ = $oneof_name$_;\n"
616                  "}\n");
617 }
618 
GenerateMergingCode(io::Printer * printer) const619 void ImmutablePrimitiveOneofFieldGenerator::GenerateMergingCode(
620     io::Printer* printer) const {
621   printer->Print(variables_,
622                  "set$capitalized_name$(other.get$capitalized_name$());\n");
623 }
624 
GenerateBuilderParsingCode(io::Printer * printer) const625 void ImmutablePrimitiveOneofFieldGenerator::GenerateBuilderParsingCode(
626     io::Printer* printer) const {
627   printer->Print(variables_,
628                  "$oneof_name$_ = input.read$capitalized_type$();\n"
629                  "$set_oneof_case_message$;\n");
630 }
631 
GenerateSerializationCode(io::Printer * printer) const632 void ImmutablePrimitiveOneofFieldGenerator::GenerateSerializationCode(
633     io::Printer* printer) const {
634   printer->Print(variables_,
635                  "if ($has_oneof_case_message$) {\n"
636                  "  output.write$capitalized_type$(\n");
637   // $type$ and $boxed_type$ is the same for bytes fields so we don't need to
638   // do redundant casts.
639   if (GetJavaType(descriptor_) == JAVATYPE_BYTES) {
640     printer->Print(variables_, "      $number$, ($type$) $oneof_name$_);\n");
641   } else {
642     printer->Print(
643         variables_,
644         "      $number$, ($type$)(($boxed_type$) $oneof_name$_));\n");
645   }
646   printer->Print("}\n");
647 }
648 
GenerateSerializedSizeCode(io::Printer * printer) const649 void ImmutablePrimitiveOneofFieldGenerator::GenerateSerializedSizeCode(
650     io::Printer* printer) const {
651   printer->Print(variables_,
652                  "if ($has_oneof_case_message$) {\n"
653                  "  size += com.google.protobuf.CodedOutputStream\n"
654                  "    .compute$capitalized_type$Size(\n");
655   // $type$ and $boxed_type$ is the same for bytes fields so we don't need to
656   // do redundant casts.
657   if (GetJavaType(descriptor_) == JAVATYPE_BYTES) {
658     printer->Print(variables_, "        $number$, ($type$) $oneof_name$_);\n");
659   } else {
660     printer->Print(
661         variables_,
662         "        $number$, ($type$)(($boxed_type$) $oneof_name$_));\n");
663   }
664   printer->Print("}\n");
665 }
666 
667 // ===================================================================
668 
669 RepeatedImmutablePrimitiveFieldGenerator::
RepeatedImmutablePrimitiveFieldGenerator(const FieldDescriptor * descriptor,int messageBitIndex,int builderBitIndex,Context * context)670     RepeatedImmutablePrimitiveFieldGenerator(const FieldDescriptor* descriptor,
671                                              int messageBitIndex,
672                                              int builderBitIndex,
673                                              Context* context)
674     : descriptor_(descriptor), name_resolver_(context->GetNameResolver()) {
675   SetPrimitiveVariables(descriptor, messageBitIndex, builderBitIndex,
676                         context->GetFieldGeneratorInfo(descriptor),
677                         name_resolver_, &variables_);
678 }
679 
680 RepeatedImmutablePrimitiveFieldGenerator::
~RepeatedImmutablePrimitiveFieldGenerator()681     ~RepeatedImmutablePrimitiveFieldGenerator() {}
682 
GetNumBitsForMessage() const683 int RepeatedImmutablePrimitiveFieldGenerator::GetNumBitsForMessage() const {
684   return 0;
685 }
686 
GetNumBitsForBuilder() const687 int RepeatedImmutablePrimitiveFieldGenerator::GetNumBitsForBuilder() const {
688   return 1;
689 }
690 
GenerateInterfaceMembers(io::Printer * printer) const691 void RepeatedImmutablePrimitiveFieldGenerator::GenerateInterfaceMembers(
692     io::Printer* printer) const {
693   WriteFieldAccessorDocComment(printer, descriptor_, LIST_GETTER);
694   printer->Print(variables_,
695                  "$deprecation$java.util.List<$boxed_type$> "
696                  "get$capitalized_name$List();\n");
697   WriteFieldAccessorDocComment(printer, descriptor_, LIST_COUNT);
698   printer->Print(variables_,
699                  "$deprecation$int get$capitalized_name$Count();\n");
700   WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_GETTER);
701   printer->Print(variables_,
702                  "$deprecation$$type$ get$capitalized_name$(int index);\n");
703 }
704 
GenerateMembers(io::Printer * printer) const705 void RepeatedImmutablePrimitiveFieldGenerator::GenerateMembers(
706     io::Printer* printer) const {
707   printer->Print(variables_, "private $field_list_type$ $name$_;\n");
708   PrintExtraFieldInfo(variables_, printer);
709   WriteFieldAccessorDocComment(printer, descriptor_, LIST_GETTER);
710   printer->Print(variables_,
711                  "@java.lang.Override\n"
712                  "$deprecation$public java.util.List<$boxed_type$>\n"
713                  "    ${$get$capitalized_name$List$}$() {\n"
714                  "  return $name$_;\n"  // note:  unmodifiable list
715                  "}\n");
716   printer->Annotate("{", "}", descriptor_);
717   WriteFieldAccessorDocComment(printer, descriptor_, LIST_COUNT);
718   printer->Print(
719       variables_,
720       "$deprecation$public int ${$get$capitalized_name$Count$}$() {\n"
721       "  return $name$_.size();\n"
722       "}\n");
723   printer->Annotate("{", "}", descriptor_);
724   WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_GETTER);
725   printer->Print(
726       variables_,
727       "$deprecation$public $type$ ${$get$capitalized_name$$}$(int index) {\n"
728       "  return $repeated_get$(index);\n"
729       "}\n");
730   printer->Annotate("{", "}", descriptor_);
731 
732   if (descriptor_->is_packed()) {
733     printer->Print(variables_,
734                    "private int $name$MemoizedSerializedSize = -1;\n");
735   }
736 }
737 
GenerateBuilderMembers(io::Printer * printer) const738 void RepeatedImmutablePrimitiveFieldGenerator::GenerateBuilderMembers(
739     io::Printer* printer) const {
740   // One field is the list and the bit field keeps track of whether the
741   // list is immutable. If it's immutable, the invariant is that it must
742   // either an instance of Collections.emptyList() or it's an ArrayList
743   // wrapped in a Collections.unmodifiableList() wrapper and nobody else has
744   // a reference to the underlying ArrayList. This invariant allows us to
745   // share instances of lists between protocol buffers avoiding expensive
746   // memory allocations. Note, immutable is a strong guarantee here -- not
747   // just that the list cannot be modified via the reference but that the
748   // list can never be modified.
749   printer->Print(variables_,
750                  "private $field_list_type$ $name$_ = $empty_list$;\n");
751 
752   printer->Print(variables_,
753                  "private void ensure$capitalized_name$IsMutable() {\n"
754                  "  if (!$get_mutable_bit_builder$) {\n"
755                  "    $name$_ = $mutable_copy_list$;\n"
756                  "    $set_mutable_bit_builder$;\n"
757                  "   }\n"
758                  "}\n");
759 
760   // Note:  We return an unmodifiable list because otherwise the caller
761   //   could hold on to the returned list and modify it after the message
762   //   has been built, thus mutating the message which is supposed to be
763   //   immutable.
764   WriteFieldAccessorDocComment(printer, descriptor_, LIST_GETTER);
765   printer->Print(
766       variables_,
767       "$deprecation$public java.util.List<$boxed_type$>\n"
768       "    ${$get$capitalized_name$List$}$() {\n"
769       "  return $get_mutable_bit_builder$ ?\n"
770       "           java.util.Collections.unmodifiableList($name$_) : $name$_;\n"
771       "}\n");
772   printer->Annotate("{", "}", descriptor_);
773   WriteFieldAccessorDocComment(printer, descriptor_, LIST_COUNT);
774   printer->Print(
775       variables_,
776       "$deprecation$public int ${$get$capitalized_name$Count$}$() {\n"
777       "  return $name$_.size();\n"
778       "}\n");
779   printer->Annotate("{", "}", descriptor_);
780   WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_GETTER);
781   printer->Print(
782       variables_,
783       "$deprecation$public $type$ ${$get$capitalized_name$$}$(int index) {\n"
784       "  return $repeated_get$(index);\n"
785       "}\n");
786   printer->Annotate("{", "}", descriptor_);
787   WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_SETTER,
788                                /* builder */ true);
789   printer->Print(variables_,
790                  "$deprecation$public Builder ${$set$capitalized_name$$}$(\n"
791                  "    int index, $type$ value) {\n"
792                  "$null_check$"
793                  "  ensure$capitalized_name$IsMutable();\n"
794                  "  $repeated_set$(index, value);\n"
795                  "  $on_changed$\n"
796                  "  return this;\n"
797                  "}\n");
798   printer->Annotate("{", "}", descriptor_);
799   WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER,
800                                /* builder */ true);
801   printer->Print(variables_,
802                  "$deprecation$public Builder "
803                  "${$add$capitalized_name$$}$($type$ value) {\n"
804                  "$null_check$"
805                  "  ensure$capitalized_name$IsMutable();\n"
806                  "  $repeated_add$(value);\n"
807                  "  $on_changed$\n"
808                  "  return this;\n"
809                  "}\n");
810   printer->Annotate("{", "}", descriptor_);
811   WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER,
812                                /* builder */ true);
813   printer->Print(variables_,
814                  "$deprecation$public Builder ${$addAll$capitalized_name$$}$(\n"
815                  "    java.lang.Iterable<? extends $boxed_type$> values) {\n"
816                  "  ensure$capitalized_name$IsMutable();\n"
817                  "  com.google.protobuf.AbstractMessageLite.Builder.addAll(\n"
818                  "      values, $name$_);\n"
819                  "  $on_changed$\n"
820                  "  return this;\n"
821                  "}\n");
822   printer->Annotate("{", "}", descriptor_);
823   WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
824                                /* builder */ true);
825   printer->Print(
826       variables_,
827       "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n"
828       "  $name$_ = $empty_list$;\n"
829       "  $clear_mutable_bit_builder$;\n"
830       "  $on_changed$\n"
831       "  return this;\n"
832       "}\n");
833   printer->Annotate("{", "}", descriptor_);
834 }
835 
GenerateKotlinDslMembers(io::Printer * printer) const836 void RepeatedImmutablePrimitiveFieldGenerator::GenerateKotlinDslMembers(
837     io::Printer* printer) const {
838   printer->Print(
839       variables_,
840       "/**\n"
841       " * An uninstantiable, behaviorless type to represent the field in\n"
842       " * generics.\n"
843       " */\n"
844       "@kotlin.OptIn"
845       "(com.google.protobuf.kotlin.OnlyForUseByGeneratedProtoCode::class)\n"
846       "public class ${$$kt_capitalized_name$Proxy$}$ private constructor()"
847       " : com.google.protobuf.kotlin.DslProxy()\n");
848 
849   WriteFieldDocComment(printer, descriptor_);
850   printer->Print(variables_,
851                  "$kt_deprecation$ public val $kt_name$: "
852                  "com.google.protobuf.kotlin.DslList"
853                  "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>\n"
854                  "  @kotlin.jvm.JvmSynthetic\n"
855                  "  get() = com.google.protobuf.kotlin.DslList(\n"
856                  "    $kt_dsl_builder$.${$get$capitalized_name$List$}$()\n"
857                  "  )\n");
858 
859   WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER,
860                                /* builder */ false);
861   printer->Print(variables_,
862                  "@kotlin.jvm.JvmSynthetic\n"
863                  "@kotlin.jvm.JvmName(\"add$kt_capitalized_name$\")\n"
864                  "public fun com.google.protobuf.kotlin.DslList"
865                  "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
866                  "add(value: $kt_type$) {\n"
867                  "  $kt_dsl_builder$.${$add$capitalized_name$$}$(value)\n"
868                  "}");
869 
870   WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER,
871                                /* builder */ false);
872   printer->Print(variables_,
873                  "@kotlin.jvm.JvmSynthetic\n"
874                  "@kotlin.jvm.JvmName(\"plusAssign$kt_capitalized_name$\")\n"
875                  "@Suppress(\"NOTHING_TO_INLINE\")\n"
876                  "public inline operator fun com.google.protobuf.kotlin.DslList"
877                  "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
878                  "plusAssign(value: $kt_type$) {\n"
879                  "  add(value)\n"
880                  "}");
881 
882   WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER,
883                                /* builder */ false);
884   printer->Print(variables_,
885                  "@kotlin.jvm.JvmSynthetic\n"
886                  "@kotlin.jvm.JvmName(\"addAll$kt_capitalized_name$\")\n"
887                  "public fun com.google.protobuf.kotlin.DslList"
888                  "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
889                  "addAll(values: kotlin.collections.Iterable<$kt_type$>) {\n"
890                  "  $kt_dsl_builder$.${$addAll$capitalized_name$$}$(values)\n"
891                  "}");
892 
893   WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER,
894                                /* builder */ false);
895   printer->Print(
896       variables_,
897       "@kotlin.jvm.JvmSynthetic\n"
898       "@kotlin.jvm.JvmName(\"plusAssignAll$kt_capitalized_name$\")\n"
899       "@Suppress(\"NOTHING_TO_INLINE\")\n"
900       "public inline operator fun com.google.protobuf.kotlin.DslList"
901       "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
902       "plusAssign(values: kotlin.collections.Iterable<$kt_type$>) {\n"
903       "  addAll(values)\n"
904       "}");
905 
906   WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_SETTER,
907                                /* builder */ false);
908   printer->Print(
909       variables_,
910       "@kotlin.jvm.JvmSynthetic\n"
911       "@kotlin.jvm.JvmName(\"set$kt_capitalized_name$\")\n"
912       "public operator fun com.google.protobuf.kotlin.DslList"
913       "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
914       "set(index: kotlin.Int, value: $kt_type$) {\n"
915       "  $kt_dsl_builder$.${$set$capitalized_name$$}$(index, value)\n"
916       "}");
917 
918   WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
919                                /* builder */ false);
920   printer->Print(variables_,
921                  "@kotlin.jvm.JvmSynthetic\n"
922                  "@kotlin.jvm.JvmName(\"clear$kt_capitalized_name$\")\n"
923                  "public fun com.google.protobuf.kotlin.DslList"
924                  "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
925                  "clear() {\n"
926                  "  $kt_dsl_builder$.${$clear$capitalized_name$$}$()\n"
927                  "}");
928 }
929 
930 void RepeatedImmutablePrimitiveFieldGenerator::
GenerateFieldBuilderInitializationCode(io::Printer * printer) const931     GenerateFieldBuilderInitializationCode(io::Printer* printer) const {
932   // noop for primitives
933 }
934 
GenerateInitializationCode(io::Printer * printer) const935 void RepeatedImmutablePrimitiveFieldGenerator::GenerateInitializationCode(
936     io::Printer* printer) const {
937   printer->Print(variables_, "$name$_ = $empty_list$;\n");
938 }
939 
GenerateBuilderClearCode(io::Printer * printer) const940 void RepeatedImmutablePrimitiveFieldGenerator::GenerateBuilderClearCode(
941     io::Printer* printer) const {
942   printer->Print(variables_,
943                  "$name$_ = $empty_list$;\n"
944                  "$clear_mutable_bit_builder$;\n");
945 }
946 
GenerateMergingCode(io::Printer * printer) const947 void RepeatedImmutablePrimitiveFieldGenerator::GenerateMergingCode(
948     io::Printer* printer) const {
949   // The code below does two optimizations:
950   //   1. If the other list is empty, there's nothing to do. This ensures we
951   //      don't allocate a new array if we already have an immutable one.
952   //   2. If the other list is non-empty and our current list is empty, we can
953   //      reuse the other list which is guaranteed to be immutable.
954   printer->Print(variables_,
955                  "if (!other.$name$_.isEmpty()) {\n"
956                  "  if ($name$_.isEmpty()) {\n"
957                  "    $name$_ = other.$name$_;\n"
958                  "    $clear_mutable_bit_builder$;\n"
959                  "  } else {\n"
960                  "    ensure$capitalized_name$IsMutable();\n"
961                  "    $name$_.addAll(other.$name$_);\n"
962                  "  }\n"
963                  "  $on_changed$\n"
964                  "}\n");
965 }
966 
GenerateBuildingCode(io::Printer * printer) const967 void RepeatedImmutablePrimitiveFieldGenerator::GenerateBuildingCode(
968     io::Printer* printer) const {
969   // The code below ensures that the result has an immutable list. If our
970   // list is immutable, we can just reuse it. If not, we make it immutable.
971   printer->Print(variables_,
972                  "if ($get_mutable_bit_builder$) {\n"
973                  "  $name_make_immutable$;\n"
974                  "  $clear_mutable_bit_builder$;\n"
975                  "}\n"
976                  "result.$name$_ = $name$_;\n");
977 }
978 
GenerateBuilderParsingCode(io::Printer * printer) const979 void RepeatedImmutablePrimitiveFieldGenerator::GenerateBuilderParsingCode(
980     io::Printer* printer) const {
981   printer->Print(variables_,
982                  "$type$ v = input.read$capitalized_type$();\n"
983                  "ensure$capitalized_name$IsMutable();\n"
984                  "$repeated_add$(v);\n");
985 }
986 
987 void RepeatedImmutablePrimitiveFieldGenerator::
GenerateBuilderParsingCodeFromPacked(io::Printer * printer) const988     GenerateBuilderParsingCodeFromPacked(io::Printer* printer) const {
989   printer->Print(variables_,
990                  "int length = input.readRawVarint32();\n"
991                  "int limit = input.pushLimit(length);\n"
992                  "ensure$capitalized_name$IsMutable();\n"
993                  "while (input.getBytesUntilLimit() > 0) {\n"
994                  "  $repeated_add$(input.read$capitalized_type$());\n"
995                  "}\n"
996                  "input.popLimit(limit);\n");
997 }
998 
GenerateSerializationCode(io::Printer * printer) const999 void RepeatedImmutablePrimitiveFieldGenerator::GenerateSerializationCode(
1000     io::Printer* printer) const {
1001   if (descriptor_->is_packed()) {
1002     // We invoke getSerializedSize in writeTo for messages that have packed
1003     // fields in ImmutableMessageGenerator::GenerateMessageSerializationMethods.
1004     // That makes it safe to rely on the memoized size here.
1005     printer->Print(variables_,
1006                    "if (get$capitalized_name$List().size() > 0) {\n"
1007                    "  output.writeUInt32NoTag($tag$);\n"
1008                    "  output.writeUInt32NoTag($name$MemoizedSerializedSize);\n"
1009                    "}\n"
1010                    "for (int i = 0; i < $name$_.size(); i++) {\n"
1011                    "  output.write$capitalized_type$NoTag($repeated_get$(i));\n"
1012                    "}\n");
1013   } else {
1014     printer->Print(
1015         variables_,
1016         "for (int i = 0; i < $name$_.size(); i++) {\n"
1017         "  output.write$capitalized_type$($number$, $repeated_get$(i));\n"
1018         "}\n");
1019   }
1020 }
1021 
GenerateSerializedSizeCode(io::Printer * printer) const1022 void RepeatedImmutablePrimitiveFieldGenerator::GenerateSerializedSizeCode(
1023     io::Printer* printer) const {
1024   printer->Print(variables_,
1025                  "{\n"
1026                  "  int dataSize = 0;\n");
1027   printer->Indent();
1028 
1029   if (FixedSize(GetType(descriptor_)) == -1) {
1030     printer->Print(
1031         variables_,
1032         "for (int i = 0; i < $name$_.size(); i++) {\n"
1033         "  dataSize += com.google.protobuf.CodedOutputStream\n"
1034         "    .compute$capitalized_type$SizeNoTag($repeated_get$(i));\n"
1035         "}\n");
1036   } else {
1037     printer->Print(
1038         variables_,
1039         "dataSize = $fixed_size$ * get$capitalized_name$List().size();\n");
1040   }
1041 
1042   printer->Print("size += dataSize;\n");
1043 
1044   if (descriptor_->is_packed()) {
1045     printer->Print(variables_,
1046                    "if (!get$capitalized_name$List().isEmpty()) {\n"
1047                    "  size += $tag_size$;\n"
1048                    "  size += com.google.protobuf.CodedOutputStream\n"
1049                    "      .computeInt32SizeNoTag(dataSize);\n"
1050                    "}\n");
1051   } else {
1052     printer->Print(
1053         variables_,
1054         "size += $tag_size$ * get$capitalized_name$List().size();\n");
1055   }
1056 
1057   // cache the data size for packed fields.
1058   if (descriptor_->is_packed()) {
1059     printer->Print(variables_, "$name$MemoizedSerializedSize = dataSize;\n");
1060   }
1061 
1062   printer->Outdent();
1063   printer->Print("}\n");
1064 }
1065 
GenerateEqualsCode(io::Printer * printer) const1066 void RepeatedImmutablePrimitiveFieldGenerator::GenerateEqualsCode(
1067     io::Printer* printer) const {
1068   printer->Print(
1069       variables_,
1070       "if (!get$capitalized_name$List()\n"
1071       "    .equals(other.get$capitalized_name$List())) return false;\n");
1072 }
1073 
GenerateHashCode(io::Printer * printer) const1074 void RepeatedImmutablePrimitiveFieldGenerator::GenerateHashCode(
1075     io::Printer* printer) const {
1076   printer->Print(
1077       variables_,
1078       "if (get$capitalized_name$Count() > 0) {\n"
1079       "  hash = (37 * hash) + $constant_name$;\n"
1080       "  hash = (53 * hash) + get$capitalized_name$List().hashCode();\n"
1081       "}\n");
1082 }
1083 
GetBoxedType() const1084 std::string RepeatedImmutablePrimitiveFieldGenerator::GetBoxedType() const {
1085   return BoxedPrimitiveTypeName(GetJavaType(descriptor_));
1086 }
1087 
1088 }  // namespace java
1089 }  // namespace compiler
1090 }  // namespace protobuf
1091 }  // namespace google
1092