Browse Source

Add base generators for Client/Server

- Make common class for source code generation
- Move QtClassGenerator to separate file and rename accordingly
- Add Source and header generation for Service Client
- Add dummy generator for sever class
- Few coding style improvements
Alexey Edelev 6 years ago
parent
commit
90e0054a0e

+ 4 - 0
CMakeLists.txt

@@ -37,6 +37,10 @@ add_executable(${PROJECT_NAME}
     src/generator/globalenumsgenerator.cpp
     src/generator/servicegeneratorbase.cpp
     src/generator/templates.cpp
+    src/generator/clientgenerator.cpp
+    src/generator/classsourcegeneratorbase.cpp
+    src/generator/protobufsourcegenerator.cpp
+    src/generator/clientsourcegenerator.cpp
 )
 
 if(WIN32)

+ 50 - 0
src/generator/classsourcegeneratorbase.cpp

@@ -0,0 +1,50 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2019 Alexey Edelev <semlanik@gmail.com>, Tatyana Borisova <tanusshhka@mail.ru>
+ *
+ * This file is part of qtprotobuf project https://git.semlanik.org/semlanik/qtprotobuf
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this
+ * software and associated documentation files (the "Software"), to deal in the Software
+ * without restriction, including without limitation the rights to use, copy, modify,
+ * merge, publish, distribute, sublicense, and/or sell copies of the Software, and
+ * to permit persons to whom the Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all copies
+ * or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+ * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+ * FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include "classsourcegeneratorbase.h"
+
+#include <google/protobuf/io/zero_copy_stream.h>
+
+#include "templates.h"
+#include "utils.h"
+
+using namespace qtprotobuf::generator;
+using namespace ::google::protobuf;
+using namespace ::google::protobuf::io;
+using namespace ::google::protobuf::compiler;
+
+ClassSourceGeneratorBase::ClassSourceGeneratorBase(std::string fullClassName,
+                                                   std::unique_ptr<::google::protobuf::io::ZeroCopyOutputStream> out) :
+    ClassGeneratorBase(fullClassName, std::move(out))
+{
+
+}
+
+void ClassSourceGeneratorBase::printClassHeaderInclude()
+{
+    std::string includeFileName = mClassName;
+    utils::tolower(includeFileName);
+    mPrinter.Print({{"type_lower", includeFileName}}, Templates::InternalIncludeTemplate);
+}

+ 47 - 0
src/generator/classsourcegeneratorbase.h

@@ -0,0 +1,47 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2019 Alexey Edelev <semlanik@gmail.com>, Tatyana Borisova <tanusshhka@mail.ru>
+ *
+ * This file is part of qtprotobuf project https://git.semlanik.org/semlanik/qtprotobuf
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this
+ * software and associated documentation files (the "Software"), to deal in the Software
+ * without restriction, including without limitation the rights to use, copy, modify,
+ * merge, publish, distribute, sublicense, and/or sell copies of the Software, and
+ * to permit persons to whom the Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all copies
+ * or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+ * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+ * FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#pragma once
+
+#include <google/protobuf/io/printer.h>
+#include <memory>
+#include "classgeneratorbase.h"
+
+namespace qtprotobuf {
+namespace generator {
+
+class ClassSourceGeneratorBase : public ClassGeneratorBase
+{
+public:
+    ClassSourceGeneratorBase(std::string className, std::unique_ptr<google::protobuf::io::ZeroCopyOutputStream> out);
+    virtual ~ClassSourceGeneratorBase() = default;
+    virtual void run() = 0;
+
+protected:
+    void printClassHeaderInclude();
+};
+
+} //namespace qtprotobuf
+} //namespace generator

+ 47 - 0
src/generator/clientgenerator.cpp

