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.
Files changed (34) hide show
  1. EmbeddedProto/EmbeddedProto.py +63 -0
  2. EmbeddedProto/Field.py +578 -0
  3. EmbeddedProto/Oneof.py +78 -0
  4. EmbeddedProto/ProtoFile.py +188 -0
  5. EmbeddedProto/TypeDefinitions.py +255 -0
  6. EmbeddedProto/__init__.py +0 -0
  7. EmbeddedProto/__main__.py +35 -0
  8. EmbeddedProto/embedded_proto_options_pb2.py +37 -0
  9. EmbeddedProto/main.py +199 -0
  10. EmbeddedProto/templates/FieldBasic_Deserialize.h.jinja2 +33 -0
  11. EmbeddedProto/templates/FieldBasic_GetSet.h.jinja2 +92 -0
  12. EmbeddedProto/templates/FieldBasic_Serialize.h.jinja2 +37 -0
  13. EmbeddedProto/templates/FieldBytes_GetSet.h.jinja2 +86 -0
  14. EmbeddedProto/templates/FieldEnum_Deserialize.h.jinja2 +33 -0
  15. EmbeddedProto/templates/FieldEnum_GetSet.h.jinja2 +86 -0
  16. EmbeddedProto/templates/FieldEnum_Serialize.h.jinja2 +37 -0
  17. EmbeddedProto/templates/FieldErrorRecursive_GetSet.h.jinja2 +36 -0
  18. EmbeddedProto/templates/FieldMsg_Deserialize.h.jinja2 +33 -0
  19. EmbeddedProto/templates/FieldMsg_GetSet.h.jinja2 +100 -0
  20. EmbeddedProto/templates/FieldMsg_Serialize.h.jinja2 +37 -0
  21. EmbeddedProto/templates/FieldRepeated_GetSet.h.jinja2 +95 -0
  22. EmbeddedProto/templates/FieldRepeated_Serialize.h.jinja2 +33 -0
  23. EmbeddedProto/templates/FieldStringBytes_Serialize.h.jinja2 +37 -0
  24. EmbeddedProto/templates/FieldString_GetSet.h.jinja2 +86 -0
  25. EmbeddedProto/templates/Header.h.jinja2 +75 -0
  26. EmbeddedProto/templates/TypeDefEnum.h.jinja2 +35 -0
  27. EmbeddedProto/templates/TypeDefMsg.h.jinja2 +473 -0
  28. EmbeddedProto/templates/TypeOneof.h.jinja2 +180 -0
  29. EmbeddedProto/version.json +3 -0
  30. EmbeddedProto-4.0.0.dev19.dist-info/METADATA +210 -0
  31. EmbeddedProto-4.0.0.dev19.dist-info/RECORD +34 -0
  32. EmbeddedProto-4.0.0.dev19.dist-info/WHEEL +5 -0
  33. EmbeddedProto-4.0.0.dev19.dist-info/entry_points.txt +3 -0
  34. EmbeddedProto-4.0.0.dev19.dist-info/top_level.txt +1 -0
