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 | |
51 | namespace google { |
52 | namespace protobuf { |
53 | namespace compiler { |
54 | namespace java { |
55 | |
56 | using internal::WireFormat; |
57 | |
58 | namespace { |
59 | |
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(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 | |
206 | ImmutablePrimitiveFieldGenerator::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 | |
215 | ImmutablePrimitiveFieldGenerator::~ImmutablePrimitiveFieldGenerator() {} |
216 | |
217 | int ImmutablePrimitiveFieldGenerator::GetNumBitsForMessage() const { |
218 | return HasHasbit(descriptor: descriptor_) ? 1 : 0; |
219 | } |
220 | |
221 | int ImmutablePrimitiveFieldGenerator::GetNumBitsForBuilder() const { |
222 | return GetNumBitsForMessage(); |
223 | } |
224 | |
225 | void 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 | |
236 | void 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 | |
260 | void 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 | |
319 | void 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 | |
348 | void ImmutablePrimitiveFieldGenerator::GenerateFieldBuilderInitializationCode( |
349 | io::Printer* printer) const { |
350 | // noop for primitives |
351 | } |
352 | |
353 | void ImmutablePrimitiveFieldGenerator::GenerateInitializationCode( |
354 | io::Printer* printer) const { |
355 | if (!IsDefaultValueJavaDefault(field: descriptor_)) { |
356 | printer->Print(variables: variables_, text: "$name$_ = $default$;\n" ); |
357 | } |
358 | } |
359 | |
360 | void 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 | |
367 | void 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 | |
382 | void 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 | |
403 | void 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 | |
410 | void ImmutablePrimitiveFieldGenerator::GenerateParsingDoneCode( |
411 | io::Printer* printer) const { |
412 | // noop for primitives. |
413 | } |
414 | |
415 | void 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 | |
423 | void 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 | |
432 | void 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 | |
475 | void 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 | |
526 | std::string ImmutablePrimitiveFieldGenerator::GetBoxedType() const { |
527 | return BoxedPrimitiveTypeName(type: GetJavaType(field: descriptor_)); |
528 | } |
529 | |
530 | // =================================================================== |
531 | |
532 | ImmutablePrimitiveOneofFieldGenerator::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 | |
542 | ImmutablePrimitiveOneofFieldGenerator:: |
543 | ~ImmutablePrimitiveOneofFieldGenerator() {} |
544 | |
545 | void 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 | |
569 | void 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 | |
617 | void 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 | |
625 | void ImmutablePrimitiveOneofFieldGenerator::GenerateMergingCode( |
626 | io::Printer* printer) const { |
627 | printer->Print(variables: variables_, |
628 | text: "set$capitalized_name$(other.get$capitalized_name$());\n" ); |
629 | } |
630 | |
631 | void 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 | |
638 | void 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 | |
655 | void 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 | |
675 | RepeatedImmutablePrimitiveFieldGenerator:: |
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 | |
686 | RepeatedImmutablePrimitiveFieldGenerator:: |
687 | ~RepeatedImmutablePrimitiveFieldGenerator() {} |
688 | |
689 | int RepeatedImmutablePrimitiveFieldGenerator::GetNumBitsForMessage() const { |
690 | return 0; |
691 | } |
692 | |
693 | int RepeatedImmutablePrimitiveFieldGenerator::GetNumBitsForBuilder() const { |
694 | return 1; |
695 | } |
696 | |
697 | void 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 | |
711 | void 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 | |
744 | void 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 | |
842 | void 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 | |
936 | void RepeatedImmutablePrimitiveFieldGenerator:: |
937 | GenerateFieldBuilderInitializationCode(io::Printer* printer) const { |
938 | // noop for primitives |
939 | } |
940 | |
941 | void RepeatedImmutablePrimitiveFieldGenerator::GenerateInitializationCode( |
942 | io::Printer* printer) const { |
943 | printer->Print(variables: variables_, text: "$name$_ = $empty_list$;\n" ); |
944 | } |
945 | |
946 | void 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 | |
953 | void 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 | |
973 | void 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 | |
985 | void 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 | |
995 | void 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 | |
1011 | void 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 | |
1019 | void 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 | |
1042 | void 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 | |
1086 | void 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 | |
1094 | void 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 | |
1104 | std::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 | |