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