aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAntony Male <antony.male@gmail.com>2024-05-15 15:18:39 +0100
committerPetteri Aimonen <jpa@github.mail.kapsi.fi>2024-05-15 19:50:13 +0300
commit9e37f6126e9ad480b30fb8742c76b41f396ca629 (patch)
tree9fdbc4cbfe00fda4e711c21a8465c65fdc08d65f
parent7f88274070afa5edfaf608f4d8e32f3d3c1de139 (diff)
downloadnanopb-c-upstream-master.tar.gz
Add label_override field optionupstream-master
This lets proto3 files define submessage fields which nanopb treats as required (even though proto3 doesn't support 'required'). This means that nanopb won't generate a has_xxx field, will reject messages where this field is missing, and will always serialize the field. However, other consumers of the proto file won't see the field as required, and are therefore safe to it being removed in future. To do this, use: Submessage some_submessage = 1 [(nanopb).label_override = LABEL_REQUIRED]; This mechanism also lets users change whether nanopb treats the field as optional or repeated in both proto2 and proto3. Fixes: #962
-rwxr-xr-xgenerator/nanopb_generator.py8
-rw-r--r--generator/proto/nanopb.proto5
-rw-r--r--tests/options/proto3_options.expected2
-rw-r--r--tests/options/proto3_options.proto1
4 files changed, 14 insertions, 2 deletions
diff --git a/generator/nanopb_generator.py b/generator/nanopb_generator.py
index 57d082e..a700a02 100755
--- a/generator/nanopb_generator.py
+++ b/generator/nanopb_generator.py
@@ -615,6 +615,9 @@ class Field(ProtoElement):
self.default = desc.default_value
# Check field rules, i.e. required/optional/repeated.
+ if field_options.HasField("label_override"):
+ desc.label = field_options.label_override
+
can_be_static = True
if desc.label == FieldD.LABEL_REPEATED:
self.rules = 'REPEATED'
@@ -625,6 +628,9 @@ class Field(ProtoElement):
if field_options.fixed_count:
self.rules = 'FIXARRAY'
+ elif desc.label == FieldD.LABEL_REQUIRED:
+ # We allow LABEL_REQUIRED using label_override even for proto3 (see #962)
+ self.rules = 'REQUIRED'
elif field_options.proto3:
if desc.type == FieldD.TYPE_MESSAGE and not field_options.proto3_singular_msgs:
# In most other protobuf libraries proto3 submessages have
@@ -636,8 +642,6 @@ class Field(ProtoElement):
else:
# Proto3 singular fields (without has_field)
self.rules = 'SINGULAR'
- elif desc.label == FieldD.LABEL_REQUIRED:
- self.rules = 'REQUIRED'
elif desc.label == FieldD.LABEL_OPTIONAL:
self.rules = 'OPTIONAL'
else:
diff --git a/generator/proto/nanopb.proto b/generator/proto/nanopb.proto
index 660685a..cf86270 100644
--- a/generator/proto/nanopb.proto
+++ b/generator/proto/nanopb.proto
@@ -143,6 +143,11 @@ message NanoPBOptions {
// Override type of the field in generated C code. Only to be used with related field types
optional google.protobuf.FieldDescriptorProto.Type type_override = 27;
+ // Override of the label of the field (see FieldDescriptorProto.Label). Can be used to create
+ // fields which nanopb considers required in proto3, or whether nanopb treats the field as
+ // optional/required/repeated.
+ optional google.protobuf.FieldDescriptorProto.Label label_override = 31;
+
// Due to historical reasons, nanopb orders fields in structs by their tag number
// instead of the order in .proto. Set this to false to keep the .proto order.
// The default value will probably change to false in nanopb-0.5.0.
diff --git a/tests/options/proto3_options.expected b/tests/options/proto3_options.expected
index 26985b1..1dbcbb0 100644
--- a/tests/options/proto3_options.expected
+++ b/tests/options/proto3_options.expected
@@ -3,3 +3,5 @@ bool has_proto3_off
! bool has_proto3_on
bool has_normal_submsg
! bool has_sng_submsg
+! bool has_required_submsg
+X\(a,\s*STATIC,\s*REQUIRED,\s*MESSAGE,\s*required_submsg,
diff --git a/tests/options/proto3_options.proto b/tests/options/proto3_options.proto
index b73d03c..12ec9ca 100644
--- a/tests/options/proto3_options.proto
+++ b/tests/options/proto3_options.proto
@@ -14,5 +14,6 @@ message Message1
int32 proto3_on = 3 [(nanopb).proto3 = true];
SubMsg normal_submsg = 4;
SubMsg sng_submsg = 5 [(nanopb).proto3_singular_msgs = true];
+ SubMsg required_submsg = 6 [(nanopb).label_override = LABEL_REQUIRED];
}