@@ -0,0 +1,47 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2019 Alexey Edelev <semlanik@gmail.com>, Tatyana Borisova <tanusshhka@mail.ru>
+ *
+ * This file is part of qtprotobuf project https://git.semlanik.org/semlanik/qtprotobuf
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this
+ * software and associated documentation files (the "Software"), to deal in the Software
+ * without restriction, including without limitation the rights to use, copy, modify,
+ * merge, publish, distribute, sublicense, and/or sell copies of the Software, and
+ * to permit persons to whom the Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all copies
+ * or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+ * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+ * FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include "clientgenerator.h"
+
+#include <google/protobuf/stubs/logging.h>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/io/zero_copy_stream.h>
+#include <google/protobuf/descriptor.h>
+
+#include <unordered_set>
+
+#include "utils.h"
+#include "templates.h"
+
+using namespace ::qtprotobuf::generator;
+using namespace ::google::protobuf;
+using namespace ::google::protobuf::compiler;
+
+ClientGenerator::ClientGenerator(const ServiceDescriptor *service, std::unique_ptr<io::ZeroCopyOutputStream> out) :
+    ServiceGeneratorBase(service, std::move(out))
+{
+    mClassName += "Client";
+}

+ 62 - 0
src/generator/clientgenerator.h

@@ -0,0 +1,62 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2019 Alexey Edelev <semlanik@gmail.com>, Tatyana Borisova <tanusshhka@mail.ru>
+ *
+ * This file is part of qtprotobuf project https://git.semlanik.org/semlanik/qtprotobuf
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this
+ * software and associated documentation files (the "Software"), to deal in the Software
+ * without restriction, including without limitation the rights to use, copy, modify,
+ * merge, publish, distribute, sublicense, and/or sell copies of the Software, and
+ * to permit persons to whom the Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all copies
+ * or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+ * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+ * FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#pragma once
+
+#include "servicegeneratorbase.h"
+#include <string>
+#include <memory>
+#include <google/protobuf/io/printer.h>
+
+namespace google { namespace protobuf {
+class ServiceDescriptor;
+class Message;
+}}
+
+namespace qtprotobuf {
+namespace generator {
+
+class ClientGenerator : public ServiceGeneratorBase
+{
+public:
+    ClientGenerator(const ::google::protobuf::ServiceDescriptor* service,
+                    std::unique_ptr<google::protobuf::io::ZeroCopyOutputStream> out);
+    ~ClientGenerator() = default;
+
+    void run() {
+        printPreamble();
+        printIncludes();
+        printNamespaces();
+        printClassName();
+        printPublic();
+        printMethodsDeclaration(Templates::ClientMethodDeclarationSyncTemplate, Templates::ClientMethodDeclarationAsyncTemplate);
+        encloseClass();
+        encloseNamespaces();
+    }
+};
+
+
+} //namespace generator
+} //namespace qtprotobuf

+ 66 - 0
src/generator/clientsourcegenerator.cpp

@@ -0,0 +1,66 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2019 Alexey Edelev <semlanik@gmail.com>, Tatyana Borisova <tanusshhka@mail.ru>
+ *
+ * This file is part of qtprotobuf project https://git.semlanik.org/semlanik/qtprotobuf
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this
+ * software and associated documentation files (the "Software"), to deal in the Software
+ * without restriction, including without limitation the rights to use, copy, modify,
+ * merge, publish, distribute, sublicense, and/or sell copies of the Software, and
+ * to permit persons to whom the Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all copies
+ * or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+ * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+ * FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include "clientsourcegenerator.h"
+
+#include <google/protobuf/io/zero_copy_stream.h>
+
+#include "utils.h"
+#include "templates.h"
+
+using namespace qtprotobuf::generator;
+using namespace ::google::protobuf;
+using namespace ::google::protobuf::compiler;
+
+ClientSourceGenerator::ClientSourceGenerator(const google::protobuf::ServiceDescriptor *service,
+                                             std::unique_ptr<google::protobuf::io::ZeroCopyOutputStream> out) :
+    ClassSourceGeneratorBase(service->full_name(), std::move(out))
+  , mService(service)
+{
+    mClassName += "Client";
+}
+
+void ClientSourceGenerator::printMethods()
+{
+    Indent();
+    for(int i = 0; i < mService->method_count(); i++) {
+        const MethodDescriptor* method = mService->method(i);
+        std::string inputTypeName = method->input_type()->full_name();
+        std::string outputTypeName = method->output_type()->full_name();
+        utils::replace(inputTypeName, ".", "::");
+        utils::replace(outputTypeName, ".", "::");
+        std::map<std::string, std::string> parameters = {{"classname", mClassName},
+                                                         {"return_type", outputTypeName},
+                                                         {"method_name", method->name()},
+                                                         {"param_type", inputTypeName},
+                                                         {"param_name", ""},
+                                                         {"return_name", ""}
+                                                        };
+        mPrinter.Print(parameters, Templates::ClientMethodDefinitionSyncTemplate);
+        mPrinter.Print(parameters, Templates::ClientMethodDefinitionAsyncTemplate);
+    }
+    Outdent();
+}
+

