EmbeddedProto 4.0.0.dev19__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- EmbeddedProto/EmbeddedProto.py +63 -0
- EmbeddedProto/Field.py +578 -0
- EmbeddedProto/Oneof.py +78 -0
- EmbeddedProto/ProtoFile.py +188 -0
- EmbeddedProto/TypeDefinitions.py +255 -0
- EmbeddedProto/__init__.py +0 -0
- EmbeddedProto/__main__.py +35 -0
- EmbeddedProto/embedded_proto_options_pb2.py +37 -0
- EmbeddedProto/main.py +199 -0
- EmbeddedProto/templates/FieldBasic_Deserialize.h.jinja2 +33 -0
- EmbeddedProto/templates/FieldBasic_GetSet.h.jinja2 +92 -0
- EmbeddedProto/templates/FieldBasic_Serialize.h.jinja2 +37 -0
- EmbeddedProto/templates/FieldBytes_GetSet.h.jinja2 +86 -0
- EmbeddedProto/templates/FieldEnum_Deserialize.h.jinja2 +33 -0
- EmbeddedProto/templates/FieldEnum_GetSet.h.jinja2 +86 -0
- EmbeddedProto/templates/FieldEnum_Serialize.h.jinja2 +37 -0
- EmbeddedProto/templates/FieldErrorRecursive_GetSet.h.jinja2 +36 -0
- EmbeddedProto/templates/FieldMsg_Deserialize.h.jinja2 +33 -0
- EmbeddedProto/templates/FieldMsg_GetSet.h.jinja2 +100 -0
- EmbeddedProto/templates/FieldMsg_Serialize.h.jinja2 +37 -0
- EmbeddedProto/templates/FieldRepeated_GetSet.h.jinja2 +95 -0
- EmbeddedProto/templates/FieldRepeated_Serialize.h.jinja2 +33 -0
- EmbeddedProto/templates/FieldStringBytes_Serialize.h.jinja2 +37 -0
- EmbeddedProto/templates/FieldString_GetSet.h.jinja2 +86 -0
- EmbeddedProto/templates/Header.h.jinja2 +75 -0
- EmbeddedProto/templates/TypeDefEnum.h.jinja2 +35 -0
- EmbeddedProto/templates/TypeDefMsg.h.jinja2 +473 -0
- EmbeddedProto/templates/TypeOneof.h.jinja2 +180 -0
- EmbeddedProto/version.json +3 -0
- EmbeddedProto-4.0.0.dev19.dist-info/METADATA +210 -0
- EmbeddedProto-4.0.0.dev19.dist-info/RECORD +34 -0
- EmbeddedProto-4.0.0.dev19.dist-info/WHEEL +5 -0
- EmbeddedProto-4.0.0.dev19.dist-info/entry_points.txt +3 -0
- EmbeddedProto-4.0.0.dev19.dist-info/top_level.txt +1 -0
EmbeddedProto/Oneof.py
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Copyright (C) 2020-2024 Embedded AMS B.V. - All Rights Reserved
|
|
3
|
+
#
|
|
4
|
+
# This file is part of Embedded Proto.
|
|
5
|
+
#
|
|
6
|
+
# Embedded Proto is open source software: you can redistribute it and/or
|
|
7
|
+
# modify it under the terms of the GNU General Public License as published
|
|
8
|
+
# by the Free Software Foundation, version 3 of the license.
|
|
9
|
+
#
|
|
10
|
+
# Embedded Proto is distributed in the hope that it will be useful,
|
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
13
|
+
# GNU General Public License for more details.
|
|
14
|
+
#
|
|
15
|
+
# You should have received a copy of the GNU General Public License
|
|
16
|
+
# along with Embedded Proto. If not, see <https://www.gnu.org/licenses/>.
|
|
17
|
+
#
|
|
18
|
+
# For commercial and closed source application please visit:
|
|
19
|
+
# <https://embeddedproto.com/pricing/>.
|
|
20
|
+
#
|
|
21
|
+
# Embedded AMS B.V.
|
|
22
|
+
# Info:
|
|
23
|
+
# info at EmbeddedProto dot com
|
|
24
|
+
#
|
|
25
|
+
# Postal address:
|
|
26
|
+
# Atoomweg 2
|
|
27
|
+
# 1627 LE, Hoorn
|
|
28
|
+
# the Netherlands
|
|
29
|
+
#
|
|
30
|
+
|
|
31
|
+
from .Field import Field
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class Oneof:
|
|
35
|
+
def __init__(self, oneof_proto_descriptor, index, msg_descriptor, parent_msg):
|
|
36
|
+
# A reference to the OneofDescriptorProto object which defines this field.
|
|
37
|
+
self.descriptor = oneof_proto_descriptor
|
|
38
|
+
|
|
39
|
+
# A reference to the parent message in which this oneof is defined.
|
|
40
|
+
self.parent = parent_msg
|
|
41
|
+
|
|
42
|
+
self.fields = []
|
|
43
|
+
# Loop over all the fields in this oneof
|
|
44
|
+
for f in msg_descriptor.field:
|
|
45
|
+
if f.HasField('oneof_index') and index == f.oneof_index:
|
|
46
|
+
new_field = Field.factory(f, self.parent, oneof=self)
|
|
47
|
+
self.fields.append(new_field)
|
|
48
|
+
|
|
49
|
+
def get_name(self):
|
|
50
|
+
return self.descriptor.name
|
|
51
|
+
|
|
52
|
+
def get_variable_name(self):
|
|
53
|
+
return self.get_name() + "_"
|
|
54
|
+
|
|
55
|
+
def get_which_oneof(self):
|
|
56
|
+
return "which_" + self.get_name() + "_"
|
|
57
|
+
|
|
58
|
+
def get_fields(self):
|
|
59
|
+
return self.fields
|
|
60
|
+
|
|
61
|
+
def match_field_with_definitions(self, all_types_definitions):
|
|
62
|
+
for field in self.fields:
|
|
63
|
+
field.match_field_with_definitions(all_types_definitions)
|
|
64
|
+
|
|
65
|
+
def register_template_parameters(self):
|
|
66
|
+
all_parameters_registered = True
|
|
67
|
+
for field in self.fields:
|
|
68
|
+
all_parameters_registered = field.register_template_parameters() and all_parameters_registered
|
|
69
|
+
return all_parameters_registered
|
|
70
|
+
|
|
71
|
+
# Returns true if in oneof.init the new& function needs to be call to initialize already allocated memory.
|
|
72
|
+
def oneof_allocation_required(self):
|
|
73
|
+
result = False
|
|
74
|
+
for field in self.fields:
|
|
75
|
+
result = field.oneof_allocation_required()
|
|
76
|
+
if result:
|
|
77
|
+
break
|
|
78
|
+
return result
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Copyright (C) 2020-2024 Embedded AMS B.V. - All Rights Reserved
|
|
3
|
+
#
|
|
4
|
+
# This file is part of Embedded Proto.
|
|
5
|
+
#
|
|
6
|
+
# Embedded Proto is open source software: you can redistribute it and/or
|
|
7
|
+
# modify it under the terms of the GNU General Public License as published
|
|
8
|
+
# by the Free Software Foundation, version 3 of the license.
|
|
9
|
+
#
|
|
10
|
+
# Embedded Proto is distributed in the hope that it will be useful,
|
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
13
|
+
# GNU General Public License for more details.
|
|
14
|
+
#
|
|
15
|
+
# You should have received a copy of the GNU General Public License
|
|
16
|
+
# along with Embedded Proto. If not, see <https://www.gnu.org/licenses/>.
|
|
17
|
+
#
|
|
18
|
+
# For commercial and closed source application please visit:
|
|
19
|
+
# <https://embeddedproto.com/pricing/>.
|
|
20
|
+
#
|
|
21
|
+
# Embedded AMS B.V.
|
|
22
|
+
# Info:
|
|
23
|
+
# info at EmbeddedProto dot com
|
|
24
|
+
#
|
|
25
|
+
# Postal address:
|
|
26
|
+
# Atoomweg 2
|
|
27
|
+
# 1627 LE, Hoorn
|
|
28
|
+
# the Netherlands
|
|
29
|
+
#
|
|
30
|
+
|
|
31
|
+
from .TypeDefinitions import *
|
|
32
|
+
import os
|
|
33
|
+
from toposort import CircularDependencyError, toposort_flatten
|
|
34
|
+
from google.protobuf.descriptor_pb2 import FieldDescriptorProto
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
# -----------------------------------------------------------------------------
|
|
38
|
+
|
|
39
|
+
def toposort_add_msg(msg, namespace, dependency_data):
|
|
40
|
+
|
|
41
|
+
local_definitions = []
|
|
42
|
+
local_namespace = namespace + "." + msg.name
|
|
43
|
+
|
|
44
|
+
dependencies = {namespace}
|
|
45
|
+
|
|
46
|
+
for nested_msg in msg.nested_type:
|
|
47
|
+
dependency_data = toposort_add_msg(nested_msg, local_namespace, dependency_data)
|
|
48
|
+
full_msg_type = local_namespace + "." + nested_msg.name
|
|
49
|
+
local_definitions.append(full_msg_type)
|
|
50
|
+
for dep in dependency_data[full_msg_type]:
|
|
51
|
+
# Add requirements on other namespaces.
|
|
52
|
+
if not dep.startswith(local_namespace):
|
|
53
|
+
dependencies.add(dep)
|
|
54
|
+
|
|
55
|
+
for nested_enum in msg.enum_type:
|
|
56
|
+
full_enum_type = local_namespace + "." + nested_enum.name
|
|
57
|
+
dependency_data[full_enum_type] = {local_namespace}
|
|
58
|
+
local_definitions.append(full_enum_type)
|
|
59
|
+
|
|
60
|
+
for f in msg.field:
|
|
61
|
+
if ((FieldDescriptorProto.TYPE_MESSAGE == f.type) or (FieldDescriptorProto.TYPE_ENUM == f.type)) \
|
|
62
|
+
and (f.type_name not in local_definitions):
|
|
63
|
+
dependencies.add(f.type_name)
|
|
64
|
+
|
|
65
|
+
# If we have any dependencies add them
|
|
66
|
+
if 0 < len(dependencies):
|
|
67
|
+
dependency_data[local_namespace] = dependencies
|
|
68
|
+
|
|
69
|
+
return dependency_data
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
# -----------------------------------------------------------------------------
|
|
73
|
+
|
|
74
|
+
class ProtoFile:
|
|
75
|
+
def __init__(self, proto_descriptor):
|
|
76
|
+
self.descriptor = proto_descriptor
|
|
77
|
+
|
|
78
|
+
if "proto2" == proto_descriptor.syntax:
|
|
79
|
+
raise Exception(proto_descriptor.name + ": Sorry, proto2 is not supported, please use proto3.")
|
|
80
|
+
|
|
81
|
+
# These file names are the ones used for creating the C++ files.
|
|
82
|
+
self.filename_with_folder = os.path.splitext(proto_descriptor.name)[0]
|
|
83
|
+
self.filename_without_folder = os.path.basename(self.filename_with_folder)
|
|
84
|
+
|
|
85
|
+
# Construct the base scope used in this file.
|
|
86
|
+
self.scope = None
|
|
87
|
+
if self.descriptor.package:
|
|
88
|
+
package_list = self.descriptor.package.split(".")
|
|
89
|
+
# The first element is the base scope.
|
|
90
|
+
self.scope = Scope(package_list[0], None)
|
|
91
|
+
# Next add additional scopes nesting the previous one.
|
|
92
|
+
for package in package_list[1:]:
|
|
93
|
+
self.scope = Scope(package, self.scope)
|
|
94
|
+
|
|
95
|
+
self.enum_definitions = [EnumDefinition(enum, self.scope) for enum in self.descriptor.enum_type]
|
|
96
|
+
self.msg_definitions = [MessageDefinition(msg, self.scope) for msg in self.descriptor.message_type]
|
|
97
|
+
|
|
98
|
+
self.all_parameters_registered = False
|
|
99
|
+
|
|
100
|
+
# Sort the message definitions such that the dependencies work out.
|
|
101
|
+
dependency_data = {}
|
|
102
|
+
toposort_namespace = ""
|
|
103
|
+
if self.descriptor.package:
|
|
104
|
+
toposort_namespace = "." + self.descriptor.package
|
|
105
|
+
|
|
106
|
+
for msg in self.descriptor.message_type:
|
|
107
|
+
dependency_data = toposort_add_msg(msg, toposort_namespace, dependency_data)
|
|
108
|
+
|
|
109
|
+
try:
|
|
110
|
+
# Sort the message in the order they should appear in the code.
|
|
111
|
+
message_order = toposort_flatten(dependency_data)
|
|
112
|
+
|
|
113
|
+
# If we are in a namespace this appears in the list and should be removed.
|
|
114
|
+
my_scope = ""
|
|
115
|
+
if self.scope and (0 < len(message_order)):
|
|
116
|
+
my_scope = "." + self.scope.get_scope_str().replace("::", ".")
|
|
117
|
+
message_order.remove(my_scope)
|
|
118
|
+
|
|
119
|
+
# Based on the desired order assign each message definition an index.
|
|
120
|
+
for index, msg_name in enumerate(message_order):
|
|
121
|
+
for msg_def in self.msg_definitions:
|
|
122
|
+
if msg_def.name == msg_name.replace(my_scope + ".", ''):
|
|
123
|
+
msg_def.sorted_index = index
|
|
124
|
+
break
|
|
125
|
+
|
|
126
|
+
# Next sort the messages based on their index.
|
|
127
|
+
self.msg_definitions.sort(key=lambda msg: msg.sorted_index)
|
|
128
|
+
|
|
129
|
+
# Sort al the nested message definitions.
|
|
130
|
+
for msg in self.msg_definitions:
|
|
131
|
+
msg.sort_nested_msg_definitions(message_order)
|
|
132
|
+
|
|
133
|
+
except CircularDependencyError as e:
|
|
134
|
+
raise Exception("There are possible circular dependencies in the message definitions of "
|
|
135
|
+
+ proto_descriptor.name + ". Embedded Proto is not able to support this. "
|
|
136
|
+
"Please remove these dependencies.")
|
|
137
|
+
|
|
138
|
+
def get_dependencies(self):
|
|
139
|
+
imported_dependencies = []
|
|
140
|
+
if self.descriptor.dependency:
|
|
141
|
+
imported_dependencies = [os.path.splitext(dependency)[0] + ".h" for dependency in
|
|
142
|
+
self.descriptor.dependency if "embedded_proto_options.proto" not in dependency]
|
|
143
|
+
return imported_dependencies
|
|
144
|
+
|
|
145
|
+
def get_namespaces(self):
|
|
146
|
+
if self.scope:
|
|
147
|
+
result = self.scope.get_list_of_scope_str()
|
|
148
|
+
else:
|
|
149
|
+
result = []
|
|
150
|
+
return result
|
|
151
|
+
|
|
152
|
+
def get_header_guard(self):
|
|
153
|
+
return self.filename_with_folder.replace("/", "_").upper()
|
|
154
|
+
|
|
155
|
+
# Obtain a dictionary with references to all nested enums and messages
|
|
156
|
+
def get_all_nested_types(self):
|
|
157
|
+
nested_types = {"enums": [], "messages": []}
|
|
158
|
+
nested_types["enums"].extend(self.enum_definitions)
|
|
159
|
+
for msg in self.msg_definitions:
|
|
160
|
+
nt = msg.get_all_nested_types()
|
|
161
|
+
nested_types["enums"].extend(nt["enums"])
|
|
162
|
+
nested_types["messages"].extend(nt["messages"])
|
|
163
|
+
nested_types["messages"].append(msg)
|
|
164
|
+
|
|
165
|
+
return nested_types
|
|
166
|
+
|
|
167
|
+
def match_fields_with_definitions(self, all_types_definitions):
|
|
168
|
+
for msg in self.msg_definitions:
|
|
169
|
+
msg.match_fields_with_definitions(all_types_definitions)
|
|
170
|
+
|
|
171
|
+
def register_template_parameters(self):
|
|
172
|
+
all_parameters_registered = True
|
|
173
|
+
for msg in self.msg_definitions:
|
|
174
|
+
all_parameters_registered = msg.register_template_parameters() and all_parameters_registered
|
|
175
|
+
return all_parameters_registered
|
|
176
|
+
|
|
177
|
+
def render(self, jinja_environment):
|
|
178
|
+
template_file = "Header.h.jinja2"
|
|
179
|
+
template = jinja_environment.get_template(template_file)
|
|
180
|
+
file_str = template.render(proto_file=self, environment=jinja_environment)
|
|
181
|
+
return file_str
|
|
182
|
+
|
|
183
|
+
def print_template_data(self, indent):
|
|
184
|
+
print(indent + "File: " + self.filename_without_folder)
|
|
185
|
+
if self.msg_definitions:
|
|
186
|
+
for msg in self.msg_definitions:
|
|
187
|
+
msg.print_template_data(indent + "\t")
|
|
188
|
+
|
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Copyright (C) 2020-2024 Embedded AMS B.V. - All Rights Reserved
|
|
3
|
+
#
|
|
4
|
+
# This file is part of Embedded Proto.
|
|
5
|
+
#
|
|
6
|
+
# Embedded Proto is open source software: you can redistribute it and/or
|
|
7
|
+
# modify it under the terms of the GNU General Public License as published
|
|
8
|
+
# by the Free Software Foundation, version 3 of the license.
|
|
9
|
+
#
|
|
10
|
+
# Embedded Proto is distributed in the hope that it will be useful,
|
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
13
|
+
# GNU General Public License for more details.
|
|
14
|
+
#
|
|
15
|
+
# You should have received a copy of the GNU General Public License
|
|
16
|
+
# along with Embedded Proto. If not, see <https://www.gnu.org/licenses/>.
|
|
17
|
+
#
|
|
18
|
+
# For commercial and closed source application please visit:
|
|
19
|
+
# <https://embeddedproto.com/pricing/>.
|
|
20
|
+
#
|
|
21
|
+
# Embedded AMS B.V.
|
|
22
|
+
# Info:
|
|
23
|
+
# info at EmbeddedProto dot com
|
|
24
|
+
#
|
|
25
|
+
# Postal address:
|
|
26
|
+
# Atoomweg 2
|
|
27
|
+
# 1627 LE, Hoorn
|
|
28
|
+
# the Netherlands
|
|
29
|
+
#
|
|
30
|
+
|
|
31
|
+
from .Field import Field
|
|
32
|
+
from .Oneof import Oneof
|
|
33
|
+
import jinja2
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
# This class deal with the scope in which definitions and field are located. It is used to keep track of template
|
|
37
|
+
# parameters required for a given scope.
|
|
38
|
+
class Scope:
|
|
39
|
+
def __init__(self, scope_name, parent):
|
|
40
|
+
# The name of this scope/namespace
|
|
41
|
+
self.name = scope_name
|
|
42
|
+
|
|
43
|
+
# A reference to the scope above this scope. If we are at the top level this will be None.
|
|
44
|
+
self.parent = parent
|
|
45
|
+
|
|
46
|
+
# Start of without any children.
|
|
47
|
+
self.child_scopes = []
|
|
48
|
+
|
|
49
|
+
# Register this object with it's parent.
|
|
50
|
+
if self.parent:
|
|
51
|
+
self.parent.child_scopes.append(self)
|
|
52
|
+
|
|
53
|
+
self.fields_with_templates = []
|
|
54
|
+
|
|
55
|
+
# This function is used
|
|
56
|
+
def get_list_of_scope_str(self):
|
|
57
|
+
if self.parent:
|
|
58
|
+
result = self.parent.get_list_of_scope_str()
|
|
59
|
+
result.append(self.name)
|
|
60
|
+
else:
|
|
61
|
+
result = [self.name]
|
|
62
|
+
return result
|
|
63
|
+
|
|
64
|
+
# When searching for the definition of a field this function returns a scope string equal to the type defined by
|
|
65
|
+
# protobuf.
|
|
66
|
+
def get_scope_str(self):
|
|
67
|
+
if self.parent:
|
|
68
|
+
scope_str = self.parent.get_scope_str() + "::" + self.name
|
|
69
|
+
else:
|
|
70
|
+
scope_str = self.name
|
|
71
|
+
|
|
72
|
+
return scope_str
|
|
73
|
+
|
|
74
|
+
def register_template_parameters(self, field):
|
|
75
|
+
self.fields_with_templates.append(field)
|
|
76
|
+
|
|
77
|
+
# Return the list of template parameters required for this scope alone.
|
|
78
|
+
def get_template_parameters(self):
|
|
79
|
+
result = []
|
|
80
|
+
for field in self.fields_with_templates:
|
|
81
|
+
result.extend(field.get_template_parameters())
|
|
82
|
+
return result
|
|
83
|
+
|
|
84
|
+
# Return a full list of the scope, parent scopes and their templates
|
|
85
|
+
def get(self):
|
|
86
|
+
result = []
|
|
87
|
+
if self.parent:
|
|
88
|
+
result.extend(self.parent.get())
|
|
89
|
+
result.extend([{"name": self.name, "templates": self.get_template_parameters()}])
|
|
90
|
+
return result
|
|
91
|
+
|
|
92
|
+
# -----------------------------------------------------------------------------
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
class TypeDefinition:
|
|
96
|
+
def __init__(self, proto_descriptor, parent_scope, template_filename):
|
|
97
|
+
self.descriptor = proto_descriptor
|
|
98
|
+
self.name = proto_descriptor.name
|
|
99
|
+
self.scope = Scope(self.name, parent_scope)
|
|
100
|
+
self.template_file = template_filename
|
|
101
|
+
|
|
102
|
+
def get_name(self):
|
|
103
|
+
return self.name
|
|
104
|
+
|
|
105
|
+
def render(self, jinja_environment):
|
|
106
|
+
template = jinja_environment.get_template(self.template_file)
|
|
107
|
+
render_result = template.render(typedef=self, environment=jinja_environment)
|
|
108
|
+
return render_result
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
# -----------------------------------------------------------------------------
|
|
112
|
+
|
|
113
|
+
class EnumDefinition(TypeDefinition):
|
|
114
|
+
def __init__(self, proto_descriptor, parent_scope):
|
|
115
|
+
super().__init__(proto_descriptor, parent_scope, "TypeDefEnum.h.jinja2")
|
|
116
|
+
|
|
117
|
+
# Loop through the values defined in the enum.
|
|
118
|
+
def values(self):
|
|
119
|
+
for value in self.descriptor.value:
|
|
120
|
+
yield value
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
# -----------------------------------------------------------------------------
|
|
124
|
+
|
|
125
|
+
class MessageDefinition(TypeDefinition):
|
|
126
|
+
def __init__(self, proto_descriptor, parent_scope):
|
|
127
|
+
super().__init__(proto_descriptor, parent_scope, "TypeDefMsg.h.jinja2")
|
|
128
|
+
|
|
129
|
+
self.nested_enum_definitions = [EnumDefinition(enum, self.scope) for enum in self.descriptor.enum_type]
|
|
130
|
+
self.nested_msg_definitions = [MessageDefinition(msg, self.scope) for msg in self.descriptor.nested_type]
|
|
131
|
+
|
|
132
|
+
# Store the id numbers of all the fields to create the ID enum.
|
|
133
|
+
self.field_ids = []
|
|
134
|
+
|
|
135
|
+
# This message contains optional fields, or not.
|
|
136
|
+
self.optional_fields = []
|
|
137
|
+
|
|
138
|
+
# Store all the variable fields in this message.
|
|
139
|
+
self.fields = []
|
|
140
|
+
for f in self.descriptor.field:
|
|
141
|
+
if (not f.HasField('oneof_index')) or f.proto3_optional:
|
|
142
|
+
new_field = Field.factory(f, self)
|
|
143
|
+
self.fields.append(new_field)
|
|
144
|
+
self.field_ids.append((new_field.variable_id, new_field.variable_id_name))
|
|
145
|
+
|
|
146
|
+
# Store for which fields presence needs to be tracked.
|
|
147
|
+
if f.proto3_optional:
|
|
148
|
+
self.optional_fields.append(new_field)
|
|
149
|
+
|
|
150
|
+
# Store all the oneof definitions in this message.
|
|
151
|
+
self.oneofs = []
|
|
152
|
+
for index, oneof in enumerate(self.descriptor.oneof_decl):
|
|
153
|
+
new_oneof = Oneof(oneof, index, proto_descriptor, self)
|
|
154
|
+
oneof_fields = new_oneof.get_fields()
|
|
155
|
+
# For backwards compatibility proto3 optional fields are also include as oneof's with a single field. These
|
|
156
|
+
# dummy oneof's should not actually end up in code. Lets filter them out.
|
|
157
|
+
if oneof_fields[0].optional:
|
|
158
|
+
continue
|
|
159
|
+
else:
|
|
160
|
+
self.oneofs.append(new_oneof)
|
|
161
|
+
for oneof_field in new_oneof.get_fields():
|
|
162
|
+
self.field_ids.append((oneof_field.variable_id, oneof_field.variable_id_name))
|
|
163
|
+
|
|
164
|
+
# Sort the field id's such they will appear in order in the id enum.
|
|
165
|
+
self.field_ids.sort()
|
|
166
|
+
|
|
167
|
+
# Not all template parameters for this message definition have been registered with the scope. This is
|
|
168
|
+
# most likely due to a message defined later in the proto file.
|
|
169
|
+
self.all_parameters_registered = False
|
|
170
|
+
|
|
171
|
+
# Does this message definition contains fields with template parameters.
|
|
172
|
+
self.contains_template_parameters = False
|
|
173
|
+
|
|
174
|
+
# The index where in the source file this definition should be placed. This is later set by the ProtoFile class
|
|
175
|
+
# when the dependencies on other messages has been sorted.
|
|
176
|
+
self.sorted_index = 0
|
|
177
|
+
|
|
178
|
+
# Sort the nested message defintions based on the dependencies found by the sort algorithms.
|
|
179
|
+
def sort_nested_msg_definitions(self, message_order):
|
|
180
|
+
my_scope = "." + self.scope.get_scope_str().replace("::", ".")
|
|
181
|
+
|
|
182
|
+
for index, msg_name in enumerate(message_order):
|
|
183
|
+
for msg_def in self.nested_msg_definitions:
|
|
184
|
+
if msg_def.name == msg_name.replace(my_scope + ".", ''):
|
|
185
|
+
msg_def.sorted_index = index
|
|
186
|
+
break
|
|
187
|
+
|
|
188
|
+
# Next sort the messages based on their index.
|
|
189
|
+
self.nested_msg_definitions.sort(key=lambda msg: msg.sorted_index)
|
|
190
|
+
|
|
191
|
+
# Sort al the nested message definitions in the nested message definitions.
|
|
192
|
+
for nested_msg in self.nested_msg_definitions:
|
|
193
|
+
nested_msg.sort_nested_msg_definitions(message_order)
|
|
194
|
+
|
|
195
|
+
# Obtain a dictionary with references to all nested enums and messages
|
|
196
|
+
def get_all_nested_types(self):
|
|
197
|
+
nested_types = {"enums": [], "messages": []}
|
|
198
|
+
nested_types["enums"].extend(self.nested_enum_definitions)
|
|
199
|
+
for msg in self.nested_msg_definitions:
|
|
200
|
+
nt = msg.get_all_nested_types()
|
|
201
|
+
nested_types["enums"].extend(nt["enums"])
|
|
202
|
+
nested_types["messages"].extend(nt["messages"])
|
|
203
|
+
nested_types["messages"].append(msg)
|
|
204
|
+
|
|
205
|
+
return nested_types
|
|
206
|
+
|
|
207
|
+
def match_fields_with_definitions(self, all_types_definitions):
|
|
208
|
+
# Resolve the types of the nested messages.
|
|
209
|
+
for msg in self.nested_msg_definitions:
|
|
210
|
+
msg.match_fields_with_definitions(all_types_definitions)
|
|
211
|
+
|
|
212
|
+
# Resolve the types of the fields defined in this message.
|
|
213
|
+
for field in self.fields:
|
|
214
|
+
field.match_field_with_definitions(all_types_definitions)
|
|
215
|
+
|
|
216
|
+
for oneof in self.oneofs:
|
|
217
|
+
oneof.match_field_with_definitions(all_types_definitions)
|
|
218
|
+
|
|
219
|
+
# TODO This function will fail to return True if this definitions contains it self as a nested field.
|
|
220
|
+
def register_template_parameters(self):
|
|
221
|
+
self.all_parameters_registered = True
|
|
222
|
+
# First resolve the template parameters for all nested message definitions.
|
|
223
|
+
for nested_msg in self.nested_msg_definitions:
|
|
224
|
+
self.all_parameters_registered = nested_msg.register_template_parameters() \
|
|
225
|
+
and self.all_parameters_registered
|
|
226
|
+
|
|
227
|
+
# Next see if we our self have any fields that have template parameters.
|
|
228
|
+
for field in self.fields:
|
|
229
|
+
self.all_parameters_registered = field.register_template_parameters() and self.all_parameters_registered
|
|
230
|
+
|
|
231
|
+
for oneof in self.oneofs:
|
|
232
|
+
self.all_parameters_registered = oneof.register_template_parameters() and self.all_parameters_registered
|
|
233
|
+
|
|
234
|
+
return self.all_parameters_registered
|
|
235
|
+
|
|
236
|
+
def register_child_with_template(self, child):
|
|
237
|
+
self.scope.register_template_parameters(child)
|
|
238
|
+
self.contains_template_parameters = True
|
|
239
|
+
|
|
240
|
+
def get_templates(self):
|
|
241
|
+
return self.scope.get_template_parameters()
|
|
242
|
+
|
|
243
|
+
def get_type(self):
|
|
244
|
+
return self.scope.get_scope_str()
|
|
245
|
+
|
|
246
|
+
def print_template_data(self, indent):
|
|
247
|
+
print(indent + "Message definition: " + self.name)
|
|
248
|
+
if self.nested_msg_definitions:
|
|
249
|
+
for msg in self.nested_msg_definitions:
|
|
250
|
+
msg.print_template_data(indent + "\t")
|
|
251
|
+
|
|
252
|
+
if self.fields:
|
|
253
|
+
for field in self.fields:
|
|
254
|
+
print(indent + "Field: " + field.name, end='')
|
|
255
|
+
print(field.get_template_parameters())
|
|
File without changes
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Copyright (C) 2020-2024 Embedded AMS B.V. - All Rights Reserved
|
|
3
|
+
#
|
|
4
|
+
# This file is part of Embedded Proto.
|
|
5
|
+
#
|
|
6
|
+
# Embedded Proto is open source software: you can redistribute it and/or
|
|
7
|
+
# modify it under the terms of the GNU General Public License as published
|
|
8
|
+
# by the Free Software Foundation, version 3 of the license.
|
|
9
|
+
#
|
|
10
|
+
# Embedded Proto is distributed in the hope that it will be useful,
|
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
13
|
+
# GNU General Public License for more details.
|
|
14
|
+
#
|
|
15
|
+
# You should have received a copy of the GNU General Public License
|
|
16
|
+
# along with Embedded Proto. If not, see <https://www.gnu.org/licenses/>.
|
|
17
|
+
#
|
|
18
|
+
# For commercial and closed source application please visit:
|
|
19
|
+
# <https://embeddedproto.com/pricing/>.
|
|
20
|
+
#
|
|
21
|
+
# Embedded AMS B.V.
|
|
22
|
+
# Info:
|
|
23
|
+
# info at EmbeddedProto dot com
|
|
24
|
+
#
|
|
25
|
+
# Postal address:
|
|
26
|
+
# Atoomweg 2
|
|
27
|
+
# 1627 LE, Hoorn
|
|
28
|
+
# the Netherlands
|
|
29
|
+
#
|
|
30
|
+
|
|
31
|
+
from .main import main
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
if __name__ == '__main__':
|
|
35
|
+
main()
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# Generated by the protocol buffer compiler. DO NOT EDIT!
|
|
3
|
+
# NO CHECKED-IN PROTOBUF GENCODE
|
|
4
|
+
# source: embedded_proto_options.proto
|
|
5
|
+
# Protobuf Python Version: 5.27.2
|
|
6
|
+
"""Generated protocol buffer code."""
|
|
7
|
+
from google.protobuf import descriptor as _descriptor
|
|
8
|
+
from google.protobuf import descriptor_pool as _descriptor_pool
|
|
9
|
+
from google.protobuf import runtime_version as _runtime_version
|
|
10
|
+
from google.protobuf import symbol_database as _symbol_database
|
|
11
|
+
from google.protobuf.internal import builder as _builder
|
|
12
|
+
_runtime_version.ValidateProtobufRuntimeVersion(
|
|
13
|
+
_runtime_version.Domain.PUBLIC,
|
|
14
|
+
5,
|
|
15
|
+
27,
|
|
16
|
+
2,
|
|
17
|
+
'',
|
|
18
|
+
'embedded_proto_options.proto'
|
|
19
|
+
)
|
|
20
|
+
# @@protoc_insertion_point(imports)
|
|
21
|
+
|
|
22
|
+
_sym_db = _symbol_database.Default()
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
from google.protobuf import descriptor_pb2 as google_dot_protobuf_dot_descriptor__pb2
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1c\x65mbedded_proto_options.proto\x12\rEmbeddedProto\x1a google/protobuf/descriptor.proto\"\x1c\n\x07Options\x12\x11\n\tmaxLength\x18\x01 \x01(\r:G\n\x07options\x12\x1d.google.protobuf.FieldOptions\x18\xf5\x08 \x01(\x0b\x32\x16.EmbeddedProto.Optionsb\x06proto3')
|
|
29
|
+
|
|
30
|
+
_globals = globals()
|
|
31
|
+
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
|
|
32
|
+
_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'embedded_proto_options_pb2', _globals)
|
|
33
|
+
if not _descriptor._USE_C_DESCRIPTORS:
|
|
34
|
+
DESCRIPTOR._loaded_options = None
|
|
35
|
+
_globals['_OPTIONS']._serialized_start=81
|
|
36
|
+
_globals['_OPTIONS']._serialized_end=109
|
|
37
|
+
# @@protoc_insertion_point(module_scope)
|