New generator options for oneofs: allow skipping or generating as normal 'optional' fields.
The behaviour with no_unions:true is the same as of nanopb 0.3.1 and earlier.
This commit is contained in:
@@ -11,6 +11,25 @@ are included, in order to make it easier to find this document.
|
|||||||
|
|
||||||
.. contents ::
|
.. contents ::
|
||||||
|
|
||||||
|
Nanopb-0.3.2 (2015-01-xx)
|
||||||
|
=========================
|
||||||
|
|
||||||
|
Add support for OneOfs
|
||||||
|
----------------------
|
||||||
|
**Rationale:** Previously nanopb did not support the *oneof* construct in
|
||||||
|
*.proto* files. Those fields were generated as regular *optional* fields.
|
||||||
|
|
||||||
|
**Changes:** OneOfs are now generated as C unions. Callback fields are not
|
||||||
|
supported inside oneof and generator gives an error.
|
||||||
|
|
||||||
|
**Required actions:** The generator option *no_unions* can be used to restore old
|
||||||
|
behaviour and to allow callbacks to be used. To use unions, one change is
|
||||||
|
needed: use *which_xxxx* field to detect which field is present, instead
|
||||||
|
of *has_xxxx*. Compare the value against *MyStruct_myfield_tag*.
|
||||||
|
|
||||||
|
**Error indications:** Generator error: "Callback fields inside of oneof are
|
||||||
|
not supported". Compiler error: "Message" has no member named "has_xxxx".
|
||||||
|
|
||||||
Nanopb-0.3.0 (2014-08-26)
|
Nanopb-0.3.0 (2014-08-26)
|
||||||
=========================
|
=========================
|
||||||
|
|
||||||
|
|||||||
@@ -591,7 +591,7 @@ class OneOf(Field):
|
|||||||
def add_field(self, field):
|
def add_field(self, field):
|
||||||
if field.allocation == 'CALLBACK':
|
if field.allocation == 'CALLBACK':
|
||||||
raise Exception("Callback fields inside of oneof are not supported"
|
raise Exception("Callback fields inside of oneof are not supported"
|
||||||
+ " (field %s)" % field.fullname)
|
+ " (field %s)" % field.name)
|
||||||
|
|
||||||
field.union_name = self.name
|
field.union_name = self.name
|
||||||
field.rules = 'ONEOF'
|
field.rules = 'ONEOF'
|
||||||
@@ -652,12 +652,19 @@ class Message:
|
|||||||
def __init__(self, names, desc, message_options):
|
def __init__(self, names, desc, message_options):
|
||||||
self.name = names
|
self.name = names
|
||||||
self.fields = []
|
self.fields = []
|
||||||
self.oneofs = []
|
self.oneofs = {}
|
||||||
|
no_unions = []
|
||||||
|
|
||||||
if hasattr(desc, 'oneof_decl'):
|
if hasattr(desc, 'oneof_decl'):
|
||||||
for f in desc.oneof_decl:
|
for i, f in enumerate(desc.oneof_decl):
|
||||||
|
oneof_options = get_nanopb_suboptions(desc, message_options, self.name + f.name)
|
||||||
|
if oneof_options.no_unions:
|
||||||
|
no_unions.append(i) # No union, but add fields normally
|
||||||
|
elif oneof_options.type == nanopb_pb2.FT_IGNORE:
|
||||||
|
pass # No union and skip fields also
|
||||||
|
else:
|
||||||
oneof = OneOf(self.name, f)
|
oneof = OneOf(self.name, f)
|
||||||
self.oneofs.append(oneof)
|
self.oneofs[i] = oneof
|
||||||
self.fields.append(oneof)
|
self.fields.append(oneof)
|
||||||
|
|
||||||
for f in desc.field:
|
for f in desc.field:
|
||||||
@@ -666,7 +673,10 @@ class Message:
|
|||||||
continue
|
continue
|
||||||
|
|
||||||
field = Field(self.name, f, field_options)
|
field = Field(self.name, f, field_options)
|
||||||
if hasattr(f, 'oneof_index') and f.HasField('oneof_index'):
|
if (hasattr(f, 'oneof_index') and
|
||||||
|
f.HasField('oneof_index') and
|
||||||
|
f.oneof_index not in no_unions):
|
||||||
|
if f.oneof_index in self.oneofs:
|
||||||
self.oneofs[f.oneof_index].add_field(field)
|
self.oneofs[f.oneof_index].add_field(field)
|
||||||
else:
|
else:
|
||||||
self.fields.append(field)
|
self.fields.append(field)
|
||||||
@@ -734,7 +744,7 @@ class Message:
|
|||||||
'''Returns number of required fields inside this message'''
|
'''Returns number of required fields inside this message'''
|
||||||
count = 0
|
count = 0
|
||||||
for f in self.fields:
|
for f in self.fields:
|
||||||
if f not in self.oneofs:
|
if not isinstance(f, OneOf):
|
||||||
if f.rules == 'REQUIRED':
|
if f.rules == 'REQUIRED':
|
||||||
count += 1
|
count += 1
|
||||||
return count
|
return count
|
||||||
@@ -742,7 +752,7 @@ class Message:
|
|||||||
def count_all_fields(self):
|
def count_all_fields(self):
|
||||||
count = 0
|
count = 0
|
||||||
for f in self.fields:
|
for f in self.fields:
|
||||||
if f in self.oneofs:
|
if isinstance(f, OneOf):
|
||||||
count += len(f.fields)
|
count += len(f.fields)
|
||||||
else:
|
else:
|
||||||
count += 1
|
count += 1
|
||||||
|
|||||||
@@ -53,6 +53,9 @@ message NanoPBOptions {
|
|||||||
|
|
||||||
// Skip this message
|
// Skip this message
|
||||||
optional bool skip_message = 6 [default = false];
|
optional bool skip_message = 6 [default = false];
|
||||||
|
|
||||||
|
// Generate oneof fields as normal optional fields instead of union.
|
||||||
|
optional bool no_unions = 8 [default = false];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Extensions to protoc 'Descriptor' type in order to define options
|
// Extensions to protoc 'Descriptor' type in order to define options
|
||||||
|
|||||||
Reference in New Issue
Block a user