+ 52 - 0
src/generator/clientsourcegenerator.h

@@ -0,0 +1,52 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2019 Alexey Edelev <semlanik@gmail.com>, Tatyana Borisova <tanusshhka@mail.ru>
+ *
+ * This file is part of qtprotobuf project https://git.semlanik.org/semlanik/qtprotobuf
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this
+ * software and associated documentation files (the "Software"), to deal in the Software
+ * without restriction, including without limitation the rights to use, copy, modify,
+ * merge, publish, distribute, sublicense, and/or sell copies of the Software, and
+ * to permit persons to whom the Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all copies
+ * or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+ * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+ * FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#pragma once
+
+#include "classsourcegeneratorbase.h"
+
+namespace qtprotobuf {
+namespace generator {
+
+class ClientSourceGenerator : public ClassSourceGeneratorBase
+{
+public:
+    ClientSourceGenerator(const google::protobuf::ServiceDescriptor *service,
+                          std::unique_ptr<google::protobuf::io::ZeroCopyOutputStream> out);
+    void run() override {
+        printClassHeaderInclude();
+        printNamespaces();
+        printMethods();
+        encloseNamespaces();
+    }
+
+protected:
+    void printMethods();
+
+    const ::google::protobuf::ServiceDescriptor* mService;
+};
+
+} //namespace qtprotobuf
+} //namespace generator

+ 14 - 55
src/generator/generator.cpp

@@ -27,8 +27,11 @@
 #include "templates.h"
 #include "classgeneratorbase.h"
 #include "protobufclassgenerator.h"
+#include "protobufsourcegenerator.h"
 #include "globalenumsgenerator.h"
 #include "servergenerator.h"
+#include "clientgenerator.h"
+#include "clientsourcegenerator.h"
 #include "utils.h"
 
 #include <google/protobuf/stubs/logging.h>
@@ -41,58 +44,6 @@ using namespace ::qtprotobuf::generator;
 using namespace ::google::protobuf;
 using namespace ::google::protobuf::compiler;
 
-class QtSourcesGenerator : public ClassGeneratorBase
-{
-    const Descriptor* mMessage;
-public:
-    QtSourcesGenerator(const Descriptor *message, std::unique_ptr<io::ZeroCopyOutputStream> out) :
-        ClassGeneratorBase(message->full_name(), std::move(out))
-      , mMessage(message) {}
-
-    void run() {
-        printClassHeaderInclude();
-        printNamespaces();
-        printFieldsOrdering();
-        printRegisterBody();
-        encloseNamespaces();
-    }
-
-    void printClassHeaderInclude() {
-        std::string includeFileName = mClassName;
-        utils::tolower(includeFileName);
-        mPrinter.Print({{"type_lower", includeFileName}}, Templates::InternalIncludeTemplate);
-    }
-
-    void printFieldsOrdering() {
-        mPrinter.Print({{"type", mClassName}}, Templates::FieldsOrderingContainerTemplate);
-        Indent();
-        for (int i = 0; i < mMessage->field_count(); i++) {
-            const FieldDescriptor* field = mMessage->field(i);
-            if (i != 0) {
-                mPrinter.Print("\n,");
-            }
-            //property_number is incremented by 1 because user properties stating from 1.
-            //Property with index 0 is "objectName"
-            mPrinter.Print({{"field_number", std::to_string(field->number())},
-                            {"property_number", std::to_string(i + 1)}}, Templates::FieldOrderTemplate);
-        }
-        Outdent();
-        mPrinter.Print(Templates::SemicolonBlockEnclosureTemplate);
-    }
-
-    void printRegisterBody()
-    {
-        std::string namespaces;
-        for(size_t i = 0; i < mNamespaces.size(); i++) {
-            if(i > 0) {
-                namespaces = namespaces.append("::");
-            }
-            namespaces = namespaces.append(mNamespaces[i]);
-        }
-        mPrinter.Print({{"classname", mClassName}, {"namespaces", namespaces}}, Templates::ComplexTypeRegistrationTemplate);
-    }
-};
-
 bool QtGenerator::Generate(const FileDescriptor *file,
                            const std::string &/*parameter*/,
                            GeneratorContext *generatorContext,
@@ -119,7 +70,7 @@ bool QtGenerator::Generate(const FileDescriptor *file,
         extractedModels.insert(std::begin(models), std::end(models));
 
         std::string sourceFileName = baseFilename + ".cpp";
-        QtSourcesGenerator classSourceGen(message,
+        ProtobufSourceGenerator classSourceGen(message,
                                   std::move(std::unique_ptr<io::ZeroCopyOutputStream>(generatorContext->Open(sourceFileName))));
         classSourceGen.run();
     }
@@ -129,12 +80,20 @@ bool QtGenerator::Generate(const FileDescriptor *file,
         std::string baseFilename(service->name());
         utils::tolower(baseFilename);
 
-        std::string headeFilename = baseFilename + "server.h";
+        std::string fullFilename = baseFilename + "server.h";
         ServerGenerator serverGen(service,
-                                  std::move(std::unique_ptr<io::ZeroCopyOutputStream>(generatorContext->Open(headeFilename))));
+                                  std::move(std::unique_ptr<io::ZeroCopyOutputStream>(generatorContext->Open(fullFilename))));
         serverGen.run();
 
+        fullFilename = baseFilename + "client.h";
+        ClientGenerator clientGen(service,
+                                  std::move(std::unique_ptr<io::ZeroCopyOutputStream>(generatorContext->Open(fullFilename))));
+        clientGen.run();
 
+        fullFilename = baseFilename + "client.cpp";
+        ClientSourceGenerator clientSrcGen(service,
+                                  std::move(std::unique_ptr<io::ZeroCopyOutputStream>(generatorContext->Open(fullFilename))));
+        clientSrcGen.run();
     }
     return true;
 }

