diff options
-rw-r--r-- | generator/nanopb.proto | 7 | ||||
-rw-r--r-- | generator/nanopb_generator.py | 21 | ||||
-rw-r--r-- | generator/nanopb_pb2.py | 41 | ||||
-rw-r--r-- | tests/options.expected | 2 | ||||
-rw-r--r-- | tests/options.proto | 5 |
5 files changed, 68 insertions, 8 deletions
diff --git a/generator/nanopb.proto b/generator/nanopb.proto index a377f63b..e7bea139 100644 --- a/generator/nanopb.proto +++ b/generator/nanopb.proto @@ -7,9 +7,16 @@ import "google/protobuf/descriptor.proto"; +enum FieldType { + FT_DEFAULT = 0; // Automatically decide field type, generate static field if possible. + FT_CALLBACK = 1; // Always generate a callback field. + FT_STATIC = 2; // Generate a static field or raise an exception if not possible. +} + message NanoPBOptions { optional int32 max_size = 1; optional int32 max_count = 2; + optional FieldType type = 3 [default = FT_DEFAULT]; } // Protocol Buffers extension number registry diff --git a/generator/nanopb_generator.py b/generator/nanopb_generator.py index 69a9eab7..860f3742 100644 --- a/generator/nanopb_generator.py +++ b/generator/nanopb_generator.py @@ -110,18 +110,18 @@ class Field: if desc.HasField('default_value'): self.default = desc.default_value - + # Decide HTYPE # HTYPE is the high-order nibble of nanopb field description, # defining whether value is required/optional/repeated. - is_callback = False + can_be_static = True if desc.label == FieldD.LABEL_REQUIRED: self.htype = 'PB_HTYPE_REQUIRED' elif desc.label == FieldD.LABEL_OPTIONAL: self.htype = 'PB_HTYPE_OPTIONAL' elif desc.label == FieldD.LABEL_REPEATED: if self.max_count is None: - is_callback = True + can_be_static = False else: self.htype = 'PB_HTYPE_ARRAY' self.array_decl = '[%d]' % self.max_count @@ -142,14 +142,14 @@ class Field: elif desc.type == FieldD.TYPE_STRING: self.ltype = 'PB_LTYPE_STRING' if self.max_size is None: - is_callback = True + can_be_static = False else: self.ctype = 'char' self.array_decl += '[%d]' % self.max_size elif desc.type == FieldD.TYPE_BYTES: self.ltype = 'PB_LTYPE_BYTES' if self.max_size is None: - is_callback = True + can_be_static = False else: self.ctype = self.struct_name + self.name + 't' elif desc.type == FieldD.TYPE_MESSAGE: @@ -158,7 +158,16 @@ class Field: else: raise NotImplementedError(desc.type) - if is_callback: + if field_options.type == nanopb_pb2.FT_DEFAULT: + if can_be_static: + field_options.type = nanopb_pb2.FT_STATIC + else: + field_options.type = nanopb_pb2.FT_CALLBACK + + if field_options.type == nanopb_pb2.FT_STATIC and not can_be_static: + raise Exception("Field %s is defined as static, but max_size or max_count is not given." % self.name) + + if field_options.type == nanopb_pb2.FT_CALLBACK: self.htype = 'PB_HTYPE_CALLBACK' self.ctype = 'pb_callback_t' self.array_decl = '' diff --git a/generator/nanopb_pb2.py b/generator/nanopb_pb2.py index 09378194..502726a5 100644 --- a/generator/nanopb_pb2.py +++ b/generator/nanopb_pb2.py @@ -12,8 +12,37 @@ import google.protobuf.descriptor_pb2 DESCRIPTOR = descriptor.FileDescriptor( name='nanopb.proto', package='', - serialized_pb='\n\x0cnanopb.proto\x1a google/protobuf/descriptor.proto\"4\n\rNanoPBOptions\x12\x10\n\x08max_size\x18\x01 \x01(\x05\x12\x11\n\tmax_count\x18\x02 \x01(\x05:E\n\x0enanopb_fileopt\x12\x1c.google.protobuf.FileOptions\x18\xf2\x07 \x01(\x0b\x32\x0e.NanoPBOptions:G\n\rnanopb_msgopt\x12\x1f.google.protobuf.MessageOptions\x18\xf2\x07 \x01(\x0b\x32\x0e.NanoPBOptions:>\n\x06nanopb\x12\x1d.google.protobuf.FieldOptions\x18\xf2\x07 \x01(\x0b\x32\x0e.NanoPBOptions') + serialized_pb='\n\x0cnanopb.proto\x1a google/protobuf/descriptor.proto\"Z\n\rNanoPBOptions\x12\x10\n\x08max_size\x18\x01 \x01(\x05\x12\x11\n\tmax_count\x18\x02 \x01(\x05\x12$\n\x04type\x18\x03 \x01(\x0e\x32\n.FieldType:\nFT_DEFAULT*;\n\tFieldType\x12\x0e\n\nFT_DEFAULT\x10\x00\x12\x0f\n\x0b\x46T_CALLBACK\x10\x01\x12\r\n\tFT_STATIC\x10\x02:E\n\x0enanopb_fileopt\x12\x1c.google.protobuf.FileOptions\x18\xf2\x07 \x01(\x0b\x32\x0e.NanoPBOptions:G\n\rnanopb_msgopt\x12\x1f.google.protobuf.MessageOptions\x18\xf2\x07 \x01(\x0b\x32\x0e.NanoPBOptions:>\n\x06nanopb\x12\x1d.google.protobuf.FieldOptions\x18\xf2\x07 \x01(\x0b\x32\x0e.NanoPBOptions') +_FIELDTYPE = descriptor.EnumDescriptor( + name='FieldType', + full_name='FieldType', + filename=None, + file=DESCRIPTOR, + values=[ + descriptor.EnumValueDescriptor( + name='FT_DEFAULT', index=0, number=0, + options=None, + type=None), + descriptor.EnumValueDescriptor( + name='FT_CALLBACK', index=1, number=1, + options=None, + type=None), + descriptor.EnumValueDescriptor( + name='FT_STATIC', index=2, number=2, + options=None, + type=None), + ], + containing_type=None, + options=None, + serialized_start=142, + serialized_end=201, +) + + +FT_DEFAULT = 0 +FT_CALLBACK = 1 +FT_STATIC = 2 NANOPB_FILEOPT_FIELD_NUMBER = 1010 nanopb_fileopt = descriptor.FieldDescriptor( @@ -62,6 +91,13 @@ _NANOPBOPTIONS = descriptor.Descriptor( message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), + descriptor.FieldDescriptor( + name='type', full_name='NanoPBOptions.type', index=2, + number=3, type=14, cpp_type=8, label=1, + has_default_value=True, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), ], extensions=[ ], @@ -72,9 +108,10 @@ _NANOPBOPTIONS = descriptor.Descriptor( is_extendable=False, extension_ranges=[], serialized_start=50, - serialized_end=102, + serialized_end=140, ) +_NANOPBOPTIONS.fields_by_name['type'].enum_type = _FIELDTYPE DESCRIPTOR.message_types_by_name['NanoPBOptions'] = _NANOPBOPTIONS class NanoPBOptions(message.Message): diff --git a/tests/options.expected b/tests/options.expected index e184cf91..ef74a00d 100644 --- a/tests/options.expected +++ b/tests/options.expected @@ -1,3 +1,5 @@ char filesize[20]; char msgsize[30]; char fieldsize[40]; +pb_callback_t int32_callback; + diff --git a/tests/options.proto b/tests/options.proto index 73edf2ba..6ba7c070 100644 --- a/tests/options.proto +++ b/tests/options.proto @@ -25,4 +25,9 @@ message Message3 required string fieldsize = 1 [(nanopb).max_size = 40]; } +// Forced callback field +message Message4 +{ + required int32 int32_callback = 1 [(nanopb).type = FT_CALLBACK]; +} |