1// Protocol Buffers - Google's data interchange format
2// Copyright 2008 Google Inc. All rights reserved.
3// https://developers.google.com/protocol-buffers/
4//
5// Redistribution and use in source and binary forms, with or without
6// modification, are permitted provided that the following conditions are
7// met:
8//
9// * Redistributions of source code must retain the above copyright
10// notice, this list of conditions and the following disclaimer.
11// * Redistributions in binary form must reproduce the above
12// copyright notice, this list of conditions and the following disclaimer
13// in the documentation and/or other materials provided with the
14// distribution.
15// * Neither the name of Google Inc. nor the names of its
16// contributors may be used to endorse or promote products derived from
17// this software without specific prior written permission.
18//
19// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
31// Author: kenton@google.com (Kenton Varda)
32// Based on original Protocol Buffers design by
33// Sanjay Ghemawat, Jeff Dean, and others.
34
35#include <google/protobuf/compiler/java/message.h>
36
37#include <algorithm>
38#include <cstdint>
39#include <map>
40#include <memory>
41#include <vector>
42
43#include <google/protobuf/io/coded_stream.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/stubs/substitute.h>
48#include <google/protobuf/compiler/java/context.h>
49#include <google/protobuf/compiler/java/doc_comment.h>
50#include <google/protobuf/compiler/java/enum.h>
51#include <google/protobuf/compiler/java/extension.h>
52#include <google/protobuf/compiler/java/generator_factory.h>
53#include <google/protobuf/compiler/java/helpers.h>
54#include <google/protobuf/compiler/java/message_builder.h>
55#include <google/protobuf/compiler/java/message_builder_lite.h>
56#include <google/protobuf/compiler/java/name_resolver.h>
57#include <google/protobuf/descriptor.pb.h>
58
59// Must be last.
60#include <google/protobuf/port_def.inc>
61
62namespace google {
63namespace protobuf {
64namespace compiler {
65namespace java {
66
67using internal::WireFormat;
68using internal::WireFormatLite;
69
70namespace {
71std::string MapValueImmutableClassdName(const Descriptor* descriptor,
72 ClassNameResolver* name_resolver) {
73 const FieldDescriptor* value_field = descriptor->map_value();
74 GOOGLE_CHECK_EQ(FieldDescriptor::TYPE_MESSAGE, value_field->type());
75 return name_resolver->GetImmutableClassName(descriptor: value_field->message_type());
76}
77} // namespace
78
79// ===================================================================
80
81MessageGenerator::MessageGenerator(const Descriptor* descriptor)
82 : descriptor_(descriptor) {
83 for (int i = 0; i < descriptor_->field_count(); i++) {
84 if (IsRealOneof(descriptor: descriptor_->field(index: i))) {
85 oneofs_.insert(x: descriptor_->field(index: i)->containing_oneof());
86 }
87 }
88}
89
90MessageGenerator::~MessageGenerator() {}
91
92// ===================================================================
93ImmutableMessageGenerator::ImmutableMessageGenerator(
94 const Descriptor* descriptor, Context* context)
95 : MessageGenerator(descriptor),
96 context_(context),
97 name_resolver_(context->GetNameResolver()),
98 field_generators_(descriptor, context_) {
99 GOOGLE_CHECK(HasDescriptorMethods(descriptor->file(), context->EnforceLite()))
100 << "Generator factory error: A non-lite message generator is used to "
101 "generate lite messages.";
102}
103
104ImmutableMessageGenerator::~ImmutableMessageGenerator() {}
105
106void ImmutableMessageGenerator::GenerateStaticVariables(
107 io::Printer* printer, int* bytecode_estimate) {
108 // Because descriptor.proto (com.google.protobuf.DescriptorProtos) is
109 // used in the construction of descriptors, we have a tricky bootstrapping
110 // problem. To help control static initialization order, we make sure all
111 // descriptors and other static data that depends on them are members of
112 // the outermost class in the file. This way, they will be initialized in
113 // a deterministic order.
114
115 std::map<std::string, std::string> vars;
116 vars["identifier"] = UniqueFileScopeIdentifier(descriptor: descriptor_);
117 vars["index"] = StrCat(a: descriptor_->index());
118 vars["classname"] = name_resolver_->GetImmutableClassName(descriptor: descriptor_);
119 if (descriptor_->containing_type() != NULL) {
120 vars["parent"] = UniqueFileScopeIdentifier(descriptor: descriptor_->containing_type());
121 }
122 if (MultipleJavaFiles(descriptor: descriptor_->file(), /* immutable = */ true)) {
123 // We can only make these package-private since the classes that use them
124 // are in separate files.
125 vars["private"] = "";
126 } else {
127 vars["private"] = "private ";
128 }
129 if (*bytecode_estimate <= kMaxStaticSize) {
130 vars["final"] = "final ";
131 } else {
132 vars["final"] = "";
133 }
134
135 // The descriptor for this type.
136 printer->Print(
137 variables: vars,
138 // TODO(teboring): final needs to be added back. The way to fix it is to
139 // generate methods that can construct the types, and then still declare
140 // the types, and then init them in clinit with the new method calls.
141 text: "$private$static $final$com.google.protobuf.Descriptors.Descriptor\n"
142 " internal_$identifier$_descriptor;\n");
143 *bytecode_estimate += 30;
144
145 // And the FieldAccessorTable.
146 GenerateFieldAccessorTable(printer, bytecode_estimate);
147
148 // Generate static members for all nested types.
149 for (int i = 0; i < descriptor_->nested_type_count(); i++) {
150 // TODO(kenton): Reuse MessageGenerator objects?
151 ImmutableMessageGenerator(descriptor_->nested_type(index: i), context_)
152 .GenerateStaticVariables(printer, bytecode_estimate);
153 }
154}
155
156int ImmutableMessageGenerator::GenerateStaticVariableInitializers(
157 io::Printer* printer) {
158 int bytecode_estimate = 0;
159 std::map<std::string, std::string> vars;
160 vars["identifier"] = UniqueFileScopeIdentifier(descriptor: descriptor_);
161 vars["index"] = StrCat(a: descriptor_->index());
162 vars["classname"] = name_resolver_->GetImmutableClassName(descriptor: descriptor_);
163 if (descriptor_->containing_type() != NULL) {
164 vars["parent"] = UniqueFileScopeIdentifier(descriptor: descriptor_->containing_type());
165 }
166
167 // The descriptor for this type.
168 if (descriptor_->containing_type() == NULL) {
169 printer->Print(variables: vars,
170 text: "internal_$identifier$_descriptor =\n"
171 " getDescriptor().getMessageTypes().get($index$);\n");
172 bytecode_estimate += 30;
173 } else {
174 printer->Print(
175 variables: vars,
176 text: "internal_$identifier$_descriptor =\n"
177 " internal_$parent$_descriptor.getNestedTypes().get($index$);\n");
178 bytecode_estimate += 30;
179 }
180
181 // And the FieldAccessorTable.
182 bytecode_estimate += GenerateFieldAccessorTableInitializer(printer);
183
184 // Generate static member initializers for all nested types.
185 for (int i = 0; i < descriptor_->nested_type_count(); i++) {
186 // TODO(kenton): Reuse MessageGenerator objects?
187 bytecode_estimate +=
188 ImmutableMessageGenerator(descriptor_->nested_type(index: i), context_)
189 .GenerateStaticVariableInitializers(printer);
190 }
191 return bytecode_estimate;
192}
193
194void ImmutableMessageGenerator::GenerateFieldAccessorTable(
195 io::Printer* printer, int* bytecode_estimate) {
196 std::map<std::string, std::string> vars;
197 vars["identifier"] = UniqueFileScopeIdentifier(descriptor: descriptor_);
198 if (MultipleJavaFiles(descriptor: descriptor_->file(), /* immutable = */ true)) {
199 // We can only make these package-private since the classes that use them
200 // are in separate files.
201 vars["private"] = "";
202 } else {
203 vars["private"] = "private ";
204 }
205 if (*bytecode_estimate <= kMaxStaticSize) {
206 vars["final"] = "final ";
207 } else {
208 vars["final"] = "";
209 }
210 vars["ver"] = GeneratedCodeVersionSuffix();
211 printer->Print(
212 variables: vars,
213 text: "$private$static $final$\n"
214 " com.google.protobuf.GeneratedMessage$ver$.FieldAccessorTable\n"
215 " internal_$identifier$_fieldAccessorTable;\n");
216
217 // The following bytecode_estimate calculation logic must stay in sync with
218 // the similar logic in the GenerateFieldAccessorTableInitializer method below
219 // to make sure that the generated static final fields are initialized in the
220 // static initialization block directly.
221 //
222 // 6 bytes per field and oneof
223 *bytecode_estimate +=
224 10 + 6 * descriptor_->field_count() + 6 * descriptor_->oneof_decl_count();
225}
226
227int ImmutableMessageGenerator::GenerateFieldAccessorTableInitializer(
228 io::Printer* printer) {
229 int bytecode_estimate = 10;
230 printer->Print(
231 text: "internal_$identifier$_fieldAccessorTable = new\n"
232 " com.google.protobuf.GeneratedMessage$ver$.FieldAccessorTable(\n"
233 " internal_$identifier$_descriptor,\n"
234 " new java.lang.String[] { ",
235 args: "identifier", args: UniqueFileScopeIdentifier(descriptor: descriptor_), args: "ver",
236 args: GeneratedCodeVersionSuffix());
237 // All the bytecode_estimate calculation logic in this method must stay in
238 // sync with the similar logic in the GenerateFieldAccessorTable method
239 // above. See the corresponding comment in GenerateFieldAccessorTable for
240 // details.
241 for (int i = 0; i < descriptor_->field_count(); i++) {
242 const FieldDescriptor* field = descriptor_->field(index: i);
243 const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field);
244 bytecode_estimate += 6;
245 printer->Print(text: "\"$field_name$\", ", args: "field_name", args: info->capitalized_name);
246 }
247 // We reproduce synthetic oneofs here since proto reflection needs these.
248 for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
249 const OneofDescriptor* oneof = descriptor_->oneof_decl(index: i);
250 const OneofGeneratorInfo* info = context_->GetOneofGeneratorInfo(oneof);
251 bytecode_estimate += 6;
252 printer->Print(text: "\"$oneof_name$\", ", args: "oneof_name", args: info->capitalized_name);
253 }
254 printer->Print(text: "});\n");
255 return bytecode_estimate;
256}
257
258// ===================================================================
259
260void ImmutableMessageGenerator::GenerateInterface(io::Printer* printer) {
261 MaybePrintGeneratedAnnotation(context: context_, printer, descriptor: descriptor_,
262 /* immutable = */ true, suffix: "OrBuilder");
263 if (descriptor_->extension_range_count() > 0) {
264 printer->Print(
265 text: "$deprecation$public interface ${$$classname$OrBuilder$}$ extends\n"
266 " $extra_interfaces$\n"
267 " com.google.protobuf.GeneratedMessage$ver$.\n"
268 " ExtendableMessageOrBuilder<$classname$> {\n",
269 args: "deprecation",
270 args: descriptor_->options().deprecated() ? "@java.lang.Deprecated " : "",
271 args: "extra_interfaces", args: ExtraMessageOrBuilderInterfaces(descriptor: descriptor_),
272 args: "classname", args: descriptor_->name(), args: "{", args: "", args: "}", args: "", args: "ver",
273 args: GeneratedCodeVersionSuffix());
274 } else {
275 printer->Print(
276 text: "$deprecation$public interface ${$$classname$OrBuilder$}$ extends\n"
277 " $extra_interfaces$\n"
278 " com.google.protobuf.MessageOrBuilder {\n",
279 args: "deprecation",
280 args: descriptor_->options().deprecated() ? "@java.lang.Deprecated " : "",
281 args: "extra_interfaces", args: ExtraMessageOrBuilderInterfaces(descriptor: descriptor_),
282 args: "classname", args: descriptor_->name(), args: "{", args: "", args: "}", args: "");
283 }
284 printer->Annotate(begin_varname: "{", end_varname: "}", descriptor: descriptor_);
285
286 printer->Indent();
287 for (int i = 0; i < descriptor_->field_count(); i++) {
288 printer->Print(text: "\n");
289 field_generators_.get(field: descriptor_->field(index: i))
290 .GenerateInterfaceMembers(printer);
291 }
292 for (auto oneof : oneofs_) {
293 printer->Print(
294 text: "\n"
295 "public $classname$.$oneof_capitalized_name$Case "
296 "get$oneof_capitalized_name$Case();\n",
297 args: "oneof_capitalized_name",
298 args: context_->GetOneofGeneratorInfo(oneof)->capitalized_name, args: "classname",
299 args: context_->GetNameResolver()->GetImmutableClassName(descriptor: descriptor_));
300 }
301 printer->Outdent();
302
303 printer->Print(text: "}\n");
304}
305
306// ===================================================================
307
308void ImmutableMessageGenerator::Generate(io::Printer* printer) {
309 bool is_own_file = IsOwnFile(descriptor: descriptor_, /* immutable = */ true);
310
311 std::map<std::string, std::string> variables;
312 variables["static"] = is_own_file ? "" : "static ";
313 variables["classname"] = descriptor_->name();
314 variables["extra_interfaces"] = ExtraMessageInterfaces(descriptor: descriptor_);
315 variables["ver"] = GeneratedCodeVersionSuffix();
316 variables["deprecation"] =
317 descriptor_->options().deprecated() ? "@java.lang.Deprecated " : "";
318
319 WriteMessageDocComment(printer, message: descriptor_);
320 MaybePrintGeneratedAnnotation(context: context_, printer, descriptor: descriptor_,
321 /* immutable = */ true);
322 // The builder_type stores the super type name of the nested Builder class.
323 std::string builder_type;
324 if (descriptor_->extension_range_count() > 0) {
325 printer->Print(
326 variables,
327 text: "$deprecation$public $static$final class $classname$ extends\n");
328 printer->Annotate(varname: "classname", descriptor: descriptor_);
329 printer->Print(
330 variables,
331 text: " com.google.protobuf.GeneratedMessage$ver$.ExtendableMessage<\n"
332 " $classname$> implements\n"
333 " $extra_interfaces$\n"
334 " $classname$OrBuilder {\n");
335 builder_type = strings::Substitute(
336 format: "com.google.protobuf.GeneratedMessage$1.ExtendableBuilder<$0, ?>",
337 arg0: name_resolver_->GetImmutableClassName(descriptor: descriptor_),
338 arg1: GeneratedCodeVersionSuffix());
339 } else {
340 printer->Print(
341 variables,
342 text: "$deprecation$public $static$final class $classname$ extends\n");
343 printer->Annotate(varname: "classname", descriptor: descriptor_);
344 printer->Print(variables,
345 text: " com.google.protobuf.GeneratedMessage$ver$ implements\n"
346 " $extra_interfaces$\n"
347 " $classname$OrBuilder {\n");
348 builder_type =
349 strings::Substitute(format: "com.google.protobuf.GeneratedMessage$0.Builder<?>",
350 arg0: GeneratedCodeVersionSuffix());
351 }
352 printer->Print(text: "private static final long serialVersionUID = 0L;\n");
353
354 printer->Indent();
355 // Using builder_type, instead of Builder, prevents the Builder class from
356 // being loaded into PermGen space when the default instance is created.
357 // This optimizes the PermGen space usage for clients that do not modify
358 // messages.
359 printer->Print(
360 text: "// Use $classname$.newBuilder() to construct.\n"
361 "private $classname$($buildertype$ builder) {\n"
362 " super(builder);\n"
363 "}\n",
364 args: "classname", args: descriptor_->name(), args: "buildertype", args: builder_type);
365 printer->Print(text: "private $classname$() {\n", args: "classname", args: descriptor_->name());
366 printer->Indent();
367 GenerateInitializers(printer);
368 printer->Outdent();
369 printer->Print(
370 text: "}\n"
371 "\n");
372
373 printer->Print(variables,
374 text: "@java.lang.Override\n"
375 "@SuppressWarnings({\"unused\"})\n"
376 "protected java.lang.Object newInstance(\n"
377 " UnusedPrivateParameter unused) {\n"
378 " return new $classname$();\n"
379 "}\n"
380 "\n");
381
382 printer->Print(
383 text: "@java.lang.Override\n"
384 "public final com.google.protobuf.UnknownFieldSet\n"
385 "getUnknownFields() {\n"
386 " return this.unknownFields;\n"
387 "}\n");
388
389 if (context_->HasGeneratedMethods(descriptor: descriptor_)) {
390 GenerateParsingConstructor(printer);
391 }
392
393 GenerateDescriptorMethods(printer);
394
395 // Nested types
396 for (int i = 0; i < descriptor_->enum_type_count(); i++) {
397 EnumGenerator(descriptor_->enum_type(index: i), true, context_).Generate(printer);
398 }
399
400 for (int i = 0; i < descriptor_->nested_type_count(); i++) {
401 // Don't generate Java classes for map entry messages.
402 if (IsMapEntry(descriptor: descriptor_->nested_type(index: i))) continue;
403 ImmutableMessageGenerator messageGenerator(descriptor_->nested_type(index: i),
404 context_);
405 messageGenerator.GenerateInterface(printer);
406 messageGenerator.Generate(printer);
407 }
408
409 // Integers for bit fields.
410 int totalBits = 0;
411 for (int i = 0; i < descriptor_->field_count(); i++) {
412 totalBits +=
413 field_generators_.get(field: descriptor_->field(index: i)).GetNumBitsForMessage();
414 }
415 int totalInts = (totalBits + 31) / 32;
416 for (int i = 0; i < totalInts; i++) {
417 printer->Print(text: "private int $bit_field_name$;\n", args: "bit_field_name",
418 args: GetBitFieldName(index: i));
419 }
420
421 // oneof
422 std::map<std::string, std::string> vars;
423 for (auto oneof : oneofs_) {
424 vars["oneof_name"] = context_->GetOneofGeneratorInfo(oneof)->name;
425 vars["oneof_capitalized_name"] =
426 context_->GetOneofGeneratorInfo(oneof)->capitalized_name;
427 vars["oneof_index"] = StrCat(a: (oneof)->index());
428 // oneofCase_ and oneof_
429 printer->Print(variables: vars,
430 text: "private int $oneof_name$Case_ = 0;\n"
431 "private java.lang.Object $oneof_name$_;\n");
432 // OneofCase enum
433 printer->Print(
434 variables: vars,
435 text: "public enum $oneof_capitalized_name$Case\n"
436 // TODO(dweis): Remove EnumLite when we want to break compatibility with
437 // 3.x users
438 " implements com.google.protobuf.Internal.EnumLite,\n"
439 " com.google.protobuf.AbstractMessage.InternalOneOfEnum {\n");
440 printer->Indent();
441 for (int j = 0; j < (oneof)->field_count(); j++) {
442 const FieldDescriptor* field = (oneof)->field(index: j);
443 printer->Print(
444 text: "$deprecation$$field_name$($field_number$),\n", args: "deprecation",
445 args: field->options().deprecated() ? "@java.lang.Deprecated " : "",
446 args: "field_name", args: ToUpper(s: field->name()), args: "field_number",
447 args: StrCat(a: field->number()));
448 }
449 printer->Print(text: "$cap_oneof_name$_NOT_SET(0);\n", args: "cap_oneof_name",
450 args: ToUpper(s: vars["oneof_name"]));
451 printer->Print(variables: vars,
452 text: "private final int value;\n"
453 "private $oneof_capitalized_name$Case(int value) {\n"
454 " this.value = value;\n"
455 "}\n");
456 printer->Print(
457 variables: vars,
458 text: "/**\n"
459 " * @param value The number of the enum to look for.\n"
460 " * @return The enum associated with the given number.\n"
461 " * @deprecated Use {@link #forNumber(int)} instead.\n"
462 " */\n"
463 "@java.lang.Deprecated\n"
464 "public static $oneof_capitalized_name$Case valueOf(int value) {\n"
465 " return forNumber(value);\n"
466 "}\n"
467 "\n"
468 "public static $oneof_capitalized_name$Case forNumber(int value) {\n"
469 " switch (value) {\n");
470 for (int j = 0; j < (oneof)->field_count(); j++) {
471 const FieldDescriptor* field = (oneof)->field(index: j);
472 printer->Print(text: " case $field_number$: return $field_name$;\n",
473 args: "field_number", args: StrCat(a: field->number()),
474 args: "field_name", args: ToUpper(s: field->name()));
475 }
476 printer->Print(
477 text: " case 0: return $cap_oneof_name$_NOT_SET;\n"
478 " default: return null;\n"
479 " }\n"
480 "}\n"
481 "public int getNumber() {\n"
482 " return this.value;\n"
483 "}\n",
484 args: "cap_oneof_name", args: ToUpper(s: vars["oneof_name"]));
485 printer->Outdent();
486 printer->Print(text: "};\n\n");
487 // oneofCase()
488 printer->Print(variables: vars,
489 text: "public $oneof_capitalized_name$Case\n"
490 "get$oneof_capitalized_name$Case() {\n"
491 " return $oneof_capitalized_name$Case.forNumber(\n"
492 " $oneof_name$Case_);\n"
493 "}\n"
494 "\n");
495 }
496
497 if (IsAnyMessage(descriptor: descriptor_)) {
498 GenerateAnyMethods(printer);
499 }
500
501 // Fields
502 for (int i = 0; i < descriptor_->field_count(); i++) {
503 printer->Print(text: "public static final int $constant_name$ = $number$;\n",
504 args: "constant_name", args: FieldConstantName(field: descriptor_->field(index: i)),
505 args: "number", args: StrCat(a: descriptor_->field(index: i)->number()));
506 printer->Annotate(varname: "constant_name", descriptor: descriptor_->field(index: i));
507 field_generators_.get(field: descriptor_->field(index: i)).GenerateMembers(printer);
508 printer->Print(text: "\n");
509 }
510
511 if (context_->HasGeneratedMethods(descriptor: descriptor_)) {
512 GenerateIsInitialized(printer);
513 GenerateMessageSerializationMethods(printer);
514 GenerateEqualsAndHashCode(printer);
515 }
516
517
518 GenerateParseFromMethods(printer);
519 GenerateBuilder(printer);
520
521 printer->Print(
522 text: "\n"
523 "// @@protoc_insertion_point(class_scope:$full_name$)\n",
524 args: "full_name", args: descriptor_->full_name());
525
526 // Carefully initialize the default instance in such a way that it doesn't
527 // conflict with other initialization.
528 printer->Print(text: "private static final $classname$ DEFAULT_INSTANCE;\n",
529 args: "classname",
530 args: name_resolver_->GetImmutableClassName(descriptor: descriptor_));
531 printer->Print(
532 text: "static {\n"
533 " DEFAULT_INSTANCE = new $classname$();\n"
534 "}\n"
535 "\n",
536 args: "classname", args: name_resolver_->GetImmutableClassName(descriptor: descriptor_));
537
538 printer->Print(
539 text: "public static $classname$ getDefaultInstance() {\n"
540 " return DEFAULT_INSTANCE;\n"
541 "}\n"
542 "\n",
543 args: "classname", args: name_resolver_->GetImmutableClassName(descriptor: descriptor_));
544
545 // 'of' method for Wrappers
546 if (IsWrappersProtoFile(descriptor: descriptor_->file())) {
547 printer->Print(
548 text: "public static $classname$ of($field_type$ value) {\n"
549 " return newBuilder().setValue(value).build();\n"
550 "}\n"
551 "\n",
552 args: "classname", args: name_resolver_->GetImmutableClassName(descriptor: descriptor_),
553 args: "field_type", args: PrimitiveTypeName(type: GetJavaType(field: descriptor_->field(index: 0))));
554 }
555
556 GenerateParser(printer);
557
558 printer->Print(
559 text: "@java.lang.Override\n"
560 "public $classname$ getDefaultInstanceForType() {\n"
561 " return DEFAULT_INSTANCE;\n"
562 "}\n"
563 "\n",
564 args: "classname", args: name_resolver_->GetImmutableClassName(descriptor: descriptor_));
565
566 // Extensions must be declared after the DEFAULT_INSTANCE is initialized
567 // because the DEFAULT_INSTANCE is used by the extension to lazily retrieve
568 // the outer class's FileDescriptor.
569 for (int i = 0; i < descriptor_->extension_count(); i++) {
570 ImmutableExtensionGenerator(descriptor_->extension(index: i), context_)
571 .Generate(printer);
572 }
573
574 printer->Outdent();
575 printer->Print(text: "}\n\n");
576}
577
578// ===================================================================
579
580void ImmutableMessageGenerator::GenerateMessageSerializationMethods(
581 io::Printer* printer) {
582 std::unique_ptr<const FieldDescriptor*[]> sorted_fields(
583 SortFieldsByNumber(descriptor: descriptor_));
584
585 std::vector<const Descriptor::ExtensionRange*> sorted_extensions;
586 sorted_extensions.reserve(n: descriptor_->extension_range_count());
587 for (int i = 0; i < descriptor_->extension_range_count(); ++i) {
588 sorted_extensions.push_back(x: descriptor_->extension_range(index: i));
589 }
590 std::sort(first: sorted_extensions.begin(), last: sorted_extensions.end(),
591 comp: ExtensionRangeOrdering());
592 printer->Print(
593 text: "@java.lang.Override\n"
594 "public void writeTo(com.google.protobuf.CodedOutputStream output)\n"
595 " throws java.io.IOException {\n");
596 printer->Indent();
597
598 if (HasPackedFields(descriptor: descriptor_)) {
599 // writeTo(CodedOutputStream output) might be invoked without
600 // getSerializedSize() ever being called, but we need the memoized
601 // sizes in case this message has packed fields. Rather than emit checks
602 // for each packed field, just call getSerializedSize() up front. In most
603 // cases, getSerializedSize() will have already been called anyway by one
604 // of the wrapper writeTo() methods, making this call cheap.
605 printer->Print(text: "getSerializedSize();\n");
606 }
607
608 if (descriptor_->extension_range_count() > 0) {
609 if (descriptor_->options().message_set_wire_format()) {
610 printer->Print(
611 text: "com.google.protobuf.GeneratedMessage$ver$\n"
612 " .ExtendableMessage<$classname$>.ExtensionWriter\n"
613 " extensionWriter = newMessageSetExtensionWriter();\n",
614 args: "classname", args: name_resolver_->GetImmutableClassName(descriptor: descriptor_),
615 args: "ver", args: GeneratedCodeVersionSuffix());
616 } else {
617 printer->Print(
618 text: "com.google.protobuf.GeneratedMessage$ver$\n"
619 " .ExtendableMessage<$classname$>.ExtensionWriter\n"
620 " extensionWriter = newExtensionWriter();\n",
621 args: "classname", args: name_resolver_->GetImmutableClassName(descriptor: descriptor_),
622 args: "ver", args: GeneratedCodeVersionSuffix());
623 }
624 }
625
626 // Merge the fields and the extension ranges, both sorted by field number.
627 for (int i = 0, j = 0;
628 i < descriptor_->field_count() || j < sorted_extensions.size();) {
629 if (i == descriptor_->field_count()) {
630 GenerateSerializeOneExtensionRange(printer, range: sorted_extensions[j++]);
631 } else if (j == sorted_extensions.size()) {
632 GenerateSerializeOneField(printer, field: sorted_fields[i++]);
633 } else if (sorted_fields[i]->number() < sorted_extensions[j]->start) {
634 GenerateSerializeOneField(printer, field: sorted_fields[i++]);
635 } else {
636 GenerateSerializeOneExtensionRange(printer, range: sorted_extensions[j++]);
637 }
638 }
639
640 if (descriptor_->options().message_set_wire_format()) {
641 printer->Print(text: "unknownFields.writeAsMessageSetTo(output);\n");
642 } else {
643 printer->Print(text: "unknownFields.writeTo(output);\n");
644 }
645
646 printer->Outdent();
647 printer->Print(
648 text: "}\n"
649 "\n"
650 "@java.lang.Override\n"
651 "public int getSerializedSize() {\n"
652 " int size = memoizedSize;\n"
653 " if (size != -1) return size;\n"
654 "\n");
655 printer->Indent();
656
657 printer->Print(text: "size = 0;\n");
658
659 for (int i = 0; i < descriptor_->field_count(); i++) {
660 field_generators_.get(field: sorted_fields[i]).GenerateSerializedSizeCode(printer);
661 }
662
663 if (descriptor_->extension_range_count() > 0) {
664 if (descriptor_->options().message_set_wire_format()) {
665 printer->Print(text: "size += extensionsSerializedSizeAsMessageSet();\n");
666 } else {
667 printer->Print(text: "size += extensionsSerializedSize();\n");
668 }
669 }
670
671 if (descriptor_->options().message_set_wire_format()) {
672 printer->Print(text: "size += unknownFields.getSerializedSizeAsMessageSet();\n");
673 } else {
674 printer->Print(text: "size += unknownFields.getSerializedSize();\n");
675 }
676
677 printer->Print(
678 text: "memoizedSize = size;\n"
679 "return size;\n");
680
681 printer->Outdent();
682 printer->Print(
683 text: "}\n"
684 "\n");
685}
686
687void ImmutableMessageGenerator::GenerateParseFromMethods(io::Printer* printer) {
688 // Note: These are separate from GenerateMessageSerializationMethods()
689 // because they need to be generated even for messages that are optimized
690 // for code size.
691 printer->Print(
692 text: "public static $classname$ parseFrom(\n"
693 " java.nio.ByteBuffer data)\n"
694 " throws com.google.protobuf.InvalidProtocolBufferException {\n"
695 " return PARSER.parseFrom(data);\n"
696 "}\n"
697 "public static $classname$ parseFrom(\n"
698 " java.nio.ByteBuffer data,\n"
699 " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
700 " throws com.google.protobuf.InvalidProtocolBufferException {\n"
701 " return PARSER.parseFrom(data, extensionRegistry);\n"
702 "}\n"
703 "public static $classname$ parseFrom(\n"
704 " com.google.protobuf.ByteString data)\n"
705 " throws com.google.protobuf.InvalidProtocolBufferException {\n"
706 " return PARSER.parseFrom(data);\n"
707 "}\n"
708 "public static $classname$ parseFrom(\n"
709 " com.google.protobuf.ByteString data,\n"
710 " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
711 " throws com.google.protobuf.InvalidProtocolBufferException {\n"
712 " return PARSER.parseFrom(data, extensionRegistry);\n"
713 "}\n"
714 "public static $classname$ parseFrom(byte[] data)\n"
715 " throws com.google.protobuf.InvalidProtocolBufferException {\n"
716 " return PARSER.parseFrom(data);\n"
717 "}\n"
718 "public static $classname$ parseFrom(\n"
719 " byte[] data,\n"
720 " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
721 " throws com.google.protobuf.InvalidProtocolBufferException {\n"
722 " return PARSER.parseFrom(data, extensionRegistry);\n"
723 "}\n"
724 "public static $classname$ parseFrom(java.io.InputStream input)\n"
725 " throws java.io.IOException {\n"
726 " return com.google.protobuf.GeneratedMessage$ver$\n"
727 " .parseWithIOException(PARSER, input);\n"
728 "}\n"
729 "public static $classname$ parseFrom(\n"
730 " java.io.InputStream input,\n"
731 " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
732 " throws java.io.IOException {\n"
733 " return com.google.protobuf.GeneratedMessage$ver$\n"
734 " .parseWithIOException(PARSER, input, extensionRegistry);\n"
735 "}\n"
736 "public static $classname$ parseDelimitedFrom(java.io.InputStream "
737 "input)\n"
738 " throws java.io.IOException {\n"
739 " return com.google.protobuf.GeneratedMessage$ver$\n"
740 " .parseDelimitedWithIOException(PARSER, input);\n"
741 "}\n"
742 "public static $classname$ parseDelimitedFrom(\n"
743 " java.io.InputStream input,\n"
744 " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
745 " throws java.io.IOException {\n"
746 " return com.google.protobuf.GeneratedMessage$ver$\n"
747 " .parseDelimitedWithIOException(PARSER, input, "
748 "extensionRegistry);\n"
749 "}\n"
750 "public static $classname$ parseFrom(\n"
751 " com.google.protobuf.CodedInputStream input)\n"
752 " throws java.io.IOException {\n"
753 " return com.google.protobuf.GeneratedMessage$ver$\n"
754 " .parseWithIOException(PARSER, input);\n"
755 "}\n"
756 "public static $classname$ parseFrom(\n"
757 " com.google.protobuf.CodedInputStream input,\n"
758 " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
759 " throws java.io.IOException {\n"
760 " return com.google.protobuf.GeneratedMessage$ver$\n"
761 " .parseWithIOException(PARSER, input, extensionRegistry);\n"
762 "}\n"
763 "\n",
764 args: "classname", args: name_resolver_->GetImmutableClassName(descriptor: descriptor_), args: "ver",
765 args: GeneratedCodeVersionSuffix());
766}
767
768void ImmutableMessageGenerator::GenerateSerializeOneField(
769 io::Printer* printer, const FieldDescriptor* field) {
770 field_generators_.get(field).GenerateSerializationCode(printer);
771}
772
773void ImmutableMessageGenerator::GenerateSerializeOneExtensionRange(
774 io::Printer* printer, const Descriptor::ExtensionRange* range) {
775 printer->Print(text: "extensionWriter.writeUntil($end$, output);\n", args: "end",
776 args: StrCat(a: range->end));
777}
778
779// ===================================================================
780
781void ImmutableMessageGenerator::GenerateBuilder(io::Printer* printer) {
782 // LITE_RUNTIME implements this at the GeneratedMessageLite level.
783 printer->Print(
784 text: "@java.lang.Override\n"
785 "public Builder newBuilderForType() { return newBuilder(); }\n");
786
787 printer->Print(
788 text: "public static Builder newBuilder() {\n"
789 " return DEFAULT_INSTANCE.toBuilder();\n"
790 "}\n"
791 "public static Builder newBuilder($classname$ prototype) {\n"
792 " return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);\n"
793 "}\n"
794 "@java.lang.Override\n"
795 "public Builder toBuilder() {\n"
796 " return this == DEFAULT_INSTANCE\n"
797 " ? new Builder() : new Builder().mergeFrom(this);\n"
798 "}\n"
799 "\n",
800 args: "classname", args: name_resolver_->GetImmutableClassName(descriptor: descriptor_));
801
802 printer->Print(
803 text: "@java.lang.Override\n"
804 "protected Builder newBuilderForType(\n"
805 " com.google.protobuf.GeneratedMessage$ver$.BuilderParent parent) {\n"
806 " Builder builder = new Builder(parent);\n"
807 " return builder;\n"
808 "}\n",
809 args: "ver", args: GeneratedCodeVersionSuffix());
810
811 MessageBuilderGenerator builderGenerator(descriptor_, context_);
812 builderGenerator.Generate(printer);
813}
814
815void ImmutableMessageGenerator::GenerateDescriptorMethods(
816 io::Printer* printer) {
817 if (!descriptor_->options().no_standard_descriptor_accessor()) {
818 printer->Print(
819 text: "public static final com.google.protobuf.Descriptors.Descriptor\n"
820 " getDescriptor() {\n"
821 " return $fileclass$.internal_$identifier$_descriptor;\n"
822 "}\n"
823 "\n",
824 args: "fileclass", args: name_resolver_->GetImmutableClassName(descriptor: descriptor_->file()),
825 args: "identifier", args: UniqueFileScopeIdentifier(descriptor: descriptor_));
826 }
827 std::vector<const FieldDescriptor*> map_fields;
828 for (int i = 0; i < descriptor_->field_count(); i++) {
829 const FieldDescriptor* field = descriptor_->field(index: i);
830 if (GetJavaType(field) == JAVATYPE_MESSAGE &&
831 IsMapEntry(descriptor: field->message_type())) {
832 map_fields.push_back(x: field);
833 }
834 }
835 if (!map_fields.empty()) {
836 printer->Print(
837 text: "@SuppressWarnings({\"rawtypes\"})\n"
838 "@java.lang.Override\n"
839 "protected com.google.protobuf.MapField internalGetMapField(\n"
840 " int number) {\n"
841 " switch (number) {\n");
842 printer->Indent();
843 printer->Indent();
844 for (int i = 0; i < map_fields.size(); ++i) {
845 const FieldDescriptor* field = map_fields[i];
846 const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field);
847 printer->Print(
848 text: "case $number$:\n"
849 " return internalGet$capitalized_name$();\n",
850 args: "number", args: StrCat(a: field->number()), args: "capitalized_name",
851 args: info->capitalized_name);
852 }
853 printer->Print(
854 text: "default:\n"
855 " throw new RuntimeException(\n"
856 " \"Invalid map field number: \" + number);\n");
857 printer->Outdent();
858 printer->Outdent();
859 printer->Print(
860 text: " }\n"
861 "}\n");
862 }
863 printer->Print(
864 text: "@java.lang.Override\n"
865 "protected com.google.protobuf.GeneratedMessage$ver$.FieldAccessorTable\n"
866 " internalGetFieldAccessorTable() {\n"
867 " return $fileclass$.internal_$identifier$_fieldAccessorTable\n"
868 " .ensureFieldAccessorsInitialized(\n"
869 " $classname$.class, $classname$.Builder.class);\n"
870 "}\n"
871 "\n",
872 args: "classname", args: name_resolver_->GetImmutableClassName(descriptor: descriptor_),
873 args: "fileclass", args: name_resolver_->GetImmutableClassName(descriptor: descriptor_->file()),
874 args: "identifier", args: UniqueFileScopeIdentifier(descriptor: descriptor_), args: "ver",
875 args: GeneratedCodeVersionSuffix());
876}
877
878// ===================================================================
879
880void ImmutableMessageGenerator::GenerateIsInitialized(io::Printer* printer) {
881 // Memoizes whether the protocol buffer is fully initialized (has all
882 // required fields). -1 means not yet computed. 0 means false and 1 means
883 // true.
884 printer->Print(text: "private byte memoizedIsInitialized = -1;\n");
885 printer->Print(
886 text: "@java.lang.Override\n"
887 "public final boolean isInitialized() {\n");
888 printer->Indent();
889
890 // Don't directly compare to -1 to avoid an Android x86 JIT bug.
891 printer->Print(
892 text: "byte isInitialized = memoizedIsInitialized;\n"
893 "if (isInitialized == 1) return true;\n"
894 "if (isInitialized == 0) return false;\n"
895 "\n");
896
897 // Check that all required fields in this message are set.
898 // TODO(kenton): We can optimize this when we switch to putting all the
899 // "has" fields into a single bitfield.
900 for (int i = 0; i < descriptor_->field_count(); i++) {
901 const FieldDescriptor* field = descriptor_->field(index: i);
902 const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field);
903
904 if (field->is_required()) {
905 printer->Print(
906 text: "if (!has$name$()) {\n"
907 " memoizedIsInitialized = 0;\n"
908 " return false;\n"
909 "}\n",
910 args: "name", args: info->capitalized_name);
911 }
912 }
913
914 // Now check that all embedded messages are initialized.
915 for (int i = 0; i < descriptor_->field_count(); i++) {
916 const FieldDescriptor* field = descriptor_->field(index: i);
917 const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field);
918 if (GetJavaType(field) == JAVATYPE_MESSAGE &&
919 HasRequiredFields(descriptor: field->message_type())) {
920 switch (field->label()) {
921 case FieldDescriptor::LABEL_REQUIRED:
922 printer->Print(
923 text: "if (!get$name$().isInitialized()) {\n"
924 " memoizedIsInitialized = 0;\n"
925 " return false;\n"
926 "}\n",
927 args: "type",
928 args: name_resolver_->GetImmutableClassName(descriptor: field->message_type()),
929 args: "name", args: info->capitalized_name);
930 break;
931 case FieldDescriptor::LABEL_OPTIONAL:
932 printer->Print(
933 text: "if (has$name$()) {\n"
934 " if (!get$name$().isInitialized()) {\n"
935 " memoizedIsInitialized = 0;\n"
936 " return false;\n"
937 " }\n"
938 "}\n",
939 args: "name", args: info->capitalized_name);
940 break;
941 case FieldDescriptor::LABEL_REPEATED:
942 if (IsMapEntry(descriptor: field->message_type())) {
943 printer->Print(
944 text: "for ($type$ item : get$name$Map().values()) {\n"
945 " if (!item.isInitialized()) {\n"
946 " memoizedIsInitialized = 0;\n"
947 " return false;\n"
948 " }\n"
949 "}\n",
950 args: "type",
951 args: MapValueImmutableClassdName(descriptor: field->message_type(),
952 name_resolver: name_resolver_),
953 args: "name", args: info->capitalized_name);
954 } else {
955 printer->Print(
956 text: "for (int i = 0; i < get$name$Count(); i++) {\n"
957 " if (!get$name$(i).isInitialized()) {\n"
958 " memoizedIsInitialized = 0;\n"
959 " return false;\n"
960 " }\n"
961 "}\n",
962 args: "type",
963 args: name_resolver_->GetImmutableClassName(descriptor: field->message_type()),
964 args: "name", args: info->capitalized_name);
965 }
966 break;
967 }
968 }
969 }
970
971 if (descriptor_->extension_range_count() > 0) {
972 printer->Print(
973 text: "if (!extensionsAreInitialized()) {\n"
974 " memoizedIsInitialized = 0;\n"
975 " return false;\n"
976 "}\n");
977 }
978
979 printer->Outdent();
980
981 printer->Print(text: " memoizedIsInitialized = 1;\n");
982
983 printer->Print(
984 text: " return true;\n"
985 "}\n"
986 "\n");
987}
988
989// ===================================================================
990
991namespace {
992bool CheckHasBitsForEqualsAndHashCode(const FieldDescriptor* field) {
993 if (field->is_repeated()) {
994 return false;
995 }
996 if (HasHasbit(descriptor: field)) {
997 return true;
998 }
999 return GetJavaType(field) == JAVATYPE_MESSAGE && !IsRealOneof(descriptor: field);
1000}
1001} // namespace
1002
1003void ImmutableMessageGenerator::GenerateEqualsAndHashCode(
1004 io::Printer* printer) {
1005 printer->Print(
1006 text: "@java.lang.Override\n"
1007 "public boolean equals(");
1008 printer->Print(text: "final java.lang.Object obj) {\n");
1009 printer->Indent();
1010 printer->Print(
1011 text: "if (obj == this) {\n"
1012 " return true;\n"
1013 "}\n"
1014 "if (!(obj instanceof $classname$)) {\n"
1015 " return super.equals(obj);\n"
1016 "}\n"
1017 "$classname$ other = ($classname$) obj;\n"
1018 "\n",
1019 args: "classname", args: name_resolver_->GetImmutableClassName(descriptor: descriptor_));
1020
1021 for (int i = 0; i < descriptor_->field_count(); i++) {
1022 const FieldDescriptor* field = descriptor_->field(index: i);
1023 if (!IsRealOneof(descriptor: field)) {
1024 const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field);
1025 bool check_has_bits = CheckHasBitsForEqualsAndHashCode(field);
1026 if (check_has_bits) {
1027 printer->Print(
1028 text: "if (has$name$() != other.has$name$()) return false;\n"
1029 "if (has$name$()) {\n",
1030 args: "name", args: info->capitalized_name);
1031 printer->Indent();
1032 }
1033 field_generators_.get(field).GenerateEqualsCode(printer);
1034 if (check_has_bits) {
1035 printer->Outdent();
1036 printer->Print(text: "}\n");
1037 }
1038 }
1039 }
1040
1041 // Compare oneofs.
1042 for (auto oneof : oneofs_) {
1043 printer->Print(
1044 text: "if (!get$oneof_capitalized_name$Case().equals("
1045 "other.get$oneof_capitalized_name$Case())) return false;\n",
1046 args: "oneof_capitalized_name",
1047 args: context_->GetOneofGeneratorInfo(oneof)->capitalized_name);
1048 printer->Print(text: "switch ($oneof_name$Case_) {\n", args: "oneof_name",
1049 args: context_->GetOneofGeneratorInfo(oneof)->name);
1050 printer->Indent();
1051 for (int j = 0; j < (oneof)->field_count(); j++) {
1052 const FieldDescriptor* field = (oneof)->field(index: j);
1053 printer->Print(text: "case $field_number$:\n", args: "field_number",
1054 args: StrCat(a: field->number()));
1055 printer->Indent();
1056 field_generators_.get(field).GenerateEqualsCode(printer);
1057 printer->Print(text: "break;\n");
1058 printer->Outdent();
1059 }
1060 printer->Print(
1061 text: "case 0:\n"
1062 "default:\n");
1063 printer->Outdent();
1064 printer->Print(text: "}\n");
1065 }
1066
1067 // Always consider unknown fields for equality. This will sometimes return
1068 // false for non-canonical ordering when running in LITE_RUNTIME but it's
1069 // the best we can do.
1070 printer->Print(
1071 text: "if (!unknownFields.equals(other.unknownFields)) return false;\n");
1072 if (descriptor_->extension_range_count() > 0) {
1073 printer->Print(
1074 text: "if (!getExtensionFields().equals(other.getExtensionFields()))\n"
1075 " return false;\n");
1076 }
1077 printer->Print(text: "return true;\n");
1078 printer->Outdent();
1079 printer->Print(
1080 text: "}\n"
1081 "\n");
1082
1083 printer->Print(
1084 text: "@java.lang.Override\n"
1085 "public int hashCode() {\n");
1086 printer->Indent();
1087 printer->Print(text: "if (memoizedHashCode != 0) {\n");
1088 printer->Indent();
1089 printer->Print(text: "return memoizedHashCode;\n");
1090 printer->Outdent();
1091 printer->Print(
1092 text: "}\n"
1093 "int hash = 41;\n");
1094
1095 // If we output a getDescriptor() method, use that as it is more efficient.
1096 if (descriptor_->options().no_standard_descriptor_accessor()) {
1097 printer->Print(text: "hash = (19 * hash) + getDescriptorForType().hashCode();\n");
1098 } else {
1099 printer->Print(text: "hash = (19 * hash) + getDescriptor().hashCode();\n");
1100 }
1101
1102 // hashCode non-oneofs.
1103 for (int i = 0; i < descriptor_->field_count(); i++) {
1104 const FieldDescriptor* field = descriptor_->field(index: i);
1105 if (!IsRealOneof(descriptor: field)) {
1106 const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field);
1107 bool check_has_bits = CheckHasBitsForEqualsAndHashCode(field);
1108 if (check_has_bits) {
1109 printer->Print(text: "if (has$name$()) {\n", args: "name", args: info->capitalized_name);
1110 printer->Indent();
1111 }
1112 field_generators_.get(field).GenerateHashCode(printer);
1113 if (check_has_bits) {
1114 printer->Outdent();
1115 printer->Print(text: "}\n");
1116 }
1117 }
1118 }
1119
1120 // hashCode oneofs.
1121 for (auto oneof : oneofs_) {
1122 printer->Print(text: "switch ($oneof_name$Case_) {\n", args: "oneof_name",
1123 args: context_->GetOneofGeneratorInfo(oneof)->name);
1124 printer->Indent();
1125 for (int j = 0; j < (oneof)->field_count(); j++) {
1126 const FieldDescriptor* field = (oneof)->field(index: j);
1127 printer->Print(text: "case $field_number$:\n", args: "field_number",
1128 args: StrCat(a: field->number()));
1129 printer->Indent();
1130 field_generators_.get(field).GenerateHashCode(printer);
1131 printer->Print(text: "break;\n");
1132 printer->Outdent();
1133 }
1134 printer->Print(
1135 text: "case 0:\n"
1136 "default:\n");
1137 printer->Outdent();
1138 printer->Print(text: "}\n");
1139 }
1140
1141 if (descriptor_->extension_range_count() > 0) {
1142 printer->Print(text: "hash = hashFields(hash, getExtensionFields());\n");
1143 }
1144
1145 printer->Print(text: "hash = (29 * hash) + unknownFields.hashCode();\n");
1146 printer->Print(
1147 text: "memoizedHashCode = hash;\n"
1148 "return hash;\n");
1149 printer->Outdent();
1150 printer->Print(
1151 text: "}\n"
1152 "\n");
1153}
1154
1155// ===================================================================
1156
1157void ImmutableMessageGenerator::GenerateExtensionRegistrationCode(
1158 io::Printer* printer) {
1159 for (int i = 0; i < descriptor_->extension_count(); i++) {
1160 ImmutableExtensionGenerator(descriptor_->extension(index: i), context_)
1161 .GenerateRegistrationCode(printer);
1162 }
1163
1164 for (int i = 0; i < descriptor_->nested_type_count(); i++) {
1165 ImmutableMessageGenerator(descriptor_->nested_type(index: i), context_)
1166 .GenerateExtensionRegistrationCode(printer);
1167 }
1168}
1169
1170// ===================================================================
1171void ImmutableMessageGenerator::GenerateParsingConstructor(
1172 io::Printer* printer) {
1173 std::unique_ptr<const FieldDescriptor*[]> sorted_fields(
1174 SortFieldsByNumber(descriptor: descriptor_));
1175
1176 printer->Print(
1177 text: "private $classname$(\n"
1178 " com.google.protobuf.CodedInputStream input,\n"
1179 " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
1180 " throws com.google.protobuf.InvalidProtocolBufferException {\n",
1181 args: "classname", args: descriptor_->name());
1182 printer->Indent();
1183
1184 // Initialize all fields to default.
1185 printer->Print(
1186 text: "this();\n"
1187 "if (extensionRegistry == null) {\n"
1188 " throw new java.lang.NullPointerException();\n"
1189 "}\n");
1190
1191 // Use builder bits to track mutable repeated fields.
1192 int totalBuilderBits = 0;
1193 for (int i = 0; i < descriptor_->field_count(); i++) {
1194 const ImmutableFieldGenerator& field =
1195 field_generators_.get(field: descriptor_->field(index: i));
1196 totalBuilderBits += field.GetNumBitsForBuilder();
1197 }
1198 int totalBuilderInts = (totalBuilderBits + 31) / 32;
1199 for (int i = 0; i < totalBuilderInts; i++) {
1200 printer->Print(text: "int mutable_$bit_field_name$ = 0;\n", args: "bit_field_name",
1201 args: GetBitFieldName(index: i));
1202 }
1203
1204 printer->Print(
1205 text: "com.google.protobuf.UnknownFieldSet.Builder unknownFields =\n"
1206 " com.google.protobuf.UnknownFieldSet.newBuilder();\n");
1207
1208 printer->Print(text: "try {\n");
1209 printer->Indent();
1210
1211 printer->Print(
1212 text: "boolean done = false;\n"
1213 "while (!done) {\n");
1214 printer->Indent();
1215
1216 printer->Print(
1217 text: "int tag = input.readTag();\n"
1218 "switch (tag) {\n");
1219 printer->Indent();
1220
1221 printer->Print(
1222 text: "case 0:\n" // zero signals EOF / limit reached
1223 " done = true;\n"
1224 " break;\n");
1225
1226 for (int i = 0; i < descriptor_->field_count(); i++) {
1227 const FieldDescriptor* field = sorted_fields[i];
1228 uint32_t tag = WireFormatLite::MakeTag(
1229 field_number: field->number(), type: WireFormat::WireTypeForFieldType(type: field->type()));
1230
1231 printer->Print(text: "case $tag$: {\n", args: "tag",
1232 args: StrCat(a: static_cast<int32_t>(tag)));
1233 printer->Indent();
1234
1235 field_generators_.get(field).GenerateParsingCode(printer);
1236
1237 printer->Outdent();
1238 printer->Print(
1239 text: " break;\n"
1240 "}\n");
1241
1242 if (field->is_packable()) {
1243 // To make packed = true wire compatible, we generate parsing code from a
1244 // packed version of this field regardless of field->options().packed().
1245 uint32_t packed_tag = WireFormatLite::MakeTag(
1246 field_number: field->number(), type: WireFormatLite::WIRETYPE_LENGTH_DELIMITED);
1247 printer->Print(text: "case $tag$: {\n", args: "tag",
1248 args: StrCat(a: static_cast<int32_t>(packed_tag)));
1249 printer->Indent();
1250
1251 field_generators_.get(field).GenerateParsingCodeFromPacked(printer);
1252
1253 printer->Outdent();
1254 printer->Print(
1255 text: " break;\n"
1256 "}\n");
1257 }
1258 }
1259
1260 printer->Print(
1261 text: "default: {\n"
1262 " if (!parseUnknownField(\n"
1263 " input, unknownFields, extensionRegistry, tag)) {\n"
1264 " done = true;\n" // it's an endgroup tag
1265 " }\n"
1266 " break;\n"
1267 "}\n");
1268
1269 printer->Outdent();
1270 printer->Outdent();
1271 printer->Print(
1272 text: " }\n" // switch (tag)
1273 "}\n"); // while (!done)
1274
1275 printer->Outdent();
1276 printer->Print(
1277 text: "} catch (com.google.protobuf.InvalidProtocolBufferException e) {\n"
1278 " throw e.setUnfinishedMessage(this);\n"
1279 "} catch (com.google.protobuf.UninitializedMessageException e) {\n"
1280 " throw "
1281 "e.asInvalidProtocolBufferException().setUnfinishedMessage(this);\n"
1282 "} catch (java.io.IOException e) {\n"
1283 " throw new com.google.protobuf.InvalidProtocolBufferException(\n"
1284 " e).setUnfinishedMessage(this);\n"
1285 "} finally {\n");
1286 printer->Indent();
1287
1288 // Make repeated field list immutable.
1289 for (int i = 0; i < descriptor_->field_count(); i++) {
1290 const FieldDescriptor* field = sorted_fields[i];
1291 field_generators_.get(field).GenerateParsingDoneCode(printer);
1292 }
1293
1294 // Make unknown fields immutable.
1295 printer->Print(text: "this.unknownFields = unknownFields.build();\n");
1296
1297 // Make extensions immutable.
1298 printer->Print(text: "makeExtensionsImmutable();\n");
1299
1300 printer->Outdent();
1301 printer->Outdent();
1302 printer->Print(
1303 text: " }\n" // finally
1304 "}\n");
1305}
1306
1307// ===================================================================
1308void ImmutableMessageGenerator::GenerateParser(io::Printer* printer) {
1309 printer->Print(
1310 text: "$visibility$ static final com.google.protobuf.Parser<$classname$>\n"
1311 " PARSER = new com.google.protobuf.AbstractParser<$classname$>() {\n",
1312 args: "visibility",
1313 args: ExposePublicParser(descriptor: descriptor_->file()) ? "@java.lang.Deprecated public"
1314 : "private",
1315 args: "classname", args: descriptor_->name());
1316 printer->Indent();
1317 printer->Print(
1318 text: "@java.lang.Override\n"
1319 "public $classname$ parsePartialFrom(\n"
1320 " com.google.protobuf.CodedInputStream input,\n"
1321 " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
1322 " throws com.google.protobuf.InvalidProtocolBufferException {\n",
1323 args: "classname", args: descriptor_->name());
1324 if (context_->HasGeneratedMethods(descriptor: descriptor_)) {
1325 printer->Print(text: " return new $classname$(input, extensionRegistry);\n",
1326 args: "classname", args: descriptor_->name());
1327 } else {
1328 // When parsing constructor isn't generated, use builder to parse
1329 // messages. Note, will fallback to use reflection based mergeFieldFrom()
1330 // in AbstractMessage.Builder.
1331 printer->Indent();
1332 printer->Print(
1333 text: "Builder builder = newBuilder();\n"
1334 "try {\n"
1335 " builder.mergeFrom(input, extensionRegistry);\n"
1336 "} catch (com.google.protobuf.InvalidProtocolBufferException e) {\n"
1337 " throw e.setUnfinishedMessage(builder.buildPartial());\n"
1338 "} catch (java.io.IOException e) {\n"
1339 " throw new com.google.protobuf.InvalidProtocolBufferException(\n"
1340 " e.getMessage()).setUnfinishedMessage(\n"
1341 " builder.buildPartial());\n"
1342 "}\n"
1343 "return builder.buildPartial();\n");
1344 printer->Outdent();
1345 }
1346 printer->Print(text: "}\n");
1347 printer->Outdent();
1348 printer->Print(
1349 text: "};\n"
1350 "\n");
1351
1352 printer->Print(
1353 text: "public static com.google.protobuf.Parser<$classname$> parser() {\n"
1354 " return PARSER;\n"
1355 "}\n"
1356 "\n"
1357 "@java.lang.Override\n"
1358 "public com.google.protobuf.Parser<$classname$> getParserForType() {\n"
1359 " return PARSER;\n"
1360 "}\n"
1361 "\n",
1362 args: "classname", args: descriptor_->name());
1363}
1364
1365// ===================================================================
1366void ImmutableMessageGenerator::GenerateInitializers(io::Printer* printer) {
1367 for (int i = 0; i < descriptor_->field_count(); i++) {
1368 if (!IsRealOneof(descriptor: descriptor_->field(index: i))) {
1369 field_generators_.get(field: descriptor_->field(index: i))
1370 .GenerateInitializationCode(printer);
1371 }
1372 }
1373}
1374
1375// ===================================================================
1376void ImmutableMessageGenerator::GenerateMutableCopy(io::Printer* printer) {
1377 printer->Print(
1378 text: "protected com.google.protobuf.MutableMessage\n"
1379 " internalMutableDefault() {\n"
1380 " return MutableDefaultLoader.get();\n"
1381 "}\n"
1382 "\n"
1383 "private static final class MutableDefaultLoader {\n"
1384 " private static final java.lang.Object defaultOrRuntimeException;\n"
1385 " static {\n"
1386 " java.lang.Object local;\n"
1387 " try {\n"
1388 " local = internalMutableDefault(\"$mutable_name$\");\n"
1389 " } catch (java.lang.RuntimeException e) {\n"
1390 " local = e;\n"
1391 " }\n"
1392 " defaultOrRuntimeException = local;\n"
1393 " }\n"
1394 "\n"
1395 " private MutableDefaultLoader() {}\n"
1396 "\n"
1397 " public static com.google.protobuf.MutableMessage get() {\n"
1398 " if (defaultOrRuntimeException\n"
1399 " instanceof java.lang.RuntimeException) {\n"
1400 " throw (java.lang.RuntimeException) defaultOrRuntimeException;\n"
1401 " }\n"
1402 " return\n"
1403 " (com.google.protobuf.MutableMessage) "
1404 "defaultOrRuntimeException;\n"
1405 " }\n"
1406 "}\n",
1407 args: "mutable_name", args: name_resolver_->GetJavaMutableClassName(descriptor: descriptor_));
1408}
1409
1410void ImmutableMessageGenerator::GenerateKotlinDsl(io::Printer* printer) const {
1411 printer->Print(
1412 text: "@kotlin.OptIn"
1413 "(com.google.protobuf.kotlin.OnlyForUseByGeneratedProtoCode::class)\n"
1414 "@com.google.protobuf.kotlin.ProtoDslMarker\n");
1415 printer->Print(
1416 text: "class Dsl private constructor(\n"
1417 " private val _builder: $message$.Builder\n"
1418 ") {\n"
1419 " companion object {\n"
1420 " @kotlin.jvm.JvmSynthetic\n"
1421 " @kotlin.PublishedApi\n"
1422 " internal fun _create(builder: $message$.Builder): Dsl = "
1423 "Dsl(builder)\n"
1424 " }\n"
1425 "\n"
1426 " @kotlin.jvm.JvmSynthetic\n"
1427 " @kotlin.PublishedApi\n"
1428 " internal fun _build(): $message$ = _builder.build()\n",
1429 args: "message", args: name_resolver_->GetClassName(descriptor: descriptor_, immutable: true));
1430
1431 printer->Indent();
1432
1433 for (int i = 0; i < descriptor_->field_count(); i++) {
1434 printer->Print(text: "\n");
1435 field_generators_.get(field: descriptor_->field(index: i))
1436 .GenerateKotlinDslMembers(printer);
1437 }
1438
1439 for (auto oneof : oneofs_) {
1440 printer->Print(
1441 text: "val $oneof_name$Case: $message$.$oneof_capitalized_name$Case\n"
1442 " @JvmName(\"get$oneof_capitalized_name$Case\")\n"
1443 " get() = _builder.get$oneof_capitalized_name$Case()\n\n"
1444 "fun clear$oneof_capitalized_name$() {\n"
1445 " _builder.clear$oneof_capitalized_name$()\n"
1446 "}\n",
1447 args: "oneof_name", args: context_->GetOneofGeneratorInfo(oneof)->name,
1448 args: "oneof_capitalized_name",
1449 args: context_->GetOneofGeneratorInfo(oneof)->capitalized_name, args: "message",
1450 args: name_resolver_->GetClassName(descriptor: descriptor_, immutable: true));
1451 }
1452
1453 if (descriptor_->extension_range_count() > 0) {
1454 GenerateKotlinExtensions(printer);
1455 }
1456
1457 printer->Outdent();
1458 printer->Print(text: "}\n");
1459}
1460
1461void ImmutableMessageGenerator::GenerateKotlinMembers(
1462 io::Printer* printer) const {
1463 printer->Print(
1464 text: "@kotlin.jvm.JvmName(\"-initialize$camelcase_name$\")\n"
1465 "inline fun $camelcase_name$(block: $message_kt$.Dsl.() -> "
1466 "kotlin.Unit): "
1467 "$message$ "
1468 "=\n"
1469 " $message_kt$.Dsl._create($message$.newBuilder()).apply { block() "
1470 "}._build()\n",
1471 args: "camelcase_name", args: name_resolver_->GetKotlinFactoryName(descriptor: descriptor_),
1472 args: "message_kt", args: name_resolver_->GetKotlinExtensionsClassName(descriptor: descriptor_),
1473 args: "message", args: name_resolver_->GetClassName(descriptor: descriptor_, immutable: true));
1474
1475 printer->Print(text: "object $name$Kt {\n", args: "name", args: descriptor_->name());
1476 printer->Indent();
1477 GenerateKotlinDsl(printer);
1478 for (int i = 0; i < descriptor_->nested_type_count(); i++) {
1479 if (IsMapEntry(descriptor: descriptor_->nested_type(index: i))) continue;
1480 ImmutableMessageGenerator(descriptor_->nested_type(index: i), context_)
1481 .GenerateKotlinMembers(printer);
1482 }
1483 printer->Outdent();
1484 printer->Print(text: "}\n");
1485}
1486
1487void ImmutableMessageGenerator::GenerateTopLevelKotlinMembers(
1488 io::Printer* printer) const {
1489 printer->Print(
1490 text: "@kotlin.jvm.JvmSynthetic\n"
1491 "inline fun $message$.copy(block: $message_kt$.Dsl.() -> "
1492 "kotlin.Unit): "
1493 "$message$ =\n"
1494 " $message_kt$.Dsl._create(this.toBuilder()).apply { block() "
1495 "}._build()\n\n",
1496 args: "message", args: name_resolver_->GetClassName(descriptor: descriptor_, immutable: true), args: "message_kt",
1497 args: name_resolver_->GetKotlinExtensionsClassName(descriptor: descriptor_));
1498
1499 for (int i = 0; i < descriptor_->nested_type_count(); i++) {
1500 if (IsMapEntry(descriptor: descriptor_->nested_type(index: i))) continue;
1501 ImmutableMessageGenerator(descriptor_->nested_type(index: i), context_)
1502 .GenerateTopLevelKotlinMembers(printer);
1503 }
1504
1505 GenerateKotlinOrNull(printer);
1506}
1507
1508void ImmutableMessageGenerator::GenerateKotlinOrNull(io::Printer* printer) const {
1509 for (int i = 0; i < descriptor_->field_count(); i++) {
1510 const FieldDescriptor* field = descriptor_->field(index: i);
1511 if (field->has_presence() && GetJavaType(field) == JAVATYPE_MESSAGE) {
1512 printer->Print(
1513 text: "val $full_classname$OrBuilder.$camelcase_name$OrNull: $full_name$?\n"
1514 " get() = if (has$name$()) get$name$() else null\n\n",
1515 args: "full_classname", args: name_resolver_->GetClassName(descriptor: descriptor_, immutable: true),
1516 args: "camelcase_name", args: context_->GetFieldGeneratorInfo(field)->name,
1517 args: "full_name",
1518 args: name_resolver_->GetImmutableClassName(descriptor: field->message_type()), args: "name",
1519 args: context_->GetFieldGeneratorInfo(field)->capitalized_name);
1520 }
1521 }
1522}
1523
1524void ImmutableMessageGenerator::GenerateKotlinExtensions(
1525 io::Printer* printer) const {
1526 std::string message_name = name_resolver_->GetClassName(descriptor: descriptor_, immutable: true);
1527
1528 printer->Print(
1529 text: "@Suppress(\"UNCHECKED_CAST\")\n"
1530 "@kotlin.jvm.JvmSynthetic\n"
1531 "operator fun <T : kotlin.Any> get(extension: "
1532 "com.google.protobuf.ExtensionLite<$message$, T>): T {\n"
1533 " return if (extension.isRepeated) {\n"
1534 " get(extension as com.google.protobuf.ExtensionLite<$message$, "
1535 "List<*>>) as T\n"
1536 " } else {\n"
1537 " _builder.getExtension(extension)\n"
1538 " }\n"
1539 "}\n\n",
1540 args: "message", args: message_name);
1541
1542 printer->Print(
1543 text: "@kotlin.jvm.JvmSynthetic\n"
1544 "@kotlin.OptIn"
1545 "(com.google.protobuf.kotlin.OnlyForUseByGeneratedProtoCode::class)\n"
1546 "@kotlin.jvm.JvmName(\"-getRepeatedExtension\")\n"
1547 "operator fun <E : kotlin.Any> get(\n"
1548 " extension: com.google.protobuf.ExtensionLite<$message$, List<E>>\n"
1549 "): com.google.protobuf.kotlin.ExtensionList<E, $message$> {\n"
1550 " return com.google.protobuf.kotlin.ExtensionList(extension, "
1551 "_builder.getExtension(extension))\n"
1552 "}\n\n",
1553 args: "message", args: message_name);
1554
1555 printer->Print(
1556 text: "@kotlin.jvm.JvmSynthetic\n"
1557 "operator fun contains(extension: "
1558 "com.google.protobuf.ExtensionLite<$message$, *>): "
1559 "Boolean {\n"
1560 " return _builder.hasExtension(extension)\n"
1561 "}\n\n",
1562 args: "message", args: message_name);
1563
1564 printer->Print(
1565 text: "@kotlin.jvm.JvmSynthetic\n"
1566 "fun clear(extension: "
1567 "com.google.protobuf.ExtensionLite<$message$, *>) "
1568 "{\n"
1569 " _builder.clearExtension(extension)\n"
1570 "}\n\n",
1571 args: "message", args: message_name);
1572
1573 printer->Print(
1574 text: "@kotlin.jvm.JvmSynthetic\n"
1575 "@kotlin.PublishedApi\n"
1576 "internal fun <T : kotlin.Any> setExtension(extension: "
1577 "com.google.protobuf.ExtensionLite<$message$, T>, "
1578 "value: T) {\n"
1579 " _builder.setExtension(extension, value)\n"
1580 "}\n\n",
1581 args: "message", args: message_name);
1582
1583 printer->Print(
1584 text: "@kotlin.jvm.JvmSynthetic\n"
1585 "@Suppress(\"NOTHING_TO_INLINE\")\n"
1586 "inline operator fun <T : Comparable<T>> set(\n"
1587 " extension: com.google.protobuf.ExtensionLite<$message$, T>,\n"
1588 " value: T\n"
1589 ") {\n"
1590 " setExtension(extension, value)\n"
1591 "}\n\n",
1592 args: "message", args: message_name);
1593
1594 printer->Print(
1595 text: "@kotlin.jvm.JvmSynthetic\n"
1596 "@Suppress(\"NOTHING_TO_INLINE\")\n"
1597 "inline operator fun set(\n"
1598 " extension: com.google.protobuf.ExtensionLite<$message$, "
1599 "com.google.protobuf.ByteString>,\n"
1600 " value: com.google.protobuf.ByteString\n"
1601 ") {\n"
1602 " setExtension(extension, value)\n"
1603 "}\n\n",
1604 args: "message", args: message_name);
1605
1606 printer->Print(
1607 text: "@kotlin.jvm.JvmSynthetic\n"
1608 "@Suppress(\"NOTHING_TO_INLINE\")\n"
1609 "inline operator fun <T : com.google.protobuf.MessageLite> set(\n"
1610 " extension: com.google.protobuf.ExtensionLite<$message$, T>,\n"
1611 " value: T\n"
1612 ") {\n"
1613 " setExtension(extension, value)\n"
1614 "}\n\n",
1615 args: "message", args: message_name);
1616
1617 printer->Print(
1618 text: "@kotlin.jvm.JvmSynthetic\n"
1619 "fun <E : kotlin.Any> com.google.protobuf.kotlin.ExtensionList<E, "
1620 "$message$>.add(value: E) {\n"
1621 " _builder.addExtension(this.extension, value)\n"
1622 "}\n\n",
1623 args: "message", args: message_name);
1624
1625 printer->Print(
1626 text: "@kotlin.jvm.JvmSynthetic\n"
1627 "@Suppress(\"NOTHING_TO_INLINE\")\n"
1628 "inline operator fun <E : kotlin.Any> "
1629 "com.google.protobuf.kotlin.ExtensionList<E, "
1630 "$message$>.plusAssign"
1631 "(value: E) {\n"
1632 " add(value)\n"
1633 "}\n\n",
1634 args: "message", args: message_name);
1635
1636 printer->Print(
1637 text: "@kotlin.jvm.JvmSynthetic\n"
1638 "fun <E : kotlin.Any> com.google.protobuf.kotlin.ExtensionList<E, "
1639 "$message$>.addAll(values: Iterable<E>) {\n"
1640 " for (value in values) {\n"
1641 " add(value)\n"
1642 " }\n"
1643 "}\n\n",
1644 args: "message", args: message_name);
1645
1646 printer->Print(
1647 text: "@kotlin.jvm.JvmSynthetic\n"
1648 "@Suppress(\"NOTHING_TO_INLINE\")\n"
1649 "inline operator fun <E : kotlin.Any> "
1650 "com.google.protobuf.kotlin.ExtensionList<E, "
1651 "$message$>.plusAssign(values: "
1652 "Iterable<E>) {\n"
1653 " addAll(values)\n"
1654 "}\n\n",
1655 args: "message", args: message_name);
1656
1657 printer->Print(
1658 text: "@kotlin.jvm.JvmSynthetic\n"
1659 "operator fun <E : kotlin.Any> "
1660 "com.google.protobuf.kotlin.ExtensionList<E, "
1661 "$message$>.set(index: Int, value: "
1662 "E) {\n"
1663 " _builder.setExtension(this.extension, index, value)\n"
1664 "}\n\n",
1665 args: "message", args: message_name);
1666
1667 printer->Print(
1668 text: "@kotlin.jvm.JvmSynthetic\n"
1669 "@Suppress(\"NOTHING_TO_INLINE\")\n"
1670 "inline fun com.google.protobuf.kotlin.ExtensionList<*, "
1671 "$message$>.clear() {\n"
1672 " clear(extension)\n"
1673 "}\n\n",
1674 args: "message", args: message_name);
1675}
1676
1677void ImmutableMessageGenerator::GenerateAnyMethods(io::Printer* printer) {
1678 printer->Print(
1679 text: "private static String getTypeUrl(\n"
1680 " java.lang.String typeUrlPrefix,\n"
1681 " com.google.protobuf.Descriptors.Descriptor descriptor) {\n"
1682 " return typeUrlPrefix.endsWith(\"/\")\n"
1683 " ? typeUrlPrefix + descriptor.getFullName()\n"
1684 " : typeUrlPrefix + \"/\" + descriptor.getFullName();\n"
1685 "}\n"
1686 "\n"
1687 "private static String getTypeNameFromTypeUrl(\n"
1688 " java.lang.String typeUrl) {\n"
1689 " int pos = typeUrl.lastIndexOf('/');\n"
1690 " return pos == -1 ? \"\" : typeUrl.substring(pos + 1);\n"
1691 "}\n"
1692 "\n"
1693 "public static <T extends com.google.protobuf.Message> Any pack(\n"
1694 " T message) {\n"
1695 " return Any.newBuilder()\n"
1696 " .setTypeUrl(getTypeUrl(\"type.googleapis.com\",\n"
1697 " message.getDescriptorForType()))\n"
1698 " .setValue(message.toByteString())\n"
1699 " .build();\n"
1700 "}\n"
1701 "\n"
1702 "/**\n"
1703 " * Packs a message using the given type URL prefix. The type URL will\n"
1704 " * be constructed by concatenating the message type's full name to the\n"
1705 " * prefix with an optional \"/\" separator if the prefix doesn't end\n"
1706 " * with \"/\" already.\n"
1707 " */\n"
1708 "public static <T extends com.google.protobuf.Message> Any pack(\n"
1709 " T message, java.lang.String typeUrlPrefix) {\n"
1710 " return Any.newBuilder()\n"
1711 " .setTypeUrl(getTypeUrl(typeUrlPrefix,\n"
1712 " message.getDescriptorForType()))\n"
1713 " .setValue(message.toByteString())\n"
1714 " .build();\n"
1715 "}\n"
1716 "\n"
1717 "public <T extends com.google.protobuf.Message> boolean is(\n"
1718 " java.lang.Class<T> clazz) {\n"
1719 " T defaultInstance =\n"
1720 " com.google.protobuf.Internal.getDefaultInstance(clazz);\n"
1721 " return getTypeNameFromTypeUrl(getTypeUrl()).equals(\n"
1722 " defaultInstance.getDescriptorForType().getFullName());\n"
1723 "}\n"
1724 "\n"
1725 "private volatile com.google.protobuf.Message cachedUnpackValue;\n"
1726 "\n"
1727 "@java.lang.SuppressWarnings(\"unchecked\")\n"
1728 "public <T extends com.google.protobuf.Message> T unpack(\n"
1729 " java.lang.Class<T> clazz)\n"
1730 " throws com.google.protobuf.InvalidProtocolBufferException {\n"
1731 " boolean invalidClazz = false;\n"
1732 " if (cachedUnpackValue != null) {\n"
1733 " if (cachedUnpackValue.getClass() == clazz) {\n"
1734 " return (T) cachedUnpackValue;\n"
1735 " }\n"
1736 " invalidClazz = true;\n"
1737 " }\n"
1738 " if (invalidClazz || !is(clazz)) {\n"
1739 " throw new com.google.protobuf.InvalidProtocolBufferException(\n"
1740 " \"Type of the Any message does not match the given class.\");\n"
1741 " }\n"
1742 " T defaultInstance =\n"
1743 " com.google.protobuf.Internal.getDefaultInstance(clazz);\n"
1744 " T result = (T) defaultInstance.getParserForType()\n"
1745 " .parseFrom(getValue());\n"
1746 " cachedUnpackValue = result;\n"
1747 " return result;\n"
1748 "}\n");
1749}
1750
1751} // namespace java
1752} // namespace compiler
1753} // namespace protobuf
1754} // namespace google
1755
1756#include <google/protobuf/port_undef.inc>
1757