xref: /aosp_15_r20/external/cronet/third_party/protobuf/src/google/protobuf/compiler/java/primitive_field.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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: [email protected] (Kenton Varda)
32 //  Based on original Protocol Buffers design by
33 //  Sanjay Ghemawat, Jeff Dean, and others.
34 
35 #include "google/protobuf/compiler/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/context.h"
47 #include "google/protobuf/compiler/java/doc_comment.h"
48 #include "google/protobuf/compiler/java/helpers.h"
49 #include "google/protobuf/compiler/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,Context * context)60 void SetPrimitiveVariables(
61     const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex,
62     const FieldGeneratorInfo* info, ClassNameResolver* name_resolver,
63     std::map<std::string, std::string>* variables,
64     Context* context) {
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->insert({"field_type", (*variables)["type"]});
72 
73   std::string name = (*variables)["name"];
74   if (javaType == JAVATYPE_BOOLEAN || javaType == JAVATYPE_DOUBLE ||
75       javaType == JAVATYPE_FLOAT || javaType == JAVATYPE_INT ||
76       javaType == JAVATYPE_LONG) {
77     std::string capitalized_type = UnderscoresToCamelCase(
78         PrimitiveTypeName(javaType), /*cap_first_letter=*/true);
79     (*variables)["field_list_type"] =
80         StrCat("com.google.protobuf.Internal.", capitalized_type, "List");
81     (*variables)["empty_list"] =
82         StrCat("empty", capitalized_type, "List()");
83     (*variables)["create_list"] =
84         StrCat("new", capitalized_type, "List()");
85     (*variables)["mutable_copy_list"] =
86         StrCat("mutableCopy(", name, "_)");
87     (*variables)["name_make_immutable"] =
88         StrCat(name, "_.makeImmutable()");
89     (*variables)["repeated_get"] =
90         StrCat(name, "_.get", capitalized_type);
91     (*variables)["repeated_add"] =
92         StrCat(name, "_.add", capitalized_type);
93     (*variables)["repeated_set"] =
94         StrCat(name, "_.set", capitalized_type);
95   } else {
96     std::string boxed_type = (*variables)["boxed_type"];
97     (*variables)["field_list_type"] =
98         StrCat("java.util.List<", boxed_type, ">");
99     (*variables)["create_list"] =
100         StrCat("new java.util.ArrayList<", boxed_type, ">()");
101     (*variables)["mutable_copy_list"] =
102         StrCat("new java.util.ArrayList<", boxed_type, ">(", name, "_)");
103     (*variables)["empty_list"] = "java.util.Collections.emptyList()";
104     (*variables)["name_make_immutable"] = StrCat(
105         name, "_ = java.util.Collections.unmodifiableList(", name, "_)");
106     (*variables)["repeated_get"] = StrCat(name, "_.get");
107     (*variables)["repeated_add"] = StrCat(name, "_.add");
108     (*variables)["repeated_set"] = StrCat(name, "_.set");
109   }
110 
111   (*variables)["default"] = ImmutableDefaultValue(descriptor, name_resolver);
112   (*variables)["default_init"] =
113       IsDefaultValueJavaDefault(descriptor)
114           ? ""
115           : ("= " + ImmutableDefaultValue(descriptor, name_resolver));
116   (*variables)["capitalized_type"] =
117       GetCapitalizedType(descriptor, /* immutable = */ true);
118   (*variables)["tag"] =
119       StrCat(static_cast<int32_t>(WireFormat::MakeTag(descriptor)));
120   (*variables)["tag_size"] = StrCat(
121       WireFormat::TagSize(descriptor->number(), GetType(descriptor)));
122   if (IsReferenceType(GetJavaType(descriptor))) {
123     (*variables)["null_check"] =
124         "if (value == null) { throw new NullPointerException(); }";
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           ? StrCat("@kotlin.Deprecated(message = \"Field ", 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     // Note that these have a trailing ";".
147     (*variables)["set_has_field_bit_to_local"] =
148         GenerateSetBitToLocal(messageBitIndex) + ";";
149     (*variables)["is_field_present_message"] = GenerateGetBit(messageBitIndex);
150   } else {
151     (*variables)["set_has_field_bit_to_local"] = "";
152     switch (descriptor->type()) {
153       case FieldDescriptor::TYPE_BYTES:
154         (*variables)["is_field_present_message"] =
155             StrCat("!", name, "_.isEmpty()");
156         break;
157       case FieldDescriptor::TYPE_FLOAT:
158         (*variables)["is_field_present_message"] =
159             StrCat("java.lang.Float.floatToRawIntBits(", name, "_) != 0");
160         break;
161       case FieldDescriptor::TYPE_DOUBLE:
162         (*variables)["is_field_present_message"] = StrCat(
163             "java.lang.Double.doubleToRawLongBits(", name, "_) != 0");
164         break;
165       default:
166         variables->insert(
167             {"is_field_present_message",
168              StrCat(name, "_ != ", (*variables)["default"])});
169         break;
170     }
171   }
172 
173   // For repeated builders, one bit is used for whether the array is immutable.
174   (*variables)["get_mutable_bit_builder"] = GenerateGetBit(builderBitIndex);
175   (*variables)["set_mutable_bit_builder"] = GenerateSetBit(builderBitIndex);
176   (*variables)["clear_mutable_bit_builder"] = GenerateClearBit(builderBitIndex);
177 
178   // Always track the presence of a field explicitly in the builder, regardless
179   // of syntax.
180   (*variables)["get_has_field_bit_builder"] = GenerateGetBit(builderBitIndex);
181   (*variables)["get_has_field_bit_from_local"] =
182       GenerateGetBitFromLocal(builderBitIndex);
183   (*variables)["set_has_field_bit_builder"] =
184       GenerateSetBit(builderBitIndex) + ";";
185   (*variables)["clear_has_field_bit_builder"] =
186       GenerateClearBit(builderBitIndex) + ";";
187 }
188 
189 }  // namespace
190 
191 // ===================================================================
192 
ImmutablePrimitiveFieldGenerator(const FieldDescriptor * descriptor,int messageBitIndex,int builderBitIndex,Context * context)193 ImmutablePrimitiveFieldGenerator::ImmutablePrimitiveFieldGenerator(
194     const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex,
195     Context* context)
196     : descriptor_(descriptor),
197       message_bit_index_(messageBitIndex),
198       builder_bit_index_(builderBitIndex),
199       name_resolver_(context->GetNameResolver()) {
200   SetPrimitiveVariables(descriptor, messageBitIndex, builderBitIndex,
201                         context->GetFieldGeneratorInfo(descriptor),
202                         name_resolver_, &variables_, context);
203 }
204 
~ImmutablePrimitiveFieldGenerator()205 ImmutablePrimitiveFieldGenerator::~ImmutablePrimitiveFieldGenerator() {}
206 
GetMessageBitIndex() const207 int ImmutablePrimitiveFieldGenerator::GetMessageBitIndex() const {
208   return message_bit_index_;
209 }
210 
GetBuilderBitIndex() const211 int ImmutablePrimitiveFieldGenerator::GetBuilderBitIndex() const {
212   return builder_bit_index_;
213 }
214 
GetNumBitsForMessage() const215 int ImmutablePrimitiveFieldGenerator::GetNumBitsForMessage() const {
216   return HasHasbit(descriptor_) ? 1 : 0;
217 }
218 
GetNumBitsForBuilder() const219 int ImmutablePrimitiveFieldGenerator::GetNumBitsForBuilder() const { return 1; }
220 
GenerateInterfaceMembers(io::Printer * printer) const221 void ImmutablePrimitiveFieldGenerator::GenerateInterfaceMembers(
222     io::Printer* printer) const {
223   if (HasHazzer(descriptor_)) {
224     WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
225     printer->Print(variables_,
226                    "$deprecation$boolean has$capitalized_name$();\n");
227   }
228   WriteFieldAccessorDocComment(printer, descriptor_, GETTER);
229   printer->Print(variables_, "$deprecation$$type$ get$capitalized_name$();\n");
230 }
231 
GenerateMembers(io::Printer * printer) const232 void ImmutablePrimitiveFieldGenerator::GenerateMembers(
233     io::Printer* printer) const {
234   printer->Print(variables_, "private $field_type$ $name$_ = $default$;\n");
235   PrintExtraFieldInfo(variables_, printer);
236   if (HasHazzer(descriptor_)) {
237     WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
238     printer->Print(
239         variables_,
240         "@java.lang.Override\n"
241         "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
242         "  return $get_has_field_bit_message$;\n"
243         "}\n");
244     printer->Annotate("{", "}", descriptor_);
245   }
246 
247   WriteFieldAccessorDocComment(printer, descriptor_, GETTER);
248   printer->Print(variables_,
249                  "@java.lang.Override\n"
250                  "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
251                  "  return $name$_;\n"
252                  "}\n");
253   printer->Annotate("{", "}", descriptor_);
254 }
255 
GenerateBuilderMembers(io::Printer * printer) const256 void ImmutablePrimitiveFieldGenerator::GenerateBuilderMembers(
257     io::Printer* printer) const {
258   printer->Print(variables_, "private $field_type$ $name$_ $default_init$;\n");
259 
260   if (HasHazzer(descriptor_)) {
261     WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
262     printer->Print(
263         variables_,
264         "@java.lang.Override\n"
265         "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
266         "  return $get_has_field_bit_builder$;\n"
267         "}\n");
268     printer->Annotate("{", "}", descriptor_);
269   }
270 
271   WriteFieldAccessorDocComment(printer, descriptor_, GETTER);
272   printer->Print(variables_,
273                  "@java.lang.Override\n"
274                  "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
275                  "  return $name$_;\n"
276                  "}\n");
277   printer->Annotate("{", "}", descriptor_);
278 
279   WriteFieldAccessorDocComment(printer, descriptor_, SETTER,
280                                /* builder */ true);
281   printer->Print(variables_,
282                  "$deprecation$public Builder "
283                  "${$set$capitalized_name$$}$($type$ value) {\n"
284                  "  $null_check$\n"
285                  "  $name$_ = value;\n"
286                  "  $set_has_field_bit_builder$\n"
287                  "  $on_changed$\n"
288                  "  return this;\n"
289                  "}\n");
290   printer->Annotate("{", "}", descriptor_);
291 
292   WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
293                                /* builder */ true);
294   printer->Print(
295       variables_,
296       "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n"
297       "  $clear_has_field_bit_builder$\n");
298   printer->Annotate("{", "}", descriptor_);
299   JavaType type = GetJavaType(descriptor_);
300   if (type == JAVATYPE_STRING || type == JAVATYPE_BYTES) {
301     // The default value is not a simple literal so we want to avoid executing
302     // it multiple times.  Instead, get the default out of the default instance.
303     printer->Print(
304         variables_,
305         "  $name$_ = getDefaultInstance().get$capitalized_name$();\n");
306   } else {
307     printer->Print(variables_, "  $name$_ = $default$;\n");
308   }
309   printer->Print(variables_,
310                  "  $on_changed$\n"
311                  "  return this;\n"
312                  "}\n");
313 }
314 
GenerateKotlinDslMembers(io::Printer * printer) const315 void ImmutablePrimitiveFieldGenerator::GenerateKotlinDslMembers(
316     io::Printer* printer) const {
317   WriteFieldDocComment(printer, descriptor_);
318   printer->Print(variables_,
319                  "$kt_deprecation$public var $kt_name$: $kt_type$\n"
320                  "  @JvmName(\"${$get$kt_capitalized_name$$}$\")\n"
321                  "  get() = $kt_dsl_builder$.${$get$capitalized_name$$}$()\n"
322                  "  @JvmName(\"${$set$kt_capitalized_name$$}$\")\n"
323                  "  set(value) {\n"
324                  "    $kt_dsl_builder$.${$set$capitalized_name$$}$(value)\n"
325                  "  }\n");
326 
327   WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
328                                /* builder */ false);
329   printer->Print(variables_,
330                  "public fun ${$clear$kt_capitalized_name$$}$() {\n"
331                  "  $kt_dsl_builder$.${$clear$capitalized_name$$}$()\n"
332                  "}\n");
333 
334   if (HasHazzer(descriptor_)) {
335     WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
336     printer->Print(
337         variables_,
338         "public fun ${$has$kt_capitalized_name$$}$(): kotlin.Boolean {\n"
339         "  return $kt_dsl_builder$.${$has$capitalized_name$$}$()\n"
340         "}\n");
341   }
342 }
343 
GenerateFieldBuilderInitializationCode(io::Printer * printer) const344 void ImmutablePrimitiveFieldGenerator::GenerateFieldBuilderInitializationCode(
345     io::Printer* printer) const {
346   // noop for primitives
347 }
348 
GenerateInitializationCode(io::Printer * printer) const349 void ImmutablePrimitiveFieldGenerator::GenerateInitializationCode(
350     io::Printer* printer) const {
351   if (!IsDefaultValueJavaDefault(descriptor_)) {
352     printer->Print(variables_, "$name$_ = $default$;\n");
353   }
354 }
355 
GenerateBuilderClearCode(io::Printer * printer) const356 void ImmutablePrimitiveFieldGenerator::GenerateBuilderClearCode(
357     io::Printer* printer) const {
358   // No need to clear the has-bit since we clear the bitField ints all at once.
359   printer->Print(variables_, "$name$_ = $default$;\n");
360 }
361 
GenerateMergingCode(io::Printer * printer) const362 void ImmutablePrimitiveFieldGenerator::GenerateMergingCode(
363     io::Printer* printer) const {
364   if (HasHazzer(descriptor_)) {
365     printer->Print(variables_,
366                    "if (other.has$capitalized_name$()) {\n"
367                    "  set$capitalized_name$(other.get$capitalized_name$());\n"
368                    "}\n");
369   } else {
370     printer->Print(variables_,
371                    "if (other.get$capitalized_name$() != $default$) {\n"
372                    "  set$capitalized_name$(other.get$capitalized_name$());\n"
373                    "}\n");
374   }
375 }
376 
GenerateBuildingCode(io::Printer * printer) const377 void ImmutablePrimitiveFieldGenerator::GenerateBuildingCode(
378     io::Printer* printer) const {
379   printer->Print(variables_,
380                  "if ($get_has_field_bit_from_local$) {\n"
381                  "  result.$name$_ = $name$_;\n");
382   if (GetNumBitsForMessage() > 0) {
383     printer->Print(variables_, "  $set_has_field_bit_to_local$\n");
384   }
385   printer->Print("}\n");
386 }
387 
GenerateBuilderParsingCode(io::Printer * printer) const388 void ImmutablePrimitiveFieldGenerator::GenerateBuilderParsingCode(
389     io::Printer* printer) const {
390   printer->Print(variables_,
391                  "$name$_ = input.read$capitalized_type$();\n"
392                  "$set_has_field_bit_builder$\n");
393 }
394 
GenerateSerializationCode(io::Printer * printer) const395 void ImmutablePrimitiveFieldGenerator::GenerateSerializationCode(
396     io::Printer* printer) const {
397   printer->Print(variables_,
398                  "if ($is_field_present_message$) {\n"
399                  "  output.write$capitalized_type$($number$, $name$_);\n"
400                  "}\n");
401 }
402 
GenerateSerializedSizeCode(io::Printer * printer) const403 void ImmutablePrimitiveFieldGenerator::GenerateSerializedSizeCode(
404     io::Printer* printer) const {
405   printer->Print(variables_,
406                  "if ($is_field_present_message$) {\n"
407                  "  size += com.google.protobuf.CodedOutputStream\n"
408                  "    .compute$capitalized_type$Size($number$, $name$_);\n"
409                  "}\n");
410 }
411 
GenerateEqualsCode(io::Printer * printer) const412 void ImmutablePrimitiveFieldGenerator::GenerateEqualsCode(
413     io::Printer* printer) const {
414   switch (GetJavaType(descriptor_)) {
415     case JAVATYPE_INT:
416     case JAVATYPE_LONG:
417     case JAVATYPE_BOOLEAN:
418       printer->Print(variables_,
419                      "if (get$capitalized_name$()\n"
420                      "    != other.get$capitalized_name$()) return false;\n");
421       break;
422 
423     case JAVATYPE_FLOAT:
424       printer->Print(
425           variables_,
426           "if (java.lang.Float.floatToIntBits(get$capitalized_name$())\n"
427           "    != java.lang.Float.floatToIntBits(\n"
428           "        other.get$capitalized_name$())) return false;\n");
429       break;
430 
431     case JAVATYPE_DOUBLE:
432       printer->Print(
433           variables_,
434           "if (java.lang.Double.doubleToLongBits(get$capitalized_name$())\n"
435           "    != java.lang.Double.doubleToLongBits(\n"
436           "        other.get$capitalized_name$())) return false;\n");
437       break;
438 
439     case JAVATYPE_STRING:
440     case JAVATYPE_BYTES:
441       printer->Print(
442           variables_,
443           "if (!get$capitalized_name$()\n"
444           "    .equals(other.get$capitalized_name$())) return false;\n");
445       break;
446 
447     case JAVATYPE_ENUM:
448     case JAVATYPE_MESSAGE:
449     default:
450       GOOGLE_LOG(FATAL) << "Can't get here.";
451       break;
452   }
453 }
454 
GenerateHashCode(io::Printer * printer) const455 void ImmutablePrimitiveFieldGenerator::GenerateHashCode(
456     io::Printer* printer) const {
457   printer->Print(variables_, "hash = (37 * hash) + $constant_name$;\n");
458   switch (GetJavaType(descriptor_)) {
459     case JAVATYPE_INT:
460       printer->Print(variables_,
461                      "hash = (53 * hash) + get$capitalized_name$();\n");
462       break;
463 
464     case JAVATYPE_LONG:
465       printer->Print(
466           variables_,
467           "hash = (53 * hash) + com.google.protobuf.Internal.hashLong(\n"
468           "    get$capitalized_name$());\n");
469       break;
470 
471     case JAVATYPE_BOOLEAN:
472       printer->Print(
473           variables_,
474           "hash = (53 * hash) + com.google.protobuf.Internal.hashBoolean(\n"
475           "    get$capitalized_name$());\n");
476       break;
477 
478     case JAVATYPE_FLOAT:
479       printer->Print(variables_,
480                      "hash = (53 * hash) + java.lang.Float.floatToIntBits(\n"
481                      "    get$capitalized_name$());\n");
482       break;
483 
484     case JAVATYPE_DOUBLE:
485       printer->Print(
486           variables_,
487           "hash = (53 * hash) + com.google.protobuf.Internal.hashLong(\n"
488           "    java.lang.Double.doubleToLongBits(get$capitalized_name$()));\n");
489       break;
490 
491     case JAVATYPE_STRING:
492     case JAVATYPE_BYTES:
493       printer->Print(
494           variables_,
495           "hash = (53 * hash) + get$capitalized_name$().hashCode();\n");
496       break;
497 
498     case JAVATYPE_ENUM:
499     case JAVATYPE_MESSAGE:
500     default:
501       GOOGLE_LOG(FATAL) << "Can't get here.";
502       break;
503   }
504 }
505 
GetBoxedType() const506 std::string ImmutablePrimitiveFieldGenerator::GetBoxedType() const {
507   return BoxedPrimitiveTypeName(GetJavaType(descriptor_));
508 }
509 
510 // ===================================================================
511 
ImmutablePrimitiveOneofFieldGenerator(const FieldDescriptor * descriptor,int messageBitIndex,int builderBitIndex,Context * context)512 ImmutablePrimitiveOneofFieldGenerator::ImmutablePrimitiveOneofFieldGenerator(
513     const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex,
514     Context* context)
515     : ImmutablePrimitiveFieldGenerator(descriptor, messageBitIndex,
516                                        builderBitIndex, context) {
517   const OneofGeneratorInfo* info =
518       context->GetOneofGeneratorInfo(descriptor->containing_oneof());
519   SetCommonOneofVariables(descriptor, info, &variables_);
520 }
521 
522 ImmutablePrimitiveOneofFieldGenerator::
~ImmutablePrimitiveOneofFieldGenerator()523     ~ImmutablePrimitiveOneofFieldGenerator() {}
524 
GenerateMembers(io::Printer * printer) const525 void ImmutablePrimitiveOneofFieldGenerator::GenerateMembers(
526     io::Printer* printer) const {
527   PrintExtraFieldInfo(variables_, printer);
528   GOOGLE_DCHECK(HasHazzer(descriptor_));
529   WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
530   printer->Print(variables_,
531                  "@java.lang.Override\n"
532                  "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
533                  "  return $has_oneof_case_message$;\n"
534                  "}\n");
535   printer->Annotate("{", "}", descriptor_);
536 
537   WriteFieldAccessorDocComment(printer, descriptor_, GETTER);
538   printer->Print(variables_,
539                  "@java.lang.Override\n"
540                  "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
541                  "  if ($has_oneof_case_message$) {\n"
542                  "    return ($boxed_type$) $oneof_name$_;\n"
543                  "  }\n"
544                  "  return $default$;\n"
545                  "}\n");
546   printer->Annotate("{", "}", descriptor_);
547 }
548 
GenerateBuilderMembers(io::Printer * printer) const549 void ImmutablePrimitiveOneofFieldGenerator::GenerateBuilderMembers(
550     io::Printer* printer) const {
551   GOOGLE_DCHECK(HasHazzer(descriptor_));
552   WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
553   printer->Print(variables_,
554                  "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
555                  "  return $has_oneof_case_message$;\n"
556                  "}\n");
557   printer->Annotate("{", "}", descriptor_);
558 
559   WriteFieldAccessorDocComment(printer, descriptor_, GETTER);
560   printer->Print(variables_,
561                  "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
562                  "  if ($has_oneof_case_message$) {\n"
563                  "    return ($boxed_type$) $oneof_name$_;\n"
564                  "  }\n"
565                  "  return $default$;\n"
566                  "}\n");
567   printer->Annotate("{", "}", descriptor_);
568 
569   WriteFieldAccessorDocComment(printer, descriptor_, SETTER,
570                                /* builder */ true);
571   printer->Print(variables_,
572                  "$deprecation$public Builder "
573                  "${$set$capitalized_name$$}$($type$ value) {\n"
574                  "  $null_check$\n"
575                  "  $set_oneof_case_message$;\n"
576                  "  $oneof_name$_ = value;\n"
577                  "  $on_changed$\n"
578                  "  return this;\n"
579                  "}\n");
580   printer->Annotate("{", "}", descriptor_);
581 
582   WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
583                                /* builder */ true);
584   printer->Print(
585       variables_,
586       "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n"
587       "  if ($has_oneof_case_message$) {\n"
588       "    $clear_oneof_case_message$;\n"
589       "    $oneof_name$_ = null;\n"
590       "    $on_changed$\n"
591       "  }\n"
592       "  return this;\n"
593       "}\n");
594   printer->Annotate("{", "}", descriptor_);
595 }
596 
GenerateBuilderClearCode(io::Printer * printer) const597 void ImmutablePrimitiveOneofFieldGenerator::GenerateBuilderClearCode(
598     io::Printer* printer) const {
599   // No-Op: When a primitive field is in a oneof, clearing the oneof clears that
600   // field.
601 }
602 
GenerateBuildingCode(io::Printer * printer) const603 void ImmutablePrimitiveOneofFieldGenerator::GenerateBuildingCode(
604     io::Printer* printer) const {
605   // no-op
606 }
607 
GenerateMergingCode(io::Printer * printer) const608 void ImmutablePrimitiveOneofFieldGenerator::GenerateMergingCode(
609     io::Printer* printer) const {
610   printer->Print(variables_,
611                  "set$capitalized_name$(other.get$capitalized_name$());\n");
612 }
613 
GenerateBuilderParsingCode(io::Printer * printer) const614 void ImmutablePrimitiveOneofFieldGenerator::GenerateBuilderParsingCode(
615     io::Printer* printer) const {
616   printer->Print(variables_,
617                  "$oneof_name$_ = input.read$capitalized_type$();\n"
618                  "$set_oneof_case_message$;\n");
619 }
620 
GenerateSerializationCode(io::Printer * printer) const621 void ImmutablePrimitiveOneofFieldGenerator::GenerateSerializationCode(
622     io::Printer* printer) const {
623   printer->Print(variables_,
624                  "if ($has_oneof_case_message$) {\n"
625                  "  output.write$capitalized_type$(\n");
626   // $type$ and $boxed_type$ is the same for bytes fields so we don't need to
627   // do redundant casts.
628   if (GetJavaType(descriptor_) == JAVATYPE_BYTES) {
629     printer->Print(variables_, "      $number$, ($type$) $oneof_name$_);\n");
630   } else {
631     printer->Print(
632         variables_,
633         "      $number$, ($type$)(($boxed_type$) $oneof_name$_));\n");
634   }
635   printer->Print("}\n");
636 }
637 
GenerateSerializedSizeCode(io::Printer * printer) const638 void ImmutablePrimitiveOneofFieldGenerator::GenerateSerializedSizeCode(
639     io::Printer* printer) const {
640   printer->Print(variables_,
641                  "if ($has_oneof_case_message$) {\n"
642                  "  size += com.google.protobuf.CodedOutputStream\n"
643                  "    .compute$capitalized_type$Size(\n");
644   // $type$ and $boxed_type$ is the same for bytes fields so we don't need to
645   // do redundant casts.
646   if (GetJavaType(descriptor_) == JAVATYPE_BYTES) {
647     printer->Print(variables_, "        $number$, ($type$) $oneof_name$_);\n");
648   } else {
649     printer->Print(
650         variables_,
651         "        $number$, ($type$)(($boxed_type$) $oneof_name$_));\n");
652   }
653   printer->Print("}\n");
654 }
655 
656 // ===================================================================
657 
658 RepeatedImmutablePrimitiveFieldGenerator::
RepeatedImmutablePrimitiveFieldGenerator(const FieldDescriptor * descriptor,int messageBitIndex,int builderBitIndex,Context * context)659     RepeatedImmutablePrimitiveFieldGenerator(const FieldDescriptor* descriptor,
660                                              int messageBitIndex,
661                                              int builderBitIndex,
662                                              Context* context)
663     : ImmutablePrimitiveFieldGenerator(descriptor, messageBitIndex,
664                                        builderBitIndex, context) {}
665 
666 RepeatedImmutablePrimitiveFieldGenerator::
~RepeatedImmutablePrimitiveFieldGenerator()667     ~RepeatedImmutablePrimitiveFieldGenerator() {}
668 
GetNumBitsForMessage() const669 int RepeatedImmutablePrimitiveFieldGenerator::GetNumBitsForMessage() const {
670   return 0;
671 }
672 
GetNumBitsForBuilder() const673 int RepeatedImmutablePrimitiveFieldGenerator::GetNumBitsForBuilder() const {
674   return 1;
675 }
676 
GenerateInterfaceMembers(io::Printer * printer) const677 void RepeatedImmutablePrimitiveFieldGenerator::GenerateInterfaceMembers(
678     io::Printer* printer) const {
679   WriteFieldAccessorDocComment(printer, descriptor_, LIST_GETTER);
680   printer->Print(variables_,
681                  "$deprecation$java.util.List<$boxed_type$> "
682                  "get$capitalized_name$List();\n");
683   WriteFieldAccessorDocComment(printer, descriptor_, LIST_COUNT);
684   printer->Print(variables_,
685                  "$deprecation$int get$capitalized_name$Count();\n");
686   WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_GETTER);
687   printer->Print(variables_,
688                  "$deprecation$$type$ get$capitalized_name$(int index);\n");
689 }
690 
GenerateMembers(io::Printer * printer) const691 void RepeatedImmutablePrimitiveFieldGenerator::GenerateMembers(
692     io::Printer* printer) const {
693   printer->Print(variables_, "@SuppressWarnings(\"serial\")\n"
694                              "private $field_list_type$ $name$_;\n");
695   PrintExtraFieldInfo(variables_, printer);
696   WriteFieldAccessorDocComment(printer, descriptor_, LIST_GETTER);
697   printer->Print(variables_,
698                  "@java.lang.Override\n"
699                  "$deprecation$public java.util.List<$boxed_type$>\n"
700                  "    ${$get$capitalized_name$List$}$() {\n"
701                  "  return $name$_;\n"  // note:  unmodifiable list
702                  "}\n");
703   printer->Annotate("{", "}", descriptor_);
704   WriteFieldAccessorDocComment(printer, descriptor_, LIST_COUNT);
705   printer->Print(
706       variables_,
707       "$deprecation$public int ${$get$capitalized_name$Count$}$() {\n"
708       "  return $name$_.size();\n"
709       "}\n");
710   printer->Annotate("{", "}", descriptor_);
711   WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_GETTER);
712   printer->Print(
713       variables_,
714       "$deprecation$public $type$ ${$get$capitalized_name$$}$(int index) {\n"
715       "  return $repeated_get$(index);\n"
716       "}\n");
717   printer->Annotate("{", "}", descriptor_);
718 
719   if (descriptor_->is_packed()) {
720     printer->Print(variables_,
721                    "private int $name$MemoizedSerializedSize = -1;\n");
722   }
723 }
724 
GenerateBuilderMembers(io::Printer * printer) const725 void RepeatedImmutablePrimitiveFieldGenerator::GenerateBuilderMembers(
726     io::Printer* printer) const {
727   // One field is the list and the bit field keeps track of whether the
728   // list is immutable. If it's immutable, the invariant is that it must
729   // either an instance of Collections.emptyList() or it's an ArrayList
730   // wrapped in a Collections.unmodifiableList() wrapper and nobody else has
731   // a reference to the underlying ArrayList. This invariant allows us to
732   // share instances of lists between protocol buffers avoiding expensive
733   // memory allocations. Note, immutable is a strong guarantee here -- not
734   // just that the list cannot be modified via the reference but that the
735   // list can never be modified.
736   printer->Print(variables_,
737                  "private $field_list_type$ $name$_ = $empty_list$;\n");
738 
739   printer->Print(variables_,
740                  "private void ensure$capitalized_name$IsMutable() {\n"
741                  "  if (!$get_mutable_bit_builder$) {\n"
742                  "    $name$_ = $mutable_copy_list$;\n"
743                  "    $set_mutable_bit_builder$;\n"
744                  "  }\n"
745                  "}\n");
746 
747   // Note:  We return an unmodifiable list because otherwise the caller
748   //   could hold on to the returned list and modify it after the message
749   //   has been built, thus mutating the message which is supposed to be
750   //   immutable.
751   WriteFieldAccessorDocComment(printer, descriptor_, LIST_GETTER);
752   printer->Print(
753       variables_,
754       "$deprecation$public java.util.List<$boxed_type$>\n"
755       "    ${$get$capitalized_name$List$}$() {\n"
756       "  return $get_mutable_bit_builder$ ?\n"
757       "           java.util.Collections.unmodifiableList($name$_) : $name$_;\n"
758       "}\n");
759   printer->Annotate("{", "}", descriptor_);
760   WriteFieldAccessorDocComment(printer, descriptor_, LIST_COUNT);
761   printer->Print(
762       variables_,
763       "$deprecation$public int ${$get$capitalized_name$Count$}$() {\n"
764       "  return $name$_.size();\n"
765       "}\n");
766   printer->Annotate("{", "}", descriptor_);
767   WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_GETTER);
768   printer->Print(
769       variables_,
770       "$deprecation$public $type$ ${$get$capitalized_name$$}$(int index) {\n"
771       "  return $repeated_get$(index);\n"
772       "}\n");
773   printer->Annotate("{", "}", descriptor_);
774   WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_SETTER,
775                                /* builder */ true);
776   printer->Print(variables_,
777                  "$deprecation$public Builder ${$set$capitalized_name$$}$(\n"
778                  "    int index, $type$ value) {\n"
779                  "  $null_check$\n"
780                  "  ensure$capitalized_name$IsMutable();\n"
781                  "  $repeated_set$(index, value);\n"
782                  "  $on_changed$\n"
783                  "  return this;\n"
784                  "}\n");
785   printer->Annotate("{", "}", descriptor_);
786   WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER,
787                                /* builder */ true);
788   printer->Print(variables_,
789                  "$deprecation$public Builder "
790                  "${$add$capitalized_name$$}$($type$ value) {\n"
791                  "  $null_check$\n"
792                  "  ensure$capitalized_name$IsMutable();\n"
793                  "  $repeated_add$(value);\n"
794                  "  $on_changed$\n"
795                  "  return this;\n"
796                  "}\n");
797   printer->Annotate("{", "}", descriptor_);
798   WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER,
799                                /* builder */ true);
800   printer->Print(variables_,
801                  "$deprecation$public Builder ${$addAll$capitalized_name$$}$(\n"
802                  "    java.lang.Iterable<? extends $boxed_type$> values) {\n"
803                  "  ensure$capitalized_name$IsMutable();\n"
804                  "  com.google.protobuf.AbstractMessageLite.Builder.addAll(\n"
805                  "      values, $name$_);\n"
806                  "  $on_changed$\n"
807                  "  return this;\n"
808                  "}\n");
809   printer->Annotate("{", "}", descriptor_);
810   WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
811                                /* builder */ true);
812   printer->Print(
813       variables_,
814       "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n"
815       "  $name$_ = $empty_list$;\n"
816       "  $clear_mutable_bit_builder$;\n"
817       "  $on_changed$\n"
818       "  return this;\n"
819       "}\n");
820   printer->Annotate("{", "}", descriptor_);
821 }
822 
GenerateKotlinDslMembers(io::Printer * printer) const823 void RepeatedImmutablePrimitiveFieldGenerator::GenerateKotlinDslMembers(
824     io::Printer* printer) const {
825   printer->Print(
826       variables_,
827       "/**\n"
828       " * An uninstantiable, behaviorless type to represent the field in\n"
829       " * generics.\n"
830       " */\n"
831       "@kotlin.OptIn"
832       "(com.google.protobuf.kotlin.OnlyForUseByGeneratedProtoCode::class)\n"
833       "public class ${$$kt_capitalized_name$Proxy$}$ private constructor()"
834       " : com.google.protobuf.kotlin.DslProxy()\n");
835 
836   WriteFieldDocComment(printer, descriptor_);
837   printer->Print(variables_,
838                  "$kt_deprecation$ public val $kt_name$: "
839                  "com.google.protobuf.kotlin.DslList"
840                  "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>\n"
841                  "  @kotlin.jvm.JvmSynthetic\n"
842                  "  get() = com.google.protobuf.kotlin.DslList(\n"
843                  "    $kt_dsl_builder$.${$get$capitalized_name$List$}$()\n"
844                  "  )\n");
845 
846   WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER,
847                                /* builder */ false);
848   printer->Print(variables_,
849                  "@kotlin.jvm.JvmSynthetic\n"
850                  "@kotlin.jvm.JvmName(\"add$kt_capitalized_name$\")\n"
851                  "public fun com.google.protobuf.kotlin.DslList"
852                  "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
853                  "add(value: $kt_type$) {\n"
854                  "  $kt_dsl_builder$.${$add$capitalized_name$$}$(value)\n"
855                  "}");
856 
857   WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER,
858                                /* builder */ false);
859   printer->Print(variables_,
860                  "@kotlin.jvm.JvmSynthetic\n"
861                  "@kotlin.jvm.JvmName(\"plusAssign$kt_capitalized_name$\")\n"
862                  "@Suppress(\"NOTHING_TO_INLINE\")\n"
863                  "public inline operator fun com.google.protobuf.kotlin.DslList"
864                  "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
865                  "plusAssign(value: $kt_type$) {\n"
866                  "  add(value)\n"
867                  "}");
868 
869   WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER,
870                                /* builder */ false);
871   printer->Print(variables_,
872                  "@kotlin.jvm.JvmSynthetic\n"
873                  "@kotlin.jvm.JvmName(\"addAll$kt_capitalized_name$\")\n"
874                  "public fun com.google.protobuf.kotlin.DslList"
875                  "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
876                  "addAll(values: kotlin.collections.Iterable<$kt_type$>) {\n"
877                  "  $kt_dsl_builder$.${$addAll$capitalized_name$$}$(values)\n"
878                  "}");
879 
880   WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER,
881                                /* builder */ false);
882   printer->Print(
883       variables_,
884       "@kotlin.jvm.JvmSynthetic\n"
885       "@kotlin.jvm.JvmName(\"plusAssignAll$kt_capitalized_name$\")\n"
886       "@Suppress(\"NOTHING_TO_INLINE\")\n"
887       "public inline operator fun com.google.protobuf.kotlin.DslList"
888       "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
889       "plusAssign(values: kotlin.collections.Iterable<$kt_type$>) {\n"
890       "  addAll(values)\n"
891       "}");
892 
893   WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_SETTER,
894                                /* builder */ false);
895   printer->Print(
896       variables_,
897       "@kotlin.jvm.JvmSynthetic\n"
898       "@kotlin.jvm.JvmName(\"set$kt_capitalized_name$\")\n"
899       "public operator fun com.google.protobuf.kotlin.DslList"
900       "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
901       "set(index: kotlin.Int, value: $kt_type$) {\n"
902       "  $kt_dsl_builder$.${$set$capitalized_name$$}$(index, value)\n"
903       "}");
904 
905   WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
906                                /* builder */ false);
907   printer->Print(variables_,
908                  "@kotlin.jvm.JvmSynthetic\n"
909                  "@kotlin.jvm.JvmName(\"clear$kt_capitalized_name$\")\n"
910                  "public fun com.google.protobuf.kotlin.DslList"
911                  "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
912                  "clear() {\n"
913                  "  $kt_dsl_builder$.${$clear$capitalized_name$$}$()\n"
914                  "}");
915 }
916 
917 void RepeatedImmutablePrimitiveFieldGenerator::
GenerateFieldBuilderInitializationCode(io::Printer * printer) const918     GenerateFieldBuilderInitializationCode(io::Printer* printer) const {
919   // noop for primitives
920 }
921 
GenerateInitializationCode(io::Printer * printer) const922 void RepeatedImmutablePrimitiveFieldGenerator::GenerateInitializationCode(
923     io::Printer* printer) const {
924   printer->Print(variables_, "$name$_ = $empty_list$;\n");
925 }
926 
GenerateBuilderClearCode(io::Printer * printer) const927 void RepeatedImmutablePrimitiveFieldGenerator::GenerateBuilderClearCode(
928     io::Printer* printer) const {
929   printer->Print(variables_, "$name$_ = $empty_list$;\n");
930 }
931 
GenerateMergingCode(io::Printer * printer) const932 void RepeatedImmutablePrimitiveFieldGenerator::GenerateMergingCode(
933     io::Printer* printer) const {
934   // The code below does two optimizations:
935   //   1. If the other list is empty, there's nothing to do. This ensures we
936   //      don't allocate a new array if we already have an immutable one.
937   //   2. If the other list is non-empty and our current list is empty, we can
938   //      reuse the other list which is guaranteed to be immutable.
939   printer->Print(variables_,
940                  "if (!other.$name$_.isEmpty()) {\n"
941                  "  if ($name$_.isEmpty()) {\n"
942                  "    $name$_ = other.$name$_;\n"
943                  "    $clear_mutable_bit_builder$;\n"
944                  "  } else {\n"
945                  "    ensure$capitalized_name$IsMutable();\n"
946                  "    $name$_.addAll(other.$name$_);\n"
947                  "  }\n"
948                  "  $on_changed$\n"
949                  "}\n");
950 }
951 
GenerateBuildingCode(io::Printer * printer) const952 void RepeatedImmutablePrimitiveFieldGenerator::GenerateBuildingCode(
953     io::Printer* printer) const {
954   // The code below ensures that the result has an immutable list. If our
955   // list is immutable, we can just reuse it. If not, we make it immutable.
956   printer->Print(variables_,
957                  "if ($get_mutable_bit_builder$) {\n"
958                  "  $name_make_immutable$;\n"
959                  "  $clear_mutable_bit_builder$;\n"
960                  "}\n"
961                  "result.$name$_ = $name$_;\n");
962 }
963 
GenerateBuilderParsingCode(io::Printer * printer) const964 void RepeatedImmutablePrimitiveFieldGenerator::GenerateBuilderParsingCode(
965     io::Printer* printer) const {
966   printer->Print(variables_,
967                  "$type$ v = input.read$capitalized_type$();\n"
968                  "ensure$capitalized_name$IsMutable();\n"
969                  "$repeated_add$(v);\n");
970 }
971 
972 void RepeatedImmutablePrimitiveFieldGenerator::
GenerateBuilderParsingCodeFromPacked(io::Printer * printer) const973     GenerateBuilderParsingCodeFromPacked(io::Printer* printer) const {
974   printer->Print(variables_,
975                  "int length = input.readRawVarint32();\n"
976                  "int limit = input.pushLimit(length);\n"
977                  "ensure$capitalized_name$IsMutable();\n"
978                  "while (input.getBytesUntilLimit() > 0) {\n"
979                  "  $repeated_add$(input.read$capitalized_type$());\n"
980                  "}\n"
981                  "input.popLimit(limit);\n");
982 }
983 
GenerateSerializationCode(io::Printer * printer) const984 void RepeatedImmutablePrimitiveFieldGenerator::GenerateSerializationCode(
985     io::Printer* printer) const {
986   if (descriptor_->is_packed()) {
987     // We invoke getSerializedSize in writeTo for messages that have packed
988     // fields in ImmutableMessageGenerator::GenerateMessageSerializationMethods.
989     // That makes it safe to rely on the memoized size here.
990     printer->Print(variables_,
991                    "if (get$capitalized_name$List().size() > 0) {\n"
992                    "  output.writeUInt32NoTag($tag$);\n"
993                    "  output.writeUInt32NoTag($name$MemoizedSerializedSize);\n"
994                    "}\n"
995                    "for (int i = 0; i < $name$_.size(); i++) {\n"
996                    "  output.write$capitalized_type$NoTag($repeated_get$(i));\n"
997                    "}\n");
998   } else {
999     printer->Print(
1000         variables_,
1001         "for (int i = 0; i < $name$_.size(); i++) {\n"
1002         "  output.write$capitalized_type$($number$, $repeated_get$(i));\n"
1003         "}\n");
1004   }
1005 }
1006 
GenerateSerializedSizeCode(io::Printer * printer) const1007 void RepeatedImmutablePrimitiveFieldGenerator::GenerateSerializedSizeCode(
1008     io::Printer* printer) const {
1009   printer->Print(variables_,
1010                  "{\n"
1011                  "  int dataSize = 0;\n");
1012   printer->Indent();
1013 
1014   if (FixedSize(GetType(descriptor_)) == -1) {
1015     printer->Print(
1016         variables_,
1017         "for (int i = 0; i < $name$_.size(); i++) {\n"
1018         "  dataSize += com.google.protobuf.CodedOutputStream\n"
1019         "    .compute$capitalized_type$SizeNoTag($repeated_get$(i));\n"
1020         "}\n");
1021   } else {
1022     printer->Print(
1023         variables_,
1024         "dataSize = $fixed_size$ * get$capitalized_name$List().size();\n");
1025   }
1026 
1027   printer->Print("size += dataSize;\n");
1028 
1029   if (descriptor_->is_packed()) {
1030     printer->Print(variables_,
1031                    "if (!get$capitalized_name$List().isEmpty()) {\n"
1032                    "  size += $tag_size$;\n"
1033                    "  size += com.google.protobuf.CodedOutputStream\n"
1034                    "      .computeInt32SizeNoTag(dataSize);\n"
1035                    "}\n");
1036   } else {
1037     printer->Print(
1038         variables_,
1039         "size += $tag_size$ * get$capitalized_name$List().size();\n");
1040   }
1041 
1042   // cache the data size for packed fields.
1043   if (descriptor_->is_packed()) {
1044     printer->Print(variables_, "$name$MemoizedSerializedSize = dataSize;\n");
1045   }
1046 
1047   printer->Outdent();
1048   printer->Print("}\n");
1049 }
1050 
GenerateEqualsCode(io::Printer * printer) const1051 void RepeatedImmutablePrimitiveFieldGenerator::GenerateEqualsCode(
1052     io::Printer* printer) const {
1053   printer->Print(
1054       variables_,
1055       "if (!get$capitalized_name$List()\n"
1056       "    .equals(other.get$capitalized_name$List())) return false;\n");
1057 }
1058 
GenerateHashCode(io::Printer * printer) const1059 void RepeatedImmutablePrimitiveFieldGenerator::GenerateHashCode(
1060     io::Printer* printer) const {
1061   printer->Print(
1062       variables_,
1063       "if (get$capitalized_name$Count() > 0) {\n"
1064       "  hash = (37 * hash) + $constant_name$;\n"
1065       "  hash = (53 * hash) + get$capitalized_name$List().hashCode();\n"
1066       "}\n");
1067 }
1068 
GetBoxedType() const1069 std::string RepeatedImmutablePrimitiveFieldGenerator::GetBoxedType() const {
1070   return BoxedPrimitiveTypeName(GetJavaType(descriptor_));
1071 }
1072 
1073 }  // namespace java
1074 }  // namespace compiler
1075 }  // namespace protobuf
1076 }  // namespace google
1077