+ 71 - 0
src/generator/protobufsourcegenerator.cpp

@@ -0,0 +1,71 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2019 Alexey Edelev <semlanik@gmail.com>, Tatyana Borisova <tanusshhka@mail.ru>
+ *
+ * This file is part of qtprotobuf project https://git.semlanik.org/semlanik/qtprotobuf
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this
+ * software and associated documentation files (the "Software"), to deal in the Software
+ * without restriction, including without limitation the rights to use, copy, modify,
+ * merge, publish, distribute, sublicense, and/or sell copies of the Software, and
+ * to permit persons to whom the Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all copies
+ * or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+ * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+ * FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include "protobufsourcegenerator.h"
+
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/io/zero_copy_stream.h>
+
+using namespace qtprotobuf::generator;
+using namespace ::google::protobuf;
+using namespace ::google::protobuf::io;
+using namespace ::google::protobuf::compiler;
+
+ProtobufSourceGenerator::ProtobufSourceGenerator(const google::protobuf::Descriptor *message,
+                                                 std::unique_ptr<google::protobuf::io::ZeroCopyOutputStream> out) :
+    ClassSourceGeneratorBase(message->full_name(), std::move(out))
+  , mMessage(message)
+{
+
+}
+
+void ProtobufSourceGenerator::printRegisterBody()
+{
+    std::string namespaces;
+    for(size_t i = 0; i < mNamespaces.size(); i++) {
+        if(i > 0) {
+            namespaces = namespaces.append("::");
+        }
+        namespaces = namespaces.append(mNamespaces[i]);
+    }
+    mPrinter.Print({{"classname", mClassName}, {"namespaces", namespaces}}, Templates::ComplexTypeRegistrationTemplate);
+}
+
+void ProtobufSourceGenerator::printFieldsOrdering() {
+    mPrinter.Print({{"type", mClassName}}, Templates::FieldsOrderingContainerTemplate);
+    Indent();
+    for (int i = 0; i < mMessage->field_count(); i++) {
+        const FieldDescriptor* field = mMessage->field(i);
+        if (i != 0) {
+            mPrinter.Print("\n,");
+        }
+        //property_number is incremented by 1 because user properties stating from 1.
+        //Property with index 0 is "objectName"
+        mPrinter.Print({{"field_number", std::to_string(field->number())},
+                        {"property_number", std::to_string(i + 1)}}, Templates::FieldOrderTemplate);
+    }
+    Outdent();
+    mPrinter.Print(Templates::SemicolonBlockEnclosureTemplate);
+}

