Protobuf: refactored FieldGenerator interface heavily. Now it offers much more clearier interface for names getting (separating simple names from full-qualified names)
This commit is contained in:
@@ -23,9 +23,14 @@ $(BINDIR):
|
|||||||
mkdir -p $(BINDIR)
|
mkdir -p $(BINDIR)
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -rf $(BINDIR) $(EXE)
|
rm -rf $(BINDIR)
|
||||||
|
|
||||||
generate:
|
generate:
|
||||||
./protoc --kotlin_out=$$HOME/Downloads/carkot/proto/compiler/src ./test/addressbook.proto
|
./protoc --kotlin_out=$$HOME/Downloads/carkot/proto/compiler/src ./test/addressbook.proto
|
||||||
./protoc --kotlin_out=$$HOME/Downloads/carkot/proto/compiler/src ./test/nested-msg.proto
|
./protoc --kotlin_out=$$HOME/Downloads/carkot/proto/compiler/src ./test/nested-msg.proto
|
||||||
.PHONY: clean all generate
|
|
||||||
|
debug:
|
||||||
|
gdb --args ./protoc --kotlin_out=$$HOME/Downloads/carkot/proto/compiler/src ./test/addressbook.proto
|
||||||
|
gdb --args ./protoc --kotlin_out=$$HOME/Downloads/carkot/proto/compiler/src ./test/nested-msg.proto
|
||||||
|
|
||||||
|
.PHONY: clean all generate debug
|
||||||
|
|||||||
Binary file not shown.
+19
@@ -0,0 +1,19 @@
|
|||||||
|
//
|
||||||
|
// Created by user on 7/20/16.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "UnreachableStateException.h"
|
||||||
|
namespace google {
|
||||||
|
namespace protobuf {
|
||||||
|
namespace compiler {
|
||||||
|
namespace kotlin {
|
||||||
|
|
||||||
|
UnreachableStateException::UnreachableStateException(std::string const & what)
|
||||||
|
: std::logic_error(what)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
} // namespace kotlin
|
||||||
|
} // namespace compiler
|
||||||
|
} // namespace protobuf
|
||||||
|
} // namespace google
|
||||||
|
|
||||||
+28
@@ -0,0 +1,28 @@
|
|||||||
|
//
|
||||||
|
// Created by user on 7/20/16.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef GOOGLE_UNREACHABLESTATEEXCEPTION_H
|
||||||
|
#define GOOGLE_UNREACHABLESTATEEXCEPTION_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <exception>
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
namespace google {
|
||||||
|
namespace protobuf {
|
||||||
|
namespace compiler {
|
||||||
|
namespace kotlin {
|
||||||
|
|
||||||
|
class UnreachableStateException : public std::logic_error {
|
||||||
|
public:
|
||||||
|
UnreachableStateException(std::string const & what);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace kotlin
|
||||||
|
} // namespace compiler
|
||||||
|
} // namespace protobuf
|
||||||
|
} // namespace google
|
||||||
|
|
||||||
|
|
||||||
|
#endif //GOOGLE_UNREACHABLESTATEEXCEPTION_H
|
||||||
+28
-46
@@ -80,8 +80,6 @@ ClassGenerator::ClassGenerator(Descriptor const *descriptor, NameResolver * name
|
|||||||
: descriptor(descriptor)
|
: descriptor(descriptor)
|
||||||
, nameResolver(nameResolver)
|
, nameResolver(nameResolver)
|
||||||
{
|
{
|
||||||
simpleName = descriptor->name();
|
|
||||||
|
|
||||||
int field_count = descriptor->field_count();
|
int field_count = descriptor->field_count();
|
||||||
for (int i = 0; i < field_count; ++i) {
|
for (int i = 0; i < field_count; ++i) {
|
||||||
FieldDescriptor const * fieldDescriptor = descriptor->field(i);
|
FieldDescriptor const * fieldDescriptor = descriptor->field(i);
|
||||||
@@ -91,14 +89,14 @@ ClassGenerator::ClassGenerator(Descriptor const *descriptor, NameResolver * name
|
|||||||
int nested_types_count = descriptor->nested_type_count();
|
int nested_types_count = descriptor->nested_type_count();
|
||||||
for (int i = 0; i < nested_types_count; ++i) {
|
for (int i = 0; i < nested_types_count; ++i) {
|
||||||
Descriptor const * nestedClassDescriptor = descriptor->nested_type(i);
|
Descriptor const * nestedClassDescriptor = descriptor->nested_type(i);
|
||||||
nameResolver->addClass(nestedClassDescriptor->name(), nameResolver->getClassName(simpleName));
|
nameResolver->addClass(nestedClassDescriptor->name(), getFullType());
|
||||||
classesDeclarations.push_back(new ClassGenerator(nestedClassDescriptor, nameResolver));
|
classesDeclarations.push_back(new ClassGenerator(nestedClassDescriptor, nameResolver));
|
||||||
}
|
}
|
||||||
|
|
||||||
int enums_declarations_count = descriptor->enum_type_count();
|
int enums_declarations_count = descriptor->enum_type_count();
|
||||||
for (int i = 0; i < enums_declarations_count; ++i) {
|
for (int i = 0; i < enums_declarations_count; ++i) {
|
||||||
EnumDescriptor const * nestedEnumDescriptor = descriptor->enum_type(i);
|
EnumDescriptor const * nestedEnumDescriptor = descriptor->enum_type(i);
|
||||||
nameResolver->addClass(nestedEnumDescriptor->name(), nameResolver->getClassName(simpleName));
|
nameResolver->addClass(nestedEnumDescriptor->name(), getFullType());
|
||||||
enumsDeclaraions.push_back(new EnumGenerator(nestedEnumDescriptor));
|
enumsDeclaraions.push_back(new EnumGenerator(nestedEnumDescriptor));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -109,7 +107,7 @@ ClassGenerator::ClassGenerator(Descriptor const *descriptor, NameResolver * name
|
|||||||
*/
|
*/
|
||||||
std::sort(properties.begin(), properties.end(),
|
std::sort(properties.begin(), properties.end(),
|
||||||
[](FieldGenerator const * first, FieldGenerator const * second) {
|
[](FieldGenerator const * first, FieldGenerator const * second) {
|
||||||
return first->fieldNumber < second->fieldNumber;
|
return first->getFieldNumber() < second->getFieldNumber();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -137,7 +135,7 @@ void ClassGenerator::generateMergeMethods(io::Printer *printer) const {
|
|||||||
|
|
||||||
// mergeWith(other: Message)
|
// mergeWith(other: Message)
|
||||||
printer->Print("\n");
|
printer->Print("\n");
|
||||||
vars["className"] = simpleName;
|
vars["className"] = getFullType();
|
||||||
printer->Print(vars, "fun mergeWith (other: $className$) {\n");
|
printer->Print(vars, "fun mergeWith (other: $className$) {\n");
|
||||||
printer->Indent();
|
printer->Indent();
|
||||||
|
|
||||||
@@ -145,12 +143,12 @@ void ClassGenerator::generateMergeMethods(io::Printer *printer) const {
|
|||||||
vars["fieldName"] = properties[i]->simpleName;
|
vars["fieldName"] = properties[i]->simpleName;
|
||||||
|
|
||||||
// concatenate repeated fields
|
// concatenate repeated fields
|
||||||
if (properties[i]->modifier == FieldDescriptor::LABEL_REPEATED) {
|
if (properties[i]->getProtoLabel() == FieldDescriptor::LABEL_REPEATED) {
|
||||||
printer->Print(vars, "$fieldName$.addAll(other.$fieldName$)\n");
|
printer->Print(vars, "$fieldName$.addAll(other.$fieldName$)\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bytes type is handled separately
|
// Bytes type is handled separately
|
||||||
else if (properties[i]->protoType == FieldDescriptor::TYPE_BYTES) {
|
else if (properties[i]->getProtoType() == FieldDescriptor::TYPE_BYTES) {
|
||||||
vars["initValue"] = properties[i]->getInitValue();
|
vars["initValue"] = properties[i]->getInitValue();
|
||||||
printer->Print(vars, "$fieldName$.plus(other.$fieldName$)\n");
|
printer->Print(vars, "$fieldName$.plus(other.$fieldName$)\n");
|
||||||
}
|
}
|
||||||
@@ -170,7 +168,7 @@ void ClassGenerator::generateMergeMethods(io::Printer *printer) const {
|
|||||||
printer->Print(vars, "fun mergeFrom (input: CodedInputStream) {\n");
|
printer->Print(vars, "fun mergeFrom (input: CodedInputStream) {\n");
|
||||||
printer->Indent();
|
printer->Indent();
|
||||||
|
|
||||||
vars["builderName"] = nameResolver->getBuilderName(simpleName);
|
vars["builderName"] = getBuilderFullType();
|
||||||
printer->Print(vars, "val builder = $builderName$()\n");
|
printer->Print(vars, "val builder = $builderName$()\n");
|
||||||
printer->Print("mergeWith(builder.parseFrom(input).build())");
|
printer->Print("mergeWith(builder.parseFrom(input).build())");
|
||||||
|
|
||||||
@@ -184,7 +182,7 @@ void ClassGenerator::generateSerializers(io::Printer *printer, bool isRead) cons
|
|||||||
vars["funName"]= isRead ? "readFrom" : "writeTo";
|
vars["funName"]= isRead ? "readFrom" : "writeTo";
|
||||||
vars["stream"] = isRead ? "CodedInputStream" : "CodedOutputStream";
|
vars["stream"] = isRead ? "CodedInputStream" : "CodedOutputStream";
|
||||||
vars["arg"] = isRead ? "input" : "output";
|
vars["arg"] = isRead ? "input" : "output";
|
||||||
vars["returnType"] = isRead ? nameResolver->getBuilderName(simpleName) : "Unit";
|
vars["returnType"] = isRead ? getBuilderFullType() : "Unit";
|
||||||
vars["maybeReturn"] = isRead ? "return this\n" : "";
|
vars["maybeReturn"] = isRead ? "return this\n" : "";
|
||||||
|
|
||||||
// generate function header
|
// generate function header
|
||||||
@@ -209,14 +207,14 @@ void ClassGenerator::generateHeader(io::Printer * printer, bool isBuilder) const
|
|||||||
// build list of arguments like 'field1: Type1, field2: Type2, ... '
|
// build list of arguments like 'field1: Type1, field2: Type2, ... '
|
||||||
string argumentList = "";
|
string argumentList = "";
|
||||||
for (int i = 0; i < properties.size(); ++i) {
|
for (int i = 0; i < properties.size(); ++i) {
|
||||||
argumentList += properties[i]->simpleName + ": " + properties[i]->fullType + " = " + properties[i]->getInitValue();
|
argumentList += properties[i]->simpleName + ": " + properties[i]->getFullType() + " = " + properties[i]->getInitValue();
|
||||||
if (i + 1 != properties.size()) {
|
if (i + 1 != properties.size()) {
|
||||||
argumentList += ", ";
|
argumentList += ", ";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
map<string, string> vars;
|
map<string, string> vars;
|
||||||
vars["name"] = isBuilder? "Builder" + simpleName : simpleName;
|
vars["name"] = isBuilder? getBuidlerSimpleType() : getSimpleType();
|
||||||
vars["argumentList"] = argumentList;
|
vars["argumentList"] = argumentList;
|
||||||
vars["maybePrivate"] = isBuilder? "" : " private";
|
vars["maybePrivate"] = isBuilder? "" : " private";
|
||||||
printer->Print(vars,
|
printer->Print(vars,
|
||||||
@@ -227,7 +225,7 @@ void ClassGenerator::generateHeader(io::Printer * printer, bool isBuilder) const
|
|||||||
|
|
||||||
void ClassGenerator::generateBuildMethod(io::Printer * printer) const {
|
void ClassGenerator::generateBuildMethod(io::Printer * printer) const {
|
||||||
map <string, string> vars;
|
map <string, string> vars;
|
||||||
vars["returnType"] = simpleName;
|
vars["returnType"] = getFullType();
|
||||||
printer->Print(vars,
|
printer->Print(vars,
|
||||||
"fun build(): $returnType$ {\n");
|
"fun build(): $returnType$ {\n");
|
||||||
printer->Indent();
|
printer->Indent();
|
||||||
@@ -266,7 +264,7 @@ void ClassGenerator::generateInitSection(io::Printer * printer) const {
|
|||||||
void ClassGenerator::generateParseMethods(io::Printer *printer) const {
|
void ClassGenerator::generateParseMethods(io::Printer *printer) const {
|
||||||
// parseFieldFrom(input: CodedInputStream): Boolean
|
// parseFieldFrom(input: CodedInputStream): Boolean
|
||||||
map <string, string> vars;
|
map <string, string> vars;
|
||||||
vars["builderName"] = nameResolver->getBuilderName(simpleName);
|
vars["builderName"] = getBuilderFullType();
|
||||||
|
|
||||||
printer->Print("fun parseFieldFrom(input: CodedInputStream): Boolean {\n");
|
printer->Print("fun parseFieldFrom(input: CodedInputStream): Boolean {\n");
|
||||||
printer->Indent();
|
printer->Indent();
|
||||||
@@ -287,21 +285,21 @@ void ClassGenerator::generateParseMethods(io::Printer *printer) const {
|
|||||||
printer->Indent();
|
printer->Indent();
|
||||||
|
|
||||||
for (int i = 0; i < properties.size(); ++i) {
|
for (int i = 0; i < properties.size(); ++i) {
|
||||||
vars["fieldNumber"] = std::to_string(properties[i]->fieldNumber);
|
vars["fieldNumber"] = std::to_string(properties[i]->getFieldNumber());
|
||||||
vars["kotlinFunSuffix"] = properties[i]->getKotlinFunctionSuffix();
|
vars["kotlinFunSuffix"] = properties[i]->getKotlinFunctionSuffix();
|
||||||
printer->Print(vars, "$fieldNumber$ -> ");
|
printer->Print(vars, "$fieldNumber$ -> ");
|
||||||
|
|
||||||
// code for serialization arrays and messages consists of more than one line and needs enclosing brackets
|
// code for serialization arrays and messages consists of more than one line and needs enclosing brackets
|
||||||
if (properties[i]->modifier == FieldDescriptor::LABEL_REPEATED
|
if (properties[i]->getProtoLabel() == FieldDescriptor::LABEL_REPEATED
|
||||||
|| properties[i]->protoType == FieldDescriptor::TYPE_MESSAGE) {
|
|| properties[i]->getProtoType() == FieldDescriptor::TYPE_MESSAGE) {
|
||||||
printer->Print("{\n");
|
printer->Print("{\n");
|
||||||
printer->Indent();
|
printer->Indent();
|
||||||
}
|
}
|
||||||
|
|
||||||
properties[i]->generateSerializationCode(printer, /* isRead = */ true, /* noTag = */ true);
|
properties[i]->generateSerializationCode(printer, /* isRead = */ true, /* noTag = */ true);
|
||||||
|
|
||||||
if (properties[i]->modifier == FieldDescriptor::LABEL_REPEATED
|
if (properties[i]->getProtoLabel() == FieldDescriptor::LABEL_REPEATED
|
||||||
|| properties[i]->protoType == FieldDescriptor::TYPE_MESSAGE) {
|
|| properties[i]->getProtoType() == FieldDescriptor::TYPE_MESSAGE) {
|
||||||
printer->Outdent();
|
printer->Outdent();
|
||||||
printer->Print("}\n");
|
printer->Print("}\n");
|
||||||
}
|
}
|
||||||
@@ -339,36 +337,20 @@ void ClassGenerator::generateGetSizeMethod(io::Printer *printer) const {
|
|||||||
printer->Print("}\n");
|
printer->Print("}\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
string ClassGenerator::getSimpleType() const {
|
||||||
|
return descriptor->name();
|
||||||
//int ClassGenerator::getSizeWithoutHeader() {
|
|
||||||
// int size = 0;
|
|
||||||
// for (int i = 0; i < properties.size(); ++i) {
|
|
||||||
// size += properties[i].getSizeWithHeader();
|
|
||||||
// }
|
|
||||||
// return 0;
|
|
||||||
//}
|
|
||||||
|
|
||||||
|
|
||||||
const string ClassModifier::getName() const {
|
|
||||||
string result = "";
|
|
||||||
switch (type) {
|
|
||||||
case CLASS:
|
|
||||||
result = "class";
|
|
||||||
break;
|
|
||||||
case INTERFACE:
|
|
||||||
result = "interface";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ClassModifier::ClassModifier(ClassModifier::Type type)
|
string ClassGenerator::getFullType() const {
|
||||||
: type(type)
|
return nameResolver->getClassName(getSimpleType());
|
||||||
{ }
|
}
|
||||||
|
|
||||||
ClassModifier::ClassModifier() {
|
string ClassGenerator::getBuilderFullType() const {
|
||||||
type = CLASS;
|
return nameResolver->getBuilderName(getSimpleType());
|
||||||
|
}
|
||||||
|
|
||||||
|
string ClassGenerator::getBuidlerSimpleType() const {
|
||||||
|
return "Builder" + getSimpleType();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+5
-16
@@ -20,24 +20,13 @@ namespace kotlin {
|
|||||||
class FieldGenerator; // declared in "kotlin_file_generator.h"
|
class FieldGenerator; // declared in "kotlin_file_generator.h"
|
||||||
class NameResolver; // declared in "kotlin_name_resolver.h"
|
class NameResolver; // declared in "kotlin_name_resolver.h"
|
||||||
|
|
||||||
// wrapper for enum CLASS/INTERFACE with convenience method of getting name
|
|
||||||
class ClassModifier {
|
|
||||||
public:
|
|
||||||
enum Type {
|
|
||||||
CLASS,
|
|
||||||
INTERFACE
|
|
||||||
};
|
|
||||||
ClassModifier();
|
|
||||||
ClassModifier(Type type);
|
|
||||||
Type type;
|
|
||||||
|
|
||||||
string const getName() const;
|
|
||||||
};
|
|
||||||
|
|
||||||
class ClassGenerator {
|
class ClassGenerator {
|
||||||
public:
|
public:
|
||||||
string simpleName;
|
string getSimpleType() const;
|
||||||
string fullName;
|
string getFullType() const;
|
||||||
|
string getBuidlerSimpleType() const;
|
||||||
|
string getBuilderFullType() const;
|
||||||
|
|
||||||
vector <FieldGenerator *> properties;
|
vector <FieldGenerator *> properties;
|
||||||
vector <ClassGenerator *> classesDeclarations;
|
vector <ClassGenerator *> classesDeclarations;
|
||||||
vector <EnumGenerator *> enumsDeclaraions;
|
vector <EnumGenerator *> enumsDeclaraions;
|
||||||
|
|||||||
+105
-42
@@ -7,6 +7,7 @@
|
|||||||
#include <google/protobuf/io/printer.h>
|
#include <google/protobuf/io/printer.h>
|
||||||
#include <google/protobuf/descriptor.h>
|
#include <google/protobuf/descriptor.h>
|
||||||
#include "kotlin_name_resolver.h"
|
#include "kotlin_name_resolver.h"
|
||||||
|
#include "UnreachableStateException.h"
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
namespace google {
|
namespace google {
|
||||||
@@ -15,13 +16,22 @@ namespace compiler {
|
|||||||
namespace kotlin {
|
namespace kotlin {
|
||||||
|
|
||||||
string FieldGenerator::getInitValue() const {
|
string FieldGenerator::getInitValue() const {
|
||||||
return name_resolving::protobufTypeToInitValue(this);
|
if (getProtoLabel() == FieldDescriptor::LABEL_REPEATED) {
|
||||||
|
return "mutableListOf()";
|
||||||
|
}
|
||||||
|
if (getProtoType() == FieldDescriptor::TYPE_MESSAGE) {
|
||||||
|
return getBuilderFullType() + "().build()";
|
||||||
|
}
|
||||||
|
if (getProtoType() == FieldDescriptor::TYPE_ENUM) {
|
||||||
|
return getEnumFromIntConverter() + "(0)";
|
||||||
|
}
|
||||||
|
return name_resolving::protobufTypeToInitValue(getProtoType());
|
||||||
}
|
}
|
||||||
|
|
||||||
void FieldGenerator::generateCode(io::Printer *printer, bool isBuilder) const {
|
void FieldGenerator::generateCode(io::Printer *printer, bool isBuilder) const {
|
||||||
map<string, string> vars;
|
map<string, string> vars;
|
||||||
vars["name"] = simpleName;
|
vars["name"] = simpleName;
|
||||||
vars["field"] = name_resolving::protobufToKotlinField(descriptor);
|
vars["field"] = getFullType();
|
||||||
printer->Print(vars, "var $name$ : $field$\n");
|
printer->Print(vars, "var $name$ : $field$\n");
|
||||||
|
|
||||||
// make setter private
|
// make setter private
|
||||||
@@ -35,29 +45,25 @@ void FieldGenerator::generateCode(io::Printer *printer, bool isBuilder) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// generate additional methods for repeated fields
|
// generate additional methods for repeated fields
|
||||||
if (modifier == FieldDescriptor::LABEL_REPEATED) {
|
if (getProtoLabel() == FieldDescriptor::LABEL_REPEATED) {
|
||||||
generateRepeatedMethods(printer, isBuilder);
|
generateRepeatedMethods(printer, isBuilder);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FieldGenerator::FieldGenerator(FieldDescriptor const * descriptor, ClassGenerator const * enclosingClass, NameResolver * nameResolver)
|
FieldGenerator::FieldGenerator(FieldDescriptor const * descriptor, ClassGenerator const * enclosingClass, NameResolver * nameResolver)
|
||||||
: descriptor(descriptor)
|
: descriptor(descriptor)
|
||||||
, modifier(descriptor->label())
|
|
||||||
, enclosingClass(enclosingClass)
|
, enclosingClass(enclosingClass)
|
||||||
, simpleName(descriptor->name())
|
|
||||||
, underlyingType(name_resolving::protobufToKotlinType(descriptor))
|
|
||||||
, fullType(name_resolving::protobufToKotlinField(descriptor))
|
|
||||||
, protoType(descriptor->type())
|
|
||||||
, fieldNumber(descriptor->number())
|
|
||||||
, nameResolver(nameResolver)
|
, nameResolver(nameResolver)
|
||||||
|
, simpleName(descriptor->name())
|
||||||
|
, protoLabel(descriptor->label())
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
// TODO: long, complicated and messy method. Refactor it ASAP
|
// TODO: long, complicated and messy method. Refactor it ASAP
|
||||||
void FieldGenerator::generateSerializationCode(io::Printer *printer, bool isRead, bool noTag) const {
|
void FieldGenerator::generateSerializationCode(io::Printer *printer, bool isRead, bool noTag) const {
|
||||||
map <string, string> vars;
|
map <string, string> vars;
|
||||||
vars["type"] = name_resolving::protobufTypeToKotlinFunctionSuffix(descriptor->type()) + (noTag ? "NoTag" : "");
|
vars["type"] = getKotlinFunctionSuffix() + (noTag ? "NoTag" : "");
|
||||||
vars["fieldNumber"] = std::to_string(fieldNumber);
|
vars["fieldNumber"] = std::to_string(getFieldNumber());
|
||||||
vars["maybeFieldNumber"] = noTag ? "" : std::to_string(fieldNumber);
|
vars["maybeFieldNumber"] = noTag ? "" : std::to_string(getFieldNumber());
|
||||||
vars["fieldName"] = simpleName;
|
vars["fieldName"] = simpleName;
|
||||||
vars["arg"] = isRead ? "input" : "output";
|
vars["arg"] = isRead ? "input" : "output";
|
||||||
vars["maybeComma"] = ", ";
|
vars["maybeComma"] = ", ";
|
||||||
@@ -70,7 +76,7 @@ void FieldGenerator::generateSerializationCode(io::Printer *printer, bool isRead
|
|||||||
* - Write length as int32 (note that tag shouldn't be added)
|
* - Write length as int32 (note that tag shouldn't be added)
|
||||||
* - Write all repeated elements via recursive call (again, without tags)
|
* - Write all repeated elements via recursive call (again, without tags)
|
||||||
*/
|
*/
|
||||||
if (modifier == FieldDescriptor::LABEL_REPEATED) {
|
if (getProtoLabel() == FieldDescriptor::LABEL_REPEATED) {
|
||||||
// tag
|
// tag
|
||||||
if (isRead) {
|
if (isRead) {
|
||||||
if (!noTag) {
|
if (!noTag) {
|
||||||
@@ -90,7 +96,7 @@ void FieldGenerator::generateSerializationCode(io::Printer *printer, bool isRead
|
|||||||
removed as soon as target code will support inheritance and interfaces.
|
removed as soon as target code will support inheritance and interfaces.
|
||||||
(then writing CodedOutputStream.writeMessage will be possible).
|
(then writing CodedOutputStream.writeMessage will be possible).
|
||||||
*/
|
*/
|
||||||
FieldGenerator singleFieldGen = FieldGenerator(descriptor, enclosingClass, nameResolver);
|
FieldGenerator singleFieldGen = getUnderlyingTypeGenerator();
|
||||||
|
|
||||||
/* Another dirty hack here: create tmp variable of a given type and read it from input stream
|
/* Another dirty hack here: create tmp variable of a given type and read it from input stream
|
||||||
then add that tmp var into list.
|
then add that tmp var into list.
|
||||||
@@ -99,11 +105,11 @@ void FieldGenerator::generateSerializationCode(io::Printer *printer, bool isRead
|
|||||||
to ArrayOutOfIndex errors.
|
to ArrayOutOfIndex errors.
|
||||||
*/
|
*/
|
||||||
// TODO: stub here, resolve name properly!
|
// TODO: stub here, resolve name properly!
|
||||||
vars["fieldType"] = underlyingType + ".Builder" + underlyingType;
|
vars["builderType"] = getUnderlyingTypeGenerator().getFullType();
|
||||||
vars["initValue"] = underlyingType + ".Builder" + underlyingType + "()";
|
vars["initValue"] = getUnderlyingTypeGenerator().getInitValue();
|
||||||
printer->Print(vars, "val tmp: $fieldType$ = $initValue$\n");
|
printer->Print(vars, "val tmp: $builderType$ = $initValue$\n");
|
||||||
singleFieldGen.simpleName = "tmp";
|
singleFieldGen.simpleName = "tmp";
|
||||||
singleFieldGen.modifier = FieldDescriptor::LABEL_OPTIONAL;
|
singleFieldGen.protoLabel = FieldDescriptor::LABEL_OPTIONAL;
|
||||||
|
|
||||||
// Note that primitive types are packed by default in proto3, i.e. they are should be written without tag
|
// 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 &&
|
bool isPrimitive = descriptor->type() != FieldDescriptor::TYPE_BYTES &&
|
||||||
@@ -112,9 +118,9 @@ void FieldGenerator::generateSerializationCode(io::Printer *printer, bool isRead
|
|||||||
descriptor->type() != FieldDescriptor::TYPE_ENUM;
|
descriptor->type() != FieldDescriptor::TYPE_ENUM;
|
||||||
|
|
||||||
singleFieldGen.generateSerializationCode(printer, isRead, /* noTag = */ isPrimitive);
|
singleFieldGen.generateSerializationCode(printer, isRead, /* noTag = */ isPrimitive);
|
||||||
singleFieldGen.generateSizeEstimationCode(printer, "readSize"); // add size of current element to total size
|
singleFieldGen.generateSizeEstimationCode(printer, /* varName = */ "readSize"); // add size of current element to total size
|
||||||
|
|
||||||
printer->Print(vars, "$fieldName$.add(tmp.build())\n");
|
printer->Print(vars, "$fieldName$.add(tmp)\n");
|
||||||
|
|
||||||
printer->Outdent();
|
printer->Outdent();
|
||||||
printer->Print("}\n");
|
printer->Print("}\n");
|
||||||
@@ -138,7 +144,7 @@ void FieldGenerator::generateSerializationCode(io::Printer *printer, bool isRead
|
|||||||
// hack: see above
|
// hack: see above
|
||||||
FieldGenerator singleFieldGen = FieldGenerator(descriptor, enclosingClass, nameResolver);
|
FieldGenerator singleFieldGen = FieldGenerator(descriptor, enclosingClass, nameResolver);
|
||||||
singleFieldGen.simpleName = "item";
|
singleFieldGen.simpleName = "item";
|
||||||
singleFieldGen.modifier = FieldDescriptor::LABEL_OPTIONAL;
|
singleFieldGen.protoLabel = FieldDescriptor::LABEL_OPTIONAL;
|
||||||
|
|
||||||
// TODO: maybe refactor this in name_resolving or separate method at least
|
// 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
|
// Note that primitive types are packed by default in proto3, i.e. they are should be written without tag
|
||||||
@@ -167,7 +173,7 @@ void FieldGenerator::generateSerializationCode(io::Printer *printer, bool isRead
|
|||||||
Example: output.writeEnum(42, enumField.ord)
|
Example: output.writeEnum(42, enumField.ord)
|
||||||
*/
|
*/
|
||||||
if (descriptor->type() == FieldDescriptor::TYPE_ENUM) {
|
if (descriptor->type() == FieldDescriptor::TYPE_ENUM) {
|
||||||
vars["converter"] = underlyingType + ".fromIntTo" + underlyingType;
|
vars["converter"] = getEnumFromIntConverter();
|
||||||
if (isRead) {
|
if (isRead) {
|
||||||
printer->Print(vars, "$fieldName$ = $converter$(input.read$type$($maybeFieldNumber$))\n");
|
printer->Print(vars, "$fieldName$ = $converter$(input.read$type$($maybeFieldNumber$))\n");
|
||||||
}
|
}
|
||||||
@@ -185,7 +191,7 @@ void FieldGenerator::generateSerializationCode(io::Printer *printer, bool isRead
|
|||||||
*/
|
*/
|
||||||
if (descriptor->type() == FieldDescriptor::TYPE_MESSAGE) {
|
if (descriptor->type() == FieldDescriptor::TYPE_MESSAGE) {
|
||||||
if (isRead) {
|
if (isRead) {
|
||||||
vars["fieldNumber"] = std::to_string(fieldNumber);
|
vars["fieldNumber"] = std::to_string(getFieldNumber());
|
||||||
vars["dollar"] = "$";
|
vars["dollar"] = "$";
|
||||||
|
|
||||||
// read tag
|
// read tag
|
||||||
@@ -205,7 +211,7 @@ void FieldGenerator::generateSerializationCode(io::Printer *printer, bool isRead
|
|||||||
"\") }\n");
|
"\") }\n");
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
vars["fieldNumber"] = std::to_string(fieldNumber);
|
vars["fieldNumber"] = std::to_string(getFieldNumber());
|
||||||
// write tag
|
// write tag
|
||||||
printer->Print(vars, "output.writeTag($fieldNumber$, WireType.LENGTH_DELIMITED)\n");
|
printer->Print(vars, "output.writeTag($fieldNumber$, WireType.LENGTH_DELIMITED)\n");
|
||||||
|
|
||||||
@@ -233,8 +239,8 @@ void FieldGenerator::generateSetter(io::Printer *printer) const {
|
|||||||
map <string, string> vars;
|
map <string, string> vars;
|
||||||
vars["camelCaseName"] = name_resolving::makeFirstLetterUpper(simpleName);
|
vars["camelCaseName"] = name_resolving::makeFirstLetterUpper(simpleName);
|
||||||
vars["fieldName"] = simpleName;
|
vars["fieldName"] = simpleName;
|
||||||
vars["builderName"] = nameResolver->getBuilderName(enclosingClass->simpleName);
|
vars["builderName"] = enclosingClass->getBuilderFullType();
|
||||||
vars["type"] = fullType;
|
vars["type"] = getFullType();
|
||||||
printer->Print(vars,
|
printer->Print(vars,
|
||||||
"fun set$camelCaseName$(value: $type$): $builderName$ {\n");
|
"fun set$camelCaseName$(value: $type$): $builderName$ {\n");
|
||||||
printer->Indent();
|
printer->Indent();
|
||||||
@@ -247,10 +253,10 @@ void FieldGenerator::generateSetter(io::Printer *printer) const {
|
|||||||
|
|
||||||
void FieldGenerator::generateRepeatedMethods(io::Printer * printer, bool isBuilder) const {
|
void FieldGenerator::generateRepeatedMethods(io::Printer * printer, bool isBuilder) const {
|
||||||
map <string, string> vars;
|
map <string, string> vars;
|
||||||
vars["elementType"] = underlyingType;
|
vars["elementType"] = getUnderlyingTypeGenerator().getSimpleType();
|
||||||
vars["arg"] = "value";
|
vars["arg"] = "value";
|
||||||
vars["fieldName"] = simpleName;
|
vars["fieldName"] = simpleName;
|
||||||
vars["builderName"] = nameResolver->getBuilderName(underlyingType); // TODO: call to non-existent field in map.
|
vars["builderName"] = enclosingClass->getBuilderFullType(); // TODO: call to non-existent field in map.
|
||||||
|
|
||||||
// generate indexed setter for builders
|
// generate indexed setter for builders
|
||||||
if (isBuilder) {
|
if (isBuilder) {
|
||||||
@@ -292,21 +298,14 @@ string FieldGenerator::getKotlinFunctionSuffix() const {
|
|||||||
return name_resolving::protobufTypeToKotlinFunctionSuffix(descriptor->type());
|
return name_resolving::protobufTypeToKotlinFunctionSuffix(descriptor->type());
|
||||||
}
|
}
|
||||||
|
|
||||||
string FieldGenerator::getUnderlyingTypeInitValue() const {
|
|
||||||
if (protoType == FieldDescriptor::TYPE_MESSAGE) {
|
|
||||||
return "Builder" + underlyingType + "().build()";
|
|
||||||
}
|
|
||||||
return name_resolving::protobufTypeToInitValue(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
void FieldGenerator::generateSizeEstimationCode(io::Printer *printer, string varName, bool noTag) const {
|
void FieldGenerator::generateSizeEstimationCode(io::Printer *printer, string varName, bool noTag) const {
|
||||||
map<string, string> vars;
|
map<string, string> vars;
|
||||||
vars["varName"] = varName;
|
vars["varName"] = varName;
|
||||||
vars["fieldName"] = simpleName;
|
vars["fieldName"] = simpleName;
|
||||||
vars["fieldNumber"] = std::to_string(fieldNumber);
|
vars["fieldNumber"] = std::to_string(getFieldNumber());
|
||||||
|
|
||||||
// First of all, generate code for repeated fields
|
// First of all, generate code for repeated fields
|
||||||
if (modifier == FieldDescriptor::LABEL_REPEATED) {
|
if (getProtoLabel() == FieldDescriptor::LABEL_REPEATED) {
|
||||||
// We will need total byte size of array, because that size is itself a part of the message and
|
// We will need total byte size of array, because that size is itself a part of the message and
|
||||||
// adds to total message size.
|
// adds to total message size.
|
||||||
// For the sake of hygiene, temporary variables are created in anonymous scope
|
// For the sake of hygiene, temporary variables are created in anonymous scope
|
||||||
@@ -322,7 +321,7 @@ void FieldGenerator::generateSizeEstimationCode(io::Printer *printer, string var
|
|||||||
|
|
||||||
// hack: reuse generateSizeEstimationCode in the same manner as in generateSerializationCode
|
// hack: reuse generateSizeEstimationCode in the same manner as in generateSerializationCode
|
||||||
FieldGenerator singleFieldGen = FieldGenerator(descriptor, enclosingClass, nameResolver);
|
FieldGenerator singleFieldGen = FieldGenerator(descriptor, enclosingClass, nameResolver);
|
||||||
singleFieldGen.modifier = FieldDescriptor::LABEL_OPTIONAL;
|
singleFieldGen.protoLabel = FieldDescriptor::LABEL_OPTIONAL;
|
||||||
singleFieldGen.simpleName = "item";
|
singleFieldGen.simpleName = "item";
|
||||||
singleFieldGen.generateSizeEstimationCode(printer, "arraySize");
|
singleFieldGen.generateSizeEstimationCode(printer, "arraySize");
|
||||||
|
|
||||||
@@ -348,7 +347,7 @@ void FieldGenerator::generateSizeEstimationCode(io::Printer *printer, string var
|
|||||||
|
|
||||||
// Then, call getSize recursively for nested messages
|
// Then, call getSize recursively for nested messages
|
||||||
// TODO: currently suboptimal repeatative calls getSize() are being made. We can optimize it later via caching calls to getSize()
|
// TODO: currently suboptimal repeatative calls getSize() are being made. We can optimize it later via caching calls to getSize()
|
||||||
if (protoType == FieldDescriptor::TYPE_MESSAGE) {
|
if (getProtoType() == FieldDescriptor::TYPE_MESSAGE) {
|
||||||
// don't forget about tag and length annotation
|
// don't forget about tag and length annotation
|
||||||
printer->Print(vars, "$varName$ += $fieldName$.getSize()"
|
printer->Print(vars, "$varName$ += $fieldName$.getSize()"
|
||||||
" + "
|
" + "
|
||||||
@@ -360,18 +359,82 @@ void FieldGenerator::generateSizeEstimationCode(io::Printer *printer, string var
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Next, process enums as they should be casted to ints manually
|
// Next, process enums as they should be casted to ints manually
|
||||||
if (protoType == FieldDescriptor::TYPE_ENUM) {
|
if (getProtoType() == FieldDescriptor::TYPE_ENUM) {
|
||||||
vars["enumName"] = fullType;
|
|
||||||
printer->Print(vars, "$varName$ += WireFormat.getEnumSize($fieldNumber$, $fieldName$.ord)\n");
|
printer->Print(vars, "$varName$ += WireFormat.getEnumSize($fieldNumber$, $fieldName$.ord)\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Finally, get size of all primitive types trivially via call to WireFormat in runtime
|
// Finally, get size of all primitive types trivially via call to WireFormat in runtime
|
||||||
vars["kotlinSuffix"] = name_resolving::protobufTypeToKotlinFunctionSuffix(descriptor->type());
|
vars["kotlinSuffix"] = getKotlinFunctionSuffix();
|
||||||
printer->Print(vars, "$varName$ += WireFormat.get$kotlinSuffix$Size($fieldNumber$, $fieldName$)\n");
|
printer->Print(vars, "$varName$ += WireFormat.get$kotlinSuffix$Size($fieldNumber$, $fieldName$)\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FieldDescriptor::Label FieldGenerator::getProtoLabel() const {
|
||||||
|
return protoLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
FieldDescriptor::Type FieldGenerator::getProtoType() const {
|
||||||
|
return descriptor->type();
|
||||||
|
}
|
||||||
|
|
||||||
|
int FieldGenerator::getFieldNumber() const {
|
||||||
|
return descriptor->number();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
string FieldGenerator::getSimpleType() const {
|
||||||
|
if (getProtoLabel() == FieldDescriptor::LABEL_REPEATED) {
|
||||||
|
return "MutableList <" + getUnderlyingTypeGenerator().getSimpleType() + ">";
|
||||||
|
}
|
||||||
|
if (getProtoType() == FieldDescriptor::TYPE_MESSAGE) {
|
||||||
|
return descriptor->message_type()->name();
|
||||||
|
}
|
||||||
|
if (getProtoType() == FieldDescriptor::TYPE_ENUM) {
|
||||||
|
return descriptor->enum_type()->name();
|
||||||
|
}
|
||||||
|
return name_resolving::protobufToKotlinType(descriptor->type());
|
||||||
|
}
|
||||||
|
|
||||||
|
string FieldGenerator::getFullType() const {
|
||||||
|
if (getProtoLabel() == FieldDescriptor::LABEL_REPEATED) {
|
||||||
|
return "MutableList <" + getUnderlyingTypeGenerator().getFullType() + ">";
|
||||||
|
}
|
||||||
|
if (getProtoType() == FieldDescriptor::TYPE_MESSAGE ||
|
||||||
|
getProtoType() == FieldDescriptor::TYPE_ENUM) {
|
||||||
|
return nameResolver->getClassName(getSimpleType());
|
||||||
|
}
|
||||||
|
return name_resolving::protobufToKotlinType(getProtoType());
|
||||||
|
}
|
||||||
|
|
||||||
|
string FieldGenerator::getBuilderFullType() const {
|
||||||
|
if (getProtoType() != FieldDescriptor::TYPE_MESSAGE) {
|
||||||
|
throw UnreachableStateException("Error: trying to get builder name for non-message field " + simpleName);
|
||||||
|
}
|
||||||
|
return nameResolver->getBuilderName(getSimpleType());
|
||||||
|
}
|
||||||
|
|
||||||
|
string FieldGenerator::getBuilderSimpleType() const {
|
||||||
|
if (getProtoType() != FieldDescriptor::TYPE_MESSAGE) {
|
||||||
|
throw UnreachableStateException("Error: trying to get builder name for non-message field " + simpleName);
|
||||||
|
}
|
||||||
|
return "Builder" + getSimpleType();
|
||||||
|
}
|
||||||
|
|
||||||
|
string FieldGenerator::getEnumFromIntConverter() const {
|
||||||
|
return getFullType() + ".fromIntTo" + getSimpleType();
|
||||||
|
}
|
||||||
|
|
||||||
|
FieldGenerator FieldGenerator::getUnderlyingTypeGenerator() const {
|
||||||
|
if (getProtoLabel() == FieldDescriptor::LABEL_REPEATED) {
|
||||||
|
FieldGenerator singleFieldGen = FieldGenerator(descriptor, enclosingClass, nameResolver);
|
||||||
|
singleFieldGen.protoLabel = FieldDescriptor::LABEL_OPTIONAL;
|
||||||
|
return singleFieldGen;
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
} // namespace kotlin
|
} // namespace kotlin
|
||||||
} // namespace compiler
|
} // namespace compiler
|
||||||
} // namespace protobuf
|
} // namespace protobuf
|
||||||
|
|||||||
+45
-19
@@ -27,32 +27,58 @@ private:
|
|||||||
void generateSetter(io::Printer * printer) const;
|
void generateSetter(io::Printer * printer) const;
|
||||||
void generateRepeatedMethods(io::Printer * printer, bool isBuilder) const;
|
void generateRepeatedMethods(io::Printer * printer, bool isBuilder) const;
|
||||||
public:
|
public:
|
||||||
FieldDescriptor::Label modifier;
|
|
||||||
ClassGenerator const * enclosingClass; // class, in which that field is defined
|
ClassGenerator const * enclosingClass; // class, in which that field is defined
|
||||||
string simpleName;
|
|
||||||
string underlyingType; // unwrapped type.
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Full type of field.
|
|
||||||
* fullType = Array<underlyingType> for REPEATED fields
|
|
||||||
* fullType = underlyingType? for OPTIONAL fields
|
|
||||||
* fullType = underlyingType for all other cases
|
|
||||||
*/
|
|
||||||
string fullType;
|
|
||||||
string builderName;
|
|
||||||
string fullName;
|
|
||||||
string getInitValue() const;
|
|
||||||
string getUnderlyingTypeInitValue() const;
|
|
||||||
FieldDescriptor::Type protoType;
|
|
||||||
int fieldNumber;
|
|
||||||
NameResolver * nameResolver;
|
NameResolver * nameResolver;
|
||||||
|
string simpleName;
|
||||||
|
|
||||||
|
FieldDescriptor::Label protoLabel; // TODO: hack here - this field is used for some dark magic that allows us to drop generics from the generated code
|
||||||
|
|
||||||
|
FieldDescriptor::Label getProtoLabel() const;
|
||||||
|
FieldDescriptor::Type getProtoType() const;
|
||||||
|
|
||||||
|
/* Return declared tag number */
|
||||||
|
int getFieldNumber() const;
|
||||||
|
|
||||||
|
/* Returns instance of FieldGenerator, that generated underlying type for repeated fields.
|
||||||
|
* For non-repeated fields, returns `this` */
|
||||||
|
FieldGenerator getUnderlyingTypeGenerator() const;
|
||||||
|
|
||||||
|
/* For repeated fields, returns simple name of single element.
|
||||||
|
* For all other cases, returns simple name of field, which is the same as getType()
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* For repeated fields, return simple name of single element, wrapped into corresponding Kotlin array type
|
||||||
|
* Example: Array<NestedMessage>
|
||||||
|
* For other types, return simple name (without full-qualification for non-primitive types) of field's type
|
||||||
|
*/
|
||||||
|
string getSimpleType() const;
|
||||||
|
|
||||||
|
string getBuilderSimpleType() const;
|
||||||
|
|
||||||
|
/* Returns full=qualified name of builder if field type is user-defined message */
|
||||||
|
string getBuilderFullType() const;
|
||||||
|
|
||||||
|
/* Returns the same as getType(), but with full-qualification for non-primitive types if necessary.
|
||||||
|
* Example: Array<EnclosingMessage.NestedMessage>
|
||||||
|
*/
|
||||||
|
string getFullType() const;
|
||||||
|
|
||||||
|
/* Returns initial value of this field's type.
|
||||||
|
* Note that full qualification for non-primitive types will always used here.
|
||||||
|
*/
|
||||||
|
string getInitValue() const;
|
||||||
|
|
||||||
|
/* Return string, that is suitable as suffix for corresponding IO methods in ProtoKot runtime.
|
||||||
|
* Example: int64-field -> Int64 (readInt64() and writeInt64() methods exist in ProtoKot runtime)
|
||||||
|
*/
|
||||||
|
string getKotlinFunctionSuffix() const;
|
||||||
|
|
||||||
|
/* Return function name in enum namespace that converts from enum to Int */
|
||||||
|
string getEnumFromIntConverter() const;
|
||||||
void generateCode(io::Printer * printer, bool isBuilder) const;
|
void generateCode(io::Printer * printer, bool isBuilder) const;
|
||||||
void generateSerializationCode(io::Printer * printer, bool isRead = false, bool noTag = false) const;
|
void generateSerializationCode(io::Printer * printer, bool isRead = false, bool noTag = false) const;
|
||||||
void generateSizeEstimationCode(io::Printer * printer, string varName, bool noTag = false) const;
|
void generateSizeEstimationCode(io::Printer * printer, string varName, bool noTag = false) const;
|
||||||
FieldGenerator(FieldDescriptor const * descriptor, ClassGenerator const * enclosingClass, NameResolver * nameResolver);
|
FieldGenerator(FieldDescriptor const * descriptor, ClassGenerator const * enclosingClass, NameResolver * nameResolver);
|
||||||
string getKotlinFunctionSuffix() const;
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace kotlin
|
} // namespace kotlin
|
||||||
|
|||||||
+11
-32
@@ -5,7 +5,7 @@
|
|||||||
#include "kotlin_name_resolver.h"
|
#include "kotlin_name_resolver.h"
|
||||||
#include "kotlin_field_generator.h"
|
#include "kotlin_field_generator.h"
|
||||||
#include <google/protobuf/descriptor.h>
|
#include <google/protobuf/descriptor.h>
|
||||||
|
#include "UnreachableStateException.h"
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
namespace google {
|
namespace google {
|
||||||
@@ -33,8 +33,7 @@ string getKotlinOutputByProtoName(string protoName) {
|
|||||||
return justName + ".kt";
|
return justName + ".kt";
|
||||||
}
|
}
|
||||||
|
|
||||||
string protobufToKotlinType(FieldDescriptor const * descriptor) {
|
string protobufToKotlinType(FieldDescriptor::Type type) {
|
||||||
FieldDescriptor::Type type = descriptor->type();
|
|
||||||
switch(type) {
|
switch(type) {
|
||||||
case FieldDescriptor::TYPE_BOOL:
|
case FieldDescriptor::TYPE_BOOL:
|
||||||
return "Boolean";
|
return "Boolean";
|
||||||
@@ -43,7 +42,8 @@ string protobufToKotlinType(FieldDescriptor const * descriptor) {
|
|||||||
case FieldDescriptor::TYPE_DOUBLE:
|
case FieldDescriptor::TYPE_DOUBLE:
|
||||||
return "Double";
|
return "Double";
|
||||||
case FieldDescriptor::TYPE_ENUM:
|
case FieldDescriptor::TYPE_ENUM:
|
||||||
return string(descriptor->enum_type()->name());
|
throw UnreachableStateException
|
||||||
|
("Error: mapping protobuf enum types to kotlin types should be resolved by field generator, not by protobufToKotlinType function");
|
||||||
case FieldDescriptor::TYPE_FIXED32:
|
case FieldDescriptor::TYPE_FIXED32:
|
||||||
// we map uint32 into Int, storing top bit in sign bit
|
// we map uint32 into Int, storing top bit in sign bit
|
||||||
return "Int";
|
return "Int";
|
||||||
@@ -57,7 +57,8 @@ string protobufToKotlinType(FieldDescriptor const * descriptor) {
|
|||||||
case FieldDescriptor::TYPE_INT64:
|
case FieldDescriptor::TYPE_INT64:
|
||||||
return "Long";
|
return "Long";
|
||||||
case FieldDescriptor::TYPE_MESSAGE:
|
case FieldDescriptor::TYPE_MESSAGE:
|
||||||
return string(descriptor->message_type()->name());
|
throw UnreachableStateException
|
||||||
|
("Error: mapping protobuf message types to kotlin types should be resolved by field generator, not by protobufToKotlinType function");
|
||||||
case FieldDescriptor::TYPE_SFIXED32:
|
case FieldDescriptor::TYPE_SFIXED32:
|
||||||
return "Int";
|
return "Int";
|
||||||
case FieldDescriptor::TYPE_SFIXED64:
|
case FieldDescriptor::TYPE_SFIXED64:
|
||||||
@@ -67,7 +68,7 @@ string protobufToKotlinType(FieldDescriptor const * descriptor) {
|
|||||||
case FieldDescriptor::TYPE_SINT64:
|
case FieldDescriptor::TYPE_SINT64:
|
||||||
return "Long";
|
return "Long";
|
||||||
case FieldDescriptor::TYPE_STRING:
|
case FieldDescriptor::TYPE_STRING:
|
||||||
return "kotlin.String";
|
return "String";
|
||||||
case FieldDescriptor::TYPE_UINT32:
|
case FieldDescriptor::TYPE_UINT32:
|
||||||
return "Int"; // see notes for TYPE_FIXED32
|
return "Int"; // see notes for TYPE_FIXED32
|
||||||
case FieldDescriptor::TYPE_UINT64:
|
case FieldDescriptor::TYPE_UINT64:
|
||||||
@@ -75,30 +76,9 @@ string protobufToKotlinType(FieldDescriptor const * descriptor) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
string protobufToKotlinField(FieldDescriptor const * descriptor) {
|
|
||||||
FieldDescriptor::Label modifier = descriptor->label();
|
|
||||||
string preamble = "",
|
|
||||||
postamble = "";
|
|
||||||
switch (modifier) {
|
|
||||||
case FieldDescriptor::LABEL_REQUIRED:
|
|
||||||
break;
|
|
||||||
case FieldDescriptor::LABEL_OPTIONAL:
|
|
||||||
break;
|
|
||||||
case FieldDescriptor::LABEL_REPEATED:
|
|
||||||
preamble = "MutableList <";
|
|
||||||
postamble = "> ";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return preamble + protobufToKotlinType(descriptor) + postamble;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: think about nested arrays
|
// TODO: think about nested arrays
|
||||||
string protobufTypeToInitValue(FieldGenerator const * fieldGen) {
|
string protobufTypeToInitValue(FieldDescriptor::Type type) {
|
||||||
if (fieldGen->modifier == FieldDescriptor::LABEL_REPEATED) {
|
|
||||||
return "mutableListOf()";
|
|
||||||
}
|
|
||||||
|
|
||||||
FieldDescriptor::Type type = fieldGen->protoType;
|
|
||||||
switch(type) {
|
switch(type) {
|
||||||
case FieldDescriptor::TYPE_BOOL:
|
case FieldDescriptor::TYPE_BOOL:
|
||||||
return "false";
|
return "false";
|
||||||
@@ -106,9 +86,8 @@ string protobufTypeToInitValue(FieldGenerator const * fieldGen) {
|
|||||||
return "ByteArray(0)";
|
return "ByteArray(0)";
|
||||||
case FieldDescriptor::TYPE_DOUBLE:
|
case FieldDescriptor::TYPE_DOUBLE:
|
||||||
return "0.0";
|
return "0.0";
|
||||||
case FieldDescriptor::TYPE_ENUM: {
|
case FieldDescriptor::TYPE_ENUM:
|
||||||
return fieldGen->nameResolver->getClassName(fieldGen->fullType) + ".fromIntTo" + fieldGen->fullType + "(0)"; // produce enum from 0, as demanded by Google
|
throw UnreachableStateException("Error: getting init values of enums should be handled by FieldGenerator, not by protobufToInitValue");
|
||||||
}
|
|
||||||
case FieldDescriptor::TYPE_FIXED32:
|
case FieldDescriptor::TYPE_FIXED32:
|
||||||
return "0";
|
return "0";
|
||||||
case FieldDescriptor::TYPE_FIXED64:
|
case FieldDescriptor::TYPE_FIXED64:
|
||||||
@@ -120,7 +99,7 @@ string protobufTypeToInitValue(FieldGenerator const * fieldGen) {
|
|||||||
case FieldDescriptor::TYPE_INT64:
|
case FieldDescriptor::TYPE_INT64:
|
||||||
return "0L";
|
return "0L";
|
||||||
case FieldDescriptor::TYPE_MESSAGE:
|
case FieldDescriptor::TYPE_MESSAGE:
|
||||||
return fieldGen->nameResolver->getBuilderName(fieldGen->fullType) + "().build()";
|
throw UnreachableStateException("Error: getting init values of enums should be handled by FieldGenerator, not by protobufToInitValue");
|
||||||
case FieldDescriptor::TYPE_SFIXED32:
|
case FieldDescriptor::TYPE_SFIXED32:
|
||||||
return "0";
|
return "0";
|
||||||
case FieldDescriptor::TYPE_SFIXED64:
|
case FieldDescriptor::TYPE_SFIXED64:
|
||||||
|
|||||||
+2
-4
@@ -37,11 +37,9 @@ std::string getFileNameWithoutExtension(std::string fullName);
|
|||||||
|
|
||||||
std::string getKotlinOutputByProtoName(std::string protoName);
|
std::string getKotlinOutputByProtoName(std::string protoName);
|
||||||
|
|
||||||
std::string protobufTypeToInitValue(FieldGenerator const * fieldGenerator);
|
std::string protobufTypeToInitValue(FieldDescriptor::Type type);
|
||||||
|
|
||||||
std::string protobufToKotlinField(FieldDescriptor const * descriptor);
|
std::string protobufToKotlinType(FieldDescriptor::Type type);
|
||||||
|
|
||||||
std::string protobufToKotlinType(FieldDescriptor const * descriptor);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts one of protobuf wire types to corresponding Kotlin type with proper
|
* Converts one of protobuf wire types to corresponding Kotlin type with proper
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
class Person private constructor (name: kotlin.String = "", id: Int = 0, email: kotlin.String = "", phones: MutableList <PhoneNumber> = mutableListOf(), someBytes: ByteArray = ByteArray(0)) {
|
class Person private constructor (name: String = "", id: Int = 0, email: String = "", phones: MutableList <Person.PhoneNumber> = mutableListOf(), someBytes: ByteArray = ByteArray(0)) {
|
||||||
var name : kotlin.String
|
var name : String
|
||||||
private set
|
private set
|
||||||
|
|
||||||
var id : Int
|
var id : Int
|
||||||
private set
|
private set
|
||||||
|
|
||||||
var email : kotlin.String
|
var email : String
|
||||||
private set
|
private set
|
||||||
|
|
||||||
var phones : MutableList <PhoneNumber>
|
var phones : MutableList <Person.PhoneNumber>
|
||||||
private set
|
private set
|
||||||
|
|
||||||
var someBytes : ByteArray
|
var someBytes : ByteArray
|
||||||
@@ -38,11 +38,11 @@ class Person private constructor (name: kotlin.String = "", id: Int = 0, email:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
class PhoneNumber private constructor (number: kotlin.String = "", type: PhoneType = Person.PhoneType.fromIntToPhoneType(0)) {
|
class PhoneNumber private constructor (number: String = "", type: Person.PhoneType = Person.PhoneType.fromIntToPhoneType(0)) {
|
||||||
var number : kotlin.String
|
var number : String
|
||||||
private set
|
private set
|
||||||
|
|
||||||
var type : PhoneType
|
var type : Person.PhoneType
|
||||||
private set
|
private set
|
||||||
|
|
||||||
|
|
||||||
@@ -56,17 +56,17 @@ class Person private constructor (name: kotlin.String = "", id: Int = 0, email:
|
|||||||
output.writeEnum (2, type.ord)
|
output.writeEnum (2, type.ord)
|
||||||
}
|
}
|
||||||
|
|
||||||
class BuilderPhoneNumber constructor (number: kotlin.String = "", type: PhoneType = Person.PhoneType.fromIntToPhoneType(0)) {
|
class BuilderPhoneNumber constructor (number: String = "", type: Person.PhoneType = Person.PhoneType.fromIntToPhoneType(0)) {
|
||||||
var number : kotlin.String
|
var number : String
|
||||||
private set
|
private set
|
||||||
fun setNumber(value: kotlin.String): Person.PhoneNumber.BuilderPhoneNumber {
|
fun setNumber(value: String): Person.PhoneNumber.BuilderPhoneNumber {
|
||||||
number = value
|
number = value
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
var type : PhoneType
|
var type : Person.PhoneType
|
||||||
private set
|
private set
|
||||||
fun setType(value: PhoneType): Person.PhoneNumber.BuilderPhoneNumber {
|
fun setType(value: Person.PhoneType): Person.PhoneNumber.BuilderPhoneNumber {
|
||||||
type = value
|
type = value
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
@@ -79,12 +79,12 @@ class Person private constructor (name: kotlin.String = "", id: Int = 0, email:
|
|||||||
|
|
||||||
fun readFrom (input: CodedInputStream): Person.PhoneNumber.BuilderPhoneNumber {
|
fun readFrom (input: CodedInputStream): Person.PhoneNumber.BuilderPhoneNumber {
|
||||||
number = input.readString(1)
|
number = input.readString(1)
|
||||||
type = PhoneType.fromIntToPhoneType(input.readEnum(2))
|
type = Person.PhoneType.fromIntToPhoneType(input.readEnum(2))
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
fun build(): PhoneNumber {
|
fun build(): Person.PhoneNumber {
|
||||||
return PhoneNumber(number, type)
|
return Person.PhoneNumber(number, type)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun parseFieldFrom(input: CodedInputStream): Boolean {
|
fun parseFieldFrom(input: CodedInputStream): Boolean {
|
||||||
@@ -95,7 +95,7 @@ class Person private constructor (name: kotlin.String = "", id: Int = 0, email:
|
|||||||
val wireType = WireFormat.getTagWireType(tag)
|
val wireType = WireFormat.getTagWireType(tag)
|
||||||
when(fieldNumber) {
|
when(fieldNumber) {
|
||||||
1 -> number = input.readStringNoTag()
|
1 -> number = input.readStringNoTag()
|
||||||
2 -> type = PhoneType.fromIntToPhoneType(input.readEnumNoTag())
|
2 -> type = Person.PhoneType.fromIntToPhoneType(input.readEnumNoTag())
|
||||||
}
|
}
|
||||||
return true}
|
return true}
|
||||||
fun parseFrom(input: CodedInputStream): Person.PhoneNumber.BuilderPhoneNumber {
|
fun parseFrom(input: CodedInputStream): Person.PhoneNumber.BuilderPhoneNumber {
|
||||||
@@ -111,7 +111,7 @@ class Person private constructor (name: kotlin.String = "", id: Int = 0, email:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fun mergeWith (other: PhoneNumber) {
|
fun mergeWith (other: Person.PhoneNumber) {
|
||||||
number = other.number
|
number = other.number
|
||||||
type = other.type
|
type = other.type
|
||||||
}
|
}
|
||||||
@@ -152,10 +152,10 @@ class Person private constructor (name: kotlin.String = "", id: Int = 0, email:
|
|||||||
output.writeBytes (5, someBytes)
|
output.writeBytes (5, someBytes)
|
||||||
}
|
}
|
||||||
|
|
||||||
class BuilderPerson constructor (name: kotlin.String = "", id: Int = 0, email: kotlin.String = "", phones: MutableList <PhoneNumber> = mutableListOf(), someBytes: ByteArray = ByteArray(0)) {
|
class BuilderPerson constructor (name: String = "", id: Int = 0, email: String = "", phones: MutableList <Person.PhoneNumber> = mutableListOf(), someBytes: ByteArray = ByteArray(0)) {
|
||||||
var name : kotlin.String
|
var name : String
|
||||||
private set
|
private set
|
||||||
fun setName(value: kotlin.String): Person.BuilderPerson {
|
fun setName(value: String): Person.BuilderPerson {
|
||||||
name = value
|
name = value
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
@@ -167,28 +167,28 @@ class Person private constructor (name: kotlin.String = "", id: Int = 0, email:
|
|||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
var email : kotlin.String
|
var email : String
|
||||||
private set
|
private set
|
||||||
fun setEmail(value: kotlin.String): Person.BuilderPerson {
|
fun setEmail(value: String): Person.BuilderPerson {
|
||||||
email = value
|
email = value
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
var phones : MutableList <PhoneNumber>
|
var phones : MutableList <Person.PhoneNumber>
|
||||||
private set
|
private set
|
||||||
fun setPhones(value: MutableList <PhoneNumber> ): Person.BuilderPerson {
|
fun setPhones(value: MutableList <Person.PhoneNumber>): Person.BuilderPerson {
|
||||||
phones = value
|
phones = value
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
fun setPhoneNumber(index: Int, value: PhoneNumber): Person.PhoneNumber.BuilderPhoneNumber {
|
fun setPhoneNumber(index: Int, value: PhoneNumber): Person.BuilderPerson {
|
||||||
phones[index] = value
|
phones[index] = value
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
fun addPhoneNumber(value: PhoneNumber): Person.PhoneNumber.BuilderPhoneNumber {
|
fun addPhoneNumber(value: PhoneNumber): Person.BuilderPerson {
|
||||||
phones.add(value)
|
phones.add(value)
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
fun addAllPhoneNumber(value: Iterable<PhoneNumber>): Person.PhoneNumber.BuilderPhoneNumber {
|
fun addAllPhoneNumber(value: Iterable<PhoneNumber>): Person.BuilderPerson {
|
||||||
for (item in value) {
|
for (item in value) {
|
||||||
phones.add(item)
|
phones.add(item)
|
||||||
}
|
}
|
||||||
@@ -219,13 +219,13 @@ class Person private constructor (name: kotlin.String = "", id: Int = 0, email:
|
|||||||
val expectedSize = input.readInt32NoTag()
|
val expectedSize = input.readInt32NoTag()
|
||||||
var readSize = 0
|
var readSize = 0
|
||||||
while(readSize != expectedSize) {
|
while(readSize != expectedSize) {
|
||||||
val tmp: PhoneNumber.BuilderPhoneNumber = PhoneNumber.BuilderPhoneNumber()
|
val tmp: Person.PhoneNumber = Person.PhoneNumber.BuilderPhoneNumber().build()
|
||||||
input.readTag(4, WireType.LENGTH_DELIMITED)
|
input.readTag(4, WireType.LENGTH_DELIMITED)
|
||||||
val expectedSize = input.readInt32NoTag()
|
val expectedSize = input.readInt32NoTag()
|
||||||
tmp.mergeFrom(input)
|
tmp.mergeFrom(input)
|
||||||
if (expectedSize != tmp.getSize()) { throw InvalidProtocolBufferException ("Expected size ${expectedSize} got ${tmp.getSize()}") }
|
if (expectedSize != tmp.getSize()) { throw InvalidProtocolBufferException ("Expected size ${expectedSize} got ${tmp.getSize()}") }
|
||||||
readSize += tmp.getSize() + WireFormat.getTagSize(4, WireType.LENGTH_DELIMITED) + WireFormat.getVarint32Size(tmp.getSize())
|
readSize += tmp.getSize() + WireFormat.getTagSize(4, WireType.LENGTH_DELIMITED) + WireFormat.getVarint32Size(tmp.getSize())
|
||||||
phones.add(tmp.build())
|
phones.add(tmp)
|
||||||
}
|
}
|
||||||
someBytes = input.readBytes(5)
|
someBytes = input.readBytes(5)
|
||||||
return this
|
return this
|
||||||
@@ -249,13 +249,13 @@ class Person private constructor (name: kotlin.String = "", id: Int = 0, email:
|
|||||||
val expectedSize = input.readInt32NoTag()
|
val expectedSize = input.readInt32NoTag()
|
||||||
var readSize = 0
|
var readSize = 0
|
||||||
while(readSize != expectedSize) {
|
while(readSize != expectedSize) {
|
||||||
val tmp: PhoneNumber.BuilderPhoneNumber = PhoneNumber.BuilderPhoneNumber()
|
val tmp: Person.PhoneNumber = Person.PhoneNumber.BuilderPhoneNumber().build()
|
||||||
input.readTag(4, WireType.LENGTH_DELIMITED)
|
input.readTag(4, WireType.LENGTH_DELIMITED)
|
||||||
val expectedSize = input.readInt32NoTag()
|
val expectedSize = input.readInt32NoTag()
|
||||||
tmp.mergeFrom(input)
|
tmp.mergeFrom(input)
|
||||||
if (expectedSize != tmp.getSize()) { throw InvalidProtocolBufferException ("Expected size ${expectedSize} got ${tmp.getSize()}") }
|
if (expectedSize != tmp.getSize()) { throw InvalidProtocolBufferException ("Expected size ${expectedSize} got ${tmp.getSize()}") }
|
||||||
readSize += tmp.getSize() + WireFormat.getTagSize(4, WireType.LENGTH_DELIMITED) + WireFormat.getVarint32Size(tmp.getSize())
|
readSize += tmp.getSize() + WireFormat.getTagSize(4, WireType.LENGTH_DELIMITED) + WireFormat.getVarint32Size(tmp.getSize())
|
||||||
phones.add(tmp.build())
|
phones.add(tmp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
5 -> someBytes = input.readBytesNoTag()
|
5 -> someBytes = input.readBytesNoTag()
|
||||||
@@ -312,8 +312,8 @@ class Person private constructor (name: kotlin.String = "", id: Int = 0, email:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class AddressBook private constructor (people: MutableList <Person> = mutableListOf()) {
|
class AddressBook private constructor (people: MutableList <Person> = mutableListOf()) {
|
||||||
var people : MutableList <Person>
|
var people : MutableList <Person>
|
||||||
private set
|
private set
|
||||||
|
|
||||||
|
|
||||||
@@ -341,22 +341,22 @@ class AddressBook private constructor (people: MutableList <Person> = mutableLi
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class BuilderAddressBook constructor (people: MutableList <Person> = mutableListOf()) {
|
class BuilderAddressBook constructor (people: MutableList <Person> = mutableListOf()) {
|
||||||
var people : MutableList <Person>
|
var people : MutableList <Person>
|
||||||
private set
|
private set
|
||||||
fun setPeople(value: MutableList <Person> ): AddressBook.BuilderAddressBook {
|
fun setPeople(value: MutableList <Person>): AddressBook.BuilderAddressBook {
|
||||||
people = value
|
people = value
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
fun setPerson(index: Int, value: Person): Person.BuilderPerson {
|
fun setPerson(index: Int, value: Person): AddressBook.BuilderAddressBook {
|
||||||
people[index] = value
|
people[index] = value
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
fun addPerson(value: Person): Person.BuilderPerson {
|
fun addPerson(value: Person): AddressBook.BuilderAddressBook {
|
||||||
people.add(value)
|
people.add(value)
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
fun addAllPerson(value: Iterable<Person>): Person.BuilderPerson {
|
fun addAllPerson(value: Iterable<Person>): AddressBook.BuilderAddressBook {
|
||||||
for (item in value) {
|
for (item in value) {
|
||||||
people.add(item)
|
people.add(item)
|
||||||
}
|
}
|
||||||
@@ -373,13 +373,13 @@ class AddressBook private constructor (people: MutableList <Person> = mutableLi
|
|||||||
val expectedSize = input.readInt32NoTag()
|
val expectedSize = input.readInt32NoTag()
|
||||||
var readSize = 0
|
var readSize = 0
|
||||||
while(readSize != expectedSize) {
|
while(readSize != expectedSize) {
|
||||||
val tmp: Person.BuilderPerson = Person.BuilderPerson()
|
val tmp: Person = Person.BuilderPerson().build()
|
||||||
input.readTag(1, WireType.LENGTH_DELIMITED)
|
input.readTag(1, WireType.LENGTH_DELIMITED)
|
||||||
val expectedSize = input.readInt32NoTag()
|
val expectedSize = input.readInt32NoTag()
|
||||||
tmp.mergeFrom(input)
|
tmp.mergeFrom(input)
|
||||||
if (expectedSize != tmp.getSize()) { throw InvalidProtocolBufferException ("Expected size ${expectedSize} got ${tmp.getSize()}") }
|
if (expectedSize != tmp.getSize()) { throw InvalidProtocolBufferException ("Expected size ${expectedSize} got ${tmp.getSize()}") }
|
||||||
readSize += tmp.getSize() + WireFormat.getTagSize(1, WireType.LENGTH_DELIMITED) + WireFormat.getVarint32Size(tmp.getSize())
|
readSize += tmp.getSize() + WireFormat.getTagSize(1, WireType.LENGTH_DELIMITED) + WireFormat.getVarint32Size(tmp.getSize())
|
||||||
people.add(tmp.build())
|
people.add(tmp)
|
||||||
}
|
}
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
@@ -399,13 +399,13 @@ class AddressBook private constructor (people: MutableList <Person> = mutableLi
|
|||||||
val expectedSize = input.readInt32NoTag()
|
val expectedSize = input.readInt32NoTag()
|
||||||
var readSize = 0
|
var readSize = 0
|
||||||
while(readSize != expectedSize) {
|
while(readSize != expectedSize) {
|
||||||
val tmp: Person.BuilderPerson = Person.BuilderPerson()
|
val tmp: Person = Person.BuilderPerson().build()
|
||||||
input.readTag(1, WireType.LENGTH_DELIMITED)
|
input.readTag(1, WireType.LENGTH_DELIMITED)
|
||||||
val expectedSize = input.readInt32NoTag()
|
val expectedSize = input.readInt32NoTag()
|
||||||
tmp.mergeFrom(input)
|
tmp.mergeFrom(input)
|
||||||
if (expectedSize != tmp.getSize()) { throw InvalidProtocolBufferException ("Expected size ${expectedSize} got ${tmp.getSize()}") }
|
if (expectedSize != tmp.getSize()) { throw InvalidProtocolBufferException ("Expected size ${expectedSize} got ${tmp.getSize()}") }
|
||||||
readSize += tmp.getSize() + WireFormat.getTagSize(1, WireType.LENGTH_DELIMITED) + WireFormat.getVarint32Size(tmp.getSize())
|
readSize += tmp.getSize() + WireFormat.getTagSize(1, WireType.LENGTH_DELIMITED) + WireFormat.getVarint32Size(tmp.getSize())
|
||||||
people.add(tmp.build())
|
people.add(tmp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,29 +1,29 @@
|
|||||||
class Level1 private constructor (field1: Level2 = Level1.Level2.BuilderLevel2().build()) {
|
class Level1 private constructor (field1: Level1.Level2 = Level1.Level2.BuilderLevel2().build()) {
|
||||||
var field1 : Level2
|
var field1 : Level1.Level2
|
||||||
private set
|
private set
|
||||||
|
|
||||||
|
|
||||||
init {
|
init {
|
||||||
this.field1 = field1
|
this.field1 = field1
|
||||||
}
|
}
|
||||||
class Level2 private constructor (field2: Level3 = Level1.Level2.Level3.BuilderLevel3().build()) {
|
class Level2 private constructor (field2: Level1.Level2.Level3 = Level1.Level2.Level3.BuilderLevel3().build()) {
|
||||||
var field2 : Level3
|
var field2 : Level1.Level2.Level3
|
||||||
private set
|
private set
|
||||||
|
|
||||||
|
|
||||||
init {
|
init {
|
||||||
this.field2 = field2
|
this.field2 = field2
|
||||||
}
|
}
|
||||||
class Level3 private constructor (field3: Level4 = Level1.Level2.Level3.Level4.BuilderLevel4().build()) {
|
class Level3 private constructor (field3: Level1.Level2.Level3.Level4 = Level1.Level2.Level3.Level4.BuilderLevel4().build()) {
|
||||||
var field3 : Level4
|
var field3 : Level1.Level2.Level3.Level4
|
||||||
private set
|
private set
|
||||||
|
|
||||||
|
|
||||||
init {
|
init {
|
||||||
this.field3 = field3
|
this.field3 = field3
|
||||||
}
|
}
|
||||||
class Level4 private constructor (field4: kotlin.String = "") {
|
class Level4 private constructor (field4: String = "") {
|
||||||
var field4 : kotlin.String
|
var field4 : String
|
||||||
private set
|
private set
|
||||||
|
|
||||||
|
|
||||||
@@ -35,10 +35,10 @@ class Level1 private constructor (field1: Level2 = Level1.Level2.BuilderLevel2()
|
|||||||
output.writeString (4, field4)
|
output.writeString (4, field4)
|
||||||
}
|
}
|
||||||
|
|
||||||
class BuilderLevel4 constructor (field4: kotlin.String = "") {
|
class BuilderLevel4 constructor (field4: String = "") {
|
||||||
var field4 : kotlin.String
|
var field4 : String
|
||||||
private set
|
private set
|
||||||
fun setField4(value: kotlin.String): Level1.Level2.Level3.Level4.BuilderLevel4 {
|
fun setField4(value: String): Level1.Level2.Level3.Level4.BuilderLevel4 {
|
||||||
field4 = value
|
field4 = value
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
@@ -53,8 +53,8 @@ class Level1 private constructor (field1: Level2 = Level1.Level2.BuilderLevel2()
|
|||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
fun build(): Level4 {
|
fun build(): Level1.Level2.Level3.Level4 {
|
||||||
return Level4(field4)
|
return Level1.Level2.Level3.Level4(field4)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun parseFieldFrom(input: CodedInputStream): Boolean {
|
fun parseFieldFrom(input: CodedInputStream): Boolean {
|
||||||
@@ -79,7 +79,7 @@ class Level1 private constructor (field1: Level2 = Level1.Level2.BuilderLevel2()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fun mergeWith (other: Level4) {
|
fun mergeWith (other: Level1.Level2.Level3.Level4) {
|
||||||
field4 = other.field4
|
field4 = other.field4
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -100,10 +100,10 @@ class Level1 private constructor (field1: Level2 = Level1.Level2.BuilderLevel2()
|
|||||||
field3.writeTo(output)
|
field3.writeTo(output)
|
||||||
}
|
}
|
||||||
|
|
||||||
class BuilderLevel3 constructor (field3: Level4 = Level1.Level2.Level3.Level4.BuilderLevel4().build()) {
|
class BuilderLevel3 constructor (field3: Level1.Level2.Level3.Level4 = Level1.Level2.Level3.Level4.BuilderLevel4().build()) {
|
||||||
var field3 : Level4
|
var field3 : Level1.Level2.Level3.Level4
|
||||||
private set
|
private set
|
||||||
fun setField3(value: Level4): Level1.Level2.Level3.BuilderLevel3 {
|
fun setField3(value: Level1.Level2.Level3.Level4): Level1.Level2.Level3.BuilderLevel3 {
|
||||||
field3 = value
|
field3 = value
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
@@ -121,8 +121,8 @@ class Level1 private constructor (field1: Level2 = Level1.Level2.BuilderLevel2()
|
|||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
fun build(): Level3 {
|
fun build(): Level1.Level2.Level3 {
|
||||||
return Level3(field3)
|
return Level1.Level2.Level3(field3)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun parseFieldFrom(input: CodedInputStream): Boolean {
|
fun parseFieldFrom(input: CodedInputStream): Boolean {
|
||||||
@@ -152,7 +152,7 @@ class Level1 private constructor (field1: Level2 = Level1.Level2.BuilderLevel2()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fun mergeWith (other: Level3) {
|
fun mergeWith (other: Level1.Level2.Level3) {
|
||||||
field3 = other.field3
|
field3 = other.field3
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -173,10 +173,10 @@ class Level1 private constructor (field1: Level2 = Level1.Level2.BuilderLevel2()
|
|||||||
field2.writeTo(output)
|
field2.writeTo(output)
|
||||||
}
|
}
|
||||||
|
|
||||||
class BuilderLevel2 constructor (field2: Level3 = Level1.Level2.Level3.BuilderLevel3().build()) {
|
class BuilderLevel2 constructor (field2: Level1.Level2.Level3 = Level1.Level2.Level3.BuilderLevel3().build()) {
|
||||||
var field2 : Level3
|
var field2 : Level1.Level2.Level3
|
||||||
private set
|
private set
|
||||||
fun setField2(value: Level3): Level1.Level2.BuilderLevel2 {
|
fun setField2(value: Level1.Level2.Level3): Level1.Level2.BuilderLevel2 {
|
||||||
field2 = value
|
field2 = value
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
@@ -194,8 +194,8 @@ class Level1 private constructor (field1: Level2 = Level1.Level2.BuilderLevel2()
|
|||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
fun build(): Level2 {
|
fun build(): Level1.Level2 {
|
||||||
return Level2(field2)
|
return Level1.Level2(field2)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun parseFieldFrom(input: CodedInputStream): Boolean {
|
fun parseFieldFrom(input: CodedInputStream): Boolean {
|
||||||
@@ -225,7 +225,7 @@ class Level1 private constructor (field1: Level2 = Level1.Level2.BuilderLevel2()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fun mergeWith (other: Level2) {
|
fun mergeWith (other: Level1.Level2) {
|
||||||
field2 = other.field2
|
field2 = other.field2
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -246,10 +246,10 @@ class Level1 private constructor (field1: Level2 = Level1.Level2.BuilderLevel2()
|
|||||||
field1.writeTo(output)
|
field1.writeTo(output)
|
||||||
}
|
}
|
||||||
|
|
||||||
class BuilderLevel1 constructor (field1: Level2 = Level1.Level2.BuilderLevel2().build()) {
|
class BuilderLevel1 constructor (field1: Level1.Level2 = Level1.Level2.BuilderLevel2().build()) {
|
||||||
var field1 : Level2
|
var field1 : Level1.Level2
|
||||||
private set
|
private set
|
||||||
fun setField1(value: Level2): Level1.BuilderLevel1 {
|
fun setField1(value: Level1.Level2): Level1.BuilderLevel1 {
|
||||||
field1 = value
|
field1 = value
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user