Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

make-structs cmd line option #15

Merged
merged 5 commits into from
Feb 11, 2019
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 12 additions & 3 deletions examples/add_person.d
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@ import tutorial.addressbook;
/// This function fills in a Person message based on user input.
Person promptForAddress()
{
auto person = new Person;
static if (is(Person == class))
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Three times the same static if/else, maybe a small template make!T.
Ex.: auto person = make!Person

auto person = new Person;
else
Person person;

write("Enter person ID number: ");
readf("%d", &person.id);
Expand All @@ -23,7 +26,10 @@ Person promptForAddress()

while (true)
{
auto phoneNumber = new Person.PhoneNumber;
static if (is(Person.PhoneNumber == class))
auto phoneNumber = new Person.PhoneNumber;
else
Person.PhoneNumber phoneNumber;
write("Enter a phone number (or leave blank to finish): ");
phoneNumber.number = readln!string.strip;
if (phoneNumber.number.empty)
Expand Down Expand Up @@ -57,7 +63,10 @@ int main(string[] args)
return -1;
}

auto addressBook = new AddressBook;
static if (is(AddressBook == class))
auto addressBook = new AddressBook;
else
AddressBook addressBook;
try
{
auto input = File(args[1], "rb");
Expand Down
4 changes: 2 additions & 2 deletions examples/dub.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
"sourceFiles": ["tutorial/addressbook.d"],
"sourcePaths": ["../src"],
"mainSourceFile": "add_person.d",
"preBuildCommands": ["protoc $$PROTO_PATH --plugin=../build/protoc-gen-d --d_out=. addressbook.proto"]
"preBuildCommands": ["protoc $$PROTO_PATH --plugin=../build/protoc-gen-d --d_opt=make-structs --d_out=. addressbook.proto"]
deviator marked this conversation as resolved.
Show resolved Hide resolved
},
{
"name": "list_people",
Expand All @@ -18,7 +18,7 @@
"sourceFiles": ["tutorial/addressbook.d"],
"sourcePaths": ["../src"],
"mainSourceFile": "list_people.d",
"preBuildCommands": ["protoc $$PROTO_PATH --plugin=../build/protoc-gen-d --d_out=. addressbook.proto"]
"preBuildCommands": ["protoc $$PROTO_PATH --plugin=../build/protoc-gen-d --d_opt=make-structs --d_out=. addressbook.proto"]
},
]
}
22 changes: 18 additions & 4 deletions protoc_gen_d/protoc-gen-d.d
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,18 @@ class CodeGeneratorException : Exception
class CodeGenerator
{
private enum indentSize = 4;
private bool makeStructs = false;
deviator marked this conversation as resolved.
Show resolved Hide resolved

CodeGeneratorResponse handle(CodeGeneratorRequest request)
{
import std.algorithm : filter, map;
import std.algorithm : filter, map, canFind, splitter;
import std.array : array;
import std.conv : to;
import std.format : format;

if (request.parameter.splitter(",").canFind("make-structs"))
makeStructs = true;

if (request.compilerVersion) with (request.compilerVersion)
protocVersion = format!"%d%03d%03d"(major, minor, patch);

Expand Down Expand Up @@ -146,9 +150,18 @@ class CodeGenerator
if (messageType.isMap)
return "";

auto strIndent = "%*s".format(indent, "");
deviator marked this conversation as resolved.
Show resolved Hide resolved

auto result = appender!string;
result ~= "\n%*s%sclass %s\n".format(indent, "", indent > 0 ? "static " : "", messageType.name.escapeKeywords);
result ~= "%*s{\n".format(indent, "");
result ~= "\n";
result ~= strIndent;
result ~= indent > 0 ? "static " : "";
result ~= makeStructs ? "struct" : "class";
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please check here if the protobuf message definition is recursive. struct cannot be used for recursive messages.
This should be check in the code generator, otherwise the user would need to deal with it at compile time, probably not knowing that the generated message definition is wrong.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What you mean by recursive messages? A in B as field, and B in A as field, right?
Fields must be pointers in this case and there comes more difficult code for working with its (get address of stack variable is bad idea, need use GC for allocate memory, or any other variant). I think this case is example where structs are not suits.

result ~= " ";
result ~= messageType.name.escapeKeywords;
result ~= "\n";
result ~= strIndent;
result ~= "{\n";

int[] generatedOneofs;
foreach (field; messageType.fields.sort!((a, b) => a.number < b.number))
Expand All @@ -173,7 +186,8 @@ class CodeGenerator
foreach (enumType; messageType.enumTypes)
result ~= generateEnum(enumType, indent + indentSize);

result ~= "%*s}\n".format(indent, "");
result ~= strIndent;
result ~= "}\n";

return result.data;
}
Expand Down