diff options
author | Antony Male <antony.male@gmail.com> | 2024-05-15 15:18:39 +0100 |
---|---|---|
committer | Petteri Aimonen <jpa@github.mail.kapsi.fi> | 2024-05-15 19:50:13 +0300 |
commit | 9e37f6126e9ad480b30fb8742c76b41f396ca629 (patch) | |
tree | 9fdbc4cbfe00fda4e711c21a8465c65fdc08d65f | |
parent | 7f88274070afa5edfaf608f4d8e32f3d3c1de139 (diff) | |
download | nanopb-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-x | generator/nanopb_generator.py | 8 | ||||
-rw-r--r-- | generator/proto/nanopb.proto | 5 | ||||
-rw-r--r-- | tests/options/proto3_options.expected | 2 | ||||
-rw-r--r-- | tests/options/proto3_options.proto | 1 |
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]; } |