Added support for bytes type. Fixed a bit messages serialization. Made some refactoring
This commit is contained in:
@@ -22,7 +22,7 @@ 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()
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
bin/kotlin_class_generator.o: src/kotlin_class_generator.cc \
|
||||
src/kotlin_class_generator.h src/kotlin_field_generator.h \
|
||||
src/kotlin_enum_generator.h
|
||||
BIN
Binary file not shown.
@@ -1,2 +0,0 @@
|
||||
bin/kotlin_enum_generator.o: src/kotlin_enum_generator.cc \
|
||||
src/kotlin_enum_generator.h
|
||||
Binary file not shown.
@@ -1,2 +0,0 @@
|
||||
bin/kotlin_field_generator.o: src/kotlin_field_generator.cc \
|
||||
src/kotlin_field_generator.h
|
||||
BIN
Binary file not shown.
@@ -1,3 +0,0 @@
|
||||
bin/kotlin_file_generator.o: src/kotlin_file_generator.cc \
|
||||
src/kotlin_file_generator.h src/kotlin_class_generator.h \
|
||||
src/kotlin_field_generator.h src/kotlin_enum_generator.h
|
||||
Binary file not shown.
@@ -1,3 +0,0 @@
|
||||
bin/main.o: src/main.cc src/kotlin_file_generator.h \
|
||||
src/kotlin_class_generator.h src/kotlin_field_generator.h \
|
||||
src/kotlin_enum_generator.h
|
||||
Binary file not shown.
Binary file not shown.
+2
-14
@@ -22,7 +22,7 @@ void ClassGenerator::generateCode(io::Printer *printer, bool isBuilder) const {
|
||||
* Also note that fields should be declared before init section.
|
||||
*/
|
||||
for (FieldGenerator *gen: properties) {
|
||||
gen->generateCode(printer, isBuilder);
|
||||
gen->generateCode(printer, isBuilder, simpleName);
|
||||
printer->Print("\n");
|
||||
}
|
||||
|
||||
@@ -61,9 +61,6 @@ void ClassGenerator::generateCode(io::Printer *printer, bool isBuilder) const {
|
||||
if (isBuilder) {
|
||||
printer->Print("\n");
|
||||
generateBuildMethod(printer);
|
||||
|
||||
printer->Print("\n");
|
||||
generateSetters(printer);
|
||||
}
|
||||
|
||||
printer->Outdent();
|
||||
@@ -72,7 +69,7 @@ void ClassGenerator::generateCode(io::Printer *printer, bool isBuilder) const {
|
||||
|
||||
ClassGenerator::ClassGenerator(Descriptor const *descriptor)
|
||||
: descriptor(descriptor) {
|
||||
simpleName = descriptor->name(); // TODO: think about more careful class naming
|
||||
simpleName = descriptor->name();
|
||||
|
||||
int field_count = descriptor->field_count();
|
||||
for (int i = 0; i < field_count; ++i) {
|
||||
@@ -143,7 +140,6 @@ void ClassGenerator::generateSerializers(io::Printer * printer, bool isRead) con
|
||||
"\n");
|
||||
printer->Indent();
|
||||
|
||||
//TODO: write message tag and size
|
||||
printer->Print(vars, "$maybeReturn$$funName$NoTag($arg$)\n");
|
||||
|
||||
printer->Outdent();
|
||||
@@ -234,14 +230,6 @@ void ClassGenerator::generateInitSection(io::Printer * printer) const {
|
||||
printer->Print("}\n");
|
||||
}
|
||||
|
||||
void ClassGenerator::generateSetters(io::Printer *printer) const {
|
||||
for (int i = 0; i < properties.size(); ++i) {
|
||||
properties[i]->generateSetter(printer, "Builder" + simpleName);
|
||||
printer->Print("\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const string ClassModifier::getName() const {
|
||||
string result = "";
|
||||
switch (type) {
|
||||
|
||||
+1
-2
@@ -47,7 +47,6 @@ private:
|
||||
void generateBuilder (io::Printer * printer) const;
|
||||
void generateBuildMethod (io::Printer * printer) const;
|
||||
void generateInitSection (io::Printer * printer) const;
|
||||
void generateSetters (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
|
||||
@@ -67,7 +66,7 @@ private:
|
||||
};
|
||||
|
||||
} // namespace kotlin
|
||||
} // namspace compiler
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
#endif //SRC_KOTLIN_CLASS_GENERATOR_H
|
||||
|
||||
+1
-1
@@ -114,6 +114,6 @@ EnumGenerator::EnumGenerator(EnumDescriptor const *descriptor) {
|
||||
}
|
||||
|
||||
} // namespace kotlin
|
||||
} // namspace compiler
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
+1
-1
@@ -36,7 +36,7 @@ private:
|
||||
};
|
||||
|
||||
} // namespace kotlin
|
||||
} // namspace compiler
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
|
||||
+131
-31
@@ -6,6 +6,7 @@
|
||||
#include <vector>
|
||||
#include <google/protobuf/io/printer.h>
|
||||
#include <google/protobuf/descriptor.h>
|
||||
#include "kotlin_name_resolver.h"
|
||||
#include <iostream>
|
||||
|
||||
namespace google {
|
||||
@@ -28,12 +29,19 @@ string FieldGenerator::protobufToKotlinField() const {
|
||||
postamble = "?";
|
||||
break;
|
||||
case FieldDescriptor::LABEL_REPEATED:
|
||||
#ifndef KOTLIN_GENERATED_CODE_LANGUAGE_LEVEL_LOW
|
||||
preamble = "MutableList <";
|
||||
postamble = "> ";
|
||||
break;
|
||||
#else
|
||||
preamble = "Array <";
|
||||
postamble = "> ";
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
return preamble + protobufToKotlinType() + postamble;
|
||||
}
|
||||
|
||||
/**
|
||||
* Simply maps protobuf field type to corresponding Kotlin.
|
||||
*/
|
||||
@@ -43,7 +51,7 @@ string FieldGenerator::protobufToKotlinType() const {
|
||||
case FieldDescriptor::TYPE_BOOL:
|
||||
return "Boolean";
|
||||
case FieldDescriptor::TYPE_BYTES:
|
||||
return ""; // TODO: support bytes type
|
||||
return "ByteArray";
|
||||
case FieldDescriptor::TYPE_DOUBLE:
|
||||
return "Double";
|
||||
case FieldDescriptor::TYPE_ENUM:
|
||||
@@ -56,8 +64,6 @@ string FieldGenerator::protobufToKotlinType() const {
|
||||
return "Long";
|
||||
case FieldDescriptor::TYPE_FLOAT:
|
||||
return "Float";
|
||||
case FieldDescriptor::TYPE_GROUP:
|
||||
return ""; // @deprecated //TODO: make proper error handling there
|
||||
case FieldDescriptor::TYPE_INT32:
|
||||
return "Int";
|
||||
case FieldDescriptor::TYPE_INT64:
|
||||
@@ -82,25 +88,73 @@ string FieldGenerator::protobufToKotlinType() const {
|
||||
}
|
||||
|
||||
string FieldGenerator::getInitValue() const {
|
||||
if (descriptor->is_optional()) {
|
||||
return "null";
|
||||
}
|
||||
if (descriptor->is_repeated())
|
||||
#ifndef KOTLIN_GENERATED_CODE_LANGUAGE_LEVEL_LOW
|
||||
return "mutableListOf()";
|
||||
#else
|
||||
return "arrayOf()";
|
||||
return fullType + "()";
|
||||
#endif
|
||||
|
||||
FieldDescriptor::Type type = descriptor->type();
|
||||
switch(type) {
|
||||
case FieldDescriptor::TYPE_BOOL:
|
||||
return "false";
|
||||
case FieldDescriptor::TYPE_BYTES:
|
||||
return "ByteArray(0)";
|
||||
case FieldDescriptor::TYPE_DOUBLE:
|
||||
return "0.0";
|
||||
case FieldDescriptor::TYPE_ENUM: {
|
||||
string enumType = descriptor->enum_type()->name();
|
||||
return enumType + ".fromIntTo" + enumType + "(0)"; // produce enum from 0, as demanded by Google
|
||||
}
|
||||
case FieldDescriptor::TYPE_FIXED32:
|
||||
return "0";
|
||||
case FieldDescriptor::TYPE_FIXED64:
|
||||
return "0L";
|
||||
case FieldDescriptor::TYPE_FLOAT:
|
||||
return "0f";
|
||||
case FieldDescriptor::TYPE_INT32:
|
||||
return "0";
|
||||
case FieldDescriptor::TYPE_INT64:
|
||||
return "0L";
|
||||
case FieldDescriptor::TYPE_MESSAGE:
|
||||
return string(descriptor->message_type()->name()) + "()";
|
||||
case FieldDescriptor::TYPE_SFIXED32:
|
||||
return "0";
|
||||
case FieldDescriptor::TYPE_SFIXED64:
|
||||
return "0L";
|
||||
case FieldDescriptor::TYPE_SINT32:
|
||||
return "0";
|
||||
case FieldDescriptor::TYPE_SINT64:
|
||||
return "0L";
|
||||
case FieldDescriptor::TYPE_STRING:
|
||||
return "\"\"";
|
||||
case FieldDescriptor::TYPE_UINT32:
|
||||
return "0"; // see notes for TYPE_FIXED32
|
||||
case FieldDescriptor::TYPE_UINT64:
|
||||
return "0L"; // see notes for TYPE_FIXED64
|
||||
}
|
||||
}
|
||||
|
||||
void FieldGenerator::generateCode(io::Printer *printer, bool isBuilder) const {
|
||||
void FieldGenerator::generateCode(io::Printer *printer, bool isBuilder, string className) const {
|
||||
map<string, string> vars;
|
||||
vars["name"] = simpleName;
|
||||
vars["field"] = protobufToKotlinField();
|
||||
printer->Print(vars, "var $name$ : $field$\n");
|
||||
|
||||
// make setter private for fair classes
|
||||
if (!isBuilder) {
|
||||
printer->Indent();
|
||||
printer->Print("private set\n");
|
||||
printer->Outdent();
|
||||
// make setter private
|
||||
printer->Indent();
|
||||
printer->Print("private set\n");
|
||||
printer->Outdent();
|
||||
|
||||
// generate setter for builder
|
||||
if (isBuilder) {
|
||||
generateSetter(printer, /* builderName = */ "Builder" + className);
|
||||
}
|
||||
|
||||
// generate additional methods for repeated fields
|
||||
if (modifier == FieldDescriptor::LABEL_REPEATED) {
|
||||
generateRepeatedMethods(printer, isBuilder, /* builderName = */ "Builder" + className);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -137,7 +191,7 @@ void FieldGenerator::generateSerializationCode(io::Printer *printer, bool isRead
|
||||
//TODO: dirty stub here! Normally, reading from input should be delegated to Parsers, with proper error handling and etc.
|
||||
//Currently tag is ignored, and work of the library relies heavily on the field order guarantees.
|
||||
//Thus, backward-compability and extensions are not supported.
|
||||
printer->Print(vars, "val tag = input.readTag()\n");
|
||||
printer->Print(vars, "val tag = input.readTag($fieldNumber$, WireType.LENGTH_DELIMITED)\n");
|
||||
printer->Print(vars, "val listSize = input.readInt32NoTag()\n");
|
||||
printer->Print(vars, "for (i in 1..listSize) {\n");
|
||||
printer->Indent();
|
||||
@@ -146,8 +200,12 @@ void FieldGenerator::generateSerializationCode(io::Printer *printer, bool isRead
|
||||
printer->Print("}\n");
|
||||
}
|
||||
else {
|
||||
// tag
|
||||
printer->Print(vars, "output.writeTag($fieldNumber$, WireType.LENGTH_DELIMITED)\n");
|
||||
|
||||
// length
|
||||
printer->Print(vars, "$arg$.writeInt32NoTag($fieldName$.size)\n");
|
||||
printer->Print(vars, "output.writeInt32NoTag($fieldName$.size)\n");
|
||||
printer->Print(vars, "output.writeInt32NoTag($fieldName$.size)\n");
|
||||
|
||||
// all elements
|
||||
printer->Print(vars, "for (item in $fieldName$) {\n");
|
||||
@@ -201,11 +259,16 @@ void FieldGenerator::generateSerializationCode(io::Printer *printer, bool isRead
|
||||
if (descriptor->type() == FieldDescriptor::TYPE_MESSAGE) {
|
||||
vars["fieldName"] = noTag ? "item" : simpleName;
|
||||
vars["maybeNoTag"] = noTag ? "NoTag" : "";
|
||||
vars["fieldNumber"] = std::to_string(descriptor->number());
|
||||
if (isRead) {
|
||||
printer->Print(vars, "$fieldName$.readFrom$maybeNoTag$(input)\n");
|
||||
printer->Print(vars,
|
||||
"val tag = input.readTag($fieldNumber$, WireType.LENGTH_DELIMITED)\n"
|
||||
"$fieldName$.readFrom$maybeNoTag$(input)\n");
|
||||
}
|
||||
else {
|
||||
printer->Print(vars, "$fieldName$.writeTo$maybeNoTag$(output)\n");
|
||||
printer->Print(vars,
|
||||
"output.writeTag($fieldNumber$, WireType.LENGTH_DELIMITED)\n"
|
||||
"$fieldName$.writeTo$maybeNoTag$(output)\n");
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -217,9 +280,6 @@ void FieldGenerator::generateSerializationCode(io::Printer *printer, bool isRead
|
||||
else {
|
||||
printer->Print(vars, "output.write$type$ ($fieldNumber$, $fieldName$)\n");
|
||||
}
|
||||
|
||||
|
||||
// TODO: support tricky types like enums/messages/repeated fields/etc
|
||||
}
|
||||
|
||||
string FieldGenerator::protobufTypeToKotlinFunctionSuffix(FieldDescriptor::Type type) const {
|
||||
@@ -242,12 +302,10 @@ string FieldGenerator::protobufTypeToKotlinFunctionSuffix(FieldDescriptor::Type
|
||||
return "Bool";
|
||||
case FieldDescriptor::TYPE_STRING:
|
||||
return "String";
|
||||
case FieldDescriptor::TYPE_GROUP:
|
||||
return ""; // deprecated // TODO: think about proper error handling here
|
||||
case FieldDescriptor::TYPE_MESSAGE:
|
||||
return "Message"; // TODO: support messages
|
||||
return "Message";
|
||||
case FieldDescriptor::TYPE_BYTES:
|
||||
return ""; // TODO: support bytes
|
||||
return "Bytes";
|
||||
case FieldDescriptor::TYPE_UINT32:
|
||||
return "UInt32";
|
||||
case FieldDescriptor::TYPE_ENUM:
|
||||
@@ -265,25 +323,67 @@ string FieldGenerator::protobufTypeToKotlinFunctionSuffix(FieldDescriptor::Type
|
||||
|
||||
void FieldGenerator::generateSetter(io::Printer *printer, string builderName) const {
|
||||
map <string, string> vars;
|
||||
// TODO: refactor work with names into separate class
|
||||
string camelCaseName = simpleName;
|
||||
camelCaseName[0] = char(std::toupper(camelCaseName[0]));
|
||||
vars["camelCaseName"] = camelCaseName;
|
||||
vars["name"] = simpleName;
|
||||
vars["camelCaseName"] = name_resolving::makeFirstLetterUpper(simpleName);
|
||||
vars["fieldName"] = simpleName;
|
||||
vars["builderName"] = builderName;
|
||||
vars["type"] = fullType;
|
||||
printer->Print(vars,
|
||||
"fun set$camelCaseName$(value: $type$): $builderName$ {\n");
|
||||
printer->Indent();
|
||||
printer->Print(vars,
|
||||
"$name$ = value\n"
|
||||
"$fieldName$ = value\n"
|
||||
"return this\n");
|
||||
printer->Outdent();
|
||||
printer->Print("}\n");
|
||||
}
|
||||
|
||||
void FieldGenerator::generateRepeatedMethods(io::Printer * printer, bool isBuilder, string builderName) const {
|
||||
map <string, string> vars;
|
||||
vars["elementType"] = underlyingType;
|
||||
vars["arg"] = "value";
|
||||
vars["fieldName"] = simpleName;
|
||||
vars["builderName"] = builderName;
|
||||
|
||||
// generate indexed setter for builders
|
||||
if (isBuilder) {
|
||||
printer->Print(vars, "fun set$elementType$(index: Int, $arg$: $elementType$): $builderName$ {\n");
|
||||
printer->Indent();
|
||||
printer->Print(vars, "$fieldName$[index] = $arg$\n");
|
||||
printer->Print(vars, "return this\n");
|
||||
printer->Outdent();
|
||||
printer->Print("}\n");
|
||||
}
|
||||
|
||||
#ifndef KOTLIN_GENERATED_CODE_LANGUAGE_LEVEL_LOW
|
||||
if (isBuilder) {
|
||||
// generate single-add for builders
|
||||
printer->Print(vars, "fun add$elementType$($arg$: $elementType$): $builderName$ {\n");
|
||||
printer->Indent();
|
||||
printer->Print(vars, "$fieldName$.add($arg$)\n"
|
||||
"return this\n");
|
||||
printer->Outdent();
|
||||
printer->Print(vars, "}\n");
|
||||
|
||||
// generate addAll for builders
|
||||
printer->Print(vars, "fun addAll$elementType$($arg$: Iterable<$elementType$>): $builderName$ {\n");
|
||||
printer->Indent();
|
||||
printer->Print(vars, "for (item in $arg$) {\n");
|
||||
printer->Indent();
|
||||
printer->Print(vars, "$fieldName$.add(item)\n");
|
||||
|
||||
printer->Outdent(); // for-loop
|
||||
printer->Print("}\n");
|
||||
|
||||
printer->Print("return this\n");
|
||||
|
||||
printer->Outdent(); // function body
|
||||
printer->Print("}\n");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
} // namespace kotlin
|
||||
} // namspace compiler
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
+4
-4
@@ -30,7 +30,8 @@ private:
|
||||
* CodedInputStream.readSFixed32(fieldNumber: Int)
|
||||
*/
|
||||
string protobufTypeToKotlinFunctionSuffix(FieldDescriptor::Type type) const;
|
||||
|
||||
void generateSetter(io::Printer * printer, string builderName) const;
|
||||
void generateRepeatedMethods(io::Printer * printer, bool isBuilder, string builderName) const;
|
||||
public:
|
||||
FieldDescriptor::Label modifier;
|
||||
string simpleName;
|
||||
@@ -45,15 +46,14 @@ public:
|
||||
string fullType;
|
||||
|
||||
string initValue;
|
||||
void generateCode(io::Printer * printer, bool isBuilder = false) const;
|
||||
void generateCode(io::Printer * printer, bool isBuilder, string className) const;
|
||||
void generateSerializationCode(io::Printer * printer, bool isRead = false, bool noTag = false) const;
|
||||
void generateSetter(io::Printer * printer, string builderName) const;
|
||||
FieldGenerator(FieldDescriptor const * descriptor);
|
||||
|
||||
};
|
||||
|
||||
} // namespace kotlin
|
||||
} // namspace compiler
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
|
||||
+2
-8
@@ -10,6 +10,7 @@
|
||||
#endif
|
||||
#include "kotlin_file_generator.h"
|
||||
#include <iostream>
|
||||
#include "kotlin_name_resolver.h"
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
@@ -26,14 +27,7 @@ void FileGenerator::generateCode(io::Printer *printer, std::vector<ClassGenerato
|
||||
bool FileGenerator::Generate(const FileDescriptor *file, const string ¶meter, GeneratorContext *context,
|
||||
string *error) const {
|
||||
std::vector<ClassGenerator *> classes;
|
||||
|
||||
//TODO: maybe wrap work with class names and stuff in separate class (like in Java implementation)
|
||||
// Get output file name
|
||||
string const proto_file_name = file->name();
|
||||
size_t file_extension_index = proto_file_name.find(".proto");
|
||||
string const file_name = proto_file_name.substr(0, file_extension_index) + ".kt";
|
||||
|
||||
|
||||
string const file_name = name_resolving::getKotlinOutputByProtoName(file->name());
|
||||
google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> output(context->Open(file_name));
|
||||
io::Printer printer(output.get(), '$', /* annotation_collector = */ NULL);
|
||||
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
//
|
||||
// Created by user on 7/14/16.
|
||||
//
|
||||
|
||||
#include "kotlin_name_resolver.h"
|
||||
#include <string>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace compiler {
|
||||
namespace kotlin {
|
||||
|
||||
namespace name_resolving {
|
||||
|
||||
using namespace std;
|
||||
|
||||
string makeFirstLetterUpper(std::string s) {
|
||||
s[0] = std::toupper(s[0]);
|
||||
return s;
|
||||
}
|
||||
|
||||
string getFileNameWithoutExtension(string fullName) {
|
||||
size_t file_extension_index = fullName.find_last_of(".");
|
||||
return fullName.substr(0, file_extension_index);
|
||||
}
|
||||
|
||||
string getKotlinOutputByProtoName(string protoName) {
|
||||
string justName = getFileNameWithoutExtension(protoName);
|
||||
return justName + ".kt";
|
||||
}
|
||||
|
||||
} // namespace name_resolving
|
||||
} // namespace kotlin
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
@@ -0,0 +1,29 @@
|
||||
//
|
||||
// Created by user on 7/14/16.
|
||||
//
|
||||
|
||||
#ifndef GOOGLE_KOTLIN_NAME_RESOLVER_H
|
||||
#define GOOGLE_KOTLIN_NAME_RESOLVER_H
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace compiler {
|
||||
namespace kotlin {
|
||||
namespace name_resolving {
|
||||
|
||||
std::string makeFirstLetterUpper(std::string s);
|
||||
|
||||
std::string getFileNameWithoutExtension(std::string fullName);
|
||||
|
||||
std::string getKotlinOutputByProtoName(std::string protoName);
|
||||
|
||||
} // namespace name_resolving
|
||||
} // namespace kotlin
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
|
||||
#endif //GOOGLE_KOTLIN_NAME_RESOLVER_H
|
||||
@@ -3,8 +3,6 @@
|
||||
#include <google/protobuf/compiler/python/python_generator.h>
|
||||
#include <google/protobuf/compiler/java/java_generator.h>
|
||||
#include <google/protobuf/compiler/javanano/javanano_generator.h>
|
||||
// TODO(teboring): Add it back when php implementation is ready
|
||||
// #include <google/protobuf/compiler/php/php_generator.h>
|
||||
#include <google/protobuf/compiler/ruby/ruby_generator.h>
|
||||
#include <google/protobuf/compiler/csharp/csharp_generator.h>
|
||||
#include <google/protobuf/compiler/objectivec/objectivec_generator.h>
|
||||
@@ -12,6 +10,7 @@
|
||||
#include "kotlin_file_generator.h"
|
||||
#include <iostream>
|
||||
|
||||
//#define KOTLIN_GENERATED_CODE_LANGUAGE_LEVEL_LOW
|
||||
int main(int argc, const char* const * argv) {
|
||||
google::protobuf::compiler::CommandLineInterface cli;
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
class Person private constructor (name: kotlin.String? = null, id: Int? = null, email: kotlin.String? = null, phones: Array <PhoneNumber> = arrayOf()) {
|
||||
class Person private constructor (name: kotlin.String? = "", id: Int? = 0, email: kotlin.String? = "", phones: MutableList <PhoneNumber> = mutableListOf(), someBytes: ByteArray? = ByteArray(0)) {
|
||||
var name : kotlin.String?
|
||||
private set
|
||||
|
||||
@@ -8,7 +8,10 @@ class Person private constructor (name: kotlin.String? = null, id: Int? = null,
|
||||
var email : kotlin.String?
|
||||
private set
|
||||
|
||||
var phones : Array <PhoneNumber>
|
||||
var phones : MutableList <PhoneNumber>
|
||||
private set
|
||||
|
||||
var someBytes : ByteArray?
|
||||
private set
|
||||
|
||||
|
||||
@@ -17,6 +20,7 @@ class Person private constructor (name: kotlin.String? = null, id: Int? = null,
|
||||
this.id = id
|
||||
this.email = email
|
||||
this.phones = phones
|
||||
this.someBytes = someBytes
|
||||
}
|
||||
enum class PhoneType(val ord: Int) {
|
||||
MOBILE (0),
|
||||
@@ -34,7 +38,7 @@ class Person private constructor (name: kotlin.String? = null, id: Int? = null,
|
||||
}
|
||||
}
|
||||
}
|
||||
class PhoneNumber private constructor (number: kotlin.String? = null, type: PhoneType? = null) {
|
||||
class PhoneNumber private constructor (number: kotlin.String? = "", type: PhoneType? = PhoneType.fromIntToPhoneType(0)) {
|
||||
var number : kotlin.String?
|
||||
private set
|
||||
|
||||
@@ -47,19 +51,29 @@ class Person private constructor (name: kotlin.String? = null, id: Int? = null,
|
||||
this.type = type
|
||||
}
|
||||
|
||||
fun writeTo (output: CodedOutputStream) {
|
||||
fun writeTo (output: CodedOutputStream): Unit {
|
||||
writeToNoTag(output)
|
||||
}
|
||||
|
||||
fun writeToNoTag (output: CodedOutputStream) {
|
||||
fun writeToNoTag (output: CodedOutputStream): Unit {
|
||||
output.writeString (1, number)
|
||||
output.writeEnum (2, type?.ord)
|
||||
}
|
||||
|
||||
class BuilderPhoneNumber constructor (number: kotlin.String? = null, type: PhoneType? = null) {
|
||||
class BuilderPhoneNumber constructor (number: kotlin.String? = "", type: PhoneType? = PhoneType.fromIntToPhoneType(0)) {
|
||||
var number : kotlin.String?
|
||||
private set
|
||||
fun setNumber(value: kotlin.String?): BuilderPhoneNumber {
|
||||
number = value
|
||||
return this
|
||||
}
|
||||
|
||||
var type : PhoneType?
|
||||
private set
|
||||
fun setType(value: PhoneType?): BuilderPhoneNumber {
|
||||
type = value
|
||||
return this
|
||||
}
|
||||
|
||||
|
||||
init {
|
||||
@@ -67,29 +81,19 @@ class Person private constructor (name: kotlin.String? = null, id: Int? = null,
|
||||
this.type = type
|
||||
}
|
||||
|
||||
fun readFrom (input: CodedInputStream) {
|
||||
readFromNoTag(input)
|
||||
fun readFrom (input: CodedInputStream): BuilderPhoneNumber {
|
||||
return readFromNoTag(input)
|
||||
}
|
||||
|
||||
fun readFromNoTag (input: CodedInputStream) {
|
||||
fun readFromNoTag (input: CodedInputStream): BuilderPhoneNumber {
|
||||
number = input.readString(1)
|
||||
type = PhoneType.fromIntToPhoneType(input.readEnum(2))
|
||||
}
|
||||
return this
|
||||
}
|
||||
|
||||
fun build(): PhoneNumber {
|
||||
return PhoneNumber(number, type)
|
||||
}
|
||||
|
||||
fun setNumber(value: kotlin.String?): BuilderPhoneNumber {
|
||||
number = value
|
||||
return this
|
||||
}
|
||||
|
||||
fun setType(value: PhoneType?): BuilderPhoneNumber {
|
||||
type = value
|
||||
return this
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fun mergeFrom (input: CodedInputStream) {
|
||||
@@ -99,30 +103,75 @@ class Person private constructor (name: kotlin.String? = null, id: Int? = null,
|
||||
}
|
||||
|
||||
|
||||
fun writeTo (output: CodedOutputStream) {
|
||||
fun writeTo (output: CodedOutputStream): Unit {
|
||||
writeToNoTag(output)
|
||||
}
|
||||
|
||||
fun writeToNoTag (output: CodedOutputStream) {
|
||||
fun writeToNoTag (output: CodedOutputStream): Unit {
|
||||
output.writeString (1, name)
|
||||
output.writeInt32 (2, id)
|
||||
output.writeString (3, email)
|
||||
if (phones.size > 0) {
|
||||
output.writeTag(4, WireType.LENGTH_DELIMITED)
|
||||
output.writeInt32NoTag(phones.size)
|
||||
output.writeInt32NoTag(phones.size)
|
||||
for (item in phones) {
|
||||
output.writeTag(4, WireType.LENGTH_DELIMITED)
|
||||
item.writeToNoTag(output)
|
||||
}
|
||||
}
|
||||
output.writeBytes (5, someBytes)
|
||||
}
|
||||
|
||||
class BuilderPerson constructor (name: kotlin.String? = null, id: Int? = null, email: kotlin.String? = null, phones: Array <PhoneNumber> = arrayOf()) {
|
||||
class BuilderPerson constructor (name: kotlin.String? = "", id: Int? = 0, email: kotlin.String? = "", phones: MutableList <PhoneNumber> = mutableListOf(), someBytes: ByteArray? = ByteArray(0)) {
|
||||
var name : kotlin.String?
|
||||
private set
|
||||
fun setName(value: kotlin.String?): BuilderPerson {
|
||||
name = value
|
||||
return this
|
||||
}
|
||||
|
||||
var id : Int?
|
||||
private set
|
||||
fun setId(value: Int?): BuilderPerson {
|
||||
id = value
|
||||
return this
|
||||
}
|
||||
|
||||
var email : kotlin.String?
|
||||
private set
|
||||
fun setEmail(value: kotlin.String?): BuilderPerson {
|
||||
email = value
|
||||
return this
|
||||
}
|
||||
|
||||
var phones : Array <PhoneNumber>
|
||||
var phones : MutableList <PhoneNumber>
|
||||
private set
|
||||
fun setPhones(value: MutableList <PhoneNumber> ): BuilderPerson {
|
||||
phones = value
|
||||
return this
|
||||
}
|
||||
fun setPhoneNumber(index: Int, value: PhoneNumber): BuilderPerson {
|
||||
phones[index] = value
|
||||
return this
|
||||
}
|
||||
fun addPhoneNumber(value: PhoneNumber): BuilderPerson {
|
||||
phones.add(value)
|
||||
return this
|
||||
}
|
||||
fun addAllPhoneNumber(value: Iterable<PhoneNumber>): BuilderPerson {
|
||||
for (item in value) {
|
||||
phones.add(item)
|
||||
}
|
||||
return this
|
||||
}
|
||||
|
||||
var someBytes : ByteArray?
|
||||
private set
|
||||
fun setSomeBytes(value: ByteArray?): BuilderPerson {
|
||||
someBytes = value
|
||||
return this
|
||||
}
|
||||
|
||||
|
||||
init {
|
||||
@@ -130,49 +179,31 @@ class Person private constructor (name: kotlin.String? = null, id: Int? = null,
|
||||
this.id = id
|
||||
this.email = email
|
||||
this.phones = phones
|
||||
this.someBytes = someBytes
|
||||
}
|
||||
|
||||
fun readFrom (input: CodedInputStream) {
|
||||
readFromNoTag(input)
|
||||
fun readFrom (input: CodedInputStream): BuilderPerson {
|
||||
return readFromNoTag(input)
|
||||
}
|
||||
|
||||
fun readFromNoTag (input: CodedInputStream) {
|
||||
fun readFromNoTag (input: CodedInputStream): BuilderPerson {
|
||||
name = input.readString(1)
|
||||
id = input.readInt32(2)
|
||||
email = input.readString(3)
|
||||
if (phones.size > 0) {
|
||||
val tag = input.readTag()
|
||||
val tag = input.readTag(4, WireType.LENGTH_DELIMITED)
|
||||
val listSize = input.readInt32NoTag()
|
||||
for (i in 1..listSize) {
|
||||
phones[i - 1].mergeFrom(input)
|
||||
}
|
||||
}
|
||||
}
|
||||
someBytes = input.readBytes(5)
|
||||
return this
|
||||
}
|
||||
|
||||
fun build(): Person {
|
||||
return Person(name, id, email, phones)
|
||||
return Person(name, id, email, phones, someBytes)
|
||||
}
|
||||
|
||||
fun setName(value: kotlin.String?): BuilderPerson {
|
||||
name = value
|
||||
return this
|
||||
}
|
||||
|
||||
fun setId(value: Int?): BuilderPerson {
|
||||
id = value
|
||||
return this
|
||||
}
|
||||
|
||||
fun setEmail(value: kotlin.String?): BuilderPerson {
|
||||
email = value
|
||||
return this
|
||||
}
|
||||
|
||||
fun setPhones(value: Array <PhoneNumber> ): BuilderPerson {
|
||||
phones = value
|
||||
return this
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fun mergeFrom (input: CodedInputStream) {
|
||||
@@ -180,18 +211,19 @@ class Person private constructor (name: kotlin.String? = null, id: Int? = null,
|
||||
id = input.readInt32(2)
|
||||
email = input.readString(3)
|
||||
if (phones.size > 0) {
|
||||
val tag = input.readTag()
|
||||
val tag = input.readTag(4, WireType.LENGTH_DELIMITED)
|
||||
val listSize = input.readInt32NoTag()
|
||||
for (i in 1..listSize) {
|
||||
phones[i - 1].mergeFrom(input)
|
||||
}
|
||||
}
|
||||
someBytes = input.readBytes(5)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class AddressBook private constructor (people: Array <Person> = arrayOf()) {
|
||||
var people : Array <Person>
|
||||
class AddressBook private constructor (people: MutableList <Person> = mutableListOf()) {
|
||||
var people : MutableList <Person>
|
||||
private set
|
||||
|
||||
|
||||
@@ -199,55 +231,72 @@ class AddressBook private constructor (people: Array <Person> = arrayOf()) {
|
||||
this.people = people
|
||||
}
|
||||
|
||||
fun writeTo (output: CodedOutputStream) {
|
||||
fun writeTo (output: CodedOutputStream): Unit {
|
||||
writeToNoTag(output)
|
||||
}
|
||||
|
||||
fun writeToNoTag (output: CodedOutputStream) {
|
||||
fun writeToNoTag (output: CodedOutputStream): Unit {
|
||||
if (people.size > 0) {
|
||||
output.writeTag(1, WireType.LENGTH_DELIMITED)
|
||||
output.writeInt32NoTag(people.size)
|
||||
output.writeInt32NoTag(people.size)
|
||||
for (item in people) {
|
||||
output.writeTag(1, WireType.LENGTH_DELIMITED)
|
||||
item.writeToNoTag(output)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class BuilderAddressBook constructor (people: Array <Person> = arrayOf()) {
|
||||
var people : Array <Person>
|
||||
class BuilderAddressBook constructor (people: MutableList <Person> = mutableListOf()) {
|
||||
var people : MutableList <Person>
|
||||
private set
|
||||
fun setPeople(value: MutableList <Person> ): BuilderAddressBook {
|
||||
people = value
|
||||
return this
|
||||
}
|
||||
fun setPerson(index: Int, value: Person): BuilderAddressBook {
|
||||
people[index] = value
|
||||
return this
|
||||
}
|
||||
fun addPerson(value: Person): BuilderAddressBook {
|
||||
people.add(value)
|
||||
return this
|
||||
}
|
||||
fun addAllPerson(value: Iterable<Person>): BuilderAddressBook {
|
||||
for (item in value) {
|
||||
people.add(item)
|
||||
}
|
||||
return this
|
||||
}
|
||||
|
||||
|
||||
init {
|
||||
this.people = people
|
||||
}
|
||||
|
||||
fun readFrom (input: CodedInputStream) {
|
||||
readFromNoTag(input)
|
||||
fun readFrom (input: CodedInputStream): BuilderAddressBook {
|
||||
return readFromNoTag(input)
|
||||
}
|
||||
|
||||
fun readFromNoTag (input: CodedInputStream) {
|
||||
fun readFromNoTag (input: CodedInputStream): BuilderAddressBook {
|
||||
if (people.size > 0) {
|
||||
val tag = input.readTag()
|
||||
val tag = input.readTag(1, WireType.LENGTH_DELIMITED)
|
||||
val listSize = input.readInt32NoTag()
|
||||
for (i in 1..listSize) {
|
||||
people[i - 1].mergeFrom(input)
|
||||
}
|
||||
}
|
||||
}
|
||||
return this
|
||||
}
|
||||
|
||||
fun build(): AddressBook {
|
||||
return AddressBook(people)
|
||||
}
|
||||
|
||||
fun setPeople(value: Array <Person> ): BuilderAddressBook {
|
||||
people = value
|
||||
return this
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fun mergeFrom (input: CodedInputStream) {
|
||||
if (people.size > 0) {
|
||||
val tag = input.readTag()
|
||||
val tag = input.readTag(1, WireType.LENGTH_DELIMITED)
|
||||
val listSize = input.readInt32NoTag()
|
||||
for (i in 1..listSize) {
|
||||
people[i - 1].mergeFrom(input)
|
||||
|
||||
@@ -38,6 +38,8 @@ message Person {
|
||||
}
|
||||
|
||||
repeated PhoneNumber phones = 4;
|
||||
|
||||
bytes someBytes = 5;
|
||||
}
|
||||
|
||||
// Our address book file is just one of these.
|
||||
|
||||
@@ -11,7 +11,7 @@ import java.nio.ByteOrder
|
||||
*
|
||||
*/
|
||||
|
||||
// TODO: decide, if we want to optimize for performance (then we have to deal with spaghetti-code)
|
||||
// TODO: refactor correctness checks into readTag
|
||||
class CodedInputStream(input: java.io.InputStream) {
|
||||
|
||||
val bufferedInput: java.io.BufferedInputStream
|
||||
@@ -20,7 +20,7 @@ class CodedInputStream(input: java.io.InputStream) {
|
||||
}
|
||||
|
||||
fun readInt32(expectedFieldNumber: Int): Int {
|
||||
val tag = readTag()
|
||||
val tag = readTag(expectedFieldNumber, WireType.VARINT)
|
||||
val actualFieldNumber = WireFormat.getTagFieldNumber(tag)
|
||||
val actualWireType = WireFormat.getTagWireType(tag)
|
||||
checkFieldCorrectness(expectedFieldNumber, actualFieldNumber, WireType.VARINT, actualWireType)
|
||||
@@ -31,10 +31,7 @@ class CodedInputStream(input: java.io.InputStream) {
|
||||
// simply stored in the sign bit - similar to Java's protobuf implementation. Hence, all
|
||||
// methods reading unsigned ints simply redirect call to corresponding signed-reading method
|
||||
fun readUInt32(expectedFieldNumber: Int): Int {
|
||||
val tag = readTag()
|
||||
val actualFieldNumber = WireFormat.getTagFieldNumber(tag)
|
||||
val actualWireType = WireFormat.getTagWireType(tag)
|
||||
checkFieldCorrectness(expectedFieldNumber, actualFieldNumber, WireType.VARINT, actualWireType)
|
||||
val tag = readTag(expectedFieldNumber, WireType.VARINT)
|
||||
return readUInt32NoTag()
|
||||
}
|
||||
|
||||
@@ -43,19 +40,13 @@ class CodedInputStream(input: java.io.InputStream) {
|
||||
}
|
||||
|
||||
fun readInt64(expectedFieldNumber: Int): Long {
|
||||
val tag = readTag()
|
||||
val actualFieldNumber = WireFormat.getTagFieldNumber(tag)
|
||||
val actualWireType = WireFormat.getTagWireType(tag)
|
||||
checkFieldCorrectness(expectedFieldNumber, actualFieldNumber, actualWireType, WireType.VARINT)
|
||||
val tag = readTag(expectedFieldNumber, WireType.VARINT)
|
||||
return readInt64NoTag()
|
||||
}
|
||||
|
||||
// See note on unsigned integers implementations above
|
||||
fun readUInt64(expectedFieldNumber: Int): Long {
|
||||
val tag = readTag()
|
||||
val actualFieldNumber = WireFormat.getTagFieldNumber(tag)
|
||||
val actualWireType = WireFormat.getTagWireType(tag)
|
||||
checkFieldCorrectness(expectedFieldNumber, actualFieldNumber, actualWireType, WireType.VARINT)
|
||||
val tag = readTag(expectedFieldNumber, WireType.VARINT)
|
||||
return readUInt64NoTag()
|
||||
}
|
||||
|
||||
@@ -64,10 +55,7 @@ class CodedInputStream(input: java.io.InputStream) {
|
||||
}
|
||||
|
||||
fun readBool(expectedFieldNumber: Int): Boolean {
|
||||
val tag = readTag()
|
||||
val actualFieldNumber = WireFormat.getTagFieldNumber(tag)
|
||||
val actualWireType = WireFormat.getTagWireType(tag)
|
||||
checkFieldCorrectness(expectedFieldNumber, actualFieldNumber, actualWireType, WireType.VARINT)
|
||||
val tag = readTag(expectedFieldNumber, WireType.VARINT)
|
||||
return readBoolNoTag()
|
||||
}
|
||||
|
||||
@@ -83,10 +71,7 @@ class CodedInputStream(input: java.io.InputStream) {
|
||||
|
||||
// Reading enums is like reading one int32 number. Caller is responsible for converting this ordinal to enum-object
|
||||
fun readEnum(expectedFieldNumber: Int): Int {
|
||||
val tag = readTag()
|
||||
val actualFieldNumber = WireFormat.getTagFieldNumber(tag)
|
||||
val actualWireType = WireFormat.getTagWireType(tag)
|
||||
checkFieldCorrectness(expectedFieldNumber, actualFieldNumber, WireType.VARINT, actualWireType)
|
||||
val tag = readTag(expectedFieldNumber, WireType.VARINT)
|
||||
return readEnumNoTag()
|
||||
}
|
||||
|
||||
@@ -95,10 +80,7 @@ class CodedInputStream(input: java.io.InputStream) {
|
||||
}
|
||||
|
||||
fun readSInt32(expectedFieldNumber: Int): Int {
|
||||
val tag = readTag()
|
||||
val actualFieldNumber = WireFormat.getTagFieldNumber(tag)
|
||||
val actualWireType = WireFormat.getTagWireType(tag)
|
||||
checkFieldCorrectness(expectedFieldNumber, actualFieldNumber, WireType.VARINT, actualWireType)
|
||||
val tag = readTag(expectedFieldNumber, WireType.VARINT)
|
||||
return readSInt32NoTag()
|
||||
}
|
||||
|
||||
@@ -107,18 +89,12 @@ class CodedInputStream(input: java.io.InputStream) {
|
||||
}
|
||||
|
||||
fun readSInt64(expectedFieldNumber: Int): Long {
|
||||
val tag = readTag()
|
||||
val actualFieldNumber = WireFormat.getTagFieldNumber(tag)
|
||||
val actualWireType = WireFormat.getTagWireType(tag)
|
||||
checkFieldCorrectness(expectedFieldNumber, actualFieldNumber, WireType.VARINT, actualWireType)
|
||||
val tag = readTag(expectedFieldNumber, WireType.VARINT)
|
||||
return readZigZag64NoTag()
|
||||
}
|
||||
|
||||
fun readFixed32(expectedFieldNumber: Int): Int {
|
||||
val tag = readTag()
|
||||
val actualFieldNumber = WireFormat.getTagFieldNumber(tag)
|
||||
val actualWireType = WireFormat.getTagWireType(tag)
|
||||
checkFieldCorrectness(expectedFieldNumber, actualFieldNumber, WireType.FIX_32, actualWireType)
|
||||
val tag = readTag(expectedFieldNumber, WireType.FIX_32)
|
||||
return readFixed32NoInt()
|
||||
}
|
||||
|
||||
@@ -127,10 +103,7 @@ class CodedInputStream(input: java.io.InputStream) {
|
||||
}
|
||||
|
||||
fun readSFixed32(expectedFieldNumber: Int): Int {
|
||||
val tag = readTag()
|
||||
val actualFieldNumber = WireFormat.getTagFieldNumber(tag)
|
||||
val actualWireType = WireFormat.getTagWireType(tag)
|
||||
checkFieldCorrectness(expectedFieldNumber, actualFieldNumber, WireType.FIX_32, actualWireType)
|
||||
val tag = readTag(expectedFieldNumber, WireType.FIX_32)
|
||||
return readSFixed32NoTag()
|
||||
}
|
||||
|
||||
@@ -139,10 +112,7 @@ class CodedInputStream(input: java.io.InputStream) {
|
||||
}
|
||||
|
||||
fun readFixed64(expectedFieldNumber: Int): Long {
|
||||
val tag = readTag()
|
||||
val actualFieldNumber = WireFormat.getTagFieldNumber(tag)
|
||||
val actualWireType = WireFormat.getTagWireType(tag)
|
||||
checkFieldCorrectness(expectedFieldNumber, actualFieldNumber, WireType.FIX_64, actualWireType)
|
||||
val tag = readTag(expectedFieldNumber, WireType.FIX_64)
|
||||
return readFixed64NoTag()
|
||||
}
|
||||
|
||||
@@ -151,10 +121,7 @@ class CodedInputStream(input: java.io.InputStream) {
|
||||
}
|
||||
|
||||
fun readSFixed64(expectedFieldNumber: Int): Long {
|
||||
val tag = readTag()
|
||||
val actualFieldNumber = WireFormat.getTagFieldNumber(tag)
|
||||
val actualWireType = WireFormat.getTagWireType(tag)
|
||||
checkFieldCorrectness(expectedFieldNumber, actualFieldNumber, WireType.FIX_64, actualWireType)
|
||||
val tag = readTag(expectedFieldNumber, WireType.FIX_64)
|
||||
return readSFixed64NoTag()
|
||||
}
|
||||
|
||||
@@ -163,10 +130,7 @@ class CodedInputStream(input: java.io.InputStream) {
|
||||
}
|
||||
|
||||
fun readDouble(expectedFieldNumber: Int): Double {
|
||||
val tag = readTag()
|
||||
val actualFieldNumber = WireFormat.getTagFieldNumber(tag)
|
||||
val actualWireType = WireFormat.getTagWireType(tag)
|
||||
checkFieldCorrectness(expectedFieldNumber, actualFieldNumber, WireType.FIX_64, actualWireType)
|
||||
val tag = readTag(expectedFieldNumber, WireType.FIX_64)
|
||||
return readDoubleNoTag()
|
||||
}
|
||||
|
||||
@@ -175,10 +139,7 @@ class CodedInputStream(input: java.io.InputStream) {
|
||||
}
|
||||
|
||||
fun readFloat(expectedFieldNumber: Int): Float {
|
||||
val tag = readTag()
|
||||
val actualFieldNumber = WireFormat.getTagFieldNumber(tag)
|
||||
val actualWireType = WireFormat.getTagWireType(tag)
|
||||
checkFieldCorrectness(expectedFieldNumber, actualFieldNumber, WireType.FIX_32, actualWireType)
|
||||
val tag = readTag(expectedFieldNumber, WireType.FIX_32)
|
||||
return readFloatNoTag()
|
||||
}
|
||||
|
||||
@@ -187,10 +148,7 @@ class CodedInputStream(input: java.io.InputStream) {
|
||||
}
|
||||
|
||||
fun readString(expectedFieldNumber: Int): String {
|
||||
val tag = readTag()
|
||||
val actualFieldNumber = WireFormat.getTagFieldNumber(tag)
|
||||
val actualWireType = WireFormat.getTagWireType(tag)
|
||||
checkFieldCorrectness(expectedFieldNumber, actualFieldNumber, WireType.LENGTH_DELIMITED, actualWireType)
|
||||
val tag = readTag(expectedFieldNumber, WireType.LENGTH_DELIMITED)
|
||||
return readStringNoTag()
|
||||
}
|
||||
|
||||
@@ -199,6 +157,17 @@ class CodedInputStream(input: java.io.InputStream) {
|
||||
val value = String(readRawBytes(length))
|
||||
return value
|
||||
}
|
||||
|
||||
fun readBytes(expectedFieldNumber: Int): ByteArray {
|
||||
val tag = readTag(expectedFieldNumber, WireType.LENGTH_DELIMITED)
|
||||
return readBytesNoTag()
|
||||
}
|
||||
|
||||
fun readBytesNoTag(): ByteArray {
|
||||
val length = readInt32NoTag()
|
||||
return readRawBytes(length)
|
||||
}
|
||||
|
||||
/** ============ Utility methods ==================
|
||||
* They are left non-private for cases when one wants to implement her/his own protocol format.
|
||||
* Then she/he can re-use low-level methods for operating with raw values, that are not annotated with Protobuf tags.
|
||||
@@ -254,7 +223,7 @@ class CodedInputStream(input: java.io.InputStream) {
|
||||
}
|
||||
|
||||
// reads tag. Note that it returns 0 for the end of message!
|
||||
fun readTag(): Int {
|
||||
fun readTag(expectedFieldNumber: Int, expectedWireType: WireType): Int {
|
||||
if (isAtEnd()) {
|
||||
return 0 // we can safely return 0 as sign of end of message, because 0-tags are illegal
|
||||
}
|
||||
@@ -262,6 +231,10 @@ class CodedInputStream(input: java.io.InputStream) {
|
||||
if (tag == 0) { // if we somehow had read 0-tag, then message is corrupted
|
||||
throw InvalidProtocolBufferException("Invalid tag 0")
|
||||
}
|
||||
|
||||
val actualFieldNumber = WireFormat.getTagFieldNumber(tag)
|
||||
val actualWireType = WireFormat.getTagWireType(tag)
|
||||
checkFieldCorrectness(expectedFieldNumber, actualFieldNumber, WireType.LENGTH_DELIMITED, actualWireType)
|
||||
return tag
|
||||
}
|
||||
|
||||
|
||||
@@ -151,6 +151,22 @@ class CodedOutputStream(val output: java.io.OutputStream) {
|
||||
output.write(value.toByteArray())
|
||||
}
|
||||
|
||||
fun writeBytes(fieldNumber: Int, value: ByteArray?) {
|
||||
value ?: return
|
||||
writeTag(fieldNumber, WireType.LENGTH_DELIMITED)
|
||||
writeBytesNoTag(value)
|
||||
}
|
||||
|
||||
fun writeBytesNoTag(value: ByteArray) {
|
||||
writeInt32NoTag(value.size)
|
||||
output.write(value)
|
||||
}
|
||||
|
||||
/** ============ Utility methods ==================
|
||||
* They are left non-private for cases when one wants to implement her/his own protocol format.
|
||||
* Then she/he can re-use low-level methods for operating with raw values, that are not annotated with Protobuf tags.
|
||||
*/
|
||||
|
||||
fun writeLittleEndian(value: Int?) {
|
||||
value ?: return
|
||||
val bb = ByteBuffer.allocate(4)
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
package Addressbook;
|
||||
|
||||
class Person private constructor (name: kotlin.String? = null, id: Int? = null, email: kotlin.String? = null, phones: Array <PhoneNumber> = arrayOf()) {
|
||||
class Person private constructor (name: kotlin.String? = "", id: Int? = 0, email: kotlin.String? = "", phones: MutableList <PhoneNumber> = mutableListOf(), someBytes: ByteArray? = ByteArray(0)) {
|
||||
var name : kotlin.String?
|
||||
private set
|
||||
|
||||
@@ -10,7 +8,10 @@ class Person private constructor (name: kotlin.String? = null, id: Int? = null,
|
||||
var email : kotlin.String?
|
||||
private set
|
||||
|
||||
var phones : Array <PhoneNumber>
|
||||
var phones : MutableList <PhoneNumber>
|
||||
private set
|
||||
|
||||
var someBytes : ByteArray?
|
||||
private set
|
||||
|
||||
|
||||
@@ -19,8 +20,8 @@ class Person private constructor (name: kotlin.String? = null, id: Int? = null,
|
||||
this.id = id
|
||||
this.email = email
|
||||
this.phones = phones
|
||||
this.someBytes = someBytes
|
||||
}
|
||||
|
||||
enum class PhoneType(val ord: Int) {
|
||||
MOBILE (0),
|
||||
HOME (1),
|
||||
@@ -37,7 +38,7 @@ class Person private constructor (name: kotlin.String? = null, id: Int? = null,
|
||||
}
|
||||
}
|
||||
}
|
||||
class PhoneNumber private constructor (number: kotlin.String? = null, type: PhoneType? = null) {
|
||||
class PhoneNumber private constructor (number: kotlin.String? = "", type: PhoneType? = PhoneType.fromIntToPhoneType(0)) {
|
||||
var number : kotlin.String?
|
||||
private set
|
||||
|
||||
@@ -50,19 +51,29 @@ class Person private constructor (name: kotlin.String? = null, id: Int? = null,
|
||||
this.type = type
|
||||
}
|
||||
|
||||
fun writeTo (output: CodedOutputStream) {
|
||||
fun writeTo (output: CodedOutputStream): Unit {
|
||||
writeToNoTag(output)
|
||||
}
|
||||
|
||||
fun writeToNoTag (output: CodedOutputStream) {
|
||||
fun writeToNoTag (output: CodedOutputStream): Unit {
|
||||
output.writeString (1, number)
|
||||
output.writeEnum (2, type?.ord)
|
||||
}
|
||||
|
||||
class BuilderPhoneNumber constructor (number: kotlin.String? = null, type: PhoneType? = null) {
|
||||
class BuilderPhoneNumber constructor (number: kotlin.String? = "", type: PhoneType? = PhoneType.fromIntToPhoneType(0)) {
|
||||
var number : kotlin.String?
|
||||
private set
|
||||
fun setNumber(value: kotlin.String?): BuilderPhoneNumber {
|
||||
number = value
|
||||
return this
|
||||
}
|
||||
|
||||
var type : PhoneType?
|
||||
private set
|
||||
fun setType(value: PhoneType?): BuilderPhoneNumber {
|
||||
type = value
|
||||
return this
|
||||
}
|
||||
|
||||
|
||||
init {
|
||||
@@ -70,13 +81,14 @@ class Person private constructor (name: kotlin.String? = null, id: Int? = null,
|
||||
this.type = type
|
||||
}
|
||||
|
||||
fun readFrom (input: CodedInputStream) {
|
||||
readFromNoTag(input)
|
||||
fun readFrom (input: CodedInputStream): BuilderPhoneNumber {
|
||||
return readFromNoTag(input)
|
||||
}
|
||||
|
||||
fun readFromNoTag (input: CodedInputStream) {
|
||||
fun readFromNoTag (input: CodedInputStream): BuilderPhoneNumber {
|
||||
number = input.readString(1)
|
||||
type = PhoneType.fromIntToPhoneType(input.readEnum(2))
|
||||
return this
|
||||
}
|
||||
|
||||
fun build(): PhoneNumber {
|
||||
@@ -91,30 +103,75 @@ class Person private constructor (name: kotlin.String? = null, id: Int? = null,
|
||||
}
|
||||
|
||||
|
||||
fun writeTo (output: CodedOutputStream) {
|
||||
fun writeTo (output: CodedOutputStream): Unit {
|
||||
writeToNoTag(output)
|
||||
}
|
||||
|
||||
fun writeToNoTag (output: CodedOutputStream) {
|
||||
fun writeToNoTag (output: CodedOutputStream): Unit {
|
||||
output.writeString (1, name)
|
||||
output.writeInt32 (2, id)
|
||||
output.writeString (3, email)
|
||||
if (phones.size > 0) {
|
||||
output.writeTag(4, WireType.LENGTH_DELIMITED)
|
||||
output.writeInt32NoTag(phones.size)
|
||||
output.writeInt32NoTag(phones.size)
|
||||
for (item in phones) {
|
||||
output.writeTag(4, WireType.LENGTH_DELIMITED)
|
||||
item.writeToNoTag(output)
|
||||
}
|
||||
}
|
||||
output.writeBytes (5, someBytes)
|
||||
}
|
||||
|
||||
class BuilderPerson constructor (name: kotlin.String? = null, id: Int? = null, email: kotlin.String? = null, phones: Array <PhoneNumber> = arrayOf()) {
|
||||
class BuilderPerson constructor (name: kotlin.String? = "", id: Int? = 0, email: kotlin.String? = "", phones: MutableList <PhoneNumber> = mutableListOf(), someBytes: ByteArray? = ByteArray(0)) {
|
||||
var name : kotlin.String?
|
||||
private set
|
||||
fun setName(value: kotlin.String?): BuilderPerson {
|
||||
name = value
|
||||
return this
|
||||
}
|
||||
|
||||
var id : Int?
|
||||
private set
|
||||
fun setId(value: Int?): BuilderPerson {
|
||||
id = value
|
||||
return this
|
||||
}
|
||||
|
||||
var email : kotlin.String?
|
||||
private set
|
||||
fun setEmail(value: kotlin.String?): BuilderPerson {
|
||||
email = value
|
||||
return this
|
||||
}
|
||||
|
||||
var phones : Array <PhoneNumber>
|
||||
var phones : MutableList <PhoneNumber>
|
||||
private set
|
||||
fun setPhones(value: MutableList <PhoneNumber> ): BuilderPerson {
|
||||
phones = value
|
||||
return this
|
||||
}
|
||||
fun setPhoneNumber(index: Int, value: PhoneNumber): BuilderPerson {
|
||||
phones[index] = value
|
||||
return this
|
||||
}
|
||||
fun addPhoneNumber(value: PhoneNumber): BuilderPerson {
|
||||
phones.add(value)
|
||||
return this
|
||||
}
|
||||
fun addAllPhoneNumber(value: Iterable<PhoneNumber>): BuilderPerson {
|
||||
for (item in value) {
|
||||
phones.add(item)
|
||||
}
|
||||
return this
|
||||
}
|
||||
|
||||
var someBytes : ByteArray?
|
||||
private set
|
||||
fun setSomeBytes(value: ByteArray?): BuilderPerson {
|
||||
someBytes = value
|
||||
return this
|
||||
}
|
||||
|
||||
|
||||
init {
|
||||
@@ -122,27 +179,30 @@ class Person private constructor (name: kotlin.String? = null, id: Int? = null,
|
||||
this.id = id
|
||||
this.email = email
|
||||
this.phones = phones
|
||||
this.someBytes = someBytes
|
||||
}
|
||||
|
||||
fun readFrom (input: CodedInputStream) {
|
||||
readFromNoTag(input)
|
||||
fun readFrom (input: CodedInputStream): BuilderPerson {
|
||||
return readFromNoTag(input)
|
||||
}
|
||||
|
||||
fun readFromNoTag (input: CodedInputStream) {
|
||||
fun readFromNoTag (input: CodedInputStream): BuilderPerson {
|
||||
name = input.readString(1)
|
||||
id = input.readInt32(2)
|
||||
email = input.readString(3)
|
||||
if (phones.size > 0) {
|
||||
val tag = input.readTag()
|
||||
val tag = input.readTag(4, WireType.LENGTH_DELIMITED)
|
||||
val listSize = input.readInt32NoTag()
|
||||
for (i in 1..listSize) {
|
||||
phones[i - 1].mergeFrom(input)
|
||||
}
|
||||
}
|
||||
someBytes = input.readBytes(5)
|
||||
return this
|
||||
}
|
||||
|
||||
fun build(): Person {
|
||||
return Person(name, id, email, phones)
|
||||
return Person(name, id, email, phones, someBytes)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -151,18 +211,19 @@ class Person private constructor (name: kotlin.String? = null, id: Int? = null,
|
||||
id = input.readInt32(2)
|
||||
email = input.readString(3)
|
||||
if (phones.size > 0) {
|
||||
val tag = input.readTag()
|
||||
val tag = input.readTag(4, WireType.LENGTH_DELIMITED)
|
||||
val listSize = input.readInt32NoTag()
|
||||
for (i in 1..listSize) {
|
||||
phones[i - 1].mergeFrom(input)
|
||||
}
|
||||
}
|
||||
someBytes = input.readBytes(5)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class AddressBook private constructor (people: Array <Person> = arrayOf()) {
|
||||
var people : Array <Person>
|
||||
class AddressBook private constructor (people: MutableList <Person> = mutableListOf()) {
|
||||
var people : MutableList <Person>
|
||||
private set
|
||||
|
||||
|
||||
@@ -170,39 +231,62 @@ class AddressBook private constructor (people: Array <Person> = arrayOf()) {
|
||||
this.people = people
|
||||
}
|
||||
|
||||
fun writeTo (output: CodedOutputStream) {
|
||||
fun writeTo (output: CodedOutputStream): Unit {
|
||||
writeToNoTag(output)
|
||||
}
|
||||
|
||||
fun writeToNoTag (output: CodedOutputStream) {
|
||||
fun writeToNoTag (output: CodedOutputStream): Unit {
|
||||
if (people.size > 0) {
|
||||
output.writeTag(1, WireType.LENGTH_DELIMITED)
|
||||
output.writeInt32NoTag(people.size)
|
||||
output.writeInt32NoTag(people.size)
|
||||
for (item in people) {
|
||||
output.writeTag(1, WireType.LENGTH_DELIMITED)
|
||||
item.writeToNoTag(output)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class BuilderAddressBook constructor (people: Array <Person> = arrayOf()) {
|
||||
var people : Array <Person>
|
||||
class BuilderAddressBook constructor (people: MutableList <Person> = mutableListOf()) {
|
||||
var people : MutableList <Person>
|
||||
private set
|
||||
fun setPeople(value: MutableList <Person> ): BuilderAddressBook {
|
||||
people = value
|
||||
return this
|
||||
}
|
||||
fun setPerson(index: Int, value: Person): BuilderAddressBook {
|
||||
people[index] = value
|
||||
return this
|
||||
}
|
||||
fun addPerson(value: Person): BuilderAddressBook {
|
||||
people.add(value)
|
||||
return this
|
||||
}
|
||||
fun addAllPerson(value: Iterable<Person>): BuilderAddressBook {
|
||||
for (item in value) {
|
||||
people.add(item)
|
||||
}
|
||||
return this
|
||||
}
|
||||
|
||||
|
||||
init {
|
||||
this.people = people
|
||||
}
|
||||
|
||||
fun readFrom (input: CodedInputStream) {
|
||||
readFromNoTag(input)
|
||||
fun readFrom (input: CodedInputStream): BuilderAddressBook {
|
||||
return readFromNoTag(input)
|
||||
}
|
||||
|
||||
fun readFromNoTag (input: CodedInputStream) {
|
||||
fun readFromNoTag (input: CodedInputStream): BuilderAddressBook {
|
||||
if (people.size > 0) {
|
||||
val tag = input.readTag()
|
||||
val tag = input.readTag(1, WireType.LENGTH_DELIMITED)
|
||||
val listSize = input.readInt32NoTag()
|
||||
for (i in 1..listSize) {
|
||||
people[i - 1].mergeFrom(input)
|
||||
}
|
||||
}
|
||||
return this
|
||||
}
|
||||
|
||||
fun build(): AddressBook {
|
||||
@@ -212,7 +296,7 @@ class AddressBook private constructor (people: Array <Person> = arrayOf()) {
|
||||
|
||||
fun mergeFrom (input: CodedInputStream) {
|
||||
if (people.size > 0) {
|
||||
val tag = input.readTag()
|
||||
val tag = input.readTag(1, WireType.LENGTH_DELIMITED)
|
||||
val listSize = input.readInt32NoTag()
|
||||
for (i in 1..listSize) {
|
||||
people[i - 1].mergeFrom(input)
|
||||
|
||||
@@ -5,18 +5,40 @@ import java.io.ByteArrayOutputStream
|
||||
* Created by user on 7/8/16.
|
||||
*/
|
||||
|
||||
import PersonMessage
|
||||
|
||||
fun testMessageSerialization() {
|
||||
// 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)
|
||||
val msg =
|
||||
|
||||
// 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)
|
||||
|
||||
val ins = CodedInputStream(ByteArrayInputStream(s.toByteArray()))
|
||||
val readMsg = Person("", 0, "", arrayOf())
|
||||
// Now let's use output stream as input to read our message from it!
|
||||
var ins = CodedInputStream(ByteArrayInputStream(s.toByteArray()))
|
||||
|
||||
// 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)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user