@@ -0,0 +1,63 @@
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
+ import sys
32
+ import grpc_tools.protoc as protoc
33
+ from importlib import resources
34
+
35
+
36
+ def get_well_known_types_location():
37
+ # Obtain the location of the Protobuf well known types, they are a resource
38
+ # to the grpc-tools package the file system.
39
+ file_name = (
40
+ resources.files("grpc_tools") / "_proto"
41
+ ).resolve()
42
+ return str(file_name)
43
+
44
+
45
+ def run_protoc(argv=sys.argv):
46
+ # Remove the program name
47
+ argv.pop(0)
48
+
49
+ # Check if the well known types should be included.
50
+ argv = ["-I" + get_well_known_types_location() if x == "--IncludeWellKnownTypes" else x for x in argv]
51
+
52
+ # Check if a plugin is included
53
+ if not [x for x in argv if x.startswith("--plugin")]:
54
+ # If not add the EmbeddedProto plugin
55
+ argv.insert(0, "--plugin=protoc-gen-eams")
56
+
57
+ protoc.main(argv)
58
+
59
+
60
+ ####################################################################################
61
+
62
+ if __name__ == "__main__":
63
+ run_protoc(sys.argv)
EmbeddedProto/Field.py ADDED
@@ -0,0 +1,578 @@
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 google.protobuf.descriptor_pb2 import FieldDescriptorProto
32
+ from . import embedded_proto_options_pb2
33
+ import copy
34
+
35
+
36
+ # This class is the base class for any kind of field used in protobuf messages.
37
+ class Field:
38
+ def __init__(self, proto_descriptor, parent_msg, template_filename, oneof=None):
39
+ # A reference to the FieldDescriptorProto object which defines this field.
40
+ self.descriptor = proto_descriptor
41
+
42
+ # A reference to the parent message in which this field is defined.
43
+ self.parent = parent_msg
44
+
45
+ # Is this field optional, so do we need to track the presence of the field.
46
+ self.optional = self.descriptor.proto3_optional
47
+
48
+ # If this field is part of an oneof this is the reference to it.
49
+ self.oneof = oneof
50
+
51
+ self.name = self.descriptor.name
52
+ self.variable_name = self.name + "_"
53
+ self.variable_id_name = self.name.upper()
54
+ self.variable_id = self.descriptor.number
55
+ self.template_file = template_filename
56
+
57
+ self.of_type_enum = FieldDescriptorProto.TYPE_ENUM == proto_descriptor.type
58
+
59
+ @staticmethod
60
+ # This function create the appropriate field object for a variable defined in the message.
61
+ # The descriptor and parent message parameters are required parameters, all field need them to be created. The oneof
62
+ # parameter is only required for fields which are part of a oneof. The parameter is the reference to the oneof
63
+ # object.
64
+ # The last parameter is not to be used manually. It is set when we are already in a FieldNested class.
65
+ def factory(proto_descriptor, parent_msg, oneof=None, already_nested=False):
66
+
67
+ # If this field has the same type as the parent we got a recursive inclusion. We can not solve the template
68
+ # parameters in this case. This field is thus replaced by a dummy with a warning. Toposort is used to find more
69
+ # complex recursive inclusions which we can not solve like this.
70
+ parent_msg_type = "." + parent_msg.scope.get_scope_str().replace("::", ".")
71
+ if proto_descriptor.type_name == parent_msg_type:
72
+ result = FieldErrorRecursive(proto_descriptor, parent_msg, oneof)
73
+ # Now continue constructing the normal fields.
74
+ elif (FieldDescriptorProto.LABEL_REPEATED == proto_descriptor.label) and not already_nested:
75
+ result = FieldRepeated(proto_descriptor, parent_msg, oneof)
76
+ elif FieldDescriptorProto.TYPE_MESSAGE == proto_descriptor.type:
77
+ result = FieldMessage(proto_descriptor, parent_msg, oneof)
78
+ elif FieldDescriptorProto.TYPE_ENUM == proto_descriptor.type:
79
+ result = FieldEnum(proto_descriptor, parent_msg, oneof)
80
+ elif FieldDescriptorProto.TYPE_STRING == proto_descriptor.type:
81
+ result = FieldString(proto_descriptor, parent_msg, oneof)
82
+ elif FieldDescriptorProto.TYPE_BYTES == proto_descriptor.type:
83
+ result = FieldBytes(proto_descriptor, parent_msg, oneof)
84
+ else:
85
+ result = FieldBasic(proto_descriptor, parent_msg, oneof)
86
+ return result
87
+
88
+ def get_wire_type_str(self):
89
+ return ""
90
+
91
+ def get_type(self):
92
+ return ""
93
+
94
+ def get_short_type(self):
95
+ return ""
96
+
97
+ def get_default_value(self):
98
+ return ""
99
+
100
+ def get_name(self):
101
+ return self.name
102
+
103
+ def get_variable_name(self):
104
+ var_name = ""
105
+ if self.oneof:
106
+ var_name = self.oneof.get_variable_name() + "."
107
+ var_name += self.variable_name
108
+ return var_name
109
+
110
+ def get_variable_id_name(self):
111
+ return self.variable_id_name
112
+
113
+ # Returns a list with a dictionaries for each template parameter this field had. The dictionary holds the parameter
114
+ # name and its type.
115
+ def get_template_parameters(self):
116
+ # For the field that do not have any templates return an empty list.
117
+ return []
118
+
119
+ def match_field_with_definitions(self, all_types_definitions):
120
+ pass
121
+
122
+ def register_template_parameters(self):
123
+ return True
124
+
125
+ # Returns true if in oneof.init the new& function needs to be call to initialize already allocated memory.
126
+ def oneof_allocation_required(self):
127
+ return type(self) is not FieldEnum
128
+
129
+ def get_oneof_name(self):
130
+ return self.oneof.get_name()
131
+
132
+ def get_which_oneof(self):
133
+ return self.oneof.get_which_oneof()
134
+
135
+ # Get the scope relevant compared to the scope this field is used in.
136
+ def get_reduced_scope(self):
137
+ parent_scope = self.parent.scope.get()
138
+ def_scope = self.definition.scope.get()
139
+ start_index = 0
140
+ for ds, ps in zip(def_scope[:-1], parent_scope):
141
+ if ds == ps:
142
+ start_index += 1
143
+ else:
144
+ break
145
+ reduced_scope = def_scope[start_index:]
146
+ return reduced_scope
147
+
148
+ def render(self, filename, jinja_environment):
149
+ template = jinja_environment.get_template(filename)
150
+ rendered_str = template.render(field=self, environment=jinja_environment)
151
+ return rendered_str
152
+
153
+ # -----------------------------------------------------------------------------
154
+
155
+
156
+ # This class is used to define any type of basic field.
157
+ class FieldBasic(Field):
158
+ # A dictionary to convert the wire type into a default value.
159
+ type_to_default_value = {FieldDescriptorProto.TYPE_DOUBLE: "0.0",
160
+ FieldDescriptorProto.TYPE_FLOAT: "0.0f",
161
+ FieldDescriptorProto.TYPE_INT64: "0",
162
+ FieldDescriptorProto.TYPE_UINT64: "0U",
163
+ FieldDescriptorProto.TYPE_INT32: "0",
164
+ FieldDescriptorProto.TYPE_FIXED64: "0U",
165
+ FieldDescriptorProto.TYPE_FIXED32: "0U",
166
+ FieldDescriptorProto.TYPE_BOOL: "false",
167
+ FieldDescriptorProto.TYPE_UINT32: "0U",
168
+ FieldDescriptorProto.TYPE_SFIXED32: "0",
169
+ FieldDescriptorProto.TYPE_SFIXED64: "0",
170
+ FieldDescriptorProto.TYPE_SINT32: "0",
171
+ FieldDescriptorProto.TYPE_SINT64: "0"}
172
+
173
+ # A dictionary to convert the protobuf wire type into an Embedded Proto C++ type.
174
+ type_to_cpp_type = {FieldDescriptorProto.TYPE_DOUBLE: "EmbeddedProto::doublefixed",
175
+ FieldDescriptorProto.TYPE_FLOAT: "EmbeddedProto::floatfixed",
176
+ FieldDescriptorProto.TYPE_INT64: "EmbeddedProto::int64",
177
+ FieldDescriptorProto.TYPE_UINT64: "EmbeddedProto::uint64",
178
+ FieldDescriptorProto.TYPE_INT32: "EmbeddedProto::int32",
179
+ FieldDescriptorProto.TYPE_FIXED64: "EmbeddedProto::fixed64",
180
+ FieldDescriptorProto.TYPE_FIXED32: "EmbeddedProto::fixed32",
181
+ FieldDescriptorProto.TYPE_BOOL: "EmbeddedProto::boolean",
182
+ FieldDescriptorProto.TYPE_UINT32: "EmbeddedProto::uint32",
183
+ FieldDescriptorProto.TYPE_SFIXED32: "EmbeddedProto::sfixed32",
184
+ FieldDescriptorProto.TYPE_SFIXED64: "EmbeddedProto::sfixed64",
185
+ FieldDescriptorProto.TYPE_SINT32: "EmbeddedProto::sint32",
186
+ FieldDescriptorProto.TYPE_SINT64: "EmbeddedProto::sint64"}
187
+
188
+ # A dictionary to convert the protobuf wire type into a C++ type.
189
+ type_to_cstdint = {FieldDescriptorProto.TYPE_DOUBLE: "double",
190
+ FieldDescriptorProto.TYPE_FLOAT: "float",
191
+ FieldDescriptorProto.TYPE_INT64: "int64_t",
192
+ FieldDescriptorProto.TYPE_UINT64: "uint64_t",
193
+ FieldDescriptorProto.TYPE_INT32: "int32_t",
194
+ FieldDescriptorProto.TYPE_FIXED64: "uint64_t",
195
+ FieldDescriptorProto.TYPE_FIXED32: "uint32_t",
196
+ FieldDescriptorProto.TYPE_BOOL: "bool",
197
+ FieldDescriptorProto.TYPE_UINT32: "uint32_t",
198
+ FieldDescriptorProto.TYPE_SFIXED32: "int32_t",
199
+ FieldDescriptorProto.TYPE_SFIXED64: "int64_t",
200
+ FieldDescriptorProto.TYPE_SINT32: "int32_t",
201
+ FieldDescriptorProto.TYPE_SINT64: "int64_t"}
202
+
203
+ # A dictionary to convert the wire type number into a wire type string.
204
+ type_to_wire_type = {FieldDescriptorProto.TYPE_INT32: "VARINT",
205
+ FieldDescriptorProto.TYPE_INT64: "VARINT",
206
+ FieldDescriptorProto.TYPE_UINT32: "VARINT",
207
+ FieldDescriptorProto.TYPE_UINT64: "VARINT",
208
+ FieldDescriptorProto.TYPE_SINT32: "VARINT",
209
+ FieldDescriptorProto.TYPE_SINT64: "VARINT",
210
+ FieldDescriptorProto.TYPE_BOOL: "VARINT",
211
+ FieldDescriptorProto.TYPE_FIXED64: "FIXED64",
212
+ FieldDescriptorProto.TYPE_SFIXED64: "FIXED64",
213
+ FieldDescriptorProto.TYPE_DOUBLE: "FIXED64",
214
+ FieldDescriptorProto.TYPE_FIXED32: "FIXED32",
215
+ FieldDescriptorProto.TYPE_FLOAT: "FIXED32",
216
+ FieldDescriptorProto.TYPE_SFIXED32: "FIXED32"}
217
+
218
+ def __init__(self, proto_descriptor, parent_msg, oneof=None):
219
+ super().__init__(proto_descriptor, parent_msg, "FieldBasic.h.jinja2", oneof)
220
+
221
+ def get_wire_type_str(self):
222
+ return self.type_to_wire_type[self.descriptor.type]
223
+
224
+ def get_type(self):
225
+ return self.type_to_cpp_type[self.descriptor.type]
226
+
227
+ def get_short_type(self):
228
+ return self.get_type().split("::")[-1]
229
+
230
+ def get_cstdint_type(self):
231
+ return self.type_to_cstdint[self.descriptor.type]
232
+
233
+ def get_default_value(self):
234
+ return self.type_to_default_value[self.descriptor.type]
235
+
236
+ def render_get_set(self, jinja_env):
237
+ return self.render("FieldBasic_GetSet.h.jinja2", jinja_environment=jinja_env)
238
+
239
+ def render_serialize(self, jinja_env):
240
+ return self.render("FieldBasic_Serialize.h.jinja2", jinja_environment=jinja_env)
241
+
242
+ def render_deserialize(self, jinja_env):
243
+ str = self.render("FieldBasic_Deserialize.h.jinja2", jinja_environment=jinja_env)
244
+ return str.rstrip()
245
+
246
+ # -----------------------------------------------------------------------------
247
+
248
+
249
+ # A base class for both the String and Bytes type field
250
+ class BaseStringBytes(Field):
251
+ def __init__(self, proto_descriptor, parent_msg, oneof=None):
252
+ super().__init__(proto_descriptor, parent_msg, "FieldString.h.jinja2", oneof)
253
+
254
+ # This is the name given to the template parameter for the length.
255
+ self.template_param_str = self.parent.name + "_" + self.variable_name + "LENGTH"
256
+
257
+ # Find options we know and use in this type of field.
258
+ self.MaxLength = None
259
+ if self.descriptor.options.HasExtension(embedded_proto_options_pb2.options):
260
+ self.MaxLength = self.descriptor.options.Extensions[embedded_proto_options_pb2.options].maxLength
261
+
262
+ def get_wire_type_str(self):
263
+ return "LENGTH_DELIMITED"
264
+
265
+ def get_template_parameters(self):
266
+ result = []
267
+ # When we do not have a maximum length specified add the length as a template param.
268
+ if not self.MaxLength:
269
+ result.append({"name": self.template_param_str, "type": "uint32_t"})
270
+ return result
271
+
272
+ def register_template_parameters(self):
273
+ # If we do not have a max length defined register the template parameter.
274
+ if not self.MaxLength:
275
+ self.parent.register_child_with_template(self)
276
+ return True
277
+
278
+ def render_serialize(self, jinja_env):
279
+ return self.render("FieldStringBytes_Serialize.h.jinja2", jinja_environment=jinja_env)
280
+
281
+ def render_deserialize(self, jinja_env):
282
+ str = self.render("FieldBasic_Deserialize.h.jinja2", jinja_environment=jinja_env)
283
+ return str.rstrip()
284
+
285
+ # -----------------------------------------------------------------------------
286
+
287
+
288
+ # This class defines a string field
289
+ class FieldString(BaseStringBytes):
290
+ def __init__(self, proto_descriptor, parent_msg, oneof=None):
291
+ super().__init__(proto_descriptor, parent_msg, oneof)
292
+
293
+ def get_type(self):
294
+ str_type = "::EmbeddedProto::FieldString<"
295
+ if self.MaxLength:
296
+ str_type += str(self.MaxLength) + ">"
297
+ else:
298
+ str_type += self.template_param_str + ">"
299
+ return str_type
300
+
301
+ def get_short_type(self):
302
+ return "FieldString"
303
+
304
+ def render_get_set(self, jinja_env):
305
+ return self.render("FieldString_GetSet.h.jinja2", jinja_environment=jinja_env)
306
+
307
+ # -----------------------------------------------------------------------------
308
+
309
+
310
+ # This class defines a bytes array field
311
+ class FieldBytes(BaseStringBytes):
312
+ def __init__(self, proto_descriptor, parent_msg, oneof=None):
313
+ super().__init__(proto_descriptor, parent_msg, oneof)
314
+
315
+ def get_type(self):
316
+ str_type = "::EmbeddedProto::FieldBytes<"
317
+ if self.MaxLength:
318
+ str_type += str(self.MaxLength) + ">"
319
+ else:
320
+ str_type += self.template_param_str + ">"
321
+ return str_type
322
+
323
+ def get_short_type(self):
324
+ return "FieldBytes"
325
+
326
+ def render_get_set(self, jinja_env):
327
+ return self.render("FieldBytes_GetSet.h.jinja2", jinja_environment=jinja_env)
328
+
329
+ # -----------------------------------------------------------------------------
330
+
331
+
332
+ # This class is used to wrap around any enum used as a field.
333
+ class FieldEnum(Field):
334
+ def __init__(self, proto_descriptor, parent_msg, oneof=None):
335
+ super().__init__(proto_descriptor, parent_msg, "FieldEnum.h.jinja2", oneof)
336
+
337
+ # Reserve a member variable for the reference to the enum definition used for this field.
338
+ self.definition = None
339
+
340
+ def get_wire_type_str(self):
341
+ return "VARINT"
342
+
343
+ def get_type_as_defined(self):
344
+ if not self.definition:
345
+ # When the actual definition is unknown use the protobuf type.
346
+ type_name = self.descriptor.type_name if "." != self.descriptor.type_name[0] else self.descriptor.type_name[1:]
347
+ type_name = type_name.replace(".", "::")
348
+ else:
349
+ scopes = self.get_reduced_scope()
350
+ type_name = ""
351
+ for scope in scopes:
352
+ if scope["templates"]:
353
+ raise Exception("You are trying to use a field with the type: \"" + self.descriptor.type_name +
354
+ "\". It is defined in different scope as where you are using it. But the scope of "
355
+ "definition includes template parameters for repeated, string or byte fields. It "
356
+ "is there for not possible to define the field where you are using it as we do not "
357
+ "know the template value. Try defining the field in the main scope or the one you "
358
+ "are using it in.")
359
+
360
+ type_name += scope["name"] + "::"
361
+ # Remove the last ::
362
+ type_name = type_name[:-2]
363
+
364
+ return type_name
365
+
366
+ def get_max_enum_value(self):
367
+ # Return the maximum value used by any of the enum items as a string. This is used to calculate the maximum serialized size.
368
+ max_number = self.definition.descriptor.value[0].number
369
+ for value in self.definition.descriptor.value[1:]:
370
+ if max_number < value.number:
371
+ max_number = value.number
372
+ return str(max_number)
373
+ def get_type(self):
374
+ return "EmbeddedProto::enumeration<" + self.get_type_as_defined() + ", EmbeddedProto::WireFormatter::VarintSize(" + self.get_max_enum_value() + ")>"
375
+
376
+ def get_short_type(self):
377
+ return "EmbeddedProto::enumeration<" + self.get_type_as_defined().split("::")[-1] + ", EmbeddedProto::WireFormatter::VarintSize(" + self.get_max_enum_value() + ")>"
378
+
379
+ def get_default_value(self):
380
+ return "static_cast<" + self.get_type_as_defined() + ">(0)"
381
+
382
+ def match_field_with_definitions(self, all_types_definitions):
383
+ found = False
384
+ my_type = self.get_type_as_defined()
385
+ for enum_defs in all_types_definitions["enums"]:
386
+ other_scope = enum_defs.scope.get_scope_str()
387
+ if my_type == other_scope:
388
+ self.definition = enum_defs
389
+ found = True
390
+ break
391
+
392
+ if not found:
393
+ raise Exception("Unable to find the definition of this enum: " + self.name)
394
+
395
+ def render_get_set(self, jinja_env):
396
+ return self.render("FieldEnum_GetSet.h.jinja2", jinja_environment=jinja_env)
397
+
398
+ def render_serialize(self, jinja_env):
399
+ return self.render("FieldEnum_Serialize.h.jinja2", jinja_environment=jinja_env)
400
+
401
+ def render_deserialize(self, jinja_env):
402
+ return self.render("FieldEnum_Deserialize.h.jinja2", jinja_environment=jinja_env)
403
+
404
+ # -----------------------------------------------------------------------------
405
+
406
+
407
+ # This class is used to wrap around any type of message used as a field.
408
+ class FieldMessage(Field):
409
+ def __init__(self, proto_descriptor, parent_msg, oneof=None):
410
+ super().__init__(proto_descriptor, parent_msg, "FieldMsg.h.jinja2", oneof)
411
+
412
+ # Reserve a member variable for the reference to the message definition used for this field.
413
+ self.definition = None
414
+
415
+ def get_wire_type_str(self):
416
+ return "LENGTH_DELIMITED"
417
+
418
+ def get_type(self):
419
+ if not self.definition:
420
+ # When the actual definition is unknown use the protobuf type.
421
+ type_name = self.descriptor.type_name if "." != self.descriptor.type_name[0] else self.descriptor.type_name[1:]
422
+ type_name = type_name.replace(".", "::")
423
+ else:
424
+ scopes = self.get_reduced_scope()
425
+ type_name = ""
426
+ for scope in scopes:
427
+ type_name += scope["name"] + "::"
428
+ # Remove the last ::
429
+ type_name = type_name[:-2]
430
+
431
+ tmpl_param = self.get_template_parameters()
432
+ if tmpl_param:
433
+ type_name += "<"
434
+ for param in tmpl_param:
435
+ type_name += param["name"] + ", "
436
+ type_name = type_name[:-2] + ">"
437
+
438
+ return type_name
439
+
440
+ def get_short_type(self):
441
+ return self.get_type().split("::")[-1]
442
+
443
+ def get_default_value(self):
444
+ # Just call the default constructor.
445
+ return ""
446
+
447
+ def get_template_parameters(self):
448
+ # Get the template names used by the definition.
449
+ templates = copy.deepcopy(self.definition.get_templates())
450
+ # Next add our variable name to make them unique.
451
+ for tmp in templates:
452
+ tmp["name"] = self.parent.name + "_" + self.variable_name + tmp["name"]
453
+ return templates
454
+
455
+ def match_field_with_definitions(self, all_types_definitions):
456
+ found = False
457
+ my_type = self.get_type()
458
+ for msg_defs in all_types_definitions["messages"]:
459
+ other_scope = msg_defs.scope.get_scope_str()
460
+ if my_type == other_scope:
461
+ self.definition = msg_defs
462
+ found = True
463
+ break
464
+
465
+ if not found:
466
+ raise Exception("Unable to find the definition of this message: " + self.name)
467
+
468
+ def register_template_parameters(self):
469
+ if self.definition.all_parameters_registered:
470
+ if self.definition.contains_template_parameters:
471
+ self.parent.register_child_with_template(self)
472
+ return True
473
+ else:
474
+ return False
475
+
476
+ # Get the whole scope of the definition of this field.
477
+ def get_scope(self):
478
+ return self.definition.scope.get()
479
+
480
+ def render_get_set(self, jinja_env):
481
+ return self.render("FieldMsg_GetSet.h.jinja2", jinja_environment=jinja_env)
482
+
483
+ def render_serialize(self, jinja_env):
484
+ return self.render("FieldMsg_Serialize.h.jinja2", jinja_environment=jinja_env)
485
+
486
+ def render_deserialize(self, jinja_env):
487
+ return self.render("FieldMsg_Deserialize.h.jinja2", jinja_environment=jinja_env)
488
+
489
+ # -----------------------------------------------------------------------------
490
+
491
+
492
+ # This class wraps around any other type of field which is repeated.
493
+ class FieldRepeated(Field):
494
+ def __init__(self, proto_descriptor, parent_msg, oneof=None):
495
+ super().__init__(proto_descriptor, parent_msg, "FieldRepeated.h", oneof)
496
+
497
+ # To make use of the field object actual type create one of their objects.
498
+ self.actual_type = Field.factory(proto_descriptor, parent_msg, oneof, already_nested=True)
499
+
500
+ # This is the name given to the template parameter for the length.
501
+ self.template_param_str = self.parent.name + "_" + self.variable_name + "REP_LENGTH"
502
+
503
+ # Find options we know and use in this type of field.
504
+ self.MaxLength = None
505
+ if self.descriptor.options.HasExtension(embedded_proto_options_pb2.options):
506
+ self.MaxLength = self.descriptor.options.Extensions[embedded_proto_options_pb2.options].maxLength
507
+
508
+ def get_wire_type_str(self):
509
+ return "LENGTH_DELIMITED"
510
+
511
+ def get_type(self):
512
+ type_str = "::EmbeddedProto::RepeatedFieldFixedSize<" + self.actual_type.get_type() + ", "
513
+ if self.MaxLength:
514
+ type_str += str(self.MaxLength) + ">"
515
+ else:
516
+ type_str += self.template_param_str + ">"
517
+ return type_str
518
+
519
+ def get_short_type(self):
520
+ type_str = "::EmbeddedProto::RepeatedFieldFixedSize<" + self.actual_type.get_type() + ", "
521
+ if self.MaxLength:
522
+ type_str += str(self.MaxLength) + ">"
523
+ else:
524
+ type_str += self.template_param_str + ">"
525
+ return type_str
526
+
527
+ # As this is a repeated field we need a function to get the type we are repeating.
528
+ def get_base_type(self):
529
+ return self.actual_type.get_type()
530
+
531
+ def get_template_parameters(self):
532
+ result = []
533
+ # When we do not have a maximum length specified add the length as a template param.
534
+ if not self.MaxLength:
535
+ result.append({"name": self.template_param_str, "type": "uint32_t"})
536
+ result.extend(self.actual_type.get_template_parameters())
537
+ return result
538
+
539
+ def match_field_with_definitions(self, all_types_definitions):
540
+ self.actual_type.match_field_with_definitions(all_types_definitions)
541
+
542
+ def register_template_parameters(self):
543
+ # If we do not have a max length defined register the template parameter.
544
+ if not self.MaxLength:
545
+ self.parent.register_child_with_template(self)
546
+ return True
547
+
548
+ def render_get_set(self, jinja_env):
549
+ return self.render("FieldRepeated_GetSet.h.jinja2", jinja_environment=jinja_env)
550
+
551
+ def render_serialize(self, jinja_env):
552
+ return self.render("FieldRepeated_Serialize.h.jinja2", jinja_environment=jinja_env)
553
+
554
+ def render_deserialize(self, jinja_env):
555
+ str = self.render("FieldBasic_Deserialize.h.jinja2", jinja_environment=jinja_env)
556
+ return str.rstrip()
557
+
558
+ # -----------------------------------------------------------------------------
559
+
560
+
561
+ # This class represents a field we can not include because it causes a recursive inclusion.
562
+ class FieldErrorRecursive(Field):
563
+ def __init__(self, proto_descriptor, parent_msg, oneof=None):
564
+ super().__init__(proto_descriptor, parent_msg, "FieldRepeated.h.jinja2", oneof)
565
+
566
+ self.descriptor.type_name = "FieldErrorRecursive"
567
+
568
+ def get_type(self):
569
+ return "//"
570
+
571
+ def render_get_set(self, jinja_env):
572
+ return self.render("FieldErrorRecursive_GetSet.h.jinja2", jinja_environment=jinja_env)
573
+
574
+ def render_serialize(self, jinja_env):
575
+ return ""
576
+
577
+ def render_deserialize(self, jinja_env):
578
+ return ""