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