diff --git a/generator/nanopb_generator.py b/generator/nanopb_generator.py index 973c7610fbea38337b9792838d0efc2f2987c5dc..185a97bbd2acd539795aaa252d51af0225db99e2 100755 --- a/generator/nanopb_generator.py +++ b/generator/nanopb_generator.py @@ -258,16 +258,18 @@ class Field: # Check field rules, i.e. required/optional/repeated. can_be_static = True - if desc.label == FieldD.LABEL_REQUIRED: - self.rules = 'REQUIRED' - elif desc.label == FieldD.LABEL_OPTIONAL: - self.rules = 'OPTIONAL' - elif desc.label == FieldD.LABEL_REPEATED: + if desc.label == FieldD.LABEL_REPEATED: self.rules = 'REPEATED' if self.max_count is None: can_be_static = False else: self.array_decl = '[%d]' % self.max_count + elif field_options.HasField("proto3"): + self.rules = 'SINGULAR' + elif desc.label == FieldD.LABEL_REQUIRED: + self.rules = 'REQUIRED' + elif desc.label == FieldD.LABEL_OPTIONAL: + self.rules = 'OPTIONAL' else: raise NotImplementedError(desc.label) diff --git a/generator/proto/nanopb.proto b/generator/proto/nanopb.proto index 8aab19a1b5e88cd2bb34a1081ce12ba5dca849c8..b9961c88d32ccc7bf54463cb2dae694565cf4b6c 100644 --- a/generator/proto/nanopb.proto +++ b/generator/proto/nanopb.proto @@ -66,6 +66,9 @@ message NanoPBOptions { // decode oneof as anonymous union optional bool anonymous_oneof = 11 [default = false]; + + // Proto3 singular field does not generate a "has_" flag + optional bool proto3 = 12 [default = false]; } // Extensions to protoc 'Descriptor' type in order to define options diff --git a/pb.h b/pb.h index 4576f79abca9bc03c0f97e9e5eb4a4c4262bbe9a..0e1e92d51cdcdbe4b9a8527a850af7ce57988f5d 100644 --- a/pb.h +++ b/pb.h @@ -413,6 +413,10 @@ struct pb_extension_s { pb_delta(st, has_ ## m, m), \ pb_membersize(st, m), 0, ptr} +#define PB_SINGULAR_STATIC(tag, st, m, fd, ltype, ptr) \ + {tag, PB_ATYPE_STATIC | PB_HTYPE_OPTIONAL | ltype, \ + fd, 0, pb_membersize(st, m), 0, ptr} + /* Repeated fields have a _count field and also the maximum number of entries. */ #define PB_REPEATED_STATIC(tag, st, m, fd, ltype, ptr) \ {tag, PB_ATYPE_STATIC | PB_HTYPE_REPEATED | ltype, \ @@ -444,6 +448,11 @@ struct pb_extension_s { {tag, PB_ATYPE_POINTER | PB_HTYPE_OPTIONAL | ltype, \ fd, 0, pb_membersize(st, m[0]), 0, ptr} +/* Same as optional fields*/ +#define PB_SINGULAR_POINTER(tag, st, m, fd, ltype, ptr) \ + {tag, PB_ATYPE_POINTER | PB_HTYPE_OPTIONAL | ltype, \ + fd, 0, pb_membersize(st, m[0]), 0, ptr} + /* Repeated fields have a _count field and a pointer to array of pointers */ #define PB_REPEATED_POINTER(tag, st, m, fd, ltype, ptr) \ {tag, PB_ATYPE_POINTER | PB_HTYPE_REPEATED | ltype, \ @@ -458,6 +467,10 @@ struct pb_extension_s { #define PB_OPTIONAL_CALLBACK(tag, st, m, fd, ltype, ptr) \ {tag, PB_ATYPE_CALLBACK | PB_HTYPE_OPTIONAL | ltype, \ fd, 0, pb_membersize(st, m), 0, ptr} + +#define PB_SINGULAR_CALLBACK(tag, st, m, fd, ltype, ptr) \ + {tag, PB_ATYPE_CALLBACK | PB_HTYPE_OPTIONAL | ltype, \ + fd, 0, pb_membersize(st, m), 0, ptr} #define PB_REPEATED_CALLBACK(tag, st, m, fd, ltype, ptr) \ {tag, PB_ATYPE_CALLBACK | PB_HTYPE_REPEATED | ltype, \ diff --git a/pb_decode.c b/pb_decode.c index 7a4e29a8fda2cb8de68fab47cf31cd1bf6c396f9..1f6aeae0d87dedb4be0e594324b15e71ff98b3c5 100644 --- a/pb_decode.c +++ b/pb_decode.c @@ -360,7 +360,8 @@ static bool checkreturn decode_static_field(pb_istream_t *stream, pb_wire_type_t return func(stream, iter->pos, iter->pData); case PB_HTYPE_OPTIONAL: - *(bool*)iter->pSize = true; + if (iter->pSize != iter->pData) + *(bool*)iter->pSize = true; return func(stream, iter->pos, iter->pData); case PB_HTYPE_REPEATED: