Allow defining field type in .proto.
authorPetteri Aimonen <jpa@git.mail.kapsi.fi>
Mon, 29 Oct 2012 16:34:24 +0000 (18:34 +0200)
committerPetteri Aimonen <jpa@git.mail.kapsi.fi>
Mon, 29 Oct 2012 16:34:24 +0000 (18:34 +0200)
Update issue 30
Status: FixedInGit

generator/nanopb.proto
generator/nanopb_generator.py
generator/nanopb_pb2.py
tests/options.expected
tests/options.proto

index a377f63..e7bea13 100644 (file)
@@ -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
index 69a9eab..860f374 100644 (file)
@@ -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 = ''
index 0937819..502726a 100644 (file)
@@ -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):
index e184cf9..ef74a00 100644 (file)
@@ -1,3 +1,5 @@
 char filesize[20];
 char msgsize[30];
 char fieldsize[40];
+pb_callback_t int32_callback;
+
index 73edf2b..6ba7c07 100644 (file)
@@ -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];
+}