+ 51 - 0
src/generator/protobufsourcegenerator.h

@@ -0,0 +1,51 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2019 Alexey Edelev <semlanik@gmail.com>, Tatyana Borisova <tanusshhka@mail.ru>
+ *
+ * This file is part of qtprotobuf project https://git.semlanik.org/semlanik/qtprotobuf
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this
+ * software and associated documentation files (the "Software"), to deal in the Software
+ * without restriction, including without limitation the rights to use, copy, modify,
+ * merge, publish, distribute, sublicense, and/or sell copies of the Software, and
+ * to permit persons to whom the Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all copies
+ * or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+ * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+ * FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#pragma once
+
+#include "classsourcegeneratorbase.h"
+
+namespace qtprotobuf {
+namespace generator {
+
+class ProtobufSourceGenerator : public ClassSourceGeneratorBase
+{
+    const google::protobuf::Descriptor* mMessage;
+public:
+    ProtobufSourceGenerator(const google::protobuf::Descriptor *message, std::unique_ptr<google::protobuf::io::ZeroCopyOutputStream> out);
+    void printRegisterBody();
+    void printFieldsOrdering();
+
+    void run() override {
+        printClassHeaderInclude();
+        printNamespaces();
+        printFieldsOrdering();
+        printRegisterBody();
+        encloseNamespaces();
+    }
+};
+
+} //namespace qtprotobuf
+} //namespace generator

+ 2 - 0
src/generator/servergenerator.h

@@ -50,6 +50,8 @@ public:
         printIncludes();
         printNamespaces();
         printClassName();
+        printPublic();
+        printMethodsDeclaration(Templates::ServerMethodDeclarationTemplate);
         encloseClass();
         encloseNamespaces();
     }

+ 24 - 0
src/generator/servicegeneratorbase.cpp

