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// Author: jonp@google.com (Jon Perlow)
33// Based on original Protocol Buffers design by
34// Sanjay Ghemawat, Jeff Dean, and others.
35
36#include <google/protobuf/compiler/java/string_field.h>
37
38#include <cstdint>
39#include <map>
40#include <string>
41
42#include <google/protobuf/stubs/logging.h>
43#include <google/protobuf/stubs/common.h>
44#include <google/protobuf/io/printer.h>
45#include <google/protobuf/wire_format.h>
46#include <google/protobuf/stubs/strutil.h>
47#include <google/protobuf/compiler/java/context.h>
48#include <google/protobuf/compiler/java/doc_comment.h>
49#include <google/protobuf/compiler/java/helpers.h>
50#include <google/protobuf/compiler/java/name_resolver.h>
51
52namespace google {
53namespace protobuf {
54namespace compiler {
55namespace java {
56
57using internal::WireFormat;
58using internal::WireFormatLite;
59
60namespace {
61
62void SetPrimitiveVariables(const FieldDescriptor* descriptor,
63 int messageBitIndex, int builderBitIndex,
64 const FieldGeneratorInfo* info,
65 ClassNameResolver* name_resolver,
66 std::map<std::string, std::string>* variables) {
67 SetCommonFieldVariables(descriptor, info, variables);
68
69 (*variables)["empty_list"] = "com.google.protobuf.LazyStringArrayList.EMPTY";
70
71 (*variables)["default"] = ImmutableDefaultValue(field: descriptor, name_resolver);
72 (*variables)["default_init"] =
73 "= " + ImmutableDefaultValue(field: descriptor, name_resolver);
74 (*variables)["capitalized_type"] = "String";
75 (*variables)["tag"] =
76 StrCat(a: static_cast<int32_t>(WireFormat::MakeTag(field: descriptor)));
77 (*variables)["tag_size"] = StrCat(
78 a: WireFormat::TagSize(field_number: descriptor->number(), type: GetType(field: descriptor)));
79 (*variables)["null_check"] =
80 " if (value == null) {\n"
81 " throw new NullPointerException();\n"
82 " }\n";
83 (*variables)["isStringEmpty"] = "com.google.protobuf.GeneratedMessage" +
84 GeneratedCodeVersionSuffix() +
85 ".isStringEmpty";
86 (*variables)["writeString"] = "com.google.protobuf.GeneratedMessage" +
87 GeneratedCodeVersionSuffix() + ".writeString";
88 (*variables)["computeStringSize"] = "com.google.protobuf.GeneratedMessage" +
89 GeneratedCodeVersionSuffix() +
90 ".computeStringSize";
91
92 // TODO(birdo): Add @deprecated javadoc when generating javadoc is supported
93 // by the proto compiler
94 (*variables)["deprecation"] =
95 descriptor->options().deprecated() ? "@java.lang.Deprecated " : "";
96 (*variables)["kt_deprecation"] =
97 descriptor->options().deprecated()
98 ? "@kotlin.Deprecated(message = \"Field " + (*variables)["name"] +
99 " is deprecated\") "
100 : "";
101 (*variables)["on_changed"] = "onChanged();";
102
103 if (HasHasbit(descriptor)) {
104 // For singular messages and builders, one bit is used for the hasField bit.
105 (*variables)["get_has_field_bit_message"] = GenerateGetBit(bitIndex: messageBitIndex);
106 (*variables)["get_has_field_bit_builder"] = GenerateGetBit(bitIndex: builderBitIndex);
107
108 // Note that these have a trailing ";".
109 (*variables)["set_has_field_bit_message"] =
110 GenerateSetBit(bitIndex: messageBitIndex) + ";";
111 (*variables)["set_has_field_bit_builder"] =
112 GenerateSetBit(bitIndex: builderBitIndex) + ";";
113 (*variables)["clear_has_field_bit_builder"] =
114 GenerateClearBit(bitIndex: builderBitIndex) + ";";
115
116 (*variables)["is_field_present_message"] = GenerateGetBit(bitIndex: messageBitIndex);
117 } else {
118 (*variables)["set_has_field_bit_message"] = "";
119 (*variables)["set_has_field_bit_builder"] = "";
120 (*variables)["clear_has_field_bit_builder"] = "";
121
122 (*variables)["is_field_present_message"] =
123 "!" + (*variables)["isStringEmpty"] + "(" + (*variables)["name"] + "_)";
124 }
125
126 // For repeated builders, one bit is used for whether the array is immutable.
127 (*variables)["get_mutable_bit_builder"] = GenerateGetBit(bitIndex: builderBitIndex);
128 (*variables)["set_mutable_bit_builder"] = GenerateSetBit(bitIndex: builderBitIndex);
129 (*variables)["clear_mutable_bit_builder"] = GenerateClearBit(bitIndex: builderBitIndex);
130
131 // For repeated fields, one bit is used for whether the array is immutable
132 // in the parsing constructor.
133 (*variables)["get_mutable_bit_parser"] =
134 GenerateGetBitMutableLocal(bitIndex: builderBitIndex);
135 (*variables)["set_mutable_bit_parser"] =
136 GenerateSetBitMutableLocal(bitIndex: builderBitIndex);
137
138 (*variables)["get_has_field_bit_from_local"] =
139 GenerateGetBitFromLocal(bitIndex: builderBitIndex);
140 (*variables)["set_has_field_bit_to_local"] =
141 GenerateSetBitToLocal(bitIndex: messageBitIndex);
142}
143
144} // namespace
145
146// ===================================================================
147
148ImmutableStringFieldGenerator::ImmutableStringFieldGenerator(
149 const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex,
150 Context* context)
151 : descriptor_(descriptor), name_resolver_(context->GetNameResolver()) {
152 SetPrimitiveVariables(descriptor, messageBitIndex, builderBitIndex,
153 info: context->GetFieldGeneratorInfo(field: descriptor),
154 name_resolver: name_resolver_, variables: &variables_);
155}
156
157ImmutableStringFieldGenerator::~ImmutableStringFieldGenerator() {}
158
159int ImmutableStringFieldGenerator::GetNumBitsForMessage() const {
160 return HasHasbit(descriptor: descriptor_) ? 1 : 0;
161}
162
163int ImmutableStringFieldGenerator::GetNumBitsForBuilder() const {
164 return GetNumBitsForMessage();
165}
166
167// A note about how strings are handled. This code used to just store a String
168// in the Message. This had two issues:
169//
170// 1. It wouldn't roundtrip byte arrays that were not valid UTF-8 encoded
171// strings, but rather fields that were raw bytes incorrectly marked
172// as strings in the proto file. This is common because in the proto1
173// syntax, string was the way to indicate bytes and C++ engineers can
174// easily make this mistake without affecting the C++ API. By converting to
175// strings immediately, some java code might corrupt these byte arrays as
176// it passes through a java server even if the field was never accessed by
177// application code.
178//
179// 2. There's a performance hit to converting between bytes and strings and
180// it many cases, the field is never even read by the application code. This
181// avoids unnecessary conversions in the common use cases.
182//
183// So now, the field for String is maintained as an Object reference which can
184// either store a String or a ByteString. The code uses an instanceof check
185// to see which one it has and converts to the other one if needed. It remembers
186// the last value requested (in a thread safe manner) as this is most likely
187// the one needed next. The thread safety is such that if two threads both
188// convert the field because the changes made by each thread were not visible to
189// the other, they may cause a conversion to happen more times than would
190// otherwise be necessary. This was deemed better than adding synchronization
191// overhead. It will not cause any corruption issues or affect the behavior of
192// the API. The instanceof check is also highly optimized in the JVM and we
193// decided it was better to reduce the memory overhead by not having two
194// separate fields but rather use dynamic type checking.
195//
196// For single fields, the logic for this is done inside the generated code. For
197// repeated fields, the logic is done in LazyStringArrayList and
198// UnmodifiableLazyStringList.
199void ImmutableStringFieldGenerator::GenerateInterfaceMembers(
200 io::Printer* printer) const {
201 if (HasHazzer(descriptor: descriptor_)) {
202 WriteFieldAccessorDocComment(printer, field: descriptor_, type: HAZZER);
203 printer->Print(variables: variables_,
204 text: "$deprecation$boolean has$capitalized_name$();\n");
205 }
206 WriteFieldAccessorDocComment(printer, field: descriptor_, type: GETTER);
207 printer->Print(variables: variables_,
208 text: "$deprecation$java.lang.String get$capitalized_name$();\n");
209 WriteFieldStringBytesAccessorDocComment(printer, field: descriptor_, type: GETTER);
210 printer->Print(variables: variables_,
211 text: "$deprecation$com.google.protobuf.ByteString\n"
212 " get$capitalized_name$Bytes();\n");
213}
214
215void ImmutableStringFieldGenerator::GenerateMembers(
216 io::Printer* printer) const {
217 printer->Print(variables: variables_, text: "private volatile java.lang.Object $name$_;\n");
218 PrintExtraFieldInfo(variables: variables_, printer);
219
220 if (HasHazzer(descriptor: descriptor_)) {
221 WriteFieldAccessorDocComment(printer, field: descriptor_, type: HAZZER);
222 printer->Print(
223 variables: variables_,
224 text: "@java.lang.Override\n"
225 "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
226 " return $get_has_field_bit_message$;\n"
227 "}\n");
228 printer->Annotate(begin_varname: "{", end_varname: "}", descriptor: descriptor_);
229 }
230
231 WriteFieldAccessorDocComment(printer, field: descriptor_, type: GETTER);
232 printer->Print(
233 variables: variables_,
234 text: "@java.lang.Override\n"
235 "$deprecation$public java.lang.String ${$get$capitalized_name$$}$() {\n"
236 " java.lang.Object ref = $name$_;\n"
237 " if (ref instanceof java.lang.String) {\n"
238 " return (java.lang.String) ref;\n"
239 " } else {\n"
240 " com.google.protobuf.ByteString bs = \n"
241 " (com.google.protobuf.ByteString) ref;\n"
242 " java.lang.String s = bs.toStringUtf8();\n");
243 printer->Annotate(begin_varname: "{", end_varname: "}", descriptor: descriptor_);
244 if (CheckUtf8(descriptor: descriptor_)) {
245 printer->Print(variables: variables_, text: " $name$_ = s;\n");
246 } else {
247 printer->Print(variables: variables_,
248 text: " if (bs.isValidUtf8()) {\n"
249 " $name$_ = s;\n"
250 " }\n");
251 }
252 printer->Print(variables: variables_,
253 text: " return s;\n"
254 " }\n"
255 "}\n");
256 WriteFieldStringBytesAccessorDocComment(printer, field: descriptor_, type: GETTER);
257 printer->Print(variables: variables_,
258 text: "@java.lang.Override\n"
259 "$deprecation$public com.google.protobuf.ByteString\n"
260 " ${$get$capitalized_name$Bytes$}$() {\n"
261 " java.lang.Object ref = $name$_;\n"
262 " if (ref instanceof java.lang.String) {\n"
263 " com.google.protobuf.ByteString b = \n"
264 " com.google.protobuf.ByteString.copyFromUtf8(\n"
265 " (java.lang.String) ref);\n"
266 " $name$_ = b;\n"
267 " return b;\n"
268 " } else {\n"
269 " return (com.google.protobuf.ByteString) ref;\n"
270 " }\n"
271 "}\n");
272 printer->Annotate(begin_varname: "{", end_varname: "}", descriptor: descriptor_);
273}
274
275void ImmutableStringFieldGenerator::GenerateBuilderMembers(
276 io::Printer* printer) const {
277 printer->Print(variables: variables_,
278 text: "private java.lang.Object $name$_ $default_init$;\n");
279 if (HasHazzer(descriptor: descriptor_)) {
280 WriteFieldAccessorDocComment(printer, field: descriptor_, type: HAZZER);
281 printer->Print(
282 variables: variables_,
283 text: "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
284 " return $get_has_field_bit_builder$;\n"
285 "}\n");
286 printer->Annotate(begin_varname: "{", end_varname: "}", descriptor: descriptor_);
287 }
288
289 WriteFieldAccessorDocComment(printer, field: descriptor_, type: GETTER);
290 printer->Print(
291 variables: variables_,
292 text: "$deprecation$public java.lang.String ${$get$capitalized_name$$}$() {\n"
293 " java.lang.Object ref = $name$_;\n"
294 " if (!(ref instanceof java.lang.String)) {\n"
295 " com.google.protobuf.ByteString bs =\n"
296 " (com.google.protobuf.ByteString) ref;\n"
297 " java.lang.String s = bs.toStringUtf8();\n");
298 printer->Annotate(begin_varname: "{", end_varname: "}", descriptor: descriptor_);
299 if (CheckUtf8(descriptor: descriptor_)) {
300 printer->Print(variables: variables_, text: " $name$_ = s;\n");
301 } else {
302 printer->Print(variables: variables_,
303 text: " if (bs.isValidUtf8()) {\n"
304 " $name$_ = s;\n"
305 " }\n");
306 }
307 printer->Print(variables: variables_,
308 text: " return s;\n"
309 " } else {\n"
310 " return (java.lang.String) ref;\n"
311 " }\n"
312 "}\n");
313
314 WriteFieldStringBytesAccessorDocComment(printer, field: descriptor_, type: GETTER);
315 printer->Print(variables: variables_,
316 text: "$deprecation$public com.google.protobuf.ByteString\n"
317 " ${$get$capitalized_name$Bytes$}$() {\n"
318 " java.lang.Object ref = $name$_;\n"
319 " if (ref instanceof String) {\n"
320 " com.google.protobuf.ByteString b = \n"
321 " com.google.protobuf.ByteString.copyFromUtf8(\n"
322 " (java.lang.String) ref);\n"
323 " $name$_ = b;\n"
324 " return b;\n"
325 " } else {\n"
326 " return (com.google.protobuf.ByteString) ref;\n"
327 " }\n"
328 "}\n");
329 printer->Annotate(begin_varname: "{", end_varname: "}", descriptor: descriptor_);
330
331 WriteFieldAccessorDocComment(printer, field: descriptor_, type: SETTER,
332 /* builder */ true);
333 printer->Print(variables: variables_,
334 text: "$deprecation$public Builder ${$set$capitalized_name$$}$(\n"
335 " java.lang.String value) {\n"
336 "$null_check$"
337 " $set_has_field_bit_builder$\n"
338 " $name$_ = value;\n"
339 " $on_changed$\n"
340 " return this;\n"
341 "}\n");
342 printer->Annotate(begin_varname: "{", end_varname: "}", descriptor: descriptor_);
343 WriteFieldAccessorDocComment(printer, field: descriptor_, type: CLEARER,
344 /* builder */ true);
345 printer->Print(
346 variables: variables_,
347 text: "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n"
348 " $clear_has_field_bit_builder$\n");
349 printer->Annotate(begin_varname: "{", end_varname: "}", descriptor: descriptor_);
350 // The default value is not a simple literal so we want to avoid executing
351 // it multiple times. Instead, get the default out of the default instance.
352 printer->Print(variables: variables_,
353 text: " $name$_ = getDefaultInstance().get$capitalized_name$();\n");
354 printer->Print(variables: variables_,
355 text: " $on_changed$\n"
356 " return this;\n"
357 "}\n");
358
359 WriteFieldStringBytesAccessorDocComment(printer, field: descriptor_, type: SETTER,
360 /* builder */ true);
361 printer->Print(
362 variables: variables_,
363 text: "$deprecation$public Builder ${$set$capitalized_name$Bytes$}$(\n"
364 " com.google.protobuf.ByteString value) {\n"
365 "$null_check$");
366 printer->Annotate(begin_varname: "{", end_varname: "}", descriptor: descriptor_);
367 if (CheckUtf8(descriptor: descriptor_)) {
368 printer->Print(variables: variables_, text: " checkByteStringIsUtf8(value);\n");
369 }
370 printer->Print(variables: variables_,
371 text: " $set_has_field_bit_builder$\n"
372 " $name$_ = value;\n"
373 " $on_changed$\n"
374 " return this;\n"
375 "}\n");
376}
377
378void ImmutableStringFieldGenerator::GenerateKotlinDslMembers(
379 io::Printer* printer) const {
380 WriteFieldDocComment(printer, field: descriptor_);
381 printer->Print(variables: variables_,
382 text: "$kt_deprecation$var $kt_name$: kotlin.String\n"
383 " @JvmName(\"${$get$kt_capitalized_name$$}$\")\n"
384 " get() = $kt_dsl_builder$.${$get$capitalized_name$$}$()\n"
385 " @JvmName(\"${$set$kt_capitalized_name$$}$\")\n"
386 " set(value) {\n"
387 " $kt_dsl_builder$.${$set$capitalized_name$$}$(value)\n"
388 " }\n");
389
390 WriteFieldAccessorDocComment(printer, field: descriptor_, type: CLEARER,
391 /* builder */ false);
392 printer->Print(variables: variables_,
393 text: "fun ${$clear$kt_capitalized_name$$}$() {\n"
394 " $kt_dsl_builder$.${$clear$capitalized_name$$}$()\n"
395 "}\n");
396
397 if (HasHazzer(descriptor: descriptor_)) {
398 WriteFieldAccessorDocComment(printer, field: descriptor_, type: HAZZER);
399 printer->Print(
400 variables: variables_,
401 text: "fun ${$has$kt_capitalized_name$$}$(): kotlin.Boolean {\n"
402 " return $kt_dsl_builder$.${$has$capitalized_name$$}$()\n"
403 "}\n");
404 }
405}
406
407void ImmutableStringFieldGenerator::GenerateFieldBuilderInitializationCode(
408 io::Printer* printer) const {
409 // noop for primitives
410}
411
412void ImmutableStringFieldGenerator::GenerateInitializationCode(
413 io::Printer* printer) const {
414 printer->Print(variables: variables_, text: "$name$_ = $default$;\n");
415}
416
417void ImmutableStringFieldGenerator::GenerateBuilderClearCode(
418 io::Printer* printer) const {
419 printer->Print(variables: variables_,
420 text: "$name$_ = $default$;\n"
421 "$clear_has_field_bit_builder$\n");
422}
423
424void ImmutableStringFieldGenerator::GenerateMergingCode(
425 io::Printer* printer) const {
426 if (HasHazzer(descriptor: descriptor_)) {
427 // Allow a slight breach of abstraction here in order to avoid forcing
428 // all string fields to Strings when copying fields from a Message.
429 printer->Print(variables: variables_,
430 text: "if (other.has$capitalized_name$()) {\n"
431 " $set_has_field_bit_builder$\n"
432 " $name$_ = other.$name$_;\n"
433 " $on_changed$\n"
434 "}\n");
435 } else {
436 printer->Print(variables: variables_,
437 text: "if (!other.get$capitalized_name$().isEmpty()) {\n"
438 " $name$_ = other.$name$_;\n"
439 " $on_changed$\n"
440 "}\n");
441 }
442}
443
444void ImmutableStringFieldGenerator::GenerateBuildingCode(
445 io::Printer* printer) const {
446 if (HasHazzer(descriptor: descriptor_)) {
447 printer->Print(variables: variables_,
448 text: "if ($get_has_field_bit_from_local$) {\n"
449 " $set_has_field_bit_to_local$;\n"
450 "}\n");
451 }
452 printer->Print(variables: variables_, text: "result.$name$_ = $name$_;\n");
453}
454
455void ImmutableStringFieldGenerator::GenerateParsingCode(
456 io::Printer* printer) const {
457 if (CheckUtf8(descriptor: descriptor_)) {
458 printer->Print(variables: variables_,
459 text: "java.lang.String s = input.readStringRequireUtf8();\n"
460 "$set_has_field_bit_message$\n"
461 "$name$_ = s;\n");
462 } else {
463 printer->Print(variables: variables_,
464 text: "com.google.protobuf.ByteString bs = input.readBytes();\n"
465 "$set_has_field_bit_message$\n"
466 "$name$_ = bs;\n");
467 }
468}
469
470void ImmutableStringFieldGenerator::GenerateParsingDoneCode(
471 io::Printer* printer) const {
472 // noop for strings.
473}
474
475void ImmutableStringFieldGenerator::GenerateSerializationCode(
476 io::Printer* printer) const {
477 printer->Print(variables: variables_,
478 text: "if ($is_field_present_message$) {\n"
479 " $writeString$(output, $number$, $name$_);\n"
480 "}\n");
481}
482
483void ImmutableStringFieldGenerator::GenerateSerializedSizeCode(
484 io::Printer* printer) const {
485 printer->Print(variables: variables_,
486 text: "if ($is_field_present_message$) {\n"
487 " size += $computeStringSize$($number$, $name$_);\n"
488 "}\n");
489}
490
491void ImmutableStringFieldGenerator::GenerateEqualsCode(
492 io::Printer* printer) const {
493 printer->Print(variables: variables_,
494 text: "if (!get$capitalized_name$()\n"
495 " .equals(other.get$capitalized_name$())) return false;\n");
496}
497
498void ImmutableStringFieldGenerator::GenerateHashCode(
499 io::Printer* printer) const {
500 printer->Print(variables: variables_, text: "hash = (37 * hash) + $constant_name$;\n");
501 printer->Print(variables: variables_,
502 text: "hash = (53 * hash) + get$capitalized_name$().hashCode();\n");
503}
504
505std::string ImmutableStringFieldGenerator::GetBoxedType() const {
506 return "java.lang.String";
507}
508
509// ===================================================================
510
511ImmutableStringOneofFieldGenerator::ImmutableStringOneofFieldGenerator(
512 const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex,
513 Context* context)
514 : ImmutableStringFieldGenerator(descriptor, messageBitIndex,
515 builderBitIndex, context) {
516 const OneofGeneratorInfo* info =
517 context->GetOneofGeneratorInfo(oneof: descriptor->containing_oneof());
518 SetCommonOneofVariables(descriptor, info, variables: &variables_);
519}
520
521ImmutableStringOneofFieldGenerator::~ImmutableStringOneofFieldGenerator() {}
522
523void ImmutableStringOneofFieldGenerator::GenerateMembers(
524 io::Printer* printer) const {
525 PrintExtraFieldInfo(variables: variables_, printer);
526 GOOGLE_DCHECK(HasHazzer(descriptor_));
527 WriteFieldAccessorDocComment(printer, field: descriptor_, type: HAZZER);
528 printer->Print(variables: variables_,
529 text: "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
530 " return $has_oneof_case_message$;\n"
531 "}\n");
532 printer->Annotate(begin_varname: "{", end_varname: "}", descriptor: descriptor_);
533
534 WriteFieldAccessorDocComment(printer, field: descriptor_, type: GETTER);
535 printer->Print(
536 variables: variables_,
537 text: "$deprecation$public java.lang.String ${$get$capitalized_name$$}$() {\n"
538 " java.lang.Object ref $default_init$;\n"
539 " if ($has_oneof_case_message$) {\n"
540 " ref = $oneof_name$_;\n"
541 " }\n"
542 " if (ref instanceof java.lang.String) {\n"
543 " return (java.lang.String) ref;\n"
544 " } else {\n"
545 " com.google.protobuf.ByteString bs = \n"
546 " (com.google.protobuf.ByteString) ref;\n"
547 " java.lang.String s = bs.toStringUtf8();\n");
548 printer->Annotate(begin_varname: "{", end_varname: "}", descriptor: descriptor_);
549 if (CheckUtf8(descriptor: descriptor_)) {
550 printer->Print(variables: variables_,
551 text: " if ($has_oneof_case_message$) {\n"
552 " $oneof_name$_ = s;\n"
553 " }\n");
554 } else {
555 printer->Print(variables: variables_,
556 text: " if (bs.isValidUtf8() && ($has_oneof_case_message$)) {\n"
557 " $oneof_name$_ = s;\n"
558 " }\n");
559 }
560 printer->Print(variables: variables_,
561 text: " return s;\n"
562 " }\n"
563 "}\n");
564 WriteFieldStringBytesAccessorDocComment(printer, field: descriptor_, type: GETTER);
565
566 printer->Print(variables: variables_,
567 text: "$deprecation$public com.google.protobuf.ByteString\n"
568 " ${$get$capitalized_name$Bytes$}$() {\n"
569 " java.lang.Object ref $default_init$;\n"
570 " if ($has_oneof_case_message$) {\n"
571 " ref = $oneof_name$_;\n"
572 " }\n"
573 " if (ref instanceof java.lang.String) {\n"
574 " com.google.protobuf.ByteString b = \n"
575 " com.google.protobuf.ByteString.copyFromUtf8(\n"
576 " (java.lang.String) ref);\n"
577 " if ($has_oneof_case_message$) {\n"
578 " $oneof_name$_ = b;\n"
579 " }\n"
580 " return b;\n"
581 " } else {\n"
582 " return (com.google.protobuf.ByteString) ref;\n"
583 " }\n"
584 "}\n");
585 printer->Annotate(begin_varname: "{", end_varname: "}", descriptor: descriptor_);
586}
587
588void ImmutableStringOneofFieldGenerator::GenerateBuilderMembers(
589 io::Printer* printer) const {
590 GOOGLE_DCHECK(HasHazzer(descriptor_));
591 WriteFieldAccessorDocComment(printer, field: descriptor_, type: HAZZER);
592 printer->Print(variables: variables_,
593 text: "@java.lang.Override\n"
594 "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
595 " return $has_oneof_case_message$;\n"
596 "}\n");
597 printer->Annotate(begin_varname: "{", end_varname: "}", descriptor: descriptor_);
598
599 WriteFieldAccessorDocComment(printer, field: descriptor_, type: GETTER);
600 printer->Print(
601 variables: variables_,
602 text: "@java.lang.Override\n"
603 "$deprecation$public java.lang.String ${$get$capitalized_name$$}$() {\n"
604 " java.lang.Object ref $default_init$;\n"
605 " if ($has_oneof_case_message$) {\n"
606 " ref = $oneof_name$_;\n"
607 " }\n"
608 " if (!(ref instanceof java.lang.String)) {\n"
609 " com.google.protobuf.ByteString bs =\n"
610 " (com.google.protobuf.ByteString) ref;\n"
611 " java.lang.String s = bs.toStringUtf8();\n"
612 " if ($has_oneof_case_message$) {\n");
613 printer->Annotate(begin_varname: "{", end_varname: "}", descriptor: descriptor_);
614 if (CheckUtf8(descriptor: descriptor_)) {
615 printer->Print(variables: variables_, text: " $oneof_name$_ = s;\n");
616 } else {
617 printer->Print(variables: variables_,
618 text: " if (bs.isValidUtf8()) {\n"
619 " $oneof_name$_ = s;\n"
620 " }\n");
621 }
622 printer->Print(variables: variables_,
623 text: " }\n"
624 " return s;\n"
625 " } else {\n"
626 " return (java.lang.String) ref;\n"
627 " }\n"
628 "}\n");
629
630 WriteFieldStringBytesAccessorDocComment(printer, field: descriptor_, type: GETTER);
631 printer->Print(variables: variables_,
632 text: "@java.lang.Override\n"
633 "$deprecation$public com.google.protobuf.ByteString\n"
634 " ${$get$capitalized_name$Bytes$}$() {\n"
635 " java.lang.Object ref $default_init$;\n"
636 " if ($has_oneof_case_message$) {\n"
637 " ref = $oneof_name$_;\n"
638 " }\n"
639 " if (ref instanceof String) {\n"
640 " com.google.protobuf.ByteString b = \n"
641 " com.google.protobuf.ByteString.copyFromUtf8(\n"
642 " (java.lang.String) ref);\n"
643 " if ($has_oneof_case_message$) {\n"
644 " $oneof_name$_ = b;\n"
645 " }\n"
646 " return b;\n"
647 " } else {\n"
648 " return (com.google.protobuf.ByteString) ref;\n"
649 " }\n"
650 "}\n");
651 printer->Annotate(begin_varname: "{", end_varname: "}", descriptor: descriptor_);
652
653 WriteFieldAccessorDocComment(printer, field: descriptor_, type: SETTER,
654 /* builder */ true);
655 printer->Print(variables: variables_,
656 text: "$deprecation$public Builder ${$set$capitalized_name$$}$(\n"
657 " java.lang.String value) {\n"
658 "$null_check$"
659 " $set_oneof_case_message$;\n"
660 " $oneof_name$_ = value;\n"
661 " $on_changed$\n"
662 " return this;\n"
663 "}\n");
664 printer->Annotate(begin_varname: "{", end_varname: "}", descriptor: descriptor_);
665 WriteFieldAccessorDocComment(printer, field: descriptor_, type: CLEARER,
666 /* builder */ true);
667 printer->Print(
668 variables: variables_,
669 text: "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n"
670 " if ($has_oneof_case_message$) {\n"
671 " $clear_oneof_case_message$;\n"
672 " $oneof_name$_ = null;\n"
673 " $on_changed$\n"
674 " }\n"
675 " return this;\n"
676 "}\n");
677 printer->Annotate(begin_varname: "{", end_varname: "}", descriptor: descriptor_);
678
679 WriteFieldStringBytesAccessorDocComment(printer, field: descriptor_, type: SETTER,
680 /* builder */ true);
681 printer->Print(
682 variables: variables_,
683 text: "$deprecation$public Builder ${$set$capitalized_name$Bytes$}$(\n"
684 " com.google.protobuf.ByteString value) {\n"
685 "$null_check$");
686 printer->Annotate(begin_varname: "{", end_varname: "}", descriptor: descriptor_);
687 if (CheckUtf8(descriptor: descriptor_)) {
688 printer->Print(variables: variables_, text: " checkByteStringIsUtf8(value);\n");
689 }
690 printer->Print(variables: variables_,
691 text: " $set_oneof_case_message$;\n"
692 " $oneof_name$_ = value;\n"
693 " $on_changed$\n"
694 " return this;\n"
695 "}\n");
696}
697
698void ImmutableStringOneofFieldGenerator::GenerateMergingCode(
699 io::Printer* printer) const {
700 // Allow a slight breach of abstraction here in order to avoid forcing
701 // all string fields to Strings when copying fields from a Message.
702 printer->Print(variables: variables_,
703 text: "$set_oneof_case_message$;\n"
704 "$oneof_name$_ = other.$oneof_name$_;\n"
705 "$on_changed$\n");
706}
707
708void ImmutableStringOneofFieldGenerator::GenerateBuildingCode(
709 io::Printer* printer) const {
710 printer->Print(variables: variables_,
711 text: "if ($has_oneof_case_message$) {\n"
712 " result.$oneof_name$_ = $oneof_name$_;\n"
713 "}\n");
714}
715
716void ImmutableStringOneofFieldGenerator::GenerateParsingCode(
717 io::Printer* printer) const {
718 if (CheckUtf8(descriptor: descriptor_)) {
719 printer->Print(variables: variables_,
720 text: "java.lang.String s = input.readStringRequireUtf8();\n"
721 "$set_oneof_case_message$;\n"
722 "$oneof_name$_ = s;\n");
723 } else {
724 printer->Print(variables: variables_,
725 text: "com.google.protobuf.ByteString bs = input.readBytes();\n"
726 "$set_oneof_case_message$;\n"
727 "$oneof_name$_ = bs;\n");
728 }
729}
730
731void ImmutableStringOneofFieldGenerator::GenerateSerializationCode(
732 io::Printer* printer) const {
733 printer->Print(variables: variables_,
734 text: "if ($has_oneof_case_message$) {\n"
735 " $writeString$(output, $number$, $oneof_name$_);\n"
736 "}\n");
737}
738
739void ImmutableStringOneofFieldGenerator::GenerateSerializedSizeCode(
740 io::Printer* printer) const {
741 printer->Print(variables: variables_,
742 text: "if ($has_oneof_case_message$) {\n"
743 " size += $computeStringSize$($number$, $oneof_name$_);\n"
744 "}\n");
745}
746
747// ===================================================================
748
749RepeatedImmutableStringFieldGenerator::RepeatedImmutableStringFieldGenerator(
750 const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex,
751 Context* context)
752 : descriptor_(descriptor), name_resolver_(context->GetNameResolver()) {
753 SetPrimitiveVariables(descriptor, messageBitIndex, builderBitIndex,
754 info: context->GetFieldGeneratorInfo(field: descriptor),
755 name_resolver: name_resolver_, variables: &variables_);
756}
757
758RepeatedImmutableStringFieldGenerator::
759 ~RepeatedImmutableStringFieldGenerator() {}
760
761int RepeatedImmutableStringFieldGenerator::GetNumBitsForMessage() const {
762 return 0;
763}
764
765int RepeatedImmutableStringFieldGenerator::GetNumBitsForBuilder() const {
766 return 1;
767}
768
769void RepeatedImmutableStringFieldGenerator::GenerateInterfaceMembers(
770 io::Printer* printer) const {
771 WriteFieldAccessorDocComment(printer, field: descriptor_, type: LIST_GETTER);
772 printer->Print(
773 variables: variables_,
774 // NOTE: the same method in the implementation class actually returns
775 // com.google.protobuf.ProtocolStringList (a subclass of List). It's
776 // changed between protobuf 2.5.0 release and protobuf 2.6.1 release.
777 // To retain binary compatibility with both 2.5.0 and 2.6.1 generated
778 // code, we make this interface method return List so both methods
779 // with different return types exist in the compiled byte code.
780 text: "$deprecation$java.util.List<java.lang.String>\n"
781 " get$capitalized_name$List();\n");
782 WriteFieldAccessorDocComment(printer, field: descriptor_, type: LIST_COUNT);
783 printer->Print(variables: variables_,
784 text: "$deprecation$int get$capitalized_name$Count();\n");
785 WriteFieldAccessorDocComment(printer, field: descriptor_, type: LIST_INDEXED_GETTER);
786 printer->Print(
787 variables: variables_,
788 text: "$deprecation$java.lang.String get$capitalized_name$(int index);\n");
789 WriteFieldStringBytesAccessorDocComment(printer, field: descriptor_,
790 type: LIST_INDEXED_GETTER);
791 printer->Print(variables: variables_,
792 text: "$deprecation$com.google.protobuf.ByteString\n"
793 " get$capitalized_name$Bytes(int index);\n");
794}
795
796void RepeatedImmutableStringFieldGenerator::GenerateMembers(
797 io::Printer* printer) const {
798 printer->Print(variables: variables_,
799 text: "private com.google.protobuf.LazyStringList $name$_;\n");
800 PrintExtraFieldInfo(variables: variables_, printer);
801 WriteFieldAccessorDocComment(printer, field: descriptor_, type: LIST_GETTER);
802 printer->Print(variables: variables_,
803 text: "$deprecation$public com.google.protobuf.ProtocolStringList\n"
804 " ${$get$capitalized_name$List$}$() {\n"
805 " return $name$_;\n" // note: unmodifiable list
806 "}\n");
807 printer->Annotate(begin_varname: "{", end_varname: "}", descriptor: descriptor_);
808 WriteFieldAccessorDocComment(printer, field: descriptor_, type: LIST_COUNT);
809 printer->Print(
810 variables: variables_,
811 text: "$deprecation$public int ${$get$capitalized_name$Count$}$() {\n"
812 " return $name$_.size();\n"
813 "}\n");
814 printer->Annotate(begin_varname: "{", end_varname: "}", descriptor: descriptor_);
815 WriteFieldAccessorDocComment(printer, field: descriptor_, type: LIST_INDEXED_GETTER);
816 printer->Print(variables: variables_,
817 text: "$deprecation$public java.lang.String "
818 "${$get$capitalized_name$$}$(int index) {\n"
819 " return $name$_.get(index);\n"
820 "}\n");
821 printer->Annotate(begin_varname: "{", end_varname: "}", descriptor: descriptor_);
822 WriteFieldStringBytesAccessorDocComment(printer, field: descriptor_,
823 type: LIST_INDEXED_GETTER);
824 printer->Print(variables: variables_,
825 text: "$deprecation$public com.google.protobuf.ByteString\n"
826 " ${$get$capitalized_name$Bytes$}$(int index) {\n"
827 " return $name$_.getByteString(index);\n"
828 "}\n");
829 printer->Annotate(begin_varname: "{", end_varname: "}", descriptor: descriptor_);
830}
831
832void RepeatedImmutableStringFieldGenerator::GenerateBuilderMembers(
833 io::Printer* printer) const {
834 // One field is the list and the bit field keeps track of whether the
835 // list is immutable. If it's immutable, the invariant is that it must
836 // either an instance of Collections.emptyList() or it's an ArrayList
837 // wrapped in a Collections.unmodifiableList() wrapper and nobody else has
838 // a reference to the underlying ArrayList. This invariant allows us to
839 // share instances of lists between protocol buffers avoiding expensive
840 // memory allocations. Note, immutable is a strong guarantee here -- not
841 // just that the list cannot be modified via the reference but that the
842 // list can never be modified.
843 printer->Print(
844 variables: variables_,
845 text: "private com.google.protobuf.LazyStringList $name$_ = $empty_list$;\n");
846
847 printer->Print(
848 variables: variables_,
849 text: "private void ensure$capitalized_name$IsMutable() {\n"
850 " if (!$get_mutable_bit_builder$) {\n"
851 " $name$_ = new com.google.protobuf.LazyStringArrayList($name$_);\n"
852 " $set_mutable_bit_builder$;\n"
853 " }\n"
854 "}\n");
855
856 // Note: We return an unmodifiable list because otherwise the caller
857 // could hold on to the returned list and modify it after the message
858 // has been built, thus mutating the message which is supposed to be
859 // immutable.
860 WriteFieldAccessorDocComment(printer, field: descriptor_, type: LIST_GETTER);
861 printer->Print(variables: variables_,
862 text: "$deprecation$public com.google.protobuf.ProtocolStringList\n"
863 " ${$get$capitalized_name$List$}$() {\n"
864 " return $name$_.getUnmodifiableView();\n"
865 "}\n");
866 printer->Annotate(begin_varname: "{", end_varname: "}", descriptor: descriptor_);
867 WriteFieldAccessorDocComment(printer, field: descriptor_, type: LIST_COUNT);
868 printer->Print(
869 variables: variables_,
870 text: "$deprecation$public int ${$get$capitalized_name$Count$}$() {\n"
871 " return $name$_.size();\n"
872 "}\n");
873 printer->Annotate(begin_varname: "{", end_varname: "}", descriptor: descriptor_);
874 WriteFieldAccessorDocComment(printer, field: descriptor_, type: LIST_INDEXED_GETTER);
875 printer->Print(variables: variables_,
876 text: "$deprecation$public java.lang.String "
877 "${$get$capitalized_name$$}$(int index) {\n"
878 " return $name$_.get(index);\n"
879 "}\n");
880 printer->Annotate(begin_varname: "{", end_varname: "}", descriptor: descriptor_);
881 WriteFieldStringBytesAccessorDocComment(printer, field: descriptor_,
882 type: LIST_INDEXED_GETTER);
883 printer->Print(variables: variables_,
884 text: "$deprecation$public com.google.protobuf.ByteString\n"
885 " ${$get$capitalized_name$Bytes$}$(int index) {\n"
886 " return $name$_.getByteString(index);\n"
887 "}\n");
888 printer->Annotate(begin_varname: "{", end_varname: "}", descriptor: descriptor_);
889 WriteFieldAccessorDocComment(printer, field: descriptor_, type: LIST_INDEXED_SETTER,
890 /* builder */ true);
891 printer->Print(variables: variables_,
892 text: "$deprecation$public Builder ${$set$capitalized_name$$}$(\n"
893 " int index, java.lang.String value) {\n"
894 "$null_check$"
895 " ensure$capitalized_name$IsMutable();\n"
896 " $name$_.set(index, value);\n"
897 " $on_changed$\n"
898 " return this;\n"
899 "}\n");
900 printer->Annotate(begin_varname: "{", end_varname: "}", descriptor: descriptor_);
901 WriteFieldAccessorDocComment(printer, field: descriptor_, type: LIST_ADDER,
902 /* builder */ true);
903 printer->Print(variables: variables_,
904 text: "$deprecation$public Builder ${$add$capitalized_name$$}$(\n"
905 " java.lang.String value) {\n"
906 "$null_check$"
907 " ensure$capitalized_name$IsMutable();\n"
908 " $name$_.add(value);\n"
909 " $on_changed$\n"
910 " return this;\n"
911 "}\n");
912 printer->Annotate(begin_varname: "{", end_varname: "}", descriptor: descriptor_);
913 WriteFieldAccessorDocComment(printer, field: descriptor_, type: LIST_MULTI_ADDER,
914 /* builder */ true);
915 printer->Print(variables: variables_,
916 text: "$deprecation$public Builder ${$addAll$capitalized_name$$}$(\n"
917 " java.lang.Iterable<java.lang.String> values) {\n"
918 " ensure$capitalized_name$IsMutable();\n"
919 " com.google.protobuf.AbstractMessageLite.Builder.addAll(\n"
920 " values, $name$_);\n"
921 " $on_changed$\n"
922 " return this;\n"
923 "}\n");
924 printer->Annotate(begin_varname: "{", end_varname: "}", descriptor: descriptor_);
925 WriteFieldAccessorDocComment(printer, field: descriptor_, type: CLEARER,
926 /* builder */ true);
927 printer->Print(
928 variables: variables_,
929 text: "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n"
930 " $name$_ = $empty_list$;\n"
931 " $clear_mutable_bit_builder$;\n"
932 " $on_changed$\n"
933 " return this;\n"
934 "}\n");
935 printer->Annotate(begin_varname: "{", end_varname: "}", descriptor: descriptor_);
936
937 WriteFieldStringBytesAccessorDocComment(printer, field: descriptor_, type: LIST_ADDER,
938 /* builder */ true);
939 printer->Print(
940 variables: variables_,
941 text: "$deprecation$public Builder ${$add$capitalized_name$Bytes$}$(\n"
942 " com.google.protobuf.ByteString value) {\n"
943 "$null_check$");
944 printer->Annotate(begin_varname: "{", end_varname: "}", descriptor: descriptor_);
945 if (CheckUtf8(descriptor: descriptor_)) {
946 printer->Print(variables: variables_, text: " checkByteStringIsUtf8(value);\n");
947 }
948 printer->Print(variables: variables_,
949 text: " ensure$capitalized_name$IsMutable();\n"
950 " $name$_.add(value);\n"
951 " $on_changed$\n"
952 " return this;\n"
953 "}\n");
954}
955
956void RepeatedImmutableStringFieldGenerator::GenerateKotlinDslMembers(
957 io::Printer* printer) const {
958 printer->Print(
959 variables: variables_,
960 text: "/**\n"
961 " * An uninstantiable, behaviorless type to represent the field in\n"
962 " * generics.\n"
963 " */\n"
964 "@kotlin.OptIn"
965 "(com.google.protobuf.kotlin.OnlyForUseByGeneratedProtoCode::class)\n"
966 "class ${$$kt_capitalized_name$Proxy$}$ private constructor()"
967 " : com.google.protobuf.kotlin.DslProxy()\n");
968
969 // property for List<String>
970 WriteFieldAccessorDocComment(printer, field: descriptor_, type: LIST_GETTER);
971 printer->Print(variables: variables_,
972 text: "$kt_deprecation$ val $kt_name$: "
973 "com.google.protobuf.kotlin.DslList"
974 "<kotlin.String, ${$$kt_capitalized_name$Proxy$}$>\n"
975 " @kotlin.jvm.JvmSynthetic\n"
976 " get() = com.google.protobuf.kotlin.DslList(\n"
977 " $kt_dsl_builder$.${$get$capitalized_name$List$}$()\n"
978 " )\n");
979
980 // List<String>.add(String)
981 WriteFieldAccessorDocComment(printer, field: descriptor_, type: LIST_ADDER,
982 /* builder */ false);
983 printer->Print(variables: variables_,
984 text: "@kotlin.jvm.JvmSynthetic\n"
985 "@kotlin.jvm.JvmName(\"add$kt_capitalized_name$\")\n"
986 "fun com.google.protobuf.kotlin.DslList"
987 "<kotlin.String, ${$$kt_capitalized_name$Proxy$}$>."
988 "add(value: kotlin.String) {\n"
989 " $kt_dsl_builder$.${$add$capitalized_name$$}$(value)\n"
990 "}\n");
991
992 // List<String> += String
993 WriteFieldAccessorDocComment(printer, field: descriptor_, type: LIST_ADDER,
994 /* builder */ false);
995 printer->Print(variables: variables_,
996 text: "@kotlin.jvm.JvmSynthetic\n"
997 "@kotlin.jvm.JvmName(\"plusAssign$kt_capitalized_name$\")\n"
998 "@Suppress(\"NOTHING_TO_INLINE\")\n"
999 "inline operator fun com.google.protobuf.kotlin.DslList"
1000 "<kotlin.String, ${$$kt_capitalized_name$Proxy$}$>."
1001 "plusAssign(value: kotlin.String) {\n"
1002 " add(value)\n"
1003 "}\n");
1004
1005 // List<String>.addAll(Iterable<String>)
1006 WriteFieldAccessorDocComment(printer, field: descriptor_, type: LIST_MULTI_ADDER,
1007 /* builder */ false);
1008 printer->Print(
1009 variables: variables_,
1010 text: "@kotlin.jvm.JvmSynthetic\n"
1011 "@kotlin.jvm.JvmName(\"addAll$kt_capitalized_name$\")\n"
1012 "fun com.google.protobuf.kotlin.DslList"
1013 "<kotlin.String, ${$$kt_capitalized_name$Proxy$}$>."
1014 "addAll(values: kotlin.collections.Iterable<kotlin.String>) {\n"
1015 " $kt_dsl_builder$.${$addAll$capitalized_name$$}$(values)\n"
1016 "}\n");
1017
1018 // List<String> += Iterable<String>
1019 WriteFieldAccessorDocComment(printer, field: descriptor_, type: LIST_MULTI_ADDER,
1020 /* builder */ false);
1021 printer->Print(
1022 variables: variables_,
1023 text: "@kotlin.jvm.JvmSynthetic\n"
1024 "@kotlin.jvm.JvmName(\"plusAssignAll$kt_capitalized_name$\")\n"
1025 "@Suppress(\"NOTHING_TO_INLINE\")\n"
1026 "inline operator fun com.google.protobuf.kotlin.DslList"
1027 "<kotlin.String, ${$$kt_capitalized_name$Proxy$}$>."
1028 "plusAssign(values: kotlin.collections.Iterable<kotlin.String>) {\n"
1029 " addAll(values)\n"
1030 "}\n");
1031
1032 // List<String>[Int] = String
1033 WriteFieldAccessorDocComment(printer, field: descriptor_, type: LIST_INDEXED_SETTER,
1034 /* builder */ false);
1035 printer->Print(
1036 variables: variables_,
1037 text: "@kotlin.jvm.JvmSynthetic\n"
1038 "@kotlin.jvm.JvmName(\"set$kt_capitalized_name$\")\n"
1039 "operator fun com.google.protobuf.kotlin.DslList"
1040 "<kotlin.String, ${$$kt_capitalized_name$Proxy$}$>."
1041 "set(index: kotlin.Int, value: kotlin.String) {\n"
1042 " $kt_dsl_builder$.${$set$capitalized_name$$}$(index, value)\n"
1043 "}");
1044
1045 WriteFieldAccessorDocComment(printer, field: descriptor_, type: CLEARER,
1046 /* builder */ false);
1047 printer->Print(variables: variables_,
1048 text: "@kotlin.jvm.JvmSynthetic\n"
1049 "@kotlin.jvm.JvmName(\"clear$kt_capitalized_name$\")\n"
1050 "fun com.google.protobuf.kotlin.DslList"
1051 "<kotlin.String, ${$$kt_capitalized_name$Proxy$}$>."
1052 "clear() {\n"
1053 " $kt_dsl_builder$.${$clear$capitalized_name$$}$()\n"
1054 "}");
1055}
1056
1057void RepeatedImmutableStringFieldGenerator::
1058 GenerateFieldBuilderInitializationCode(io::Printer* printer) const {
1059 // noop for primitives
1060}
1061
1062void RepeatedImmutableStringFieldGenerator::GenerateInitializationCode(
1063 io::Printer* printer) const {
1064 printer->Print(variables: variables_, text: "$name$_ = $empty_list$;\n");
1065}
1066
1067void RepeatedImmutableStringFieldGenerator::GenerateBuilderClearCode(
1068 io::Printer* printer) const {
1069 printer->Print(variables: variables_,
1070 text: "$name$_ = $empty_list$;\n"
1071 "$clear_mutable_bit_builder$;\n");
1072}
1073
1074void RepeatedImmutableStringFieldGenerator::GenerateMergingCode(
1075 io::Printer* printer) const {
1076 // The code below does two optimizations:
1077 // 1. If the other list is empty, there's nothing to do. This ensures we
1078 // don't allocate a new array if we already have an immutable one.
1079 // 2. If the other list is non-empty and our current list is empty, we can
1080 // reuse the other list which is guaranteed to be immutable.
1081 printer->Print(variables: variables_,
1082 text: "if (!other.$name$_.isEmpty()) {\n"
1083 " if ($name$_.isEmpty()) {\n"
1084 " $name$_ = other.$name$_;\n"
1085 " $clear_mutable_bit_builder$;\n"
1086 " } else {\n"
1087 " ensure$capitalized_name$IsMutable();\n"
1088 " $name$_.addAll(other.$name$_);\n"
1089 " }\n"
1090 " $on_changed$\n"
1091 "}\n");
1092}
1093
1094void RepeatedImmutableStringFieldGenerator::GenerateBuildingCode(
1095 io::Printer* printer) const {
1096 // The code below ensures that the result has an immutable list. If our
1097 // list is immutable, we can just reuse it. If not, we make it immutable.
1098
1099 printer->Print(variables: variables_,
1100 text: "if ($get_mutable_bit_builder$) {\n"
1101 " $name$_ = $name$_.getUnmodifiableView();\n"
1102 " $clear_mutable_bit_builder$;\n"
1103 "}\n"
1104 "result.$name$_ = $name$_;\n");
1105}
1106
1107void RepeatedImmutableStringFieldGenerator::GenerateParsingCode(
1108 io::Printer* printer) const {
1109 if (CheckUtf8(descriptor: descriptor_)) {
1110 printer->Print(variables: variables_,
1111 text: "java.lang.String s = input.readStringRequireUtf8();\n");
1112 } else {
1113 printer->Print(variables: variables_,
1114 text: "com.google.protobuf.ByteString bs = input.readBytes();\n");
1115 }
1116 printer->Print(variables: variables_,
1117 text: "if (!$get_mutable_bit_parser$) {\n"
1118 " $name$_ = new com.google.protobuf.LazyStringArrayList();\n"
1119 " $set_mutable_bit_parser$;\n"
1120 "}\n");
1121 if (CheckUtf8(descriptor: descriptor_)) {
1122 printer->Print(variables: variables_, text: "$name$_.add(s);\n");
1123 } else {
1124 printer->Print(variables: variables_, text: "$name$_.add(bs);\n");
1125 }
1126}
1127
1128void RepeatedImmutableStringFieldGenerator::GenerateParsingDoneCode(
1129 io::Printer* printer) const {
1130 printer->Print(variables: variables_,
1131 text: "if ($get_mutable_bit_parser$) {\n"
1132 " $name$_ = $name$_.getUnmodifiableView();\n"
1133 "}\n");
1134}
1135
1136void RepeatedImmutableStringFieldGenerator::GenerateSerializationCode(
1137 io::Printer* printer) const {
1138 printer->Print(variables: variables_,
1139 text: "for (int i = 0; i < $name$_.size(); i++) {\n"
1140 " $writeString$(output, $number$, $name$_.getRaw(i));\n"
1141 "}\n");
1142}
1143
1144void RepeatedImmutableStringFieldGenerator::GenerateSerializedSizeCode(
1145 io::Printer* printer) const {
1146 printer->Print(variables: variables_,
1147 text: "{\n"
1148 " int dataSize = 0;\n");
1149 printer->Indent();
1150
1151 printer->Print(variables: variables_,
1152 text: "for (int i = 0; i < $name$_.size(); i++) {\n"
1153 " dataSize += computeStringSizeNoTag($name$_.getRaw(i));\n"
1154 "}\n");
1155
1156 printer->Print(text: "size += dataSize;\n");
1157
1158 printer->Print(variables: variables_,
1159 text: "size += $tag_size$ * get$capitalized_name$List().size();\n");
1160
1161 printer->Outdent();
1162 printer->Print(text: "}\n");
1163}
1164
1165void RepeatedImmutableStringFieldGenerator::GenerateEqualsCode(
1166 io::Printer* printer) const {
1167 printer->Print(
1168 variables: variables_,
1169 text: "if (!get$capitalized_name$List()\n"
1170 " .equals(other.get$capitalized_name$List())) return false;\n");
1171}
1172
1173void RepeatedImmutableStringFieldGenerator::GenerateHashCode(
1174 io::Printer* printer) const {
1175 printer->Print(
1176 variables: variables_,
1177 text: "if (get$capitalized_name$Count() > 0) {\n"
1178 " hash = (37 * hash) + $constant_name$;\n"
1179 " hash = (53 * hash) + get$capitalized_name$List().hashCode();\n"
1180 "}\n");
1181}
1182
1183std::string RepeatedImmutableStringFieldGenerator::GetBoxedType() const {
1184 return "String";
1185}
1186
1187} // namespace java
1188} // namespace compiler
1189} // namespace protobuf
1190} // namespace google
1191