• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc.  All rights reserved.
3 //
4 // Use of this source code is governed by a BSD-style
5 // license that can be found in the LICENSE file or at
6 // https://developers.google.com/open-source/licenses/bsd
7 
8 // Author: kenton@google.com (Kenton Varda)
9 //  Based on original Protocol Buffers design by
10 //  Sanjay Ghemawat, Jeff Dean, and others.
11 
12 #include "google/protobuf/compiler/java/full/primitive_field.h"
13 
14 #include <cstdint>
15 #include <string>
16 
17 #include "absl/log/absl_check.h"
18 #include "absl/log/absl_log.h"
19 #include "absl/strings/str_cat.h"
20 #include "google/protobuf/compiler/java/context.h"
21 #include "google/protobuf/compiler/java/doc_comment.h"
22 #include "google/protobuf/compiler/java/field_common.h"
23 #include "google/protobuf/compiler/java/helpers.h"
24 #include "google/protobuf/compiler/java/name_resolver.h"
25 #include "google/protobuf/descriptor.h"
26 #include "google/protobuf/io/printer.h"
27 #include "google/protobuf/wire_format.h"
28 
29 namespace google {
30 namespace protobuf {
31 namespace compiler {
32 namespace java {
33 
34 using internal::WireFormat;
35 using Semantic = ::google::protobuf::io::AnnotationCollector::Semantic;
36 
37 namespace {
38 
SetPrimitiveVariables(const FieldDescriptor * descriptor,int messageBitIndex,int builderBitIndex,const FieldGeneratorInfo * info,ClassNameResolver * name_resolver,absl::flat_hash_map<absl::string_view,std::string> * variables,Context * context)39 void SetPrimitiveVariables(
40     const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex,
41     const FieldGeneratorInfo* info, ClassNameResolver* name_resolver,
42     absl::flat_hash_map<absl::string_view, std::string>* variables,
43     Context* context) {
44   SetCommonFieldVariables(descriptor, info, variables);
45   JavaType javaType = GetJavaType(descriptor);
46 
47   (*variables)["type"] = std::string(PrimitiveTypeName(javaType));
48   (*variables)["boxed_type"] = std::string(BoxedPrimitiveTypeName(javaType));
49   (*variables)["kt_type"] = std::string(KotlinTypeName(javaType));
50   variables->insert({"field_type", (*variables)["type"]});
51 
52   std::string name = (*variables)["name"];
53   (*variables)["name_make_immutable"] = absl::StrCat(name, "_.makeImmutable()");
54   if (javaType == JAVATYPE_BOOLEAN || javaType == JAVATYPE_DOUBLE ||
55       javaType == JAVATYPE_FLOAT || javaType == JAVATYPE_INT ||
56       javaType == JAVATYPE_LONG) {
57     std::string capitalized_type = UnderscoresToCamelCase(
58         PrimitiveTypeName(javaType), /*cap_first_letter=*/true);
59     (*variables)["field_list_type"] =
60         absl::StrCat("com.google.protobuf.Internal.", capitalized_type, "List");
61     (*variables)["empty_list"] =
62         absl::StrCat("empty", capitalized_type, "List()");
63     (*variables)["repeated_get"] =
64         absl::StrCat(name, "_.get", capitalized_type);
65     (*variables)["repeated_add"] =
66         absl::StrCat(name, "_.add", capitalized_type);
67     (*variables)["repeated_set"] =
68         absl::StrCat(name, "_.set", capitalized_type);
69   } else {
70     (*variables)["field_list_type"] =
71         "com.google.protobuf.Internal.ProtobufList<com.google.protobuf."
72         "ByteString>";
73     (*variables)["empty_list"] =
74         "emptyList(com.google.protobuf.ByteString.class)";
75     (*variables)["repeated_get"] = absl::StrCat(name, "_.get");
76     (*variables)["repeated_add"] = absl::StrCat(name, "_.add");
77     (*variables)["repeated_set"] = absl::StrCat(name, "_.set");
78   }
79 
80   (*variables)["default"] =
81       ImmutableDefaultValue(descriptor, name_resolver, context->options());
82   (*variables)["default_init"] =
83       IsDefaultValueJavaDefault(descriptor)
84           ? ""
85           : absl::StrCat("= ", ImmutableDefaultValue(descriptor, name_resolver,
86                                                      context->options()));
87   (*variables)["capitalized_type"] = std::string(GetCapitalizedType(
88       descriptor, /* immutable = */ true, context->options()));
89   (*variables)["tag"] =
90       absl::StrCat(static_cast<int32_t>(WireFormat::MakeTag(descriptor)));
91   (*variables)["tag_size"] = absl::StrCat(
92       WireFormat::TagSize(descriptor->number(), GetType(descriptor)));
93   if (IsReferenceType(GetJavaType(descriptor))) {
94     (*variables)["null_check"] =
95         "if (value == null) { throw new NullPointerException(); }";
96   } else {
97     (*variables)["null_check"] = "";
98   }
99   // TODO: Add @deprecated javadoc when generating javadoc is supported
100   // by the proto compiler
101   (*variables)["deprecation"] =
102       descriptor->options().deprecated() ? "@java.lang.Deprecated " : "";
103   (*variables)["kt_deprecation"] =
104       descriptor->options().deprecated()
105           ? absl::StrCat("@kotlin.Deprecated(message = \"Field ", name,
106                          " is deprecated\") ")
107           : "";
108   int fixed_size = FixedSize(GetType(descriptor));
109   if (fixed_size != -1) {
110     (*variables)["fixed_size"] = absl::StrCat(fixed_size);
111   }
112   (*variables)["on_changed"] = "onChanged();";
113 
114   if (HasHasbit(descriptor)) {
115     // For singular messages and builders, one bit is used for the hasField bit.
116     (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex);
117     // Note that these have a trailing ";".
118     (*variables)["set_has_field_bit_to_local"] =
119         absl::StrCat(GenerateSetBitToLocal(messageBitIndex), ";");
120     (*variables)["is_field_present_message"] = GenerateGetBit(messageBitIndex);
121   } else {
122     (*variables)["set_has_field_bit_to_local"] = "";
123     switch (descriptor->type()) {
124       case FieldDescriptor::TYPE_BYTES:
125         (*variables)["is_field_present_message"] =
126             absl::StrCat("!", name, "_.isEmpty()");
127         break;
128       case FieldDescriptor::TYPE_FLOAT:
129         (*variables)["is_field_present_message"] =
130             absl::StrCat("java.lang.Float.floatToRawIntBits(", name, "_) != 0");
131         break;
132       case FieldDescriptor::TYPE_DOUBLE:
133         (*variables)["is_field_present_message"] = absl::StrCat(
134             "java.lang.Double.doubleToRawLongBits(", name, "_) != 0");
135         break;
136       default:
137         variables->insert(
138             {"is_field_present_message",
139              absl::StrCat(name, "_ != ", (*variables)["default"])});
140         break;
141     }
142   }
143 
144   // Always track the presence of a field explicitly in the builder, regardless
145   // of syntax.
146   (*variables)["get_has_field_bit_builder"] = GenerateGetBit(builderBitIndex);
147   (*variables)["get_has_field_bit_from_local"] =
148       GenerateGetBitFromLocal(builderBitIndex);
149   (*variables)["set_has_field_bit_builder"] =
150       absl::StrCat(GenerateSetBit(builderBitIndex), ";");
151   (*variables)["clear_has_field_bit_builder"] =
152       absl::StrCat(GenerateClearBit(builderBitIndex), ";");
153 }
154 
155 }  // namespace
156 
157 // ===================================================================
158 
ImmutablePrimitiveFieldGenerator(const FieldDescriptor * descriptor,int messageBitIndex,int builderBitIndex,Context * context)159 ImmutablePrimitiveFieldGenerator::ImmutablePrimitiveFieldGenerator(
160     const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex,
161     Context* context)
162     : descriptor_(descriptor),
163       message_bit_index_(messageBitIndex),
164       builder_bit_index_(builderBitIndex),
165       context_(context),
166       name_resolver_(context->GetNameResolver()) {
167   SetPrimitiveVariables(descriptor, messageBitIndex, builderBitIndex,
168                         context->GetFieldGeneratorInfo(descriptor),
169                         name_resolver_, &variables_, context);
170 }
171 
~ImmutablePrimitiveFieldGenerator()172 ImmutablePrimitiveFieldGenerator::~ImmutablePrimitiveFieldGenerator() {}
173 
GetMessageBitIndex() const174 int ImmutablePrimitiveFieldGenerator::GetMessageBitIndex() const {
175   return message_bit_index_;
176 }
177 
GetBuilderBitIndex() const178 int ImmutablePrimitiveFieldGenerator::GetBuilderBitIndex() const {
179   return builder_bit_index_;
180 }
181 
GetNumBitsForMessage() const182 int ImmutablePrimitiveFieldGenerator::GetNumBitsForMessage() const {
183   return HasHasbit(descriptor_) ? 1 : 0;
184 }
185 
GetNumBitsForBuilder() const186 int ImmutablePrimitiveFieldGenerator::GetNumBitsForBuilder() const { return 1; }
187 
GenerateInterfaceMembers(io::Printer * printer) const188 void ImmutablePrimitiveFieldGenerator::GenerateInterfaceMembers(
189     io::Printer* printer) const {
190   if (descriptor_->has_presence()) {
191     WriteFieldAccessorDocComment(printer, descriptor_, HAZZER,
192                                  context_->options());
193     printer->Print(variables_,
194                    "$deprecation$boolean has$capitalized_name$();\n");
195   }
196   WriteFieldAccessorDocComment(printer, descriptor_, GETTER,
197                                context_->options());
198   printer->Print(variables_, "$deprecation$$type$ get$capitalized_name$();\n");
199 }
200 
GenerateMembers(io::Printer * printer) const201 void ImmutablePrimitiveFieldGenerator::GenerateMembers(
202     io::Printer* printer) const {
203   printer->Print(variables_, "private $field_type$ $name$_ = $default$;\n");
204   PrintExtraFieldInfo(variables_, printer);
205   if (descriptor_->has_presence()) {
206     WriteFieldAccessorDocComment(printer, descriptor_, HAZZER,
207                                  context_->options());
208     printer->Print(
209         variables_,
210         "@java.lang.Override\n"
211         "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
212         "  return $get_has_field_bit_message$;\n"
213         "}\n");
214     printer->Annotate("{", "}", descriptor_);
215   }
216 
217   WriteFieldAccessorDocComment(printer, descriptor_, GETTER,
218                                context_->options());
219   printer->Print(variables_,
220                  "@java.lang.Override\n"
221                  "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
222                  "  return $name$_;\n"
223                  "}\n");
224   printer->Annotate("{", "}", descriptor_);
225 }
226 
GenerateBuilderMembers(io::Printer * printer) const227 void ImmutablePrimitiveFieldGenerator::GenerateBuilderMembers(
228     io::Printer* printer) const {
229   printer->Print(variables_, "private $field_type$ $name$_ $default_init$;\n");
230 
231   if (descriptor_->has_presence()) {
232     WriteFieldAccessorDocComment(printer, descriptor_, HAZZER,
233                                  context_->options());
234     printer->Print(
235         variables_,
236         "@java.lang.Override\n"
237         "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
238         "  return $get_has_field_bit_builder$;\n"
239         "}\n");
240     printer->Annotate("{", "}", descriptor_);
241   }
242 
243   WriteFieldAccessorDocComment(printer, descriptor_, GETTER,
244                                context_->options());
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   WriteFieldAccessorDocComment(printer, descriptor_, SETTER,
253                                context_->options(),
254                                /* builder */ true);
255   printer->Print(variables_,
256                  "$deprecation$public Builder "
257                  "${$set$capitalized_name$$}$($type$ value) {\n"
258                  "  $null_check$\n"
259                  "  $name$_ = value;\n"
260                  "  $set_has_field_bit_builder$\n"
261                  "  $on_changed$\n"
262                  "  return this;\n"
263                  "}\n");
264   printer->Annotate("{", "}", descriptor_, Semantic::kSet);
265 
266   WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
267                                context_->options(),
268                                /* builder */ true);
269   printer->Print(
270       variables_,
271       "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n"
272       "  $clear_has_field_bit_builder$\n");
273   printer->Annotate("{", "}", descriptor_, Semantic::kSet);
274   JavaType type = GetJavaType(descriptor_);
275   if (type == JAVATYPE_STRING || type == JAVATYPE_BYTES) {
276     // The default value is not a simple literal so we want to avoid executing
277     // it multiple times.  Instead, get the default out of the default instance.
278     printer->Print(
279         variables_,
280         "  $name$_ = getDefaultInstance().get$capitalized_name$();\n");
281   } else {
282     printer->Print(variables_, "  $name$_ = $default$;\n");
283   }
284   printer->Print(variables_,
285                  "  $on_changed$\n"
286                  "  return this;\n"
287                  "}\n");
288 }
289 
GenerateKotlinDslMembers(io::Printer * printer) const290 void ImmutablePrimitiveFieldGenerator::GenerateKotlinDslMembers(
291     io::Printer* printer) const {
292   WriteFieldDocComment(printer, descriptor_, context_->options(),
293                        /* kdoc */ true);
294   if (descriptor_->name() == "is_initialized") {
295     printer->Print(
296         variables_,
297         "// TODO: remove this hack; we should access properties\n"
298         "$kt_deprecation$public var $kt_name$: $kt_type$\n"
299         "  @JvmName(\"${$get$kt_capitalized_name$$}$\")\n"
300         "  get() = $kt_dsl_builder$.${$get$kt_capitalized_name$$}$()\n"
301         "  @JvmName(\"${$set$kt_capitalized_name$$}$\")\n"
302         "  set(value) {\n"
303         "    $kt_dsl_builder$.${$set$kt_capitalized_name$$}$(value)\n"
304         "  }\n");
305   } else {
306     printer->Print(variables_,
307                    "$kt_deprecation$public var $kt_name$: $kt_type$\n"
308                    "  @JvmName(\"${$get$kt_capitalized_name$$}$\")\n"
309                    "  get() = $kt_dsl_builder$.${$$kt_safe_name$$}$\n"
310                    "  @JvmName(\"${$set$kt_capitalized_name$$}$\")\n"
311                    "  set(value) {\n"
312                    "    $kt_dsl_builder$.${$$kt_safe_name$$}$ = value\n"
313                    "  }\n");
314   }
315 
316   WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
317                                context_->options(),
318                                /* builder */ false, /* kdoc */ true);
319   printer->Print(variables_,
320                  "public fun ${$clear$kt_capitalized_name$$}$() {\n"
321                  "  $kt_dsl_builder$.${$clear$capitalized_name$$}$()\n"
322                  "}\n");
323 
324   if (descriptor_->has_presence()) {
325     WriteFieldAccessorDocComment(printer, descriptor_, HAZZER,
326                                  context_->options(),
327                                  /* builder */ false, /* kdoc */ true);
328     printer->Print(
329         variables_,
330         "public fun ${$has$kt_capitalized_name$$}$(): kotlin.Boolean {\n"
331         "  return $kt_dsl_builder$.${$has$capitalized_name$$}$()\n"
332         "}\n");
333   }
334 }
335 
GenerateFieldBuilderInitializationCode(io::Printer * printer) const336 void ImmutablePrimitiveFieldGenerator::GenerateFieldBuilderInitializationCode(
337     io::Printer* printer) const {
338   // noop for primitives
339 }
340 
GenerateInitializationCode(io::Printer * printer) const341 void ImmutablePrimitiveFieldGenerator::GenerateInitializationCode(
342     io::Printer* printer) const {
343   if (!IsDefaultValueJavaDefault(descriptor_)) {
344     printer->Print(variables_, "$name$_ = $default$;\n");
345   }
346 }
347 
GenerateBuilderClearCode(io::Printer * printer) const348 void ImmutablePrimitiveFieldGenerator::GenerateBuilderClearCode(
349     io::Printer* printer) const {
350   // No need to clear the has-bit since we clear the bitField ints all at once.
351   printer->Print(variables_, "$name$_ = $default$;\n");
352 }
353 
GenerateMergingCode(io::Printer * printer) const354 void ImmutablePrimitiveFieldGenerator::GenerateMergingCode(
355     io::Printer* printer) const {
356   if (descriptor_->has_presence()) {
357     printer->Print(variables_,
358                    "if (other.has$capitalized_name$()) {\n"
359                    "  set$capitalized_name$(other.get$capitalized_name$());\n"
360                    "}\n");
361   } else {
362     printer->Print(variables_,
363                    "if (other.get$capitalized_name$() != $default$) {\n"
364                    "  set$capitalized_name$(other.get$capitalized_name$());\n"
365                    "}\n");
366   }
367 }
368 
GenerateBuildingCode(io::Printer * printer) const369 void ImmutablePrimitiveFieldGenerator::GenerateBuildingCode(
370     io::Printer* printer) const {
371   printer->Print(variables_,
372                  "if ($get_has_field_bit_from_local$) {\n"
373                  "  result.$name$_ = $name$_;\n");
374   if (GetNumBitsForMessage() > 0) {
375     printer->Print(variables_, "  $set_has_field_bit_to_local$\n");
376   }
377   printer->Print("}\n");
378 }
379 
GenerateBuilderParsingCode(io::Printer * printer) const380 void ImmutablePrimitiveFieldGenerator::GenerateBuilderParsingCode(
381     io::Printer* printer) const {
382   printer->Print(variables_,
383                  "$name$_ = input.read$capitalized_type$();\n"
384                  "$set_has_field_bit_builder$\n");
385 }
386 
GenerateSerializationCode(io::Printer * printer) const387 void ImmutablePrimitiveFieldGenerator::GenerateSerializationCode(
388     io::Printer* printer) const {
389   printer->Print(variables_,
390                  "if ($is_field_present_message$) {\n"
391                  "  output.write$capitalized_type$($number$, $name$_);\n"
392                  "}\n");
393 }
394 
GenerateSerializedSizeCode(io::Printer * printer) const395 void ImmutablePrimitiveFieldGenerator::GenerateSerializedSizeCode(
396     io::Printer* printer) const {
397   printer->Print(variables_,
398                  "if ($is_field_present_message$) {\n"
399                  "  size += com.google.protobuf.CodedOutputStream\n"
400                  "    .compute$capitalized_type$Size($number$, $name$_);\n"
401                  "}\n");
402 }
403 
GenerateEqualsCode(io::Printer * printer) const404 void ImmutablePrimitiveFieldGenerator::GenerateEqualsCode(
405     io::Printer* printer) const {
406   switch (GetJavaType(descriptor_)) {
407     case JAVATYPE_INT:
408     case JAVATYPE_LONG:
409     case JAVATYPE_BOOLEAN:
410       printer->Print(variables_,
411                      "if (get$capitalized_name$()\n"
412                      "    != other.get$capitalized_name$()) return false;\n");
413       break;
414 
415     case JAVATYPE_FLOAT:
416       printer->Print(
417           variables_,
418           "if (java.lang.Float.floatToIntBits(get$capitalized_name$())\n"
419           "    != java.lang.Float.floatToIntBits(\n"
420           "        other.get$capitalized_name$())) return false;\n");
421       break;
422 
423     case JAVATYPE_DOUBLE:
424       printer->Print(
425           variables_,
426           "if (java.lang.Double.doubleToLongBits(get$capitalized_name$())\n"
427           "    != java.lang.Double.doubleToLongBits(\n"
428           "        other.get$capitalized_name$())) return false;\n");
429       break;
430 
431     case JAVATYPE_STRING:
432     case JAVATYPE_BYTES:
433       printer->Print(
434           variables_,
435           "if (!get$capitalized_name$()\n"
436           "    .equals(other.get$capitalized_name$())) return false;\n");
437       break;
438 
439     case JAVATYPE_ENUM:
440     case JAVATYPE_MESSAGE:
441     default:
442       ABSL_LOG(FATAL) << "Can't get here.";
443       break;
444   }
445 }
446 
GenerateHashCode(io::Printer * printer) const447 void ImmutablePrimitiveFieldGenerator::GenerateHashCode(
448     io::Printer* printer) const {
449   printer->Print(variables_, "hash = (37 * hash) + $constant_name$;\n");
450   switch (GetJavaType(descriptor_)) {
451     case JAVATYPE_INT:
452       printer->Print(variables_,
453                      "hash = (53 * hash) + get$capitalized_name$();\n");
454       break;
455 
456     case JAVATYPE_LONG:
457       printer->Print(
458           variables_,
459           "hash = (53 * hash) + com.google.protobuf.Internal.hashLong(\n"
460           "    get$capitalized_name$());\n");
461       break;
462 
463     case JAVATYPE_BOOLEAN:
464       printer->Print(
465           variables_,
466           "hash = (53 * hash) + com.google.protobuf.Internal.hashBoolean(\n"
467           "    get$capitalized_name$());\n");
468       break;
469 
470     case JAVATYPE_FLOAT:
471       printer->Print(variables_,
472                      "hash = (53 * hash) + java.lang.Float.floatToIntBits(\n"
473                      "    get$capitalized_name$());\n");
474       break;
475 
476     case JAVATYPE_DOUBLE:
477       printer->Print(
478           variables_,
479           "hash = (53 * hash) + com.google.protobuf.Internal.hashLong(\n"
480           "    java.lang.Double.doubleToLongBits(get$capitalized_name$()));\n");
481       break;
482 
483     case JAVATYPE_STRING:
484     case JAVATYPE_BYTES:
485       printer->Print(
486           variables_,
487           "hash = (53 * hash) + get$capitalized_name$().hashCode();\n");
488       break;
489 
490     case JAVATYPE_ENUM:
491     case JAVATYPE_MESSAGE:
492     default:
493       ABSL_LOG(FATAL) << "Can't get here.";
494       break;
495   }
496 }
497 
GetBoxedType() const498 std::string ImmutablePrimitiveFieldGenerator::GetBoxedType() const {
499   return std::string(BoxedPrimitiveTypeName(GetJavaType(descriptor_)));
500 }
501 
502 // ===================================================================
503 
ImmutablePrimitiveOneofFieldGenerator(const FieldDescriptor * descriptor,int messageBitIndex,int builderBitIndex,Context * context)504 ImmutablePrimitiveOneofFieldGenerator::ImmutablePrimitiveOneofFieldGenerator(
505     const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex,
506     Context* context)
507     : ImmutablePrimitiveFieldGenerator(descriptor, messageBitIndex,
508                                        builderBitIndex, context) {
509   const OneofGeneratorInfo* info =
510       context->GetOneofGeneratorInfo(descriptor->containing_oneof());
511   SetCommonOneofVariables(descriptor, info, &variables_);
512 }
513 
514 ImmutablePrimitiveOneofFieldGenerator::
~ImmutablePrimitiveOneofFieldGenerator()515     ~ImmutablePrimitiveOneofFieldGenerator() {}
516 
GenerateMembers(io::Printer * printer) const517 void ImmutablePrimitiveOneofFieldGenerator::GenerateMembers(
518     io::Printer* printer) const {
519   PrintExtraFieldInfo(variables_, printer);
520   ABSL_DCHECK(descriptor_->has_presence());
521   WriteFieldAccessorDocComment(printer, descriptor_, HAZZER,
522                                context_->options());
523   printer->Print(variables_,
524                  "@java.lang.Override\n"
525                  "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
526                  "  return $has_oneof_case_message$;\n"
527                  "}\n");
528   printer->Annotate("{", "}", descriptor_);
529 
530   WriteFieldAccessorDocComment(printer, descriptor_, GETTER,
531                                context_->options());
532   printer->Print(variables_,
533                  "@java.lang.Override\n"
534                  "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
535                  "  if ($has_oneof_case_message$) {\n"
536                  "    return ($boxed_type$) $oneof_name$_;\n"
537                  "  }\n"
538                  "  return $default$;\n"
539                  "}\n");
540   printer->Annotate("{", "}", descriptor_);
541 }
542 
GenerateBuilderMembers(io::Printer * printer) const543 void ImmutablePrimitiveOneofFieldGenerator::GenerateBuilderMembers(
544     io::Printer* printer) const {
545   ABSL_DCHECK(descriptor_->has_presence());
546   WriteFieldAccessorDocComment(printer, descriptor_, HAZZER,
547                                context_->options());
548   printer->Print(variables_,
549                  "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
550                  "  return $has_oneof_case_message$;\n"
551                  "}\n");
552   printer->Annotate("{", "}", descriptor_);
553 
554   WriteFieldAccessorDocComment(printer, descriptor_, GETTER,
555                                context_->options());
556   printer->Print(variables_,
557                  "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
558                  "  if ($has_oneof_case_message$) {\n"
559                  "    return ($boxed_type$) $oneof_name$_;\n"
560                  "  }\n"
561                  "  return $default$;\n"
562                  "}\n");
563   printer->Annotate("{", "}", descriptor_);
564 
565   WriteFieldAccessorDocComment(printer, descriptor_, SETTER,
566                                context_->options(),
567                                /* builder */ true);
568   printer->Print(variables_,
569                  "$deprecation$public Builder "
570                  "${$set$capitalized_name$$}$($type$ value) {\n"
571                  "  $null_check$\n"
572                  "  $set_oneof_case_message$;\n"
573                  "  $oneof_name$_ = value;\n"
574                  "  $on_changed$\n"
575                  "  return this;\n"
576                  "}\n");
577   printer->Annotate("{", "}", descriptor_, Semantic::kSet);
578 
579   WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
580                                context_->options(),
581                                /* builder */ true);
582   printer->Print(
583       variables_,
584       "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n"
585       "  if ($has_oneof_case_message$) {\n"
586       "    $clear_oneof_case_message$;\n"
587       "    $oneof_name$_ = null;\n"
588       "    $on_changed$\n"
589       "  }\n"
590       "  return this;\n"
591       "}\n");
592   printer->Annotate("{", "}", descriptor_, Semantic::kSet);
593 }
594 
GenerateBuilderClearCode(io::Printer * printer) const595 void ImmutablePrimitiveOneofFieldGenerator::GenerateBuilderClearCode(
596     io::Printer* printer) const {
597   // No-Op: When a primitive field is in a oneof, clearing the oneof clears that
598   // field.
599 }
600 
GenerateBuildingCode(io::Printer * printer) const601 void ImmutablePrimitiveOneofFieldGenerator::GenerateBuildingCode(
602     io::Printer* printer) const {
603   // no-op
604 }
605 
GenerateMergingCode(io::Printer * printer) const606 void ImmutablePrimitiveOneofFieldGenerator::GenerateMergingCode(
607     io::Printer* printer) const {
608   printer->Print(variables_,
609                  "set$capitalized_name$(other.get$capitalized_name$());\n");
610 }
611 
GenerateBuilderParsingCode(io::Printer * printer) const612 void ImmutablePrimitiveOneofFieldGenerator::GenerateBuilderParsingCode(
613     io::Printer* printer) const {
614   printer->Print(variables_,
615                  "$oneof_name$_ = input.read$capitalized_type$();\n"
616                  "$set_oneof_case_message$;\n");
617 }
618 
GenerateSerializationCode(io::Printer * printer) const619 void ImmutablePrimitiveOneofFieldGenerator::GenerateSerializationCode(
620     io::Printer* printer) const {
621   printer->Print(variables_,
622                  "if ($has_oneof_case_message$) {\n"
623                  "  output.write$capitalized_type$(\n");
624   // $type$ and $boxed_type$ is the same for bytes fields so we don't need to
625   // do redundant casts.
626   if (GetJavaType(descriptor_) == JAVATYPE_BYTES) {
627     printer->Print(variables_, "      $number$, ($type$) $oneof_name$_);\n");
628   } else {
629     printer->Print(
630         variables_,
631         "      $number$, ($type$)(($boxed_type$) $oneof_name$_));\n");
632   }
633   printer->Print("}\n");
634 }
635 
GenerateSerializedSizeCode(io::Printer * printer) const636 void ImmutablePrimitiveOneofFieldGenerator::GenerateSerializedSizeCode(
637     io::Printer* printer) const {
638   printer->Print(variables_,
639                  "if ($has_oneof_case_message$) {\n"
640                  "  size += com.google.protobuf.CodedOutputStream\n"
641                  "    .compute$capitalized_type$Size(\n");
642   // $type$ and $boxed_type$ is the same for bytes fields so we don't need to
643   // do redundant casts.
644   if (GetJavaType(descriptor_) == JAVATYPE_BYTES) {
645     printer->Print(variables_, "        $number$, ($type$) $oneof_name$_);\n");
646   } else {
647     printer->Print(
648         variables_,
649         "        $number$, ($type$)(($boxed_type$) $oneof_name$_));\n");
650   }
651   printer->Print("}\n");
652 }
653 
654 // ===================================================================
655 
656 RepeatedImmutablePrimitiveFieldGenerator::
RepeatedImmutablePrimitiveFieldGenerator(const FieldDescriptor * descriptor,int messageBitIndex,int builderBitIndex,Context * context)657     RepeatedImmutablePrimitiveFieldGenerator(const FieldDescriptor* descriptor,
658                                              int messageBitIndex,
659                                              int builderBitIndex,
660                                              Context* context)
661     : ImmutablePrimitiveFieldGenerator(descriptor, messageBitIndex,
662                                        builderBitIndex, context) {}
663 
664 RepeatedImmutablePrimitiveFieldGenerator::
~RepeatedImmutablePrimitiveFieldGenerator()665     ~RepeatedImmutablePrimitiveFieldGenerator() {}
666 
GetNumBitsForMessage() const667 int RepeatedImmutablePrimitiveFieldGenerator::GetNumBitsForMessage() const {
668   return 0;
669 }
670 
GetNumBitsForBuilder() const671 int RepeatedImmutablePrimitiveFieldGenerator::GetNumBitsForBuilder() const {
672   return 1;
673 }
674 
GenerateInterfaceMembers(io::Printer * printer) const675 void RepeatedImmutablePrimitiveFieldGenerator::GenerateInterfaceMembers(
676     io::Printer* printer) const {
677   WriteFieldAccessorDocComment(printer, descriptor_, LIST_GETTER,
678                                context_->options());
679   printer->Print(variables_,
680                  "$deprecation$java.util.List<$boxed_type$> "
681                  "get$capitalized_name$List();\n");
682   WriteFieldAccessorDocComment(printer, descriptor_, LIST_COUNT,
683                                context_->options());
684   printer->Print(variables_,
685                  "$deprecation$int get$capitalized_name$Count();\n");
686   WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_GETTER,
687                                context_->options());
688   printer->Print(variables_,
689                  "$deprecation$$type$ get$capitalized_name$(int index);\n");
690 }
691 
GenerateMembers(io::Printer * printer) const692 void RepeatedImmutablePrimitiveFieldGenerator::GenerateMembers(
693     io::Printer* printer) const {
694   printer->Print(variables_,
695                  "@SuppressWarnings(\"serial\")\n"
696                  "private $field_list_type$ $name$_ =\n"
697                  "    $empty_list$;\n");
698   PrintExtraFieldInfo(variables_, printer);
699   WriteFieldAccessorDocComment(printer, descriptor_, LIST_GETTER,
700                                context_->options());
701   printer->Print(variables_,
702                  "@java.lang.Override\n"
703                  "$deprecation$public java.util.List<$boxed_type$>\n"
704                  "    ${$get$capitalized_name$List$}$() {\n"
705                  "  return $name$_;\n"  // note:  unmodifiable list
706                  "}\n");
707   printer->Annotate("{", "}", descriptor_);
708   WriteFieldAccessorDocComment(printer, descriptor_, LIST_COUNT,
709                                context_->options());
710   printer->Print(
711       variables_,
712       "$deprecation$public int ${$get$capitalized_name$Count$}$() {\n"
713       "  return $name$_.size();\n"
714       "}\n");
715   printer->Annotate("{", "}", descriptor_);
716   WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_GETTER,
717                                context_->options());
718   printer->Print(
719       variables_,
720       "$deprecation$public $type$ ${$get$capitalized_name$$}$(int index) {\n"
721       "  return $repeated_get$(index);\n"
722       "}\n");
723   printer->Annotate("{", "}", descriptor_);
724 
725   if (descriptor_->is_packed()) {
726     printer->Print(variables_,
727                    "private int $name$MemoizedSerializedSize = -1;\n");
728   }
729 }
730 
GenerateBuilderMembers(io::Printer * printer) const731 void RepeatedImmutablePrimitiveFieldGenerator::GenerateBuilderMembers(
732     io::Printer* printer) const {
733   // We use a ProtobufArrayList because it starts as a mutable list that can be
734   // switched to immutable when references are handed out. This allows copy-free
735   // sharing. A bit in the bitfield tracks whether there are any items in the
736   // list. The presence bit allows us to skip work on blocks of 32 fields by
737   // by checking if the entire bit-field int == 0 (none of the fields are
738   // present).
739   printer->Print(variables_,
740                  "private $field_list_type$ $name$_ = $empty_list$;\n"
741                  "private void ensure$capitalized_name$IsMutable() {\n"
742                  "  if (!$name$_.isModifiable()) {\n"
743                  "    $name$_ = makeMutableCopy($name$_);\n"
744                  "  }\n"
745                  "  $set_has_field_bit_builder$\n"
746                  "}\n");
747   if (FixedSize(GetType(descriptor_)) != -1) {
748     printer->Print(
749         variables_,
750         "private void ensure$capitalized_name$IsMutable(int capacity) {\n"
751         "  if (!$name$_.isModifiable()) {\n"
752         "    $name$_ = makeMutableCopy($name$_, capacity);\n"
753         "  }\n"
754         "  $set_has_field_bit_builder$\n"
755         "}\n");
756   }
757 
758   // Note:  We return an unmodifiable list because otherwise the caller
759   //   could hold on to the returned list and modify it after the message
760   //   has been built, thus mutating the message which is supposed to be
761   //   immutable.
762   WriteFieldAccessorDocComment(printer, descriptor_, LIST_GETTER,
763                                context_->options());
764   printer->Print(variables_,
765                  "$deprecation$public java.util.List<$boxed_type$>\n"
766                  "    ${$get$capitalized_name$List$}$() {\n"
767                  "  $name$_.makeImmutable();\n"
768                  "  return $name$_;\n"
769                  "}\n");
770   printer->Annotate("{", "}", descriptor_);
771   WriteFieldAccessorDocComment(printer, descriptor_, LIST_COUNT,
772                                context_->options());
773   printer->Print(
774       variables_,
775       "$deprecation$public int ${$get$capitalized_name$Count$}$() {\n"
776       "  return $name$_.size();\n"
777       "}\n");
778   printer->Annotate("{", "}", descriptor_);
779   WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_GETTER,
780                                context_->options());
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                                context_->options(),
789                                /* builder */ true);
790   printer->Print(variables_,
791                  "$deprecation$public Builder ${$set$capitalized_name$$}$(\n"
792                  "    int index, $type$ value) {\n"
793                  "  $null_check$\n"
794                  "  ensure$capitalized_name$IsMutable();\n"
795                  "  $repeated_set$(index, value);\n"
796                  "  $set_has_field_bit_builder$\n"
797                  "  $on_changed$\n"
798                  "  return this;\n"
799                  "}\n");
800   printer->Annotate("{", "}", descriptor_, Semantic::kSet);
801   WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER,
802                                context_->options(),
803                                /* builder */ true);
804   printer->Print(variables_,
805                  "$deprecation$public Builder "
806                  "${$add$capitalized_name$$}$($type$ value) {\n"
807                  "  $null_check$\n"
808                  "  ensure$capitalized_name$IsMutable();\n"
809                  "  $repeated_add$(value);\n"
810                  "  $set_has_field_bit_builder$\n"
811                  "  $on_changed$\n"
812                  "  return this;\n"
813                  "}\n");
814   printer->Annotate("{", "}", descriptor_, Semantic::kSet);
815   WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER,
816                                context_->options(),
817                                /* builder */ true);
818   printer->Print(variables_,
819                  "$deprecation$public Builder ${$addAll$capitalized_name$$}$(\n"
820                  "    java.lang.Iterable<? extends $boxed_type$> values) {\n"
821                  "  ensure$capitalized_name$IsMutable();\n"
822                  "  com.google.protobuf.AbstractMessageLite.Builder.addAll(\n"
823                  "      values, $name$_);\n"
824                  "  $set_has_field_bit_builder$\n"
825                  "  $on_changed$\n"
826                  "  return this;\n"
827                  "}\n");
828   printer->Annotate("{", "}", descriptor_, Semantic::kSet);
829   WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
830                                context_->options(),
831                                /* builder */ true);
832   printer->Print(
833       variables_,
834       "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n"
835       "  $name$_ = $empty_list$;\n"
836       "  $clear_has_field_bit_builder$\n"
837       "  $on_changed$\n"
838       "  return this;\n"
839       "}\n");
840   printer->Annotate("{", "}", descriptor_, Semantic::kSet);
841 }
842 
GenerateKotlinDslMembers(io::Printer * printer) const843 void RepeatedImmutablePrimitiveFieldGenerator::GenerateKotlinDslMembers(
844     io::Printer* printer) const {
845   printer->Print(
846       variables_,
847       "/**\n"
848       " * An uninstantiable, behaviorless type to represent the field in\n"
849       " * generics.\n"
850       " */\n"
851       "@kotlin.OptIn"
852       "(com.google.protobuf.kotlin.OnlyForUseByGeneratedProtoCode::class)\n"
853       "public class ${$$kt_capitalized_name$Proxy$}$ private constructor()"
854       " : com.google.protobuf.kotlin.DslProxy()\n");
855 
856   WriteFieldDocComment(printer, descriptor_, context_->options(),
857                        /* kdoc */ true);
858   printer->Print(variables_,
859                  "$kt_deprecation$ public val $kt_name$: "
860                  "com.google.protobuf.kotlin.DslList"
861                  "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>\n"
862                  "  @kotlin.jvm.JvmSynthetic\n"
863                  "  get() = com.google.protobuf.kotlin.DslList(\n"
864                  "    $kt_dsl_builder$.${$$kt_property_name$List$}$\n"
865                  "  )\n");
866 
867   WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER,
868                                context_->options(),
869                                /* builder */ false, /* kdoc */ true);
870   printer->Print(variables_,
871                  "@kotlin.jvm.JvmSynthetic\n"
872                  "@kotlin.jvm.JvmName(\"add$kt_capitalized_name$\")\n"
873                  "public fun com.google.protobuf.kotlin.DslList"
874                  "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
875                  "add(value: $kt_type$) {\n"
876                  "  $kt_dsl_builder$.${$add$capitalized_name$$}$(value)\n"
877                  "}");
878 
879   WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER,
880                                context_->options(),
881                                /* builder */ false, /* kdoc */ true);
882   printer->Print(variables_,
883                  "@kotlin.jvm.JvmSynthetic\n"
884                  "@kotlin.jvm.JvmName(\"plusAssign$kt_capitalized_name$\")\n"
885                  "@Suppress(\"NOTHING_TO_INLINE\")\n"
886                  "public inline operator fun com.google.protobuf.kotlin.DslList"
887                  "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
888                  "plusAssign(value: $kt_type$) {\n"
889                  "  add(value)\n"
890                  "}");
891 
892   WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER,
893                                context_->options(),
894                                /* builder */ false, /* kdoc */ true);
895   printer->Print(variables_,
896                  "@kotlin.jvm.JvmSynthetic\n"
897                  "@kotlin.jvm.JvmName(\"addAll$kt_capitalized_name$\")\n"
898                  "public fun com.google.protobuf.kotlin.DslList"
899                  "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
900                  "addAll(values: kotlin.collections.Iterable<$kt_type$>) {\n"
901                  "  $kt_dsl_builder$.${$addAll$capitalized_name$$}$(values)\n"
902                  "}");
903 
904   WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER,
905                                context_->options(),
906                                /* builder */ false, /* kdoc */ true);
907   printer->Print(
908       variables_,
909       "@kotlin.jvm.JvmSynthetic\n"
910       "@kotlin.jvm.JvmName(\"plusAssignAll$kt_capitalized_name$\")\n"
911       "@Suppress(\"NOTHING_TO_INLINE\")\n"
912       "public inline operator fun com.google.protobuf.kotlin.DslList"
913       "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
914       "plusAssign(values: kotlin.collections.Iterable<$kt_type$>) {\n"
915       "  addAll(values)\n"
916       "}");
917 
918   WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_SETTER,
919                                context_->options(),
920                                /* builder */ false, /* kdoc */ true);
921   printer->Print(
922       variables_,
923       "@kotlin.jvm.JvmSynthetic\n"
924       "@kotlin.jvm.JvmName(\"set$kt_capitalized_name$\")\n"
925       "public operator fun com.google.protobuf.kotlin.DslList"
926       "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
927       "set(index: kotlin.Int, value: $kt_type$) {\n"
928       "  $kt_dsl_builder$.${$set$capitalized_name$$}$(index, value)\n"
929       "}");
930 
931   WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
932                                context_->options(),
933                                /* builder */ false, /* kdoc */ true);
934   printer->Print(variables_,
935                  "@kotlin.jvm.JvmSynthetic\n"
936                  "@kotlin.jvm.JvmName(\"clear$kt_capitalized_name$\")\n"
937                  "public fun com.google.protobuf.kotlin.DslList"
938                  "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
939                  "clear() {\n"
940                  "  $kt_dsl_builder$.${$clear$capitalized_name$$}$()\n"
941                  "}");
942 }
943 
944 void RepeatedImmutablePrimitiveFieldGenerator::
GenerateFieldBuilderInitializationCode(io::Printer * printer) const945     GenerateFieldBuilderInitializationCode(io::Printer* printer) const {
946   // noop for primitives
947 }
948 
GenerateInitializationCode(io::Printer * printer) const949 void RepeatedImmutablePrimitiveFieldGenerator::GenerateInitializationCode(
950     io::Printer* printer) const {
951   printer->Print(variables_, "$name$_ = $empty_list$;\n");
952 }
953 
GenerateBuilderClearCode(io::Printer * printer) const954 void RepeatedImmutablePrimitiveFieldGenerator::GenerateBuilderClearCode(
955     io::Printer* printer) const {
956   printer->Print(variables_, "$name$_ = $empty_list$;\n");
957 }
958 
GenerateMergingCode(io::Printer * printer) const959 void RepeatedImmutablePrimitiveFieldGenerator::GenerateMergingCode(
960     io::Printer* printer) const {
961   // The code below does two optimizations:
962   //   1. If the other list is empty, there's nothing to do. This ensures we
963   //      don't allocate a new array if we already have an immutable one.
964   //   2. If the other list is non-empty and our current list is empty, we can
965   //      reuse the other list which is guaranteed to be immutable.
966   printer->Print(variables_,
967                  "if (!other.$name$_.isEmpty()) {\n"
968                  "  if ($name$_.isEmpty()) {\n"
969                  "    $name$_ = other.$name$_;\n"
970                  "    $name_make_immutable$;\n"
971                  "    $set_has_field_bit_builder$\n");
972   printer->Print(variables_,
973                  "  } else {\n"
974                  "    ensure$capitalized_name$IsMutable();\n"
975                  "    $name$_.addAll(other.$name$_);\n"
976                  "  }\n"
977                  "  $on_changed$\n"
978                  "}\n");
979 }
980 
GenerateBuildingCode(io::Printer * printer) const981 void RepeatedImmutablePrimitiveFieldGenerator::GenerateBuildingCode(
982     io::Printer* printer) const {
983   // The code below ensures that the result has an immutable list. If our
984   // list is immutable, we can just reuse it. If not, we make it immutable.
985   printer->Print(variables_,
986                  "if ($get_has_field_bit_from_local$) {\n"
987                  "  $name_make_immutable$;\n"
988                  "  result.$name$_ = $name$_;\n"
989                  "}\n");
990 }
991 
GenerateBuilderParsingCode(io::Printer * printer) const992 void RepeatedImmutablePrimitiveFieldGenerator::GenerateBuilderParsingCode(
993     io::Printer* printer) const {
994   printer->Print(variables_,
995                  "$type$ v = input.read$capitalized_type$();\n"
996                  "ensure$capitalized_name$IsMutable();\n"
997                  "$repeated_add$(v);\n");
998 }
999 
1000 void RepeatedImmutablePrimitiveFieldGenerator::
GenerateBuilderParsingCodeFromPacked(io::Printer * printer) const1001     GenerateBuilderParsingCodeFromPacked(io::Printer* printer) const {
1002   if (FixedSize(GetType(descriptor_)) != -1) {
1003     // 4K limit on pre-allocations to prevent OOM from malformed input.
1004     printer->Print(variables_,
1005                    "int length = input.readRawVarint32();\n"
1006                    "int limit = input.pushLimit(length);\n"
1007                    "int alloc = length > 4096 ? 4096 : length;\n"
1008                    "ensure$capitalized_name$IsMutable(alloc / $fixed_size$);\n"
1009                    "while (input.getBytesUntilLimit() > 0) {\n"
1010                    "  $repeated_add$(input.read$capitalized_type$());\n"
1011                    "}\n"
1012                    "input.popLimit(limit);\n");
1013   } else {
1014     printer->Print(variables_,
1015                    "int length = input.readRawVarint32();\n"
1016                    "int limit = input.pushLimit(length);\n"
1017                    "ensure$capitalized_name$IsMutable();\n"
1018                    "while (input.getBytesUntilLimit() > 0) {\n"
1019                    "  $repeated_add$(input.read$capitalized_type$());\n"
1020                    "}\n"
1021                    "input.popLimit(limit);\n");
1022   }
1023 }
1024 
GenerateSerializationCode(io::Printer * printer) const1025 void RepeatedImmutablePrimitiveFieldGenerator::GenerateSerializationCode(
1026     io::Printer* printer) const {
1027   if (descriptor_->is_packed()) {
1028     // We invoke getSerializedSize in writeTo for messages that have packed
1029     // fields in ImmutableMessageGenerator::GenerateMessageSerializationMethods.
1030     // That makes it safe to rely on the memoized size here.
1031     printer->Print(variables_,
1032                    "if (get$capitalized_name$List().size() > 0) {\n"
1033                    "  output.writeUInt32NoTag($tag$);\n"
1034                    "  output.writeUInt32NoTag($name$MemoizedSerializedSize);\n"
1035                    "}\n"
1036                    "for (int i = 0; i < $name$_.size(); i++) {\n"
1037                    "  output.write$capitalized_type$NoTag($repeated_get$(i));\n"
1038                    "}\n");
1039   } else {
1040     printer->Print(
1041         variables_,
1042         "for (int i = 0; i < $name$_.size(); i++) {\n"
1043         "  output.write$capitalized_type$($number$, $repeated_get$(i));\n"
1044         "}\n");
1045   }
1046 }
1047 
GenerateSerializedSizeCode(io::Printer * printer) const1048 void RepeatedImmutablePrimitiveFieldGenerator::GenerateSerializedSizeCode(
1049     io::Printer* printer) const {
1050   printer->Print(variables_,
1051                  "{\n"
1052                  "  int dataSize = 0;\n");
1053   printer->Indent();
1054 
1055   if (FixedSize(GetType(descriptor_)) == -1) {
1056     printer->Print(
1057         variables_,
1058         "for (int i = 0; i < $name$_.size(); i++) {\n"
1059         "  dataSize += com.google.protobuf.CodedOutputStream\n"
1060         "    .compute$capitalized_type$SizeNoTag($repeated_get$(i));\n"
1061         "}\n");
1062   } else {
1063     printer->Print(
1064         variables_,
1065         "dataSize = $fixed_size$ * get$capitalized_name$List().size();\n");
1066   }
1067 
1068   printer->Print("size += dataSize;\n");
1069 
1070   if (descriptor_->is_packed()) {
1071     printer->Print(variables_,
1072                    "if (!get$capitalized_name$List().isEmpty()) {\n"
1073                    "  size += $tag_size$;\n"
1074                    "  size += com.google.protobuf.CodedOutputStream\n"
1075                    "      .computeInt32SizeNoTag(dataSize);\n"
1076                    "}\n");
1077   } else {
1078     printer->Print(
1079         variables_,
1080         "size += $tag_size$ * get$capitalized_name$List().size();\n");
1081   }
1082 
1083   // cache the data size for packed fields.
1084   if (descriptor_->is_packed()) {
1085     printer->Print(variables_, "$name$MemoizedSerializedSize = dataSize;\n");
1086   }
1087 
1088   printer->Outdent();
1089   printer->Print("}\n");
1090 }
1091 
GenerateEqualsCode(io::Printer * printer) const1092 void RepeatedImmutablePrimitiveFieldGenerator::GenerateEqualsCode(
1093     io::Printer* printer) const {
1094   printer->Print(
1095       variables_,
1096       "if (!get$capitalized_name$List()\n"
1097       "    .equals(other.get$capitalized_name$List())) return false;\n");
1098 }
1099 
GenerateHashCode(io::Printer * printer) const1100 void RepeatedImmutablePrimitiveFieldGenerator::GenerateHashCode(
1101     io::Printer* printer) const {
1102   printer->Print(
1103       variables_,
1104       "if (get$capitalized_name$Count() > 0) {\n"
1105       "  hash = (37 * hash) + $constant_name$;\n"
1106       "  hash = (53 * hash) + get$capitalized_name$List().hashCode();\n"
1107       "}\n");
1108 }
1109 
GetBoxedType() const1110 std::string RepeatedImmutablePrimitiveFieldGenerator::GetBoxedType() const {
1111   return std::string(BoxedPrimitiveTypeName(GetJavaType(descriptor_)));
1112 }
1113 
1114 }  // namespace java
1115 }  // namespace compiler
1116 }  // namespace protobuf
1117 }  // namespace google
1118