@@ -51,6 +51,9 @@ ServiceGeneratorBase::ServiceGeneratorBase(const ::google::protobuf::ServiceDesc
 void ServiceGeneratorBase::printIncludes()
 {
     std::unordered_set<std::string> includeSet;
+
+    includeSet.insert("asyncreply");
+
     for(int i = 0; i < mService->method_count(); i++) {
         const MethodDescriptor* method = mService->method(i);
         std::string inputTypeName = method->input_type()->name();
@@ -70,3 +73,24 @@ void ServiceGeneratorBase::printClassName()
 {
     mPrinter.Print({{"classname", mClassName}}, Templates::NonProtoClassDefinitionTemplate);
 }
+
+void ServiceGeneratorBase::printMethodsDeclaration(const char* methodTemplate, const char* methodAsyncTemplate)
+{
+    Indent();
+    for(int i = 0; i < mService->method_count(); i++) {
+        const MethodDescriptor* method = mService->method(i);
+        std::string inputTypeName = method->input_type()->full_name();
+        std::string outputTypeName = method->output_type()->full_name();
+        utils::replace(inputTypeName, ".", "::");
+        utils::replace(outputTypeName, ".", "::");
+        std::map<std::string, std::string> parameters = {{"return_type", outputTypeName},
+                                                         {"method_name", method->name()},
+                                                         {"param_type", inputTypeName},
+                                                         {"param_name", ""},
+                                                         {"return_name", ""}
+                                                        };
+        mPrinter.Print(parameters, methodTemplate);
+        mPrinter.Print(parameters, methodAsyncTemplate);
+    }
+    Outdent();
+}

+ 1 - 0
src/generator/servicegeneratorbase.h

@@ -50,6 +50,7 @@ public:
 
     void printIncludes();
     void printClassName();
+    void printMethodsDeclaration(const char* methodTemplate, const char* methodAsyncTemplate = "");
 };
 
 } //namespace generator

+ 14 - 0
src/generator/templates.cpp

@@ -129,6 +129,20 @@ const char *Templates::DeclareComplexListTypeTemplate = "Q_DECLARE_METATYPE($nam
 
 const char *Templates::QEnumTemplate = "Q_ENUM($type$)\n";
 
+const char *Templates::ClientMethodDeclarationSyncTemplate = "Q_INVOKABLE void $method_name$(const $param_type$ &$param_name$, $return_type$ &$return_name$);\n";
+const char *Templates::ClientMethodDeclarationAsyncTemplate = "Q_INVOKABLE void $method_name$(const $param_type$ &$param_name$, const qtprotobuf::AsyncReply<$return_type$> &reply);\n";
+const char *Templates::ServerMethodDeclarationTemplate = "Q_INVOKABLE virtual $return_type$ $method_name$(const $param_type$ &$param_name$) = 0;\n";
+
+
+const char *Templates::ClientMethodDefinitionAsyncTemplate = "void $classname$::$method_name$(const $param_type$ &$param_name$, $return_type$ &$return_name$)\n"
+                                                        "{\n"
+                                                        "    //TODO: call transport method to serialize this method\n"
+                                                        "}\n";
+const char *Templates::ClientMethodDefinitionSyncTemplate = "void $classname$::$method_name$(const $param_type$ &$param_name$, const qtprotobuf::AsyncReply<$return_type$> &reply)\n"
+                                                        "{\n"
+                                                        "    //TODO: call transport method to serialize this method\n"
+                                                        "}\n";
+
 const std::unordered_map<::google::protobuf::FieldDescriptor::Type, std::string> Templates::TypeReflection = {
     {::google::protobuf::FieldDescriptor::TYPE_DOUBLE, "double"},
     {::google::protobuf::FieldDescriptor::TYPE_FLOAT, "float"},

+ 9 - 0
src/generator/templates.h

@@ -86,6 +86,15 @@ public:
     static const char *DeclareMetaTypeTemplate;
     static const char *DeclareComplexListTypeTemplate;
     static const char *QEnumTemplate;
+
+    //Service templates
+    static const char *ClientMethodDeclarationSyncTemplate;
+    static const char *ClientMethodDeclarationAsyncTemplate;
+    static const char *ServerMethodDeclarationTemplate;
+
+    static const char *ClientMethodDefinitionSyncTemplate;
+    static const char *ClientMethodDefinitionAsyncTemplate;
+
     static const std::unordered_map<::google::protobuf::FieldDescriptor::Type, std::string> TypeReflection;
 };
 

+ 4 - 2
src/lib/CMakeLists.txt

@@ -16,13 +16,15 @@ file(GLOB SOURCES universallistmodelbase.cpp
     universallistmodel.cpp
     protobufobject.cpp
     qtprotobuf.cpp
-    qtprotobuflogging.cpp)
+    qtprotobuflogging.cpp
+    asyncreply.cpp)
 
 file(GLOB HEADERS universallistmodelbase.h
     universallistmodel.h
     protobufobject.h
     qtprotobuftypes.h
-    qtprotobuf.h)
+    qtprotobuf.h
+    asyncreply.h)
 
 add_library(${SUPPORT_LIBRARY_TARGET} ${SOURCES})
 set_target_properties(${SUPPORT_LIBRARY_TARGET} PROPERTIES PUBLIC_HEADER "${HEADERS}")

+ 2 - 0
src/lib/asyncreply.cpp

@@ -0,0 +1,2 @@
+#include "asyncreply.h"
+

+ 68 - 0
src/lib/asyncreply.h

@@ -0,0 +1,68 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2019 Alexey Edelev <semlanik@gmail.com>
+ *
+ * This file is part of qtprotobuf project https://git.semlanik.org/semlanik/qtprotobuf
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this
+ * software and associated documentation files (the "Software"), to deal in the Software
+ * without restriction, including without limitation the rights to use, copy, modify,
+ * merge, publish, distribute, sublicense, and/or sell copies of the Software, and
+ * to permit persons to whom the Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all copies
+ * or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+ * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+ * FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#pragma once
+
+#include <functional>
+
+namespace qtprotobuf {
+
+template <typename M>
+class AsyncReply final
+{
+    AsyncReply();
+public:
+    AsyncReply(const std::function<void(const M&)> &callback) : m_callback(callback) {}
+    AsyncReply(AsyncReply &&other) {
+        m_callback = std::move(other.m_callback);
+    }
+
+    AsyncReply(const AsyncReply &other) {
+        m_callback = other.m_callback;
+    }
+
+    AsyncReply& operator=(AsyncReply &&other) {
+        m_callback = std::move(other.m_callback);
+        return *this;
+    }
+
+    AsyncReply& operator=(const AsyncReply &other) {
+        m_callback = other.m_callback;
+        return *this;
+    }
+
+    ~AsyncReply() {}
+
+    void operator()(const M& value) {
+        if (m_callback) {
+            m_callback(value);
+        }
+    }
+
+private:
+    std::function<void(const M&)> m_callback;
+};
+
+}

