Browse Source

Merged in feature/PROTO-1-create-the-project-setup (pull request #1)

Feature/PROTO-1 create the project setup
Bart Hertog 6 years ago
parent
commit
8c727a2442
7 changed files with 277 additions and 0 deletions
  1. 22 0
      .gitignore
  2. 13 0
      protoc-gen-eams
  3. 113 0
      protoc-gen-eams.py
  4. 2 0
      requirements.txt
  5. 62 0
      src/MessageInterface.h
  6. 40 0
      src/MessageNanopbTemplate.h
  7. 25 0
      test/proto/state.proto

+ 22 - 0
.gitignore

@@ -0,0 +1,22 @@
+
+# Ignore the python virtualenv
+venv/*
+
+# User-specific stuff
+.idea/**/workspace.xml
+.idea/**/tasks.xml
+.idea/**/usage.statistics.xml
+.idea/**/dictionaries
+.idea/**/shelf
+
+# Generated files
+.idea/**/contentModel.xml
+
+# Sensitive or high-churn files
+.idea/**/dataSources/
+.idea/**/dataSources.ids
+.idea/**/dataSources.local.xml
+.idea/**/sqlDataSources.xml
+.idea/**/dynamic.xml
+.idea/**/uiDesigner.xml
+.idea/**/dbnavigator.xml

+ 13 - 0
protoc-gen-eams

@@ -0,0 +1,13 @@
+#!/bin/sh
+
+# This file is used to invoke protoc-gen-eams.py as a plugin
+# to protoc on Linux and other *nix-style systems.
+# Use it like this:
+# protoc --plugin=protoc-gen-nanopb=..../protoc-gen-nanopb --nanopb_out=dir foo.proto
+#
+# Note that if you use the binary package of nanopb, the protoc
+# path is already set up properly and there is no need to give
+# --plugin= on the command line.
+
+
+./venv/bin/python protoc-gen-eams.py --protoc-plugin

+ 113 - 0
protoc-gen-eams.py

@@ -0,0 +1,113 @@
+import io
+import sys
+import itertools
+import json
+
+from google.protobuf.compiler import plugin_pb2 as plugin
+from google.protobuf.descriptor_pb2 import DescriptorProto, EnumDescriptorProto
+
+
+def traverse(proto_file):
+
+    def _traverse(package, items):
+        for item in items:
+            yield item, package
+
+            if isinstance(item, DescriptorProto):
+                for enum in item.enum_type:
+                    yield enum, package
+
+                for nested in item.nested_type:
+                    nested_package = package + item.name
+
+                    for nested_item in _traverse(nested, nested_package):
+                        yield nested_item, nested_package
+
+    return itertools.chain(
+        _traverse(proto_file.package, proto_file.enum_type),
+        _traverse(proto_file.package, proto_file.message_type),
+    )
+
+
+def generate_json(request, response):
+    for proto_file in request.proto_file:
+        json_output = []
+
+        # Parse request
+        for item, package in traverse(proto_file):
+            data = {
+                'package': proto_file.package or '<root>',
+                'filename': proto_file.name,
+                'name': item.name,
+            }
+
+            if isinstance(item, DescriptorProto):
+                data.update({
+                    'type': 'Message',
+                    'properties': [{'name': f.name, 'type': int(f.type)}
+                                   for f in item.field]
+                })
+
+            elif isinstance(item, EnumDescriptorProto):
+                data.update({
+                    'type': 'Enum',
+                    'values': [{'name': v.name, 'value': v.number}
+                               for v in item.value]
+                })
+
+            json_output.append(data)
+
+        # Fill response
+        f = response.file.add()
+        f.name = proto_file.name + '.json'
+        f.content = json.dumps(json_output, indent=2)
+
+
+def main_plugin():
+    # Read request message from stdin
+    data = io.open(sys.stdin.fileno(), "rb").read()
+    request = plugin.CodeGeneratorRequest.FromString(data)
+
+    # Write the requests to a file for easy debugging.
+    with open("debug_request.bin", 'wb') as file:
+        file.write(request.SerializeToString())
+
+    # Create response
+    response = plugin.CodeGeneratorResponse()
+
+    # Generate code
+    generate_json(request, response)
+
+    # Serialise response message
+    output = response.SerializeToString()
+
+    # Write to stdout
+    io.open(sys.stdout.fileno(), "wb").write(response.SerializeToString())
+
+
+def main_cli():
+    with open("debug_request.bin", 'rb') as file:
+        data = file.read()
+        request = plugin.CodeGeneratorRequest.FromString(data)
+
+        # Create response
+        response = plugin.CodeGeneratorResponse()
+
+        # Generate code
+        generate_json(request, response)
+
+        # Serialise response message
+        output = response.SerializeToString()
+
+        print(output)
+
+
+if __name__ == '__main__':
+    # Check if we are running as a plugin under protoc
+    if '--protoc-plugin' in sys.argv:
+        main_plugin()
+    else:
+        main_cli()
+
+
+# protoc --plugin=protoc-gen-eams=protoc-gen-eams.sh --eams_out=./build ./test/proto/state.proto

+ 2 - 0
requirements.txt

@@ -0,0 +1,2 @@
+protobuf==3.6.1
+six==1.12.0

+ 62 - 0
src/MessageInterface.h

@@ -0,0 +1,62 @@
+
+
+#ifndef _MESSAGE_INTERFACE_H_
+#define _MESSAGE_INTERFACE_H_
+
+#include <cstdint>
+
+namespace EmbeddedProto {
+
+class MessageInterface {
+public:
+    enum class Result {
+        OK,
+        ERROR_BUFFER_TO_SMALL,
+    }
+
+    //! This default constructor clears the message data into its default state.
+    MessageInterface() {
+        clear();
+    };
+
+    ~MessageInterface() = default;
+
+    //! Function to serialize this message.
+    /*!
+        The data this message holds will be serialized into an byte array.
+
+        \param buffer [out] The array of bytes into which the message will be serialized.
+        \param length [in]  The number of bytes in the buffer array.
+
+        \return An enum value indicating successful operation of this function or an error.
+    */
+    virtual Result serialize(uint8_t* buffer, uint32_t length) const = 0;
+
+    //! Function to deserialize this message.
+    /*!
+        From an array of date fill this message object with data.
+
+        \param buffer [in]  The array of bytes into which the message will be serialized.
+        \param length [in]  The number of bytes in the buffer array.
+
+        \return An enum value indicating successful operation of this function or an error.
+    */
+    virtual Result deserialize(const uint8_t* buffer, uint32_t length) = 0;
+
+    //! Clear the content of this message and set it to it's default state.
+    /*!
+        The defaults are to be set according to the Protobuf standard.
+    */
+    virtual void clear() = 0;
+
+protected:
+
+
+private:
+
+
+};
+
+} // End of namespace EmbeddedProto
+
+#endif // _MESSAGE_INTERFACE_H_

+ 40 - 0
src/MessageNanopbTemplate.h

@@ -0,0 +1,40 @@
+
+#ifndef _MESSAGE_NANOPB_TEMPLATE_H_
+#define _MESSAGE_NANOPB_TEMPLATE_H_
+
+#include <MessageInterface.h>
+
+namespace EmbeddedProto {
+
+template<class NANOPB_STRUCT>
+class MessageNanopbTemplate : public EmbeddedProto
+{
+public:
+    MessageNanopbTemplate() = default;
+    ~MessageNanopbTemplate() = default;
+
+
+    NANOPB_STRUCT& get() {
+        return data;
+    }
+
+    NANOPB_STRUCT& get() const {
+        return data;
+    }
+
+    NANOPB_STRUCT* operator ->() {
+        return &data;
+    }
+
+protected:
+
+    //! The actual message struct as used by nanopb.
+    NANOPB_STRUCT data;
+
+private:
+
+}
+
+} // End of namespace EmbeddedProto
+
+#endif _MESSAGE_NANOPB_TEMPLATE_H_

+ 25 - 0
test/proto/state.proto

@@ -0,0 +1,25 @@
+
+syntax = "proto3";
+
+enum State {
+    READY   = 0;
+    SET     = 1;
+    GO      = 2;
+}
+
+message Position {
+    int32 x = 1;
+    int32 y = 2;
+    int32 z = 3;
+}
+
+message Velocity {
+    float u = 1;
+    float v = 2;
+    float w = 3;
+}
+
+message Object {
+    Position pos = 1;
+    Velocity vel = 2;
+}