csharp_message.cc 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606
  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. #include <sstream>
  31. #include <algorithm>
  32. #include <map>
  33. #include <google/protobuf/compiler/code_generator.h>
  34. #include <google/protobuf/compiler/plugin.h>
  35. #include <google/protobuf/descriptor.h>
  36. #include <google/protobuf/descriptor.pb.h>
  37. #include <google/protobuf/io/printer.h>
  38. #include <google/protobuf/io/zero_copy_stream.h>
  39. #include <google/protobuf/stubs/strutil.h>
  40. #include <google/protobuf/wire_format.h>
  41. #include <google/protobuf/wire_format_lite.h>
  42. #include <google/protobuf/compiler/csharp/csharp_enum.h>
  43. #include <google/protobuf/compiler/csharp/csharp_field_base.h>
  44. #include <google/protobuf/compiler/csharp/csharp_helpers.h>
  45. #include <google/protobuf/compiler/csharp/csharp_message.h>
  46. #include <google/protobuf/compiler/csharp/csharp_names.h>
  47. using google::protobuf::internal::scoped_ptr;
  48. namespace google {
  49. namespace protobuf {
  50. namespace compiler {
  51. namespace csharp {
  52. bool CompareFieldNumbers(const FieldDescriptor* d1, const FieldDescriptor* d2) {
  53. return d1->number() < d2->number();
  54. }
  55. MessageGenerator::MessageGenerator(const Descriptor* descriptor)
  56. : SourceGeneratorBase(descriptor->file()),
  57. descriptor_(descriptor) {
  58. // sorted field names
  59. for (int i = 0; i < descriptor_->field_count(); i++) {
  60. field_names_.push_back(descriptor_->field(i)->name());
  61. }
  62. std::sort(field_names_.begin(), field_names_.end());
  63. // fields by number
  64. for (int i = 0; i < descriptor_->field_count(); i++) {
  65. fields_by_number_.push_back(descriptor_->field(i));
  66. }
  67. std::sort(fields_by_number_.begin(), fields_by_number_.end(),
  68. CompareFieldNumbers);
  69. }
  70. MessageGenerator::~MessageGenerator() {
  71. }
  72. std::string MessageGenerator::class_name() {
  73. return descriptor_->name();
  74. }
  75. std::string MessageGenerator::full_class_name() {
  76. return GetClassName(descriptor_);
  77. }
  78. const std::vector<std::string>& MessageGenerator::field_names() {
  79. return field_names_;
  80. }
  81. const std::vector<const FieldDescriptor*>& MessageGenerator::fields_by_number() {
  82. return fields_by_number_;
  83. }
  84. /// Get an identifier that uniquely identifies this type within the file.
  85. /// This is used to declare static variables related to this type at the
  86. /// outermost file scope.
  87. std::string GetUniqueFileScopeIdentifier(const Descriptor* descriptor) {
  88. std::string result = descriptor->full_name();
  89. std::replace(result.begin(), result.end(), '.', '_');
  90. return "static_" + result;
  91. }
  92. void MessageGenerator::GenerateStaticVariables(io::Printer* printer) {
  93. // Because descriptor.proto (Google.Protobuf.DescriptorProtos) is
  94. // used in the construction of descriptors, we have a tricky bootstrapping
  95. // problem. To help control static initialization order, we make sure all
  96. // descriptors and other static data that depends on them are members of
  97. // the proto-descriptor class. This way, they will be initialized in
  98. // a deterministic order.
  99. std::string identifier = GetUniqueFileScopeIdentifier(descriptor_);
  100. // The descriptor for this type.
  101. printer->Print(
  102. "internal static pbr::FieldAccessorTable internal__$identifier$__FieldAccessorTable;\n",
  103. "identifier", GetUniqueFileScopeIdentifier(descriptor_),
  104. "full_class_name", full_class_name());
  105. for (int i = 0; i < descriptor_->nested_type_count(); i++) {
  106. // Don't generate accessor table fields for maps...
  107. if (!IsMapEntryMessage(descriptor_->nested_type(i))) {
  108. MessageGenerator messageGenerator(descriptor_->nested_type(i));
  109. messageGenerator.GenerateStaticVariables(printer);
  110. }
  111. }
  112. }
  113. void MessageGenerator::GenerateStaticVariableInitializers(io::Printer* printer) {
  114. map<string, string> vars;
  115. vars["identifier"] = GetUniqueFileScopeIdentifier(descriptor_);
  116. vars["full_class_name"] = full_class_name();
  117. // Work out how to get to the message descriptor (which may be multiply nested) from the file
  118. // descriptor.
  119. string descriptor_chain;
  120. const Descriptor* current_descriptor = descriptor_;
  121. while (current_descriptor->containing_type()) {
  122. descriptor_chain = ".NestedTypes[" + SimpleItoa(current_descriptor->index()) + "]" + descriptor_chain;
  123. current_descriptor = current_descriptor->containing_type();
  124. }
  125. descriptor_chain = "descriptor.MessageTypes[" + SimpleItoa(current_descriptor->index()) + "]" + descriptor_chain;
  126. vars["descriptor_chain"] = descriptor_chain;
  127. printer->Print(
  128. vars,
  129. "internal__$identifier$__FieldAccessorTable = \n"
  130. " new pbr::FieldAccessorTable(typeof($full_class_name$), $descriptor_chain$,\n");
  131. printer->Print(" new string[] { ");
  132. for (int i = 0; i < descriptor_->field_count(); i++) {
  133. printer->Print("\"$property_name$\", ",
  134. "property_name", GetPropertyName(descriptor_->field(i)));
  135. }
  136. printer->Print("}, new string[] { ");
  137. for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
  138. printer->Print("\"$oneof_name$\", ",
  139. "oneof_name",
  140. UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true));
  141. }
  142. printer->Print("});\n");
  143. // Generate static member initializers for all non-map-entry nested types.
  144. for (int i = 0; i < descriptor_->nested_type_count(); i++) {
  145. if (!IsMapEntryMessage(descriptor_->nested_type(i))) {
  146. MessageGenerator messageGenerator(descriptor_->nested_type(i));
  147. messageGenerator.GenerateStaticVariableInitializers(printer);
  148. }
  149. }
  150. }
  151. void MessageGenerator::Generate(io::Printer* printer) {
  152. map<string, string> vars;
  153. vars["class_name"] = class_name();
  154. vars["access_level"] = class_access_level();
  155. vars["umbrella_class_name"] = GetFullUmbrellaClassName(descriptor_->file());
  156. vars["identifier"] = GetUniqueFileScopeIdentifier(descriptor_);
  157. printer->Print(
  158. "[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]\n");
  159. WriteGeneratedCodeAttributes(printer);
  160. printer->Print(
  161. vars,
  162. "$access_level$ sealed partial class $class_name$ : pb::IMessage<$class_name$> {\n");
  163. printer->Indent();
  164. // All static fields and properties
  165. printer->Print(
  166. vars,
  167. "private static readonly pb::MessageParser<$class_name$> _parser = new pb::MessageParser<$class_name$>(() => new $class_name$());\n"
  168. "public static pb::MessageParser<$class_name$> Parser { get { return _parser; } }\n\n");
  169. printer->Print(
  170. "private static readonly string[] _fieldNames = "
  171. "new string[] { $slash$$field_names$$slash$ };\n",
  172. "field_names", JoinStrings(field_names(), "\", \""),
  173. "slash", field_names().size() > 0 ? "\"" : "");
  174. std::vector<std::string> tags;
  175. for (int i = 0; i < field_names().size(); i++) {
  176. uint32 tag = FixedMakeTag(descriptor_->FindFieldByName(field_names()[i]));
  177. tags.push_back(SimpleItoa(tag));
  178. }
  179. printer->Print(
  180. "private static readonly uint[] _fieldTags = new uint[] { $tags$ };\n",
  181. "tags", JoinStrings(tags, ", "));
  182. // Access the message descriptor via the relevant file descriptor or containing message descriptor.
  183. if (!descriptor_->containing_type()) {
  184. vars["descriptor_accessor"] = GetFullUmbrellaClassName(descriptor_->file())
  185. + ".Descriptor.MessageTypes[" + SimpleItoa(descriptor_->index()) + "]";
  186. } else {
  187. vars["descriptor_accessor"] = GetClassName(descriptor_->containing_type())
  188. + ".Descriptor.NestedTypes[" + SimpleItoa(descriptor_->index()) + "]";
  189. }
  190. printer->Print(
  191. vars,
  192. "public static pbr::MessageDescriptor Descriptor {\n"
  193. " get { return $descriptor_accessor$; }\n"
  194. "}\n"
  195. "\n"
  196. "pbr::FieldAccessorTable pb::IReflectedMessage.Fields {\n"
  197. " get { return $umbrella_class_name$.internal__$identifier$__FieldAccessorTable; }\n"
  198. "}\n"
  199. "\n"
  200. "private bool _frozen = false;\n"
  201. "public bool IsFrozen { get { return _frozen; } }\n\n");
  202. // Parameterless constructor and partial OnConstruction method.
  203. printer->Print(
  204. vars,
  205. "public $class_name$() {\n"
  206. " OnConstruction();\n"
  207. "}\n\n"
  208. "partial void OnConstruction();\n\n");
  209. GenerateCloningCode(printer);
  210. GenerateFreezingCode(printer);
  211. // Fields/properties
  212. for (int i = 0; i < descriptor_->field_count(); i++) {
  213. const FieldDescriptor* fieldDescriptor = descriptor_->field(i);
  214. // Rats: we lose the debug comment here :(
  215. printer->Print(
  216. "public const int $field_constant_name$ = $index$;\n",
  217. "field_constant_name", GetFieldConstantName(fieldDescriptor),
  218. "index", SimpleItoa(fieldDescriptor->number()));
  219. scoped_ptr<FieldGeneratorBase> generator(
  220. CreateFieldGeneratorInternal(fieldDescriptor));
  221. generator->GenerateMembers(printer);
  222. printer->Print("\n");
  223. }
  224. // oneof properties
  225. for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
  226. vars["name"] = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), false);
  227. vars["property_name"] = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true);
  228. printer->Print(
  229. vars,
  230. "private object $name$_;\n"
  231. "public enum $property_name$OneofCase {\n");
  232. printer->Indent();
  233. printer->Print("None = 0,\n");
  234. for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) {
  235. const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j);
  236. printer->Print("$field_property_name$ = $index$,\n",
  237. "field_property_name", GetPropertyName(field),
  238. "index", SimpleItoa(field->number()));
  239. }
  240. printer->Outdent();
  241. printer->Print("}\n");
  242. printer->Print(
  243. vars,
  244. "private $property_name$OneofCase $name$Case_ = $property_name$OneofCase.None;\n"
  245. "public $property_name$OneofCase $property_name$Case {\n"
  246. " get { return $name$Case_; }\n"
  247. "}\n\n"
  248. "public void Clear$property_name$() {\n"
  249. " pb::Freezable.CheckMutable(this);\n"
  250. " $name$Case_ = $property_name$OneofCase.None;\n"
  251. " $name$_ = null;\n"
  252. "}\n\n");
  253. }
  254. // Standard methods
  255. GenerateFrameworkMethods(printer);
  256. GenerateMessageSerializationMethods(printer);
  257. GenerateMergingMethods(printer);
  258. // Nested messages and enums
  259. if (HasNestedGeneratedTypes()) {
  260. printer->Print("#region Nested types\n"
  261. "[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]\n");
  262. WriteGeneratedCodeAttributes(printer);
  263. printer->Print("public static partial class Types {\n");
  264. printer->Indent();
  265. for (int i = 0; i < descriptor_->enum_type_count(); i++) {
  266. EnumGenerator enumGenerator(descriptor_->enum_type(i));
  267. enumGenerator.Generate(printer);
  268. }
  269. for (int i = 0; i < descriptor_->nested_type_count(); i++) {
  270. // Don't generate nested types for maps...
  271. if (!IsMapEntryMessage(descriptor_->nested_type(i))) {
  272. MessageGenerator messageGenerator(descriptor_->nested_type(i));
  273. messageGenerator.Generate(printer);
  274. }
  275. }
  276. printer->Outdent();
  277. printer->Print("}\n"
  278. "#endregion\n"
  279. "\n");
  280. }
  281. printer->Outdent();
  282. printer->Print("}\n");
  283. printer->Print("\n");
  284. }
  285. // Helper to work out whether we need to generate a class to hold nested types/enums.
  286. // Only tricky because we don't want to generate map entry types.
  287. bool MessageGenerator::HasNestedGeneratedTypes()
  288. {
  289. if (descriptor_->enum_type_count() > 0) {
  290. return true;
  291. }
  292. for (int i = 0; i < descriptor_->nested_type_count(); i++) {
  293. if (!IsMapEntryMessage(descriptor_->nested_type(i))) {
  294. return true;
  295. }
  296. }
  297. return false;
  298. }
  299. void MessageGenerator::GenerateCloningCode(io::Printer* printer) {
  300. map<string, string> vars;
  301. vars["class_name"] = class_name();
  302. printer->Print(
  303. vars,
  304. "public $class_name$($class_name$ other) : this() {\n");
  305. printer->Indent();
  306. // Clone non-oneof fields first
  307. for (int i = 0; i < descriptor_->field_count(); i++) {
  308. if (!descriptor_->field(i)->containing_oneof()) {
  309. scoped_ptr<FieldGeneratorBase> generator(
  310. CreateFieldGeneratorInternal(descriptor_->field(i)));
  311. generator->GenerateCloningCode(printer);
  312. }
  313. }
  314. // Clone just the right field for each oneof
  315. for (int i = 0; i < descriptor_->oneof_decl_count(); ++i) {
  316. vars["name"] = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), false);
  317. vars["property_name"] = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true);
  318. printer->Print(vars, "switch (other.$property_name$Case) {\n");
  319. printer->Indent();
  320. for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) {
  321. const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j);
  322. scoped_ptr<FieldGeneratorBase> generator(CreateFieldGeneratorInternal(field));
  323. vars["field_property_name"] = GetPropertyName(field);
  324. printer->Print(
  325. vars,
  326. "case $property_name$OneofCase.$field_property_name$:\n");
  327. printer->Indent();
  328. generator->GenerateCloningCode(printer);
  329. printer->Print("break;\n");
  330. printer->Outdent();
  331. }
  332. printer->Outdent();
  333. printer->Print("}\n\n");
  334. }
  335. printer->Outdent();
  336. printer->Print("}\n\n");
  337. printer->Print(
  338. vars,
  339. "public $class_name$ Clone() {\n"
  340. " return new $class_name$(this);\n"
  341. "}\n\n");
  342. }
  343. void MessageGenerator::GenerateFreezingCode(io::Printer* printer) {
  344. map<string, string> vars;
  345. vars["class_name"] = class_name();
  346. printer->Print(
  347. "public void Freeze() {\n"
  348. " if (IsFrozen) {\n"
  349. " return;\n"
  350. " }\n"
  351. " _frozen = true;\n");
  352. printer->Indent();
  353. // Freeze non-oneof fields first (only messages and repeated fields will actually generate any code)
  354. for (int i = 0; i < descriptor_->field_count(); i++) {
  355. if (!descriptor_->field(i)->containing_oneof()) {
  356. scoped_ptr<FieldGeneratorBase> generator(
  357. CreateFieldGeneratorInternal(descriptor_->field(i)));
  358. generator->GenerateFreezingCode(printer);
  359. }
  360. }
  361. // For each oneof, if the value is freezable, freeze it. We don't actually need to know which type it was.
  362. for (int i = 0; i < descriptor_->oneof_decl_count(); ++i) {
  363. vars["name"] = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), false);
  364. printer->Print(vars,
  365. "if ($name$_ is IFreezable) ((IFreezable) $name$_).Freeze();\n");
  366. }
  367. printer->Outdent();
  368. printer->Print("}\n\n");
  369. }
  370. void MessageGenerator::GenerateFrameworkMethods(io::Printer* printer) {
  371. map<string, string> vars;
  372. vars["class_name"] = class_name();
  373. // Equality
  374. printer->Print(
  375. vars,
  376. "public override bool Equals(object other) {\n"
  377. " return Equals(other as $class_name$);\n"
  378. "}\n\n"
  379. "public bool Equals($class_name$ other) {\n"
  380. " if (ReferenceEquals(other, null)) {\n"
  381. " return false;\n"
  382. " }\n"
  383. " if (ReferenceEquals(other, this)) {\n"
  384. " return true;\n"
  385. " }\n");
  386. printer->Indent();
  387. for (int i = 0; i < descriptor_->field_count(); i++) {
  388. scoped_ptr<FieldGeneratorBase> generator(
  389. CreateFieldGeneratorInternal(descriptor_->field(i)));
  390. generator->WriteEquals(printer);
  391. }
  392. printer->Outdent();
  393. printer->Print(
  394. " return true;\n"
  395. "}\n\n");
  396. // GetHashCode
  397. // Start with a non-zero value to easily distinguish between null and "empty" messages.
  398. printer->Print(
  399. "public override int GetHashCode() {\n"
  400. " int hash = 1;\n");
  401. printer->Indent();
  402. for (int i = 0; i < descriptor_->field_count(); i++) {
  403. scoped_ptr<FieldGeneratorBase> generator(
  404. CreateFieldGeneratorInternal(descriptor_->field(i)));
  405. generator->WriteHash(printer);
  406. }
  407. printer->Print("return hash;\n");
  408. printer->Outdent();
  409. printer->Print("}\n\n");
  410. printer->Print(
  411. "public override string ToString() {\n"
  412. " return pb::JsonFormatter.Default.Format(this);\n"
  413. "}\n\n");
  414. }
  415. void MessageGenerator::GenerateMessageSerializationMethods(io::Printer* printer) {
  416. printer->Print(
  417. "public void WriteTo(pb::CodedOutputStream output) {\n");
  418. printer->Indent();
  419. // Serialize all the fields
  420. for (int i = 0; i < fields_by_number().size(); i++) {
  421. scoped_ptr<FieldGeneratorBase> generator(
  422. CreateFieldGeneratorInternal(fields_by_number()[i]));
  423. generator->GenerateSerializationCode(printer);
  424. }
  425. // TODO(jonskeet): Memoize size of frozen messages?
  426. printer->Outdent();
  427. printer->Print(
  428. "}\n"
  429. "\n"
  430. "public int CalculateSize() {\n");
  431. printer->Indent();
  432. printer->Print("int size = 0;\n");
  433. for (int i = 0; i < descriptor_->field_count(); i++) {
  434. scoped_ptr<FieldGeneratorBase> generator(
  435. CreateFieldGeneratorInternal(descriptor_->field(i)));
  436. generator->GenerateSerializedSizeCode(printer);
  437. }
  438. printer->Print("return size;\n");
  439. printer->Outdent();
  440. printer->Print("}\n\n");
  441. }
  442. void MessageGenerator::GenerateMergingMethods(io::Printer* printer) {
  443. // Note: These are separate from GenerateMessageSerializationMethods()
  444. // because they need to be generated even for messages that are optimized
  445. // for code size.
  446. map<string, string> vars;
  447. vars["class_name"] = class_name();
  448. printer->Print(
  449. vars,
  450. "public void MergeFrom($class_name$ other) {\n");
  451. printer->Indent();
  452. printer->Print(
  453. "if (other == null) {\n"
  454. " return;\n"
  455. "}\n");
  456. // Merge non-oneof fields
  457. for (int i = 0; i < descriptor_->field_count(); i++) {
  458. if (!descriptor_->field(i)->containing_oneof()) {
  459. scoped_ptr<FieldGeneratorBase> generator(
  460. CreateFieldGeneratorInternal(descriptor_->field(i)));
  461. generator->GenerateMergingCode(printer);
  462. }
  463. }
  464. // Merge oneof fields
  465. for (int i = 0; i < descriptor_->oneof_decl_count(); ++i) {
  466. vars["name"] = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), false);
  467. vars["property_name"] = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true);
  468. printer->Print(vars, "switch (other.$property_name$Case) {\n");
  469. printer->Indent();
  470. for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) {
  471. const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j);
  472. vars["field_property_name"] = GetPropertyName(field);
  473. printer->Print(
  474. vars,
  475. "case $property_name$OneofCase.$field_property_name$:\n"
  476. " $field_property_name$ = other.$field_property_name$;\n"
  477. " break;\n");
  478. }
  479. printer->Outdent();
  480. printer->Print("}\n\n");
  481. }
  482. printer->Outdent();
  483. printer->Print("}\n\n");
  484. printer->Print("public void MergeFrom(pb::CodedInputStream input) {\n");
  485. printer->Indent();
  486. printer->Print(
  487. "uint tag;\n"
  488. "while (input.ReadTag(out tag)) {\n"
  489. " switch(tag) {\n");
  490. printer->Indent();
  491. printer->Indent();
  492. printer->Print(
  493. "case 0:\n" // 0 signals EOF / limit reached
  494. " throw pb::InvalidProtocolBufferException.InvalidTag();\n"
  495. "default:\n"
  496. " if (pb::WireFormat.IsEndGroupTag(tag)) {\n"
  497. " return;\n"
  498. " }\n"
  499. " break;\n"); // Note: we're ignoring unknown fields here.
  500. for (int i = 0; i < fields_by_number().size(); i++) {
  501. const FieldDescriptor* field = fields_by_number()[i];
  502. internal::WireFormatLite::WireType wt =
  503. internal::WireFormat::WireTypeForFieldType(field->type());
  504. uint32 tag = internal::WireFormatLite::MakeTag(field->number(), wt);
  505. // Handle both packed and unpacked repeated fields with the same Read*Array call;
  506. // the two generated cases are the packed and unpacked tags.
  507. // TODO(jonskeet): Check that is_packable is equivalent to is_repeated && wt in { VARINT, FIXED32, FIXED64 }.
  508. // It looks like it is...
  509. if (field->is_packable()) {
  510. printer->Print(
  511. "case $packed_tag$:\n",
  512. "packed_tag",
  513. SimpleItoa(
  514. internal::WireFormatLite::MakeTag(
  515. field->number(),
  516. internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED)));
  517. }
  518. printer->Print("case $tag$: {\n", "tag", SimpleItoa(tag));
  519. printer->Indent();
  520. scoped_ptr<FieldGeneratorBase> generator(
  521. CreateFieldGeneratorInternal(field));
  522. generator->GenerateParsingCode(printer);
  523. printer->Print("break;\n");
  524. printer->Outdent();
  525. printer->Print("}\n");
  526. }
  527. printer->Outdent();
  528. printer->Print("}\n"); // switch
  529. printer->Outdent();
  530. printer->Print("}\n"); // while
  531. printer->Outdent();
  532. printer->Print("}\n\n"); // method
  533. }
  534. int MessageGenerator::GetFieldOrdinal(const FieldDescriptor* descriptor) {
  535. for (int i = 0; i < field_names().size(); i++) {
  536. if (field_names()[i] == descriptor->name()) {
  537. return i;
  538. }
  539. }
  540. GOOGLE_LOG(DFATAL)<< "Could not find ordinal for field " << descriptor->name();
  541. return -1;
  542. }
  543. FieldGeneratorBase* MessageGenerator::CreateFieldGeneratorInternal(
  544. const FieldDescriptor* descriptor) {
  545. return CreateFieldGenerator(descriptor, GetFieldOrdinal(descriptor));
  546. }
  547. } // namespace csharp
  548. } // namespace compiler
  549. } // namespace protobuf
  550. } // namespace google