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