1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc. All rights reserved.
3 //
4 // Use of this source code is governed by a BSD-style
5 // license that can be found in the LICENSE file or at
6 // https://developers.google.com/open-source/licenses/bsd
7
8 #include "google/protobuf/compiler/csharp/csharp_message.h"
9
10 #include <algorithm>
11 #include <sstream>
12 #include <string>
13
14 #include "google/protobuf/compiler/code_generator.h"
15 #include "absl/container/flat_hash_map.h"
16 #include "absl/log/absl_log.h"
17 #include "absl/strings/str_cat.h"
18 #include "google/protobuf/compiler/csharp/csharp_doc_comment.h"
19 #include "google/protobuf/compiler/csharp/csharp_enum.h"
20 #include "google/protobuf/compiler/csharp/csharp_field_base.h"
21 #include "google/protobuf/compiler/csharp/csharp_helpers.h"
22 #include "google/protobuf/compiler/csharp/csharp_options.h"
23 #include "google/protobuf/compiler/csharp/names.h"
24 #include "google/protobuf/descriptor.h"
25 #include "google/protobuf/descriptor.pb.h"
26 #include "google/protobuf/io/printer.h"
27 #include "google/protobuf/wire_format.h"
28 #include "google/protobuf/wire_format_lite.h"
29
30 // Must be last.
31 #include "google/protobuf/port_def.inc"
32
33 namespace google {
34 namespace protobuf {
35 namespace compiler {
36 namespace csharp {
37
CompareFieldNumbers(const FieldDescriptor * d1,const FieldDescriptor * d2)38 bool CompareFieldNumbers(const FieldDescriptor* d1, const FieldDescriptor* d2) {
39 return d1->number() < d2->number();
40 }
41
MessageGenerator(const Descriptor * descriptor,const Options * options)42 MessageGenerator::MessageGenerator(const Descriptor* descriptor,
43 const Options* options)
44 : SourceGeneratorBase(options),
45 descriptor_(descriptor),
46 has_bit_field_count_(0),
47 has_extension_ranges_(descriptor->extension_range_count() > 0) {
48 // fields by number
49 for (int i = 0; i < descriptor_->field_count(); i++) {
50 fields_by_number_.push_back(descriptor_->field(i));
51 }
52 std::sort(fields_by_number_.begin(), fields_by_number_.end(),
53 CompareFieldNumbers);
54
55 int presence_bit_count = 0;
56 for (int i = 0; i < descriptor_->field_count(); i++) {
57 const FieldDescriptor* field = descriptor_->field(i);
58 if (RequiresPresenceBit(field)) {
59 presence_bit_count++;
60 if (has_bit_field_count_ == 0 || (presence_bit_count % 32) == 0) {
61 has_bit_field_count_++;
62 }
63 }
64 }
65 }
66
~MessageGenerator()67 MessageGenerator::~MessageGenerator() {}
68
class_name()69 std::string MessageGenerator::class_name() {
70 return std::string(descriptor_->name());
71 }
72
full_class_name()73 std::string MessageGenerator::full_class_name() {
74 return GetClassName(descriptor_);
75 }
76
77 const std::vector<const FieldDescriptor*>&
fields_by_number()78 MessageGenerator::fields_by_number() {
79 return fields_by_number_;
80 }
81
AddDeprecatedFlag(io::Printer * printer)82 void MessageGenerator::AddDeprecatedFlag(io::Printer* printer) {
83 if (descriptor_->options().deprecated()) {
84 printer->Print("[global::System.ObsoleteAttribute]\n");
85 }
86 }
87
AddSerializableAttribute(io::Printer * printer)88 void MessageGenerator::AddSerializableAttribute(io::Printer* printer) {
89 if (this->options()->serializable) {
90 printer->Print("[global::System.SerializableAttribute]\n");
91 }
92 }
93
Generate(io::Printer * printer)94 void MessageGenerator::Generate(io::Printer* printer) {
95 absl::flat_hash_map<absl::string_view, std::string> vars;
96 vars["class_name"] = class_name();
97 vars["access_level"] = class_access_level();
98
99 WriteMessageDocComment(printer, options(), descriptor_);
100 AddDeprecatedFlag(printer);
101 AddSerializableAttribute(printer);
102
103 printer->Print(
104 "[global::System.Diagnostics.DebuggerDisplayAttribute(\"{ToString(),nq}"
105 "\")]\n");
106 printer->Print(vars, "$access_level$ sealed partial class $class_name$ : ");
107
108 if (has_extension_ranges_) {
109 printer->Print(vars, "pb::IExtendableMessage<$class_name$>\n");
110 } else {
111 printer->Print(vars, "pb::IMessage<$class_name$>\n");
112 }
113 printer->Print("#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE\n");
114 printer->Print(" , pb::IBufferMessage\n");
115 printer->Print("#endif\n");
116 printer->Print("{\n");
117 printer->Indent();
118
119 // All static fields and properties
120 printer->Print(
121 vars,
122 "private static readonly pb::MessageParser<$class_name$> _parser = new "
123 "pb::MessageParser<$class_name$>(() => new $class_name$());\n");
124
125 printer->Print("private pb::UnknownFieldSet _unknownFields;\n");
126
127 if (has_extension_ranges_) {
128 if (IsDescriptorProto(descriptor_->file())) {
129 printer->Print(vars,
130 // CustomOptions compatibility
131 "internal pb::ExtensionSet<$class_name$> _extensions;\n");
132 } else {
133 printer->Print(vars,
134 "private pb::ExtensionSet<$class_name$> _extensions;\n");
135 }
136
137 // a read-only property for fast
138 // retrieval of the set in IsInitialized
139 printer->Print(vars,
140 "private pb::ExtensionSet<$class_name$> _Extensions { get { "
141 "return _extensions; } }\n");
142 }
143
144 for (int i = 0; i < has_bit_field_count_; i++) {
145 // don't use arrays since all arrays are heap allocated, saving allocations
146 // use ints instead of bytes since bytes lack bitwise operators, saving
147 // casts
148 printer->Print("private int _hasBits$i$;\n", "i", absl::StrCat(i));
149 }
150
151 WriteGeneratedCodeAttributes(printer);
152
153 printer->Print(vars,
154 "public static pb::MessageParser<$class_name$> Parser { get { "
155 "return _parser; } }\n\n");
156
157 // Access the message descriptor via the relevant file descriptor or
158 // containing message descriptor.
159 if (!descriptor_->containing_type()) {
160 vars["descriptor_accessor"] =
161 absl::StrCat(GetReflectionClassName(descriptor_->file()),
162 ".Descriptor.MessageTypes[", descriptor_->index(), "]");
163 } else {
164 vars["descriptor_accessor"] =
165 absl::StrCat(GetClassName(descriptor_->containing_type()),
166 ".Descriptor.NestedTypes[", descriptor_->index(), "]");
167 }
168
169 WriteGeneratedCodeAttributes(printer);
170 printer->Print(vars,
171 "public static pbr::MessageDescriptor Descriptor {\n"
172 " get { return $descriptor_accessor$; }\n"
173 "}\n"
174 "\n");
175 WriteGeneratedCodeAttributes(printer);
176 printer->Print(vars,
177 "pbr::MessageDescriptor pb::IMessage.Descriptor {\n"
178 " get { return Descriptor; }\n"
179 "}\n"
180 "\n");
181
182 // Parameterless constructor and partial OnConstruction method.
183 WriteGeneratedCodeAttributes(printer);
184 printer->Print(vars,
185 "public $class_name$() {\n"
186 " OnConstruction();\n"
187 "}\n\n"
188 "partial void OnConstruction();\n\n");
189
190 GenerateCloningCode(printer);
191 GenerateFreezingCode(printer);
192
193 // Fields/properties
194 for (int i = 0; i < descriptor_->field_count(); i++) {
195 const FieldDescriptor* fieldDescriptor = descriptor_->field(i);
196
197 // Rats: we lose the debug comment here :(
198 printer->Print(
199 "/// <summary>Field number for the \"$field_name$\" field.</summary>\n"
200 "public const int $field_constant_name$ = $index$;\n",
201 "field_name", fieldDescriptor->name(), "field_constant_name",
202 GetFieldConstantName(fieldDescriptor), "index",
203 absl::StrCat(fieldDescriptor->number()));
204 std::unique_ptr<FieldGeneratorBase> generator(
205 CreateFieldGeneratorInternal(fieldDescriptor));
206 generator->GenerateMembers(printer);
207 printer->Print("\n");
208 }
209
210 // oneof properties (for real oneofs, which come before synthetic ones)
211 for (int i = 0; i < descriptor_->real_oneof_decl_count(); i++) {
212 const OneofDescriptor* oneof = descriptor_->oneof_decl(i);
213 vars["name"] = UnderscoresToCamelCase(oneof->name(), false);
214 vars["property_name"] = UnderscoresToCamelCase(oneof->name(), true);
215 vars["original_name"] = oneof->name();
216 printer->Print(vars,
217 "private object $name$_;\n"
218 "/// <summary>Enum of possible cases for the "
219 "\"$original_name$\" oneof.</summary>\n"
220 "public enum $property_name$OneofCase {\n");
221 printer->Indent();
222 printer->Print("None = 0,\n");
223 for (int j = 0; j < oneof->field_count(); j++) {
224 const FieldDescriptor* field = oneof->field(j);
225 printer->Print("$oneof_case_name$ = $index$,\n", "oneof_case_name",
226 GetOneofCaseName(field), "index",
227 absl::StrCat(field->number()));
228 }
229 printer->Outdent();
230 printer->Print("}\n");
231 // TODO: Should we put the oneof .proto comments here?
232 // It's unclear exactly where they should go.
233 printer->Print(vars,
234 "private $property_name$OneofCase $name$Case_ = "
235 "$property_name$OneofCase.None;\n");
236 WriteGeneratedCodeAttributes(printer);
237 printer->Print(vars,
238 "public $property_name$OneofCase $property_name$Case {\n"
239 " get { return $name$Case_; }\n"
240 "}\n\n");
241 WriteGeneratedCodeAttributes(printer);
242 printer->Print(vars,
243 "public void Clear$property_name$() {\n"
244 " $name$Case_ = $property_name$OneofCase.None;\n"
245 " $name$_ = null;\n"
246 "}\n\n");
247 }
248
249 // Standard methods
250 GenerateFrameworkMethods(printer);
251 GenerateMessageSerializationMethods(printer);
252 GenerateMergingMethods(printer);
253
254 if (has_extension_ranges_) {
255 printer->Print(
256 vars,
257 "public TValue GetExtension<TValue>(pb::Extension<$class_name$, "
258 "TValue> extension) {\n"
259 " return pb::ExtensionSet.Get(ref _extensions, extension);\n"
260 "}\n"
261 "public pbc::RepeatedField<TValue> "
262 "GetExtension<TValue>(pb::RepeatedExtension<$class_name$, TValue> "
263 "extension) {\n"
264 " return pb::ExtensionSet.Get(ref _extensions, extension);\n"
265 "}\n"
266 "public pbc::RepeatedField<TValue> "
267 "GetOrInitializeExtension<TValue>(pb::RepeatedExtension<$class_name$, "
268 "TValue> extension) {\n"
269 " return pb::ExtensionSet.GetOrInitialize(ref _extensions, "
270 "extension);\n"
271 "}\n"
272 "public void SetExtension<TValue>(pb::Extension<$class_name$, TValue> "
273 "extension, TValue value) {\n"
274 " pb::ExtensionSet.Set(ref _extensions, extension, value);\n"
275 "}\n"
276 "public bool HasExtension<TValue>(pb::Extension<$class_name$, TValue> "
277 "extension) {\n"
278 " return pb::ExtensionSet.Has(ref _extensions, extension);\n"
279 "}\n"
280 "public void ClearExtension<TValue>(pb::Extension<$class_name$, "
281 "TValue> extension) {\n"
282 " pb::ExtensionSet.Clear(ref _extensions, extension);\n"
283 "}\n"
284 "public void "
285 "ClearExtension<TValue>(pb::RepeatedExtension<$class_name$, TValue> "
286 "extension) {\n"
287 " pb::ExtensionSet.Clear(ref _extensions, extension);\n"
288 "}\n\n");
289 }
290
291 // Nested messages and enums
292 if (HasNestedGeneratedTypes()) {
293 printer->Print(vars,
294 "#region Nested types\n"
295 "/// <summary>Container for nested types declared in the "
296 "$class_name$ message type.</summary>\n");
297 WriteGeneratedCodeAttributes(printer);
298 printer->Print("public static partial class Types {\n");
299 printer->Indent();
300 for (int i = 0; i < descriptor_->enum_type_count(); i++) {
301 EnumGenerator enumGenerator(descriptor_->enum_type(i), this->options());
302 enumGenerator.Generate(printer);
303 }
304 for (int i = 0; i < descriptor_->nested_type_count(); i++) {
305 // Don't generate nested types for maps...
306 if (!IsMapEntryMessage(descriptor_->nested_type(i))) {
307 MessageGenerator messageGenerator(descriptor_->nested_type(i),
308 this->options());
309 messageGenerator.Generate(printer);
310 }
311 }
312 printer->Outdent();
313 printer->Print(
314 "}\n"
315 "#endregion\n"
316 "\n");
317 }
318
319 if (descriptor_->extension_count() > 0) {
320 printer->Print(vars,
321 "#region Extensions\n"
322 "/// <summary>Container for extensions for other messages "
323 "declared in the $class_name$ message type.</summary>\n");
324 WriteGeneratedCodeAttributes(printer);
325 printer->Print("public static partial class Extensions {\n");
326 printer->Indent();
327 for (int i = 0; i < descriptor_->extension_count(); i++) {
328 std::unique_ptr<FieldGeneratorBase> generator(
329 CreateFieldGeneratorInternal(descriptor_->extension(i)));
330 generator->GenerateExtensionCode(printer);
331 }
332 printer->Outdent();
333 printer->Print(
334 "}\n"
335 "#endregion\n"
336 "\n");
337 }
338
339 printer->Outdent();
340 printer->Print("}\n");
341 printer->Print("\n");
342 }
343
344 // Helper to work out whether we need to generate a class to hold nested
345 // types/enums. Only tricky because we don't want to generate map entry types.
HasNestedGeneratedTypes()346 bool MessageGenerator::HasNestedGeneratedTypes() {
347 if (descriptor_->enum_type_count() > 0) {
348 return true;
349 }
350 for (int i = 0; i < descriptor_->nested_type_count(); i++) {
351 if (!IsMapEntryMessage(descriptor_->nested_type(i))) {
352 return true;
353 }
354 }
355 return false;
356 }
357
GenerateCloningCode(io::Printer * printer)358 void MessageGenerator::GenerateCloningCode(io::Printer* printer) {
359 absl::flat_hash_map<absl::string_view, std::string> vars;
360 WriteGeneratedCodeAttributes(printer);
361 vars["class_name"] = class_name();
362 printer->Print(vars, "public $class_name$($class_name$ other) : this() {\n");
363 printer->Indent();
364 for (int i = 0; i < has_bit_field_count_; i++) {
365 printer->Print("_hasBits$i$ = other._hasBits$i$;\n", "i", absl::StrCat(i));
366 }
367 // Clone non-oneof fields first (treating optional proto3 fields as non-oneof)
368 for (int i = 0; i < descriptor_->field_count(); i++) {
369 const FieldDescriptor* field = descriptor_->field(i);
370 if (field->real_containing_oneof()) {
371 continue;
372 }
373 std::unique_ptr<FieldGeneratorBase> generator(
374 CreateFieldGeneratorInternal(field));
375 generator->GenerateCloningCode(printer);
376 }
377 // Clone just the right field for each real oneof
378 for (int i = 0; i < descriptor_->real_oneof_decl_count(); ++i) {
379 const OneofDescriptor* oneof = descriptor_->oneof_decl(i);
380 vars["name"] = UnderscoresToCamelCase(oneof->name(), false);
381 vars["property_name"] = UnderscoresToCamelCase(oneof->name(), true);
382 printer->Print(vars, "switch (other.$property_name$Case) {\n");
383 printer->Indent();
384 for (int j = 0; j < oneof->field_count(); j++) {
385 const FieldDescriptor* field = oneof->field(j);
386 std::unique_ptr<FieldGeneratorBase> generator(
387 CreateFieldGeneratorInternal(field));
388 vars["oneof_case_name"] = GetOneofCaseName(field);
389 printer->Print(vars,
390 "case $property_name$OneofCase.$oneof_case_name$:\n");
391 printer->Indent();
392 generator->GenerateCloningCode(printer);
393 printer->Print("break;\n");
394 printer->Outdent();
395 }
396 printer->Outdent();
397 printer->Print("}\n\n");
398 }
399 // Clone unknown fields
400 printer->Print(
401 "_unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);\n");
402 if (has_extension_ranges_) {
403 printer->Print(
404 "_extensions = pb::ExtensionSet.Clone(other._extensions);\n");
405 }
406
407 printer->Outdent();
408 printer->Print("}\n\n");
409
410 WriteGeneratedCodeAttributes(printer);
411 printer->Print(vars,
412 "public $class_name$ Clone() {\n"
413 " return new $class_name$(this);\n"
414 "}\n\n");
415 }
416
GenerateFreezingCode(io::Printer * printer)417 void MessageGenerator::GenerateFreezingCode(io::Printer* printer) {}
418
GenerateFrameworkMethods(io::Printer * printer)419 void MessageGenerator::GenerateFrameworkMethods(io::Printer* printer) {
420 absl::flat_hash_map<absl::string_view, std::string> vars;
421 vars["class_name"] = class_name();
422
423 // Equality
424 WriteGeneratedCodeAttributes(printer);
425 printer->Print(vars,
426 "public override bool Equals(object other) {\n"
427 " return Equals(other as $class_name$);\n"
428 "}\n\n");
429 WriteGeneratedCodeAttributes(printer);
430 printer->Print(vars,
431 "public bool Equals($class_name$ other) {\n"
432 " if (ReferenceEquals(other, null)) {\n"
433 " return false;\n"
434 " }\n"
435 " if (ReferenceEquals(other, this)) {\n"
436 " return true;\n"
437 " }\n");
438 printer->Indent();
439 for (int i = 0; i < descriptor_->field_count(); i++) {
440 std::unique_ptr<FieldGeneratorBase> generator(
441 CreateFieldGeneratorInternal(descriptor_->field(i)));
442 generator->WriteEquals(printer);
443 }
444 for (int i = 0; i < descriptor_->real_oneof_decl_count(); i++) {
445 printer->Print(
446 "if ($property_name$Case != other.$property_name$Case) return false;\n",
447 "property_name",
448 UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true));
449 }
450 if (has_extension_ranges_) {
451 printer->Print(
452 "if (!Equals(_extensions, other._extensions)) {\n"
453 " return false;\n"
454 "}\n");
455 }
456 printer->Outdent();
457 printer->Print(
458 " return Equals(_unknownFields, other._unknownFields);\n"
459 "}\n\n");
460
461 // GetHashCode
462 // Start with a non-zero value to easily distinguish between null and "empty"
463 // messages.
464 WriteGeneratedCodeAttributes(printer);
465 printer->Print(
466 "public override int GetHashCode() {\n"
467 " int hash = 1;\n");
468 printer->Indent();
469 for (int i = 0; i < descriptor_->field_count(); i++) {
470 std::unique_ptr<FieldGeneratorBase> generator(
471 CreateFieldGeneratorInternal(descriptor_->field(i)));
472 generator->WriteHash(printer);
473 }
474 for (int i = 0; i < descriptor_->real_oneof_decl_count(); i++) {
475 printer->Print(
476 "hash ^= (int) $name$Case_;\n", "name",
477 UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), false));
478 }
479 if (has_extension_ranges_) {
480 printer->Print(
481 "if (_extensions != null) {\n"
482 " hash ^= _extensions.GetHashCode();\n"
483 "}\n");
484 }
485 printer->Print(
486 "if (_unknownFields != null) {\n"
487 " hash ^= _unknownFields.GetHashCode();\n"
488 "}\n"
489 "return hash;\n");
490 printer->Outdent();
491 printer->Print("}\n\n");
492
493 WriteGeneratedCodeAttributes(printer);
494 printer->Print(
495 "public override string ToString() {\n"
496 " return pb::JsonFormatter.ToDiagnosticString(this);\n"
497 "}\n\n");
498 }
499
GenerateMessageSerializationMethods(io::Printer * printer)500 void MessageGenerator::GenerateMessageSerializationMethods(
501 io::Printer* printer) {
502 WriteGeneratedCodeAttributes(printer);
503 printer->Print("public void WriteTo(pb::CodedOutputStream output) {\n");
504 printer->Print("#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE\n");
505 printer->Indent();
506 printer->Print("output.WriteRawMessage(this);\n");
507 printer->Outdent();
508 printer->Print("#else\n");
509 printer->Indent();
510 GenerateWriteToBody(printer, false);
511 printer->Outdent();
512 printer->Print("#endif\n");
513 printer->Print("}\n\n");
514
515 printer->Print("#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE\n");
516 WriteGeneratedCodeAttributes(printer);
517 printer->Print(
518 "void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) "
519 "{\n");
520 printer->Indent();
521 GenerateWriteToBody(printer, true);
522 printer->Outdent();
523 printer->Print("}\n");
524 printer->Print("#endif\n\n");
525
526 WriteGeneratedCodeAttributes(printer);
527 printer->Print("public int CalculateSize() {\n");
528 printer->Indent();
529 printer->Print("int size = 0;\n");
530 for (int i = 0; i < descriptor_->field_count(); i++) {
531 std::unique_ptr<FieldGeneratorBase> generator(
532 CreateFieldGeneratorInternal(descriptor_->field(i)));
533 generator->GenerateSerializedSizeCode(printer);
534 }
535
536 if (has_extension_ranges_) {
537 printer->Print(
538 "if (_extensions != null) {\n"
539 " size += _extensions.CalculateSize();\n"
540 "}\n");
541 }
542
543 printer->Print(
544 "if (_unknownFields != null) {\n"
545 " size += _unknownFields.CalculateSize();\n"
546 "}\n");
547
548 printer->Print("return size;\n");
549 printer->Outdent();
550 printer->Print("}\n\n");
551 }
552
GenerateWriteToBody(io::Printer * printer,bool use_write_context)553 void MessageGenerator::GenerateWriteToBody(io::Printer* printer,
554 bool use_write_context) {
555 // Serialize all the fields
556 for (int i = 0; i < fields_by_number().size(); i++) {
557 std::unique_ptr<FieldGeneratorBase> generator(
558 CreateFieldGeneratorInternal(fields_by_number()[i]));
559 generator->GenerateSerializationCode(printer, use_write_context);
560 }
561
562 if (has_extension_ranges_) {
563 // Serialize extensions
564 printer->Print(use_write_context ? "if (_extensions != null) {\n"
565 " _extensions.WriteTo(ref output);\n"
566 "}\n"
567 : "if (_extensions != null) {\n"
568 " _extensions.WriteTo(output);\n"
569 "}\n");
570 }
571
572 // Serialize unknown fields
573 printer->Print(use_write_context ? "if (_unknownFields != null) {\n"
574 " _unknownFields.WriteTo(ref output);\n"
575 "}\n"
576 : "if (_unknownFields != null) {\n"
577 " _unknownFields.WriteTo(output);\n"
578 "}\n");
579
580 // TODO: Memoize size of frozen messages?
581 }
582
GenerateMergingMethods(io::Printer * printer)583 void MessageGenerator::GenerateMergingMethods(io::Printer* printer) {
584 // Note: These are separate from GenerateMessageSerializationMethods()
585 // because they need to be generated even for messages that are optimized
586 // for code size.
587 absl::flat_hash_map<absl::string_view, std::string> vars;
588 vars["class_name"] = class_name();
589
590 WriteGeneratedCodeAttributes(printer);
591 printer->Print(vars, "public void MergeFrom($class_name$ other) {\n");
592 printer->Indent();
593 printer->Print(
594 "if (other == null) {\n"
595 " return;\n"
596 "}\n");
597 // Merge non-oneof fields, treating optional proto3 fields as normal fields
598 for (int i = 0; i < descriptor_->field_count(); i++) {
599 const FieldDescriptor* field = descriptor_->field(i);
600 if (field->real_containing_oneof()) {
601 continue;
602 }
603 std::unique_ptr<FieldGeneratorBase> generator(
604 CreateFieldGeneratorInternal(field));
605 generator->GenerateMergingCode(printer);
606 }
607 // Merge oneof fields (for non-synthetic oneofs)
608 for (int i = 0; i < descriptor_->real_oneof_decl_count(); ++i) {
609 const OneofDescriptor* oneof = descriptor_->oneof_decl(i);
610 vars["name"] = UnderscoresToCamelCase(oneof->name(), false);
611 vars["property_name"] = UnderscoresToCamelCase(oneof->name(), true);
612 printer->Print(vars, "switch (other.$property_name$Case) {\n");
613 printer->Indent();
614 for (int j = 0; j < oneof->field_count(); j++) {
615 const FieldDescriptor* field = oneof->field(j);
616 vars["oneof_case_name"] = GetOneofCaseName(field);
617 printer->Print(vars,
618 "case $property_name$OneofCase.$oneof_case_name$:\n");
619 printer->Indent();
620 std::unique_ptr<FieldGeneratorBase> generator(
621 CreateFieldGeneratorInternal(field));
622 generator->GenerateMergingCode(printer);
623 printer->Print("break;\n");
624 printer->Outdent();
625 }
626 printer->Outdent();
627 printer->Print("}\n\n");
628 }
629 // Merge extensions
630 if (has_extension_ranges_) {
631 printer->Print(
632 "pb::ExtensionSet.MergeFrom(ref _extensions, other._extensions);\n");
633 }
634
635 // Merge unknown fields.
636 printer->Print(
637 "_unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, "
638 "other._unknownFields);\n");
639
640 printer->Outdent();
641 printer->Print("}\n\n");
642
643 WriteGeneratedCodeAttributes(printer);
644 printer->Print("public void MergeFrom(pb::CodedInputStream input) {\n");
645 printer->Print("#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE\n");
646 printer->Indent();
647 printer->Print("input.ReadRawMessage(this);\n");
648 printer->Outdent();
649 printer->Print("#else\n");
650 printer->Indent();
651 GenerateMainParseLoop(printer, false);
652 printer->Outdent();
653 printer->Print("#endif\n");
654 printer->Print("}\n\n");
655
656 printer->Print("#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE\n");
657 WriteGeneratedCodeAttributes(printer);
658 printer->Print(
659 "void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) "
660 "{\n");
661 printer->Indent();
662 GenerateMainParseLoop(printer, true);
663 printer->Outdent();
664 printer->Print("}\n"); // method
665 printer->Print("#endif\n\n");
666 }
667
GenerateMainParseLoop(io::Printer * printer,bool use_parse_context)668 void MessageGenerator::GenerateMainParseLoop(io::Printer* printer,
669 bool use_parse_context) {
670 absl::flat_hash_map<absl::string_view, std::string> vars;
671 vars["maybe_ref_input"] = use_parse_context ? "ref input" : "input";
672
673 printer->Emit(R"csharp(
674 uint tag;
675 while ((tag = input.ReadTag()) != 0) {
676 if ((tag & 7) == 4) {
677 // Abort on any end group tag.
678 return;
679 }
680 switch(tag) {
681 )csharp");
682 printer->Indent();
683 printer->Indent();
684 if (has_extension_ranges_) {
685 printer->Print(vars,
686 "default:\n"
687 " if (!pb::ExtensionSet.TryMergeFieldFrom(ref _extensions, "
688 "$maybe_ref_input$)) {\n"
689 " _unknownFields = "
690 "pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, "
691 "$maybe_ref_input$);\n"
692 " }\n"
693 " break;\n");
694 } else {
695 printer->Print(
696 vars,
697 "default:\n"
698 " _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, "
699 "$maybe_ref_input$);\n"
700 " break;\n");
701 }
702 for (int i = 0; i < fields_by_number().size(); i++) {
703 const FieldDescriptor* field = fields_by_number()[i];
704 internal::WireFormatLite::WireType wt =
705 internal::WireFormat::WireTypeForFieldType(field->type());
706 uint32_t tag = internal::WireFormatLite::MakeTag(field->number(), wt);
707 // Handle both packed and unpacked repeated fields with the same Read*Array
708 // call; the two generated cases are the packed and unpacked tags.
709 // TODO: Check that is_packable is equivalent to
710 // is_repeated && wt in { VARINT, FIXED32, FIXED64 }.
711 // It looks like it is...
712 if (field->is_packable()) {
713 printer->Print("case $packed_tag$:\n", "packed_tag",
714 absl::StrCat(internal::WireFormatLite::MakeTag(
715 field->number(),
716 internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED)));
717 }
718
719 printer->Print("case $tag$: {\n", "tag", absl::StrCat(tag));
720 printer->Indent();
721 std::unique_ptr<FieldGeneratorBase> generator(
722 CreateFieldGeneratorInternal(field));
723 generator->GenerateParsingCode(printer, use_parse_context);
724 printer->Print("break;\n");
725 printer->Outdent();
726 printer->Print("}\n");
727 }
728 printer->Outdent();
729 printer->Print("}\n"); // switch
730 printer->Outdent();
731 printer->Print("}\n"); // while
732 }
733
734 // it's a waste of space to track presence for all values, so we only track them
735 // if they're not nullable
GetPresenceIndex(const FieldDescriptor * descriptor)736 int MessageGenerator::GetPresenceIndex(const FieldDescriptor* descriptor) {
737 if (!RequiresPresenceBit(descriptor)) {
738 return -1;
739 }
740
741 int index = 0;
742 for (int i = 0; i < fields_by_number().size(); i++) {
743 const FieldDescriptor* field = fields_by_number()[i];
744 if (field == descriptor) {
745 return index;
746 }
747 if (RequiresPresenceBit(field)) {
748 index++;
749 }
750 }
751 ABSL_DLOG(FATAL) << "Could not find presence index for field "
752 << descriptor->name();
753 return -1;
754 }
755
CreateFieldGeneratorInternal(const FieldDescriptor * descriptor)756 FieldGeneratorBase* MessageGenerator::CreateFieldGeneratorInternal(
757 const FieldDescriptor* descriptor) {
758 return CreateFieldGenerator(descriptor, GetPresenceIndex(descriptor),
759 this->options());
760 }
761
762 } // namespace csharp
763 } // namespace compiler
764 } // namespace protobuf
765 } // namespace google
766
767 #include "google/protobuf/port_undef.inc"
768