+ 2 - 1
tests/CMakeLists.txt

@@ -45,7 +45,8 @@ file(GLOB SOURCES main.cpp
     simpletest.cpp
     serializationtest.cpp
     deserializationtest.cpp
-    servertest.cpp)
+    servertest.cpp
+    clienttest.cpp)
 
 file(GLOB PROTOS proto/*.proto)
 

+ 43 - 0
tests/clienttest.cpp

@@ -0,0 +1,43 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2019 Alexey Edelev <semlanik@gmail.com>
+ *
+ * This file is part of qtprotobuf project https://git.semlanik.org/semlanik/qtprotobuf
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this
+ * software and associated documentation files (the "Software"), to deal in the Software
+ * without restriction, including without limitation the rights to use, copy, modify,
+ * merge, publish, distribute, sublicense, and/or sell copies of the Software, and
+ * to permit persons to whom the Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all copies
+ * or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+ * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+ * FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include "clienttest.h"
+
+#include "testserviceclient.h"
+
+using namespace qtprotobufnamespace::tests;
+using namespace qtprotobuf::tests;
+
+using namespace qtprotobuf;
+
+ClientTest::ClientTest()
+{
+
+}
+
+TEST_F(ClientTest, CheckMethodsGeneration)
+{
+    TestServiceClient testClient;
+}

+ 40 - 0
tests/clienttest.h

@@ -0,0 +1,40 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2019 Alexey Edelev <semlanik@gmail.com>
+ *
+ * This file is part of qtprotobuf project https://git.semlanik.org/semlanik/qtprotobuf
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this
+ * software and associated documentation files (the "Software"), to deal in the Software
+ * without restriction, including without limitation the rights to use, copy, modify,
+ * merge, publish, distribute, sublicense, and/or sell copies of the Software, and
+ * to permit persons to whom the Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all copies
+ * or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+ * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+ * FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#pragma once
+
+#include <gtest/gtest.h>
+
+namespace qtprotobuf {
+namespace tests {
+
+class ClientTest : public ::testing::Test
+{
+public:
+    ClientTest();
+};
+
+} //namespace tests
+} //namespace qtprotobuf

+ 1 - 1
tests/proto/testservice.proto

@@ -5,5 +5,5 @@ import "simpletest.proto";
 package qtprotobufnamespace.tests;
 
 service TestService {
-  rpc TestMethod (SimpleIntMessage) returns (SimpleIntMessage) {}
+  rpc testMethod (SimpleIntMessage) returns (SimpleIntMessage) {}
 } 

+ 9 - 0
tests/serializationtest.cpp

@@ -1500,3 +1500,12 @@ TEST_F(SerializationTest, BoolMessageSerializeTest)
     ASSERT_EQ(0, result.size());
     ASSERT_TRUE(result == QByteArray::fromHex(""));
 }
+
+//TEST_F(SerializationTest, DISABLE_BenchmarkTest)
+//{
+//    SimpleIntMessage msg;
+//    for(int i = INT16_MIN; i < INT16_MAX; i++) {
+//        msg.setTestFieldInt(i);
+//        msg.serialize();
+//    }
+//}

+ 5 - 1
tests/servertest.cpp

@@ -32,11 +32,15 @@ using namespace qtprotobuf::tests;
 
 using namespace qtprotobuf;
 
+class TestServiceServerImpl : public TestServiceServer {
+    SimpleIntMessage testMethod(const SimpleIntMessage &) override { return SimpleIntMessage(); }
+};
+
 ServerTest::ServerTest()
 {
 }
 
 TEST_F(ServerTest, CheckMethodsGeneration)
 {
-    TestServiceServer testServer;
+    TestServiceServerImpl testServer;
 }

+ 2 - 2
tests/servertest.h

@@ -36,5 +36,5 @@ public:
     ServerTest();
 };
 
-}
-}
+} //namespace tests
+} //namespace qtprotobuf