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