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