From 33836aeafbc98038f07e68d6f54c30b3720147c0 Mon Sep 17 00:00:00 2001 From: dsavvinov Date: Wed, 20 Jul 2016 19:56:40 +0300 Subject: [PATCH] Protobuf: refactored generateSerializationCode() in FieldGenerator + some other little refactoring --- proto/compiler/README.md | 63 +-- .../google/protobuf/compiler/kotlin/protoc | Bin 101128 -> 105880 bytes .../kotlin/src/kotlin_class_generator.cc | 6 +- .../kotlin/src/kotlin_class_generator.h | 8 +- .../kotlin/src/kotlin_enum_generator.cc | 16 +- .../kotlin/src/kotlin_enum_generator.h | 11 +- .../kotlin/src/kotlin_field_generator.cc | 387 ++++++++++-------- .../kotlin/src/kotlin_field_generator.h | 5 + 8 files changed, 275 insertions(+), 221 deletions(-) diff --git a/proto/compiler/README.md b/proto/compiler/README.md index 1deeebe1ffa..a1c7c1b4b99 100644 --- a/proto/compiler/README.md +++ b/proto/compiler/README.md @@ -22,38 +22,41 @@ In folder /src/ you can find sources for ProtoKot-runtime, that will be used by ## Using generated code Example: - - // Messages work only with CodedStream classes, provided by ProtoKot-runtime library. - // One can create CodedStream passing any instance of corresponding Stream from Java's library. - val s = ByteArrayOutputStream() - val outs = CodedOutputStream(s) - // All messages are immutable. Use Builders for creating new messages - val msg = Person.BuilderPerson() - .setEmail("wtf@dasda.com") // all setters return this builder, so you could chain modifiers in LINQ-style - .setId(42) - .setName("John Doe") - .setPhones(arrayOf( // repeated fields stored as Array<>, so use arrayOf() for creating repeated fields - Person.PhoneNumber.BuilderPhoneNumber() - .setNumber("342143-23423-42") - .setType(Person.PhoneType.HOME) - .build() - )) - .build() // don't forget to call build() to produce message - msg.writeTo(outs) +```java +// Messages work only with CodedStream classes, provided by ProtoKot-runtime library. +// One can create CodedStream passing any instance of corresponding Stream from Java's library. +val s = ByteArrayOutputStream() +val outs = CodedOutputStream(s) - // Now let's use output stream as input to read our message from it! - var ins = CodedInputStream(ByteArrayInputStream(s.toByteArray())) +// All messages are immutable. Use Builders for creating new messages +val msg = Person.BuilderPerson() + .setEmail("wtf@dasda.com") // all setters return this builder, so you could chain modifiers in LINQ-style + .setId(42) + .setName("John Doe") + .setPhones(arrayOf( // repeated fields stored as Array<>, so use arrayOf() for creating repeated fields + Person.PhoneNumber.BuilderPhoneNumber() + .setNumber("342143-23423-42") + .setType(Person.PhoneType.HOME) + .build() + )) + .build() // don't forget to call build() to produce message +msg.writeTo(outs) - // Create default instance of message - var readMsg = Person.BuilderPerson().build() - // Read in that message data from input stream. - readMsg.mergeFrom(ins) +// Now let's use output stream as input to read our message from it! +var ins = CodedInputStream(ByteArrayInputStream(s.toByteArray())) - // Note, that currently mergeFrom is the only way to mutate instance of message. - // Don't rely on it, probably mergeFrom will be refactored lately to guarantee full immutability of mesages. +// Create default instance of message +var readMsg = Person.BuilderPerson().build() +// Read in that message data from input stream. +readMsg.mergeFrom(ins) + +// Note, that currently mergeFrom is the only way to mutate instance of message. +// Don't rely on it, probably mergeFrom will be refactored lately to guarantee full immutability of mesages. + +// Better way to read a message: +ins = CodedInputStream(ByteArrayInputStream(s.toByteArray())) +readMsg = Person.BuilderPerson().readFrom(ins).build() +assert(msg == readMsg) +``` - // Better way to read a message: - ins = CodedInputStream(ByteArrayInputStream(s.toByteArray())) - readMsg = Person.BuilderPerson().readFrom(ins).build() - assert(msg == readMsg) \ No newline at end of file diff --git a/proto/compiler/google/src/google/protobuf/compiler/kotlin/protoc b/proto/compiler/google/src/google/protobuf/compiler/kotlin/protoc index df7073bb962605d98c265cd3292c440a20eaab4e..387885f463a6e28448498c9e739119ac8dcbafde 100755 GIT binary patch delta 33327 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 QnZ_z~_kNBi3&nQ-2T5h_^8f$< delta 31917 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�Pg9uw z+L$?=$Ug;PHsPe(epHp9e|txl>Or>%k10^_mMXqO!Lh);pfE(WWK(Bvwc~wvLvhEQrF+qPXJ3pv-oZ1K{QXoz znsiYNF{*~Vp%yq@#j7r--u24ArRec4J^U~gQ?pd<%UwB+&7#eyWKi`BV~D}qt4O^I z+L=5|9QKUMF%1XMd22+2>!(>_BiCD##51m&i$NO3iFI7*>0;o{iWkK${;s*xaZvb7 zh8W^HI!zqpYWlJmv-92QVua*sI9+Vtp#6&zr%#+cHe+I+8FQ!i_C5f0&6+0GV|D5_ z+bPc!kBd7qXNv_jT))kMs#PmQy{pS4v9&8dU)1lsor!IeYtb)p-*x4sfZ0XNFs1>qPUL)T2W96d%&U5QUo1e73)YbJh9GQAoJ85@ZvtJWC z*YR%PZFdwW%yR91O>9@kyI1o5x9wA|2Y~B(x9P z{b!>XQzLpTr?y7Bwr>=>cuDMm?`lYF&)UCU$(6A+CQ{v(-*4yIPNa7`9^<-8q&m$M z#=6>XswA-opS?-!DaN|CZxVY*R~NhPf~*m%7**cD)%6XrbInqVLN|zaJzOs~`#*mz Beenum_type(i); nameResolver->addClass(nestedEnumDescriptor->name(), getFullType()); - enumsDeclaraions.push_back(new EnumGenerator(nestedEnumDescriptor)); + enumsDeclaraions.push_back(new EnumGenerator(nestedEnumDescriptor, nameResolver)); } /** @@ -275,7 +275,7 @@ void ClassGenerator::generateParseMethods(io::Printer *printer) const { // messages are not required to end with 0-tag, therefore parsing method should check for EOF printer->Print("if (input.isAtEnd()) { return false }\n"); - // read tag and check if some field will follow (0-tag inidcates end of message) + // read tag and check if some field will follow (0-tag indicates end of message) printer->Print("val tag = input.readInt32NoTag()\n"); printer->Print("if (tag == 0) { return false } \n"); @@ -308,6 +308,8 @@ void ClassGenerator::generateParseMethods(io::Printer *printer) const { } } + // TODO: add parsing of unknown fields + printer->Outdent(); printer->Print("}\n"); // when-clause diff --git a/proto/compiler/google/src/google/protobuf/compiler/kotlin/src/kotlin_class_generator.h b/proto/compiler/google/src/google/protobuf/compiler/kotlin/src/kotlin_class_generator.h index 01774e7ef30..62b59c5d4a0 100644 --- a/proto/compiler/google/src/google/protobuf/compiler/kotlin/src/kotlin_class_generator.h +++ b/proto/compiler/google/src/google/protobuf/compiler/kotlin/src/kotlin_class_generator.h @@ -19,6 +19,7 @@ namespace kotlin { class FieldGenerator; // declared in "kotlin_file_generator.h" class NameResolver; // declared in "kotlin_name_resolver.h" +class EnumGenerator; // declared in "kotlin_enum_generator.h" class ClassGenerator { public: @@ -41,6 +42,7 @@ private: void generateBuilder (io::Printer * printer) const; void generateBuildMethod (io::Printer * printer) const; void generateInitSection (io::Printer * printer) const; + /** * Flag isBuilder used for reducing code repeating, as code for class itself * and for its inner builder are structurally very alike and can be generated @@ -48,12 +50,6 @@ private: */ void generateHeader(io::Printer * printer, bool isBuilder = false) const; - /** - * IsRead flag indicates that readFrom method should be generated, otherwise - * writeTo method is generated. Motivation is similar to the isBuilder flag: - * both methods are structurally the same with some trivial substitutions - * (read -> write and etc.) - */ void generateWriteToMethod(io::Printer *printer) const; void generateMergeMethods(io::Printer *printer) const; void generateParseMethods(io::Printer * printer) const; diff --git a/proto/compiler/google/src/google/protobuf/compiler/kotlin/src/kotlin_enum_generator.cc b/proto/compiler/google/src/google/protobuf/compiler/kotlin/src/kotlin_enum_generator.cc index 8d5bd9ad3b1..c49913bcaec 100644 --- a/proto/compiler/google/src/google/protobuf/compiler/kotlin/src/kotlin_enum_generator.cc +++ b/proto/compiler/google/src/google/protobuf/compiler/kotlin/src/kotlin_enum_generator.cc @@ -54,13 +54,14 @@ void EnumGenerator::generateCode(io::Printer * printer) const { } printer->Print("\n"); - gemerateEnumConverters(printer); + generateEnumConverter(printer); printer->Outdent(); printer->Print("}"); } -void EnumGenerator::gemerateEnumConverters(io::Printer *printer) const { +void EnumGenerator::generateEnumConverter(io::Printer *printer) const { + // note that full-qualification is not necessary as this code resides in enum namespace map vars; vars["dollar"] = "$"; vars["type"] = simpleName; @@ -105,14 +106,21 @@ EnumGenerator::~EnumGenerator() { } } -EnumGenerator::EnumGenerator(EnumDescriptor const *descriptor) { - simpleName = descriptor->name(); +EnumGenerator::EnumGenerator(EnumDescriptor const *descriptor, NameResolver * nameResolver) + : simpleName(descriptor->name()) + , nameResolver(nameResolver) +{ int values_count = descriptor->value_count(); for (int i = 0; i < values_count; ++i) { enumValues.push_back(new EnumValueGenerator(descriptor->value(i))); } } +string EnumGenerator::getFullType() const { + return nameResolver->getClassName(simpleName); +} + + } // namespace kotlin } // namespace compiler } // namespace protobuf diff --git a/proto/compiler/google/src/google/protobuf/compiler/kotlin/src/kotlin_enum_generator.h b/proto/compiler/google/src/google/protobuf/compiler/kotlin/src/kotlin_enum_generator.h index 5e9c9f1b9b0..8a82731b7a4 100644 --- a/proto/compiler/google/src/google/protobuf/compiler/kotlin/src/kotlin_enum_generator.h +++ b/proto/compiler/google/src/google/protobuf/compiler/kotlin/src/kotlin_enum_generator.h @@ -7,6 +7,9 @@ #include #include +#include "kotlin_name_resolver.h" + +class NameResolver; // declared in "kotlin_name_resolver.h" namespace google { namespace protobuf { @@ -24,15 +27,19 @@ public: class EnumGenerator { public: - EnumGenerator(EnumDescriptor const * descriptor); + EnumGenerator(EnumDescriptor const * descriptor, NameResolver * nameResolver); ~EnumGenerator(); string simpleName; vector enumValues; + /* Return full-qualified name of enum */ + string getFullType() const; + void generateCode(io::Printer *) const; private: - void gemerateEnumConverters(io::Printer *printer) const; + void generateEnumConverter(io::Printer *printer) const; + NameResolver * nameResolver; }; } // namespace kotlin diff --git a/proto/compiler/google/src/google/protobuf/compiler/kotlin/src/kotlin_field_generator.cc b/proto/compiler/google/src/google/protobuf/compiler/kotlin/src/kotlin_field_generator.cc index ba059ba5acb..04a875e58c0 100644 --- a/proto/compiler/google/src/google/protobuf/compiler/kotlin/src/kotlin_field_generator.cc +++ b/proto/compiler/google/src/google/protobuf/compiler/kotlin/src/kotlin_field_generator.cc @@ -58,191 +58,224 @@ FieldGenerator::FieldGenerator(FieldDescriptor const * descriptor, ClassGenerato , protoLabel(descriptor->label()) { } -// TODO: long, complicated and messy method. Refactor it ASAP -void FieldGenerator::generateSerializationCode(io::Printer *printer, bool isRead, bool noTag) const { +void FieldGenerator::generateSerializationForRepeated(io::Printer * printer, bool isRead, bool noTag) const { map vars; - vars["type"] = getKotlinFunctionSuffix() + (noTag ? "NoTag" : ""); vars["fieldNumber"] = std::to_string(getFieldNumber()); - vars["maybeFieldNumber"] = noTag ? "" : std::to_string(getFieldNumber()); + vars["builderType"] = getUnderlyingTypeGenerator().getFullType(); + vars["initValue"] = getUnderlyingTypeGenerator().getInitValue(); vars["fieldName"] = simpleName; - vars["arg"] = isRead ? "input" : "output"; - vars["maybeComma"] = ", "; - - /** - * First of all, try to generate syntax for repeated fields because it's separate case. - * Do this according to protobuf format: - * - Check if size of array is > 0, because empty repeated fields shouldn't appear in message - * - Write tag explicitly - * - Write length as int32 (note that tag shouldn't be added) - * - Write all repeated elements via recursive call (again, without tags) - */ - if (getProtoLabel() == FieldDescriptor::LABEL_REPEATED) { - // tag - if (isRead) { - if (!noTag) { - printer->Print(vars, "val tag = input.readTag($fieldNumber$, WireType.LENGTH_DELIMITED)\n"); - } - printer->Print(vars, "val expectedSize = input.readInt32NoTag()\n"); - printer->Print("var readSize = 0\n"); - printer->Print(vars, "while(readSize != expectedSize) {\n"); - printer->Indent(); - - /* hack: copy current FieldGenerator and change label to OPTIONAL. Also change name to - name of iterator in for-loop. - This will allow to re-use this function for generating serialization code for elements of array. - More importantly, this will care about nested types too. - Efficiently, it inlines serialization code for all underlying types. - This hack isn't necessary from the architectural point of view and could be safely - removed as soon as target code will support inheritance and interfaces. - (then writing CodedOutputStream.writeMessage will be possible). - */ - FieldGenerator singleFieldGen = getUnderlyingTypeGenerator(); - - /* Another dirty hack here: create tmp variable of a given type and read it from input stream - then add that tmp var into list. - This is made because simple recursive call will generate code that tries to array[i].mergeFrom(). - This is incorrect because array has old size, while 'i' iterates over new size, which can lead - to ArrayOutOfIndex errors. - */ - // TODO: stub here, resolve name properly! - vars["builderType"] = getUnderlyingTypeGenerator().getFullType(); - vars["initValue"] = getUnderlyingTypeGenerator().getInitValue(); - printer->Print(vars, "var tmp: $builderType$ = $initValue$\n"); - singleFieldGen.simpleName = "tmp"; - singleFieldGen.protoLabel = FieldDescriptor::LABEL_OPTIONAL; - - // Note that primitive types are packed by default in proto3, i.e. they are should be written without tag - bool isPrimitive = descriptor->type() != FieldDescriptor::TYPE_BYTES && - descriptor->type() != FieldDescriptor::TYPE_MESSAGE && - descriptor->type() != FieldDescriptor::TYPE_STRING && - descriptor->type() != FieldDescriptor::TYPE_ENUM; - - singleFieldGen.generateSerializationCode(printer, isRead, /* noTag = */ isPrimitive); - singleFieldGen.generateSizeEstimationCode(printer, /* varName = */ "readSize"); // add size of current element to total size - - printer->Print(vars, "$fieldName$.add(tmp)\n"); - - printer->Outdent(); - printer->Print("}\n"); - } - else { - printer->Print(vars, "if ($fieldName$.size > 0) {\n"); - printer->Indent(); - - // tag - printer->Print(vars, "output.writeTag($fieldNumber$, WireType.LENGTH_DELIMITED)\n"); - - // length - printer->Print(vars, "var arrayByteSize = 0\n"); - generateSizeEstimationCode(printer, "arrayByteSize", /* noTag = */ true); - printer->Print(vars, "output.writeInt32NoTag(arrayByteSize)\n"); - - // all elements - printer->Print(vars, "for (item in $fieldName$) {\n"); - printer->Indent(); - - // hack: see above - FieldGenerator singleFieldGen = FieldGenerator(descriptor, enclosingClass, nameResolver); - singleFieldGen.simpleName = "item"; - singleFieldGen.protoLabel = FieldDescriptor::LABEL_OPTIONAL; - - // TODO: maybe refactor this in name_resolving or separate method at least - // Note that primitive types are packed by default in proto3, i.e. they are should be written without tag - bool isPrimitive = descriptor->type() != FieldDescriptor::TYPE_BYTES && - descriptor->type() != FieldDescriptor::TYPE_MESSAGE && - descriptor->type() != FieldDescriptor::TYPE_STRING && - descriptor->type() != FieldDescriptor::TYPE_ENUM; - - singleFieldGen.generateSerializationCode(printer, isRead, /* noTag = */ isPrimitive); - - printer->Outdent(); // for-loop - printer->Print("}\n"); - - printer->Outdent(); // if-clause - printer->Print("}\n"); - } - return; - } - - /* - Then check for conversions 'int -> enum-value' and \enum-value -> int' if current - field is enum. - This is necessary, because CodedStream stores enums as Ints in wire, delegating - responsibility for casting those Ints to enum values and vice versa to the caller. - Example: enumField = fromIntToMyEnumName(input.readEnum(42)) - Example: output.writeEnum(42, enumField.ord) - */ - if (descriptor->type() == FieldDescriptor::TYPE_ENUM) { - vars["converter"] = getEnumFromIntConverter(); - if (isRead) { - printer->Print(vars, "$fieldName$ = $converter$(input.read$type$($maybeFieldNumber$))\n"); - } - else { - printer->Print(vars, "output.write$type$ ($maybeFieldNumber$$maybeComma$$fieldName$.ord)\n"); - } - return; - } - - /* - Then check for nested messages. Then we re-use writeTo method, that should be defined in - that message. - Note that readFrom/writeTo methods write message as it's top-level message, i.e. without - any tags. Therefore, we have to prepend tags and size manually. - */ - if (descriptor->type() == FieldDescriptor::TYPE_MESSAGE) { - if (isRead) { - vars["fieldNumber"] = std::to_string(getFieldNumber()); - vars["dollar"] = "$"; - - // We will create some temporary variables - // So we place following code into separate block for the sake of hygiene - printer->Print("run {\n"); - printer->Indent(); - - // read tag - if (!noTag) { - printer->Print(vars, "input.readTag($fieldNumber$, WireType.LENGTH_DELIMITED)\n"); - } - - // read expected size - printer->Print(vars, "val expectedSize = input.readInt32NoTag()\n"); - - // read message itself without tag - printer->Print(vars, - "$fieldName$.mergeFromWithSize(input, expectedSize)\n"); - - // check that actual size equal to expected size - printer->Print(vars, "if (expectedSize != $fieldName$.getSize()) { " - "throw InvalidProtocolBufferException (" - "\"Expected size $dollar${expectedSize} got $dollar${$fieldName$.getSize()}" - "\") }\n"); - printer->Outdent(); - printer->Print("}\n"); - } - else { - vars["fieldNumber"] = std::to_string(getFieldNumber()); - // write tag - printer->Print(vars, "output.writeTag($fieldNumber$, WireType.LENGTH_DELIMITED)\n"); - - // write message length via runtime-call - printer->Print(vars, "output.writeInt32NoTag($fieldName$.getSize())\n"); - - // write message itself without tag - printer->Print(vars, - "$fieldName$.writeTo(output)\n"); - } - return; - } - - /* Finally, serialize trivial cases */ if (isRead) { - printer->Print(vars, "$fieldName$ = input.read$type$($maybeFieldNumber$)\n"); + if (!noTag) { + printer->Print(vars, "val tag = input.readTag($fieldNumber$, WireType.LENGTH_DELIMITED)\n"); + } + printer->Print(vars, "val expectedSize = input.readInt32NoTag()\n"); + printer->Print("var readSize = 0\n"); + printer->Print(vars, "while(readSize != expectedSize) {\n"); + printer->Indent(); + + /* hack: copy current FieldGenerator and change label to OPTIONAL. Also change name to + name of iterator in for-loop. + This will allow to re-use this function for generating serialization code for elements of array. + More importantly, this will care about nested types too. + Efficiently, it inlines serialization code for all underlying types. + This hack isn't necessary from the architectural point of view and could be safely + removed as soon as target code will support inheritance and interfaces. + (then writing CodedOutputStream.writeMessage will be possible). + */ + FieldGenerator singleFieldGen = getUnderlyingTypeGenerator(); + + /* Another dirty hack here: create tmp variable of a given type and read it from input stream + then add that tmp var into list. + This is made because simple recursive call will generate code that tries to array[i].mergeFrom(). + This is incorrect because array has old size, while 'i' iterates over new size, which can lead + to ArrayOutOfIndex errors. + */ + printer->Print(vars, "var tmp: $builderType$ = $initValue$\n"); + singleFieldGen.simpleName = "tmp"; + singleFieldGen.protoLabel = FieldDescriptor::LABEL_OPTIONAL; + + // Note that primitive types are packed by default in proto3, i.e. they are should be written without tag + bool isPrimitive = descriptor->type() != FieldDescriptor::TYPE_BYTES && + descriptor->type() != FieldDescriptor::TYPE_MESSAGE && + descriptor->type() != FieldDescriptor::TYPE_STRING && + descriptor->type() != FieldDescriptor::TYPE_ENUM; + + singleFieldGen.generateSerializationCode(printer, isRead, /* noTag = */ isPrimitive); + singleFieldGen.generateSizeEstimationCode(printer, /* varName = */ + "readSize"); // add size of current element to total size + + printer->Print(vars, "$fieldName$.add(tmp)\n"); + + printer->Outdent(); + printer->Print("}\n"); } else { - printer->Print(vars, "output.write$type$ ($maybeFieldNumber$$maybeComma$$fieldName$)\n"); + /** + * Protobuf format: + * - Check if size of array is > 0, because empty repeated fields shouldn't appear in message + * - Write tag explicitly + * - Write length as int32 (note that tag shouldn't be added) + * - Write all repeated elements via recursive call (for primitive types without tags) + */ + printer->Print(vars, "if ($fieldName$.size > 0) {\n"); + printer->Indent(); + + // tag + printer->Print(vars, "output.writeTag($fieldNumber$, WireType.LENGTH_DELIMITED)\n"); + + // length + printer->Print(vars, "var arrayByteSize = 0\n"); + generateSizeEstimationCode(printer, "arrayByteSize", /* noTag = */ true); + printer->Print(vars, "output.writeInt32NoTag(arrayByteSize)\n"); + + // all elements + printer->Print(vars, "for (item in $fieldName$) {\n"); + printer->Indent(); + + // hack: see above + FieldGenerator singleFieldGen = FieldGenerator(descriptor, enclosingClass, nameResolver); + singleFieldGen.simpleName = "item"; + singleFieldGen.protoLabel = FieldDescriptor::LABEL_OPTIONAL; + + // TODO: maybe refactor this in name_resolving or separate method at least + bool isPrimitive = descriptor->type() != FieldDescriptor::TYPE_BYTES && + descriptor->type() != FieldDescriptor::TYPE_MESSAGE && + descriptor->type() != FieldDescriptor::TYPE_STRING && + descriptor->type() != FieldDescriptor::TYPE_ENUM; + + singleFieldGen.generateSerializationCode(printer, isRead, /* noTag = */ isPrimitive); + + printer->Outdent(); // for-loop + printer->Print("}\n"); + + printer->Outdent(); // if-clause + printer->Print("}\n"); } } +void FieldGenerator::generateSerializationForEnums(io::Printer * printer, bool isRead, bool noTag) const { + map vars; + vars["converter"] = getEnumFromIntConverter(); + vars["fieldName"] = simpleName; + vars["suffix"] = getKotlinFunctionSuffix(); + vars["fieldNumber"] = std::to_string(getFieldNumber()); + if (isRead) { + if (noTag) { + printer->Print(vars, "$fieldName$ = $converter$(input.read$suffix$NoTag())\n"); + } + else { + printer->Print(vars, "$fieldName$ = $converter$(input.read$suffix$($fieldNumber$))\n"); + } + } + else { + if (noTag) { + printer->Print(vars, "output.write$suffix$NoTag ()\n"); + } + else { + printer->Print(vars, "output.write$suffix$ ($fieldNumber$, $fieldName$.ord)\n"); + } + } +} + +void FieldGenerator::generateSerializationForMessages(io::Printer * printer, bool isRead, bool noTag) const { + map vars; + vars["fieldNumber"] = std::to_string(getFieldNumber()); + vars["dollar"] = "$"; + vars["fieldName"] = simpleName; + + if (isRead) { + // We will create some temporary variables + // So we place following code into separate block for the sake of hygiene + printer->Print("run {\n"); + printer->Indent(); + + // read tag + if (!noTag) { + printer->Print(vars, "input.readTag($fieldNumber$, WireType.LENGTH_DELIMITED)\n"); + } + + // read expected size + printer->Print(vars, "val expectedSize = input.readInt32NoTag()\n"); + + // TODO: think about it, as it's not good approach - if some error occurs, we will read more bytes + // than expectedSize from CodedInputStream. That could potentially lead to some lingering problems in wire. + + // read message itself without tag, but limiting its size to expectedSize + printer->Print(vars, + "$fieldName$.mergeFromWithSize(input, expectedSize)\n"); + + // check that actual size equal to expected size + printer->Print(vars, "if (expectedSize != $fieldName$.getSize()) { " + "throw InvalidProtocolBufferException (" + "\"Expected size $dollar${expectedSize} got $dollar${$fieldName$.getSize()}" + "\") }\n"); + printer->Outdent(); + printer->Print("}\n"); + } + else { + // write tag + printer->Print(vars, "output.writeTag($fieldNumber$, WireType.LENGTH_DELIMITED)\n"); + + // write message length + printer->Print(vars, "output.writeInt32NoTag($fieldName$.getSize())\n"); + + // write message itself without tag + printer->Print(vars, + "$fieldName$.writeTo(output)\n"); + } +} + +void FieldGenerator::generateSerializationForPrimitives(io::Printer * printer, bool isRead, bool noTag) const { + map vars; + vars["fieldName"] = simpleName; + vars["suffix"] = getKotlinFunctionSuffix(); + vars["fieldNumber"] = std::to_string(getFieldNumber()); + if (isRead) { + if (noTag) { + printer->Print(vars, "$fieldName$ = input.read$suffix$NoTag()\n"); + } + else { + printer->Print(vars, "$fieldName$ = input.read$suffix$ ($fieldNumber$)"); + } + } + else { + if (noTag) { + printer->Print(vars, "output.write$suffix$NoTag ()\n"); + } + else { + printer->Print(vars, "output.write$suffix$ ($fieldNumber$, $fieldName$)\n"); + } + } +} + +void FieldGenerator::generateSerializationCode(io::Printer *printer, bool isRead, bool noTag) const { + /* Try to generate syntax for serialization of repeated fields. + * Note that it should be first check because of Google's FieldDescriptor structure */ + if (getProtoLabel() == FieldDescriptor::LABEL_REPEATED) { + generateSerializationForRepeated(printer, isRead, noTag); + return; + } + + /* Then check is current field is enum. We have to handle it separately too, because + * we have to pass enums as Int's to CodedStreams as per protobuf-format */ + if (descriptor->type() == FieldDescriptor::TYPE_ENUM) { + generateSerializationForEnums(printer, isRead, noTag); + return; + } + + /* Then check for nested messages. Here we re-use writeTo method, that should be defined in + * that message. + * Note that readFrom/writeTo methods write message as it's top-level message, i.e. without + * any tags. Therefore, we have to prepend tags and size manually. */ + if (descriptor->type() == FieldDescriptor::TYPE_MESSAGE) { + generateSerializationForMessages(printer, isRead, noTag); + return; + } + + /* Finally, serialize trivial cases */ + generateSerializationForPrimitives(printer, isRead, noTag); +} + void FieldGenerator::generateSetter(io::Printer *printer) const { map vars; @@ -265,7 +298,7 @@ void FieldGenerator::generateRepeatedMethods(io::Printer * printer, bool isBuild vars["elementType"] = getUnderlyingTypeGenerator().getSimpleType(); vars["arg"] = "value"; vars["fieldName"] = simpleName; - vars["builderName"] = enclosingClass->getBuilderFullType(); // TODO: call to non-existent field in map. + vars["builderName"] = enclosingClass->getBuilderFullType(); // generate indexed setter for builders if (isBuilder) { diff --git a/proto/compiler/google/src/google/protobuf/compiler/kotlin/src/kotlin_field_generator.h b/proto/compiler/google/src/google/protobuf/compiler/kotlin/src/kotlin_field_generator.h index b04629b34c3..1af1117a7b7 100644 --- a/proto/compiler/google/src/google/protobuf/compiler/kotlin/src/kotlin_field_generator.h +++ b/proto/compiler/google/src/google/protobuf/compiler/kotlin/src/kotlin_field_generator.h @@ -26,6 +26,11 @@ private: void generateSetter(io::Printer * printer) const; void generateRepeatedMethods(io::Printer * printer, bool isBuilder) const; + + void generateSerializationForRepeated (io::Printer * printer, bool isRead, bool noTag) const; + void generateSerializationForEnums (io::Printer * printer, bool isRead, bool noTag) const; + void generateSerializationForMessages (io::Printer * printer, bool isRead, bool noTag) const; + void generateSerializationForPrimitives (io::Printer * printer, bool isRead, bool noTag) const; public: ClassGenerator const * enclosingClass; // class, in which that field is defined NameResolver * nameResolver;