ソースを参照

Added demo code converting proto files into json debug output.

Bart Hertog 7 年 前
コミット
bde7cd1f22
3 ファイル変更119 行追加0 行削除
  1. 13 0
      protoc-gen-eams
  2. 81 0
      protoc-gen-eams.py
  3. 25 0
      test/proto/state.proto

+ 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

+ 81 - 0
protoc-gen-eams.py

@@ -0,0 +1,81 @@
+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)
+
+
+if __name__ == '__main__':
+    # Read request message from stdin
+    data = io.open(sys.stdin.fileno(), "rb").read()
+    request = plugin.CodeGeneratorRequest.FromString(data)
+
+    # 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())

+ 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;
+}