csharp_message.cc 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580
  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_doc_comment.h>
  43. #include <google/protobuf/compiler/csharp/csharp_enum.h>
  44. #include <google/protobuf/compiler/csharp/csharp_field_base.h>
  45. #include <google/protobuf/compiler/csharp/csharp_helpers.h>
  46. #include <google/protobuf/compiler/csharp/csharp_message.h>
  47. #include <google/protobuf/compiler/csharp/csharp_names.h>
  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. const Options* options)
  57. : SourceGeneratorBase(descriptor->file(), options),
  58. descriptor_(descriptor) {
  59. // sorted field names
  60. for (int i = 0; i < descriptor_->field_count(); i++) {
  61. field_names_.push_back(descriptor_->field(i)->name());
  62. }
  63. std::sort(field_names_.begin(), field_names_.end());
  64. // fields by number
  65. for (int i = 0; i < descriptor_->field_count(); i++) {
  66. fields_by_number_.push_back(descriptor_->field(i));
  67. }
  68. std::sort(fields_by_number_.begin(), fields_by_number_.end(),
  69. CompareFieldNumbers);
  70. }
  71. MessageGenerator::~MessageGenerator() {
  72. }
  73. std::string MessageGenerator::class_name() {
  74. return descriptor_->name();
  75. }
  76. std::string MessageGenerator::full_class_name() {
  77. return GetClassName(descriptor_);
  78. }
  79. const std::vector<std::string>& MessageGenerator::field_names() {
  80. return field_names_;
  81. }
  82. const std::vector<const FieldDescriptor*>& MessageGenerator::fields_by_number() {
  83. return fields_by_number_;
  84. }
  85. void MessageGenerator::AddDeprecatedFlag(io::Printer* printer) {
  86. if (descriptor_->options().deprecated()) {
  87. printer->Print("[global::System.ObsoleteAttribute]\n");
  88. }
  89. }
  90. void MessageGenerator::Generate(io::Printer* printer) {
  91. std::map<string, string> vars;
  92. vars["class_name"] = class_name();
  93. vars["access_level"] = class_access_level();
  94. WriteMessageDocComment(printer, descriptor_);
  95. AddDeprecatedFlag(printer);
  96. printer->Print(
  97. vars,
  98. "$access_level$ sealed partial class $class_name$ : pb::IMessage<$class_name$> {\n");
  99. printer->Indent();
  100. // All static fields and properties
  101. printer->Print(
  102. vars,
  103. "private static readonly pb::MessageParser<$class_name$> _parser = new pb::MessageParser<$class_name$>(() => new $class_name$());\n");
  104. printer->Print(
  105. "private pb::UnknownFieldSet _unknownFields;\n");
  106. WriteGeneratedCodeAttributes(printer);
  107. printer->Print(
  108. vars,
  109. "public static pb::MessageParser<$class_name$> Parser { get { return _parser; } }\n\n");
  110. // Access the message descriptor via the relevant file descriptor or containing message descriptor.
  111. if (!descriptor_->containing_type()) {
  112. vars["descriptor_accessor"] = GetReflectionClassName(descriptor_->file())
  113. + ".Descriptor.MessageTypes[" + SimpleItoa(descriptor_->index()) + "]";
  114. } else {
  115. vars["descriptor_accessor"] = GetClassName(descriptor_->containing_type())
  116. + ".Descriptor.NestedTypes[" + SimpleItoa(descriptor_->index()) + "]";
  117. }
  118. WriteGeneratedCodeAttributes(printer);
  119. printer->Print(
  120. vars,
  121. "public static pbr::MessageDescriptor Descriptor {\n"
  122. " get { return $descriptor_accessor$; }\n"
  123. "}\n"
  124. "\n");
  125. WriteGeneratedCodeAttributes(printer);
  126. printer->Print(
  127. vars,
  128. "pbr::MessageDescriptor pb::IMessage.Descriptor {\n"
  129. " get { return Descriptor; }\n"
  130. "}\n"
  131. "\n");
  132. // CustomOptions property, only for options messages
  133. if (IsDescriptorOptionMessage(descriptor_)) {
  134. printer->Print(
  135. "internal CustomOptions CustomOptions{ get; private set; } = CustomOptions.Empty;\n"
  136. "\n");
  137. }
  138. // Parameterless constructor and partial OnConstruction method.
  139. WriteGeneratedCodeAttributes(printer);
  140. printer->Print(
  141. vars,
  142. "public $class_name$() {\n"
  143. " OnConstruction();\n"
  144. "}\n\n"
  145. "partial void OnConstruction();\n\n");
  146. GenerateCloningCode(printer);
  147. GenerateFreezingCode(printer);
  148. // Fields/properties
  149. for (int i = 0; i < descriptor_->field_count(); i++) {
  150. const FieldDescriptor* fieldDescriptor = descriptor_->field(i);
  151. // Rats: we lose the debug comment here :(
  152. printer->Print(
  153. "/// <summary>Field number for the \"$field_name$\" field.</summary>\n"
  154. "public const int $field_constant_name$ = $index$;\n",
  155. "field_name", fieldDescriptor->name(),
  156. "field_constant_name", GetFieldConstantName(fieldDescriptor),
  157. "index", SimpleItoa(fieldDescriptor->number()));
  158. std::unique_ptr<FieldGeneratorBase> generator(
  159. CreateFieldGeneratorInternal(fieldDescriptor));
  160. generator->GenerateMembers(printer);
  161. printer->Print("\n");
  162. }
  163. // oneof properties
  164. for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
  165. vars["name"] = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), false);
  166. vars["property_name"] = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true);
  167. vars["original_name"] = descriptor_->oneof_decl(i)->name();
  168. printer->Print(
  169. vars,
  170. "private object $name$_;\n"
  171. "/// <summary>Enum of possible cases for the \"$original_name$\" oneof.</summary>\n"
  172. "public enum $property_name$OneofCase {\n");
  173. printer->Indent();
  174. printer->Print("None = 0,\n");
  175. for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) {
  176. const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j);
  177. printer->Print("$field_property_name$ = $index$,\n",
  178. "field_property_name", GetPropertyName(field),
  179. "index", SimpleItoa(field->number()));
  180. }
  181. printer->Outdent();
  182. printer->Print("}\n");
  183. // TODO: Should we put the oneof .proto comments here?
  184. // It's unclear exactly where they should go.
  185. printer->Print(
  186. vars,
  187. "private $property_name$OneofCase $name$Case_ = $property_name$OneofCase.None;\n");
  188. WriteGeneratedCodeAttributes(printer);
  189. printer->Print(
  190. vars,
  191. "public $property_name$OneofCase $property_name$Case {\n"
  192. " get { return $name$Case_; }\n"
  193. "}\n\n");
  194. WriteGeneratedCodeAttributes(printer);
  195. printer->Print(
  196. vars,
  197. "public void Clear$property_name$() {\n"
  198. " $name$Case_ = $property_name$OneofCase.None;\n"
  199. " $name$_ = null;\n"
  200. "}\n\n");
  201. }
  202. // Standard methods
  203. GenerateFrameworkMethods(printer);
  204. GenerateMessageSerializationMethods(printer);
  205. GenerateMergingMethods(printer);
  206. // Nested messages and enums
  207. if (HasNestedGeneratedTypes()) {
  208. printer->Print(
  209. vars,
  210. "#region Nested types\n"
  211. "/// <summary>Container for nested types declared in the $class_name$ message type.</summary>\n");
  212. WriteGeneratedCodeAttributes(printer);
  213. printer->Print("public static partial class Types {\n");
  214. printer->Indent();
  215. for (int i = 0; i < descriptor_->enum_type_count(); i++) {
  216. EnumGenerator enumGenerator(descriptor_->enum_type(i), this->options());
  217. enumGenerator.Generate(printer);
  218. }
  219. for (int i = 0; i < descriptor_->nested_type_count(); i++) {
  220. // Don't generate nested types for maps...
  221. if (!IsMapEntryMessage(descriptor_->nested_type(i))) {
  222. MessageGenerator messageGenerator(
  223. descriptor_->nested_type(i), this->options());
  224. messageGenerator.Generate(printer);
  225. }
  226. }
  227. printer->Outdent();
  228. printer->Print("}\n"
  229. "#endregion\n"
  230. "\n");
  231. }
  232. printer->Outdent();
  233. printer->Print("}\n");
  234. printer->Print("\n");
  235. }
  236. // Helper to work out whether we need to generate a class to hold nested types/enums.
  237. // Only tricky because we don't want to generate map entry types.
  238. bool MessageGenerator::HasNestedGeneratedTypes()
  239. {
  240. if (descriptor_->enum_type_count() > 0) {
  241. return true;
  242. }
  243. for (int i = 0; i < descriptor_->nested_type_count(); i++) {
  244. if (!IsMapEntryMessage(descriptor_->nested_type(i))) {
  245. return true;
  246. }
  247. }
  248. return false;
  249. }
  250. void MessageGenerator::GenerateCloningCode(io::Printer* printer) {
  251. std::map<string, string> vars;
  252. WriteGeneratedCodeAttributes(printer);
  253. vars["class_name"] = class_name();
  254. printer->Print(
  255. vars,
  256. "public $class_name$($class_name$ other) : this() {\n");
  257. printer->Indent();
  258. // Clone non-oneof fields first
  259. for (int i = 0; i < descriptor_->field_count(); i++) {
  260. if (!descriptor_->field(i)->containing_oneof()) {
  261. std::unique_ptr<FieldGeneratorBase> generator(
  262. CreateFieldGeneratorInternal(descriptor_->field(i)));
  263. generator->GenerateCloningCode(printer);
  264. }
  265. }
  266. // Clone just the right field for each oneof
  267. for (int i = 0; i < descriptor_->oneof_decl_count(); ++i) {
  268. vars["name"] = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), false);
  269. vars["property_name"] = UnderscoresToCamelCase(
  270. descriptor_->oneof_decl(i)->name(), true);
  271. printer->Print(vars, "switch (other.$property_name$Case) {\n");
  272. printer->Indent();
  273. for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) {
  274. const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j);
  275. std::unique_ptr<FieldGeneratorBase> generator(CreateFieldGeneratorInternal(field));
  276. vars["field_property_name"] = GetPropertyName(field);
  277. printer->Print(
  278. vars,
  279. "case $property_name$OneofCase.$field_property_name$:\n");
  280. printer->Indent();
  281. generator->GenerateCloningCode(printer);
  282. printer->Print("break;\n");
  283. printer->Outdent();
  284. }
  285. printer->Outdent();
  286. printer->Print("}\n\n");
  287. }
  288. // Clone unknown fields
  289. printer->Print(
  290. "_unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);\n");
  291. printer->Outdent();
  292. printer->Print("}\n\n");
  293. WriteGeneratedCodeAttributes(printer);
  294. printer->Print(
  295. vars,
  296. "public $class_name$ Clone() {\n"
  297. " return new $class_name$(this);\n"
  298. "}\n\n");
  299. }
  300. void MessageGenerator::GenerateFreezingCode(io::Printer* printer) {
  301. }
  302. void MessageGenerator::GenerateFrameworkMethods(io::Printer* printer) {
  303. std::map<string, string> vars;
  304. vars["class_name"] = class_name();
  305. // Equality
  306. WriteGeneratedCodeAttributes(printer);
  307. printer->Print(
  308. vars,
  309. "public override bool Equals(object other) {\n"
  310. " return Equals(other as $class_name$);\n"
  311. "}\n\n");
  312. WriteGeneratedCodeAttributes(printer);
  313. printer->Print(
  314. vars,
  315. "public bool Equals($class_name$ other) {\n"
  316. " if (ReferenceEquals(other, null)) {\n"
  317. " return false;\n"
  318. " }\n"
  319. " if (ReferenceEquals(other, this)) {\n"
  320. " return true;\n"
  321. " }\n");
  322. printer->Indent();
  323. for (int i = 0; i < descriptor_->field_count(); i++) {
  324. std::unique_ptr<FieldGeneratorBase> generator(
  325. CreateFieldGeneratorInternal(descriptor_->field(i)));
  326. generator->WriteEquals(printer);
  327. }
  328. for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
  329. printer->Print("if ($property_name$Case != other.$property_name$Case) return false;\n",
  330. "property_name", UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true));
  331. }
  332. printer->Outdent();
  333. printer->Print(
  334. " return Equals(_unknownFields, other._unknownFields);\n"
  335. "}\n\n");
  336. // GetHashCode
  337. // Start with a non-zero value to easily distinguish between null and "empty" messages.
  338. WriteGeneratedCodeAttributes(printer);
  339. printer->Print(
  340. "public override int GetHashCode() {\n"
  341. " int hash = 1;\n");
  342. printer->Indent();
  343. for (int i = 0; i < descriptor_->field_count(); i++) {
  344. std::unique_ptr<FieldGeneratorBase> generator(
  345. CreateFieldGeneratorInternal(descriptor_->field(i)));
  346. generator->WriteHash(printer);
  347. }
  348. for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
  349. printer->Print("hash ^= (int) $name$Case_;\n",
  350. "name", UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), false));
  351. }
  352. printer->Print(
  353. "if (_unknownFields != null) {\n"
  354. " hash ^= _unknownFields.GetHashCode();\n"
  355. "}\n"
  356. "return hash;\n");
  357. printer->Outdent();
  358. printer->Print("}\n\n");
  359. WriteGeneratedCodeAttributes(printer);
  360. printer->Print(
  361. "public override string ToString() {\n"
  362. " return pb::JsonFormatter.ToDiagnosticString(this);\n"
  363. "}\n\n");
  364. }
  365. void MessageGenerator::GenerateMessageSerializationMethods(io::Printer* printer) {
  366. WriteGeneratedCodeAttributes(printer);
  367. printer->Print(
  368. "public void WriteTo(pb::CodedOutputStream output) {\n");
  369. printer->Indent();
  370. // Serialize all the fields
  371. for (int i = 0; i < fields_by_number().size(); i++) {
  372. std::unique_ptr<FieldGeneratorBase> generator(
  373. CreateFieldGeneratorInternal(fields_by_number()[i]));
  374. generator->GenerateSerializationCode(printer);
  375. }
  376. // Serialize unknown fields
  377. printer->Print(
  378. "if (_unknownFields != null) {\n"
  379. " _unknownFields.WriteTo(output);\n"
  380. "}\n");
  381. // TODO(jonskeet): Memoize size of frozen messages?
  382. printer->Outdent();
  383. printer->Print(
  384. "}\n"
  385. "\n");
  386. WriteGeneratedCodeAttributes(printer);
  387. printer->Print(
  388. "public int CalculateSize() {\n");
  389. printer->Indent();
  390. printer->Print("int size = 0;\n");
  391. for (int i = 0; i < descriptor_->field_count(); i++) {
  392. std::unique_ptr<FieldGeneratorBase> generator(
  393. CreateFieldGeneratorInternal(descriptor_->field(i)));
  394. generator->GenerateSerializedSizeCode(printer);
  395. }
  396. printer->Print(
  397. "if (_unknownFields != null) {\n"
  398. " size += _unknownFields.CalculateSize();\n"
  399. "}\n");
  400. printer->Print("return size;\n");
  401. printer->Outdent();
  402. printer->Print("}\n\n");
  403. }
  404. void MessageGenerator::GenerateMergingMethods(io::Printer* printer) {
  405. // Note: These are separate from GenerateMessageSerializationMethods()
  406. // because they need to be generated even for messages that are optimized
  407. // for code size.
  408. std::map<string, string> vars;
  409. vars["class_name"] = class_name();
  410. WriteGeneratedCodeAttributes(printer);
  411. printer->Print(
  412. vars,
  413. "public void MergeFrom($class_name$ other) {\n");
  414. printer->Indent();
  415. printer->Print(
  416. "if (other == null) {\n"
  417. " return;\n"
  418. "}\n");
  419. // Merge non-oneof fields
  420. for (int i = 0; i < descriptor_->field_count(); i++) {
  421. if (!descriptor_->field(i)->containing_oneof()) {
  422. std::unique_ptr<FieldGeneratorBase> generator(
  423. CreateFieldGeneratorInternal(descriptor_->field(i)));
  424. generator->GenerateMergingCode(printer);
  425. }
  426. }
  427. // Merge oneof fields
  428. for (int i = 0; i < descriptor_->oneof_decl_count(); ++i) {
  429. vars["name"] = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), false);
  430. vars["property_name"] = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true);
  431. printer->Print(vars, "switch (other.$property_name$Case) {\n");
  432. printer->Indent();
  433. for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) {
  434. const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j);
  435. vars["field_property_name"] = GetPropertyName(field);
  436. printer->Print(
  437. vars,
  438. "case $property_name$OneofCase.$field_property_name$:\n");
  439. printer->Indent();
  440. std::unique_ptr<FieldGeneratorBase> generator(CreateFieldGeneratorInternal(field));
  441. generator->GenerateMergingCode(printer);
  442. printer->Print("break;\n");
  443. printer->Outdent();
  444. }
  445. printer->Outdent();
  446. printer->Print("}\n\n");
  447. }
  448. // Merge unknown fields.
  449. printer->Print(
  450. "_unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);\n");
  451. printer->Outdent();
  452. printer->Print("}\n\n");
  453. WriteGeneratedCodeAttributes(printer);
  454. printer->Print("public void MergeFrom(pb::CodedInputStream input) {\n");
  455. printer->Indent();
  456. printer->Print(
  457. "uint tag;\n"
  458. "while ((tag = input.ReadTag()) != 0) {\n"
  459. " switch(tag) {\n");
  460. printer->Indent();
  461. printer->Indent();
  462. // Option messages need to store unknown fields so that options can be parsed later.
  463. if (IsDescriptorOptionMessage(descriptor_)) {
  464. printer->Print(
  465. "default:\n"
  466. " CustomOptions = CustomOptions.ReadOrSkipUnknownField(input);\n"
  467. " break;\n");
  468. } else {
  469. printer->Print(
  470. "default:\n"
  471. " _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);\n"
  472. " break;\n");
  473. }
  474. for (int i = 0; i < fields_by_number().size(); i++) {
  475. const FieldDescriptor* field = fields_by_number()[i];
  476. internal::WireFormatLite::WireType wt =
  477. internal::WireFormat::WireTypeForFieldType(field->type());
  478. uint32 tag = internal::WireFormatLite::MakeTag(field->number(), wt);
  479. // Handle both packed and unpacked repeated fields with the same Read*Array call;
  480. // the two generated cases are the packed and unpacked tags.
  481. // TODO(jonskeet): Check that is_packable is equivalent to
  482. // is_repeated && wt in { VARINT, FIXED32, FIXED64 }.
  483. // It looks like it is...
  484. if (field->is_packable()) {
  485. printer->Print(
  486. "case $packed_tag$:\n",
  487. "packed_tag",
  488. SimpleItoa(
  489. internal::WireFormatLite::MakeTag(
  490. field->number(),
  491. internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED)));
  492. }
  493. printer->Print("case $tag$: {\n", "tag", SimpleItoa(tag));
  494. printer->Indent();
  495. std::unique_ptr<FieldGeneratorBase> generator(
  496. CreateFieldGeneratorInternal(field));
  497. generator->GenerateParsingCode(printer);
  498. printer->Print("break;\n");
  499. printer->Outdent();
  500. printer->Print("}\n");
  501. }
  502. printer->Outdent();
  503. printer->Print("}\n"); // switch
  504. printer->Outdent();
  505. printer->Print("}\n"); // while
  506. printer->Outdent();
  507. printer->Print("}\n\n"); // method
  508. }
  509. int MessageGenerator::GetFieldOrdinal(const FieldDescriptor* descriptor) {
  510. for (int i = 0; i < field_names().size(); i++) {
  511. if (field_names()[i] == descriptor->name()) {
  512. return i;
  513. }
  514. }
  515. GOOGLE_LOG(DFATAL)<< "Could not find ordinal for field " << descriptor->name();
  516. return -1;
  517. }
  518. FieldGeneratorBase* MessageGenerator::CreateFieldGeneratorInternal(
  519. const FieldDescriptor* descriptor) {
  520. return CreateFieldGenerator(descriptor, GetFieldOrdinal(descriptor), this->options());
  521. }
  522. } // namespace csharp
  523. } // namespace compiler
  524. } // namespace protobuf
  525. } // namespace google