diff options
author | Petteri Aimonen <jpa@git.mail.kapsi.fi> | 2017-02-22 21:06:32 +0200 |
---|---|---|
committer | Petteri Aimonen <jpa@git.mail.kapsi.fi> | 2017-02-22 21:10:26 +0200 |
commit | 07375a126337916f3a34ea94f8085b8f89d789a1 (patch) | |
tree | ef95d9138252d8ae4797e0a7092bc7417c1abefb /generator | |
parent | ca74746e23b5a9e7916e8fde6632d71d61603f50 (diff) |
Extend inline / fixed length bytes array support (issue #244)
Adds support for proto3 and POINTER field types to have
fixed length bytes arrays. Also changed the .proto option
to a separate fixed_length:true, while also supporting the old FT_INLINE
option.
Restructured the generator and decoder logic to threat the inline
bytes fields more like "just another field type".
Diffstat (limited to 'generator')
-rwxr-xr-x | generator/nanopb_generator.py | 64 | ||||
-rw-r--r-- | generator/proto/nanopb.proto | 5 |
2 files changed, 38 insertions, 31 deletions
diff --git a/generator/nanopb_generator.py b/generator/nanopb_generator.py index ca60c03a..9cce6a5a 100755 --- a/generator/nanopb_generator.py +++ b/generator/nanopb_generator.py @@ -262,10 +262,12 @@ class Field: self.enc_size = None self.ctype = None - self.inline = None if field_options.type == nanopb_pb2.FT_INLINE: + # Before nanopb-0.3.8, fixed length bytes arrays were specified + # by setting type to FT_INLINE. But to handle pointer typed fields, + # it makes sense to have it as a separate option. field_options.type = nanopb_pb2.FT_STATIC - self.inline = nanopb_pb2.FT_INLINE + field_options.fixed_length = True # Parse field options if field_options.HasField("max_size"): @@ -349,17 +351,17 @@ class Field: self.array_decl += '[%d]' % self.max_size self.enc_size = varint_max_size(self.max_size) + self.max_size elif desc.type == FieldD.TYPE_BYTES: - self.pbtype = 'BYTES' - if self.allocation == 'STATIC': - # Inline STATIC for BYTES is like STATIC for STRING. - if self.inline: - self.ctype = 'pb_byte_t' - self.array_decl += '[%d]' % self.max_size - else: - self.ctype = self.struct_name + self.name + 't' + if field_options.fixed_length: + self.pbtype = 'FIXED_LENGTH_BYTES' self.enc_size = varint_max_size(self.max_size) + self.max_size - elif self.allocation == 'POINTER': + self.ctype = 'pb_byte_t' + self.array_decl += '[%d]' % self.max_size + else: + self.pbtype = 'BYTES' self.ctype = 'pb_bytes_array_t' + if self.allocation == 'STATIC': + self.ctype = self.struct_name + self.name + 't' + self.enc_size = varint_max_size(self.max_size) + self.max_size elif desc.type == FieldD.TYPE_MESSAGE: self.pbtype = 'MESSAGE' self.ctype = self.submsgname = names_from_type_name(desc.type_name) @@ -379,6 +381,9 @@ class Field: if self.pbtype == 'MESSAGE': # Use struct definition, so recursive submessages are possible result += ' struct _%s *%s;' % (self.ctype, self.name) + elif self.pbtype == 'FIXED_LENGTH_BYTES': + # Pointer to fixed size array + result += ' %s (*%s)%s;' % (self.ctype, self.name, self.array_decl) elif self.rules == 'REPEATED' and self.pbtype in ['STRING', 'BYTES']: # String/bytes arrays need to be defined as pointers to pointers result += ' %s **%s;' % (self.ctype, self.name) @@ -396,7 +401,7 @@ class Field: def types(self): '''Return definitions for any special types this field might need.''' - if self.pbtype == 'BYTES' and self.allocation == 'STATIC' and not self.inline: + if self.pbtype == 'BYTES' and self.allocation == 'STATIC': result = 'typedef PB_BYTES_ARRAY_T(%d) %s;\n' % (self.max_size, self.ctype) else: result = '' @@ -425,10 +430,9 @@ class Field: if self.pbtype == 'STRING': inner_init = '""' elif self.pbtype == 'BYTES': - if self.inline: - inner_init = '{0}' - else: - inner_init = '{0, {0}}' + inner_init = '{0, {0}}' + elif self.pbtype == 'FIXED_LENGTH_BYTES': + inner_init = '{0}' elif self.pbtype in ('ENUM', 'UENUM'): inner_init = '(%s)0' % self.ctype else: @@ -440,15 +444,15 @@ class Field: elif self.pbtype == 'BYTES': data = ['0x%02x' % ord(c) for c in self.default] if len(data) == 0: - if self.inline: - inner_init = '{0}' - else: - inner_init = '{0, {0}}' + inner_init = '{0, {0}}' + else: + inner_init = '{%d, {%s}}' % (len(data), ','.join(data)) + elif self.pbtype == 'FIXED_LENGTH_BYTES': + data = ['0x%02x' % ord(c) for c in self.default] + if len(data) == 0: + inner_init = '{0}' else: - if self.inline: - inner_init = '{%s}' % ','.join(data) - else: - inner_init = '{%d, {%s}}' % (len(data), ','.join(data)) + inner_init = '{%s}' % ','.join(data) elif self.pbtype in ['FIXED32', 'UINT32']: inner_init = str(self.default) + 'u' elif self.pbtype in ['FIXED64', 'UINT64']: @@ -500,8 +504,10 @@ class Field: elif self.pbtype == 'BYTES': if self.allocation != 'STATIC': return None # Not implemented - if self.inline: - array_decl = '[%d]' % self.max_size + elif self.pbtype == 'FIXED_LENGTH_BYTES': + if self.allocation != 'STATIC': + return None # Not implemented + array_decl = '[%d]' % self.max_size if declaration_only: return 'extern const %s %s_default%s;' % (ctype, self.struct_name + self.name, array_decl) @@ -530,7 +536,7 @@ class Field: result += '%3d, ' % self.tag result += '%-8s, ' % self.pbtype result += '%s, ' % self.rules - result += '%-8s, ' % (self.allocation if not self.inline else "INLINE") + result += '%-8s, ' % self.allocation if union_index is not None and union_index > 0: result += 'UNION, ' @@ -547,7 +553,7 @@ class Field: result += '&%s_fields)' % self.submsgname elif self.default is None: result += '0)' - elif self.pbtype in ['BYTES', 'STRING'] and self.allocation != 'STATIC': + elif self.pbtype in ['BYTES', 'STRING', 'FIXED_LENGTH_BYTES'] and self.allocation != 'STATIC': result += '0)' # Arbitrary size default values not implemented elif self.rules == 'OPTEXT': result += '0)' # Default value for extensions is not implemented @@ -653,7 +659,6 @@ class ExtensionRange(Field): self.default = None self.max_size = 0 self.max_count = 0 - self.inline = None def __str__(self): return ' pb_extension_t *extensions;' @@ -731,7 +736,6 @@ class OneOf(Field): self.default = None self.rules = 'ONEOF' self.anonymous = False - self.inline = None def add_field(self, field): if field.allocation == 'CALLBACK': diff --git a/generator/proto/nanopb.proto b/generator/proto/nanopb.proto index 7d39e1c3..e4c1da79 100644 --- a/generator/proto/nanopb.proto +++ b/generator/proto/nanopb.proto @@ -16,7 +16,7 @@ enum FieldType { FT_POINTER = 4; // Always generate a dynamically allocated field. FT_STATIC = 2; // Generate a static field or raise an exception if not possible. FT_IGNORE = 3; // Ignore the field completely. - FT_INLINE = 5; // Always generate an inline array of fixed size. + FT_INLINE = 5; // Legacy option, use the separate 'fixed_length' option instead } enum IntSize { @@ -77,6 +77,9 @@ message NanoPBOptions { // Generate an enum->string mapping function (can take up lots of space). optional bool enum_to_string = 13 [default = false]; + + // Generate bytes arrays with fixed length + optional bool fixed_length = 15 [default = false]; } // Extensions to protoc 'Descriptor' type in order to define options |