Fix problem with [default=xxxx, (nanopb).proto3=true] field option combination (#558)
diff --git a/pb_encode.c b/pb_encode.c
index 54cd5ba..de716f7 100644
--- a/pb_encode.c
+++ b/pb_encode.c
@@ -265,6 +265,15 @@
* submessage fields. */
return safe_read_bool(field->pSize) == false;
}
+ else if (field->descriptor->default_value)
+ {
+ /* Proto3 messages do not have default values, but proto2 messages
+ * can contain optional fields without has_fields (generator option 'proto3').
+ * In this case they must always be encoded, to make sure that the
+ * non-zero default value is overwritten.
+ */
+ return false;
+ }
/* Rest is proto3 singular fields */
if (PB_LTYPE(type) <= PB_LTYPE_LAST_PACKABLE)
diff --git a/tests/regression/issue_558/SConscript b/tests/regression/issue_558/SConscript
new file mode 100644
index 0000000..7d418fa
--- /dev/null
+++ b/tests/regression/issue_558/SConscript
@@ -0,0 +1,8 @@
+# Regression test for #558:
+# Manually defining proto3:true on a field with default value incorrectly omits it when encoding.
+
+Import("env")
+env.NanopbProto("mixed")
+
+test = env.Program(["mixed.c", "mixed.pb.c", "$COMMON/pb_encode.o", "$COMMON/pb_decode.o", "$COMMON/pb_common.o"])
+env.RunTest(test)
diff --git a/tests/regression/issue_558/mixed.c b/tests/regression/issue_558/mixed.c
new file mode 100644
index 0000000..519d5e1
--- /dev/null
+++ b/tests/regression/issue_558/mixed.c
@@ -0,0 +1,49 @@
+#include <pb_encode.h>
+#include <pb_decode.h>
+
+#include "mixed.pb.h"
+#include "unittests.h"
+
+int main()
+{
+ int status = 0;
+ pb_byte_t buf[64];
+ size_t msglen;
+
+ {
+ pb_ostream_t ostream = pb_ostream_from_buffer(buf, sizeof(buf));
+ MixedMessage msg = MixedMessage_init_default;
+
+ msg.has_proto2_value = true;
+ msg.proto2_value = 0;
+ msg.proto3_value = 0;
+
+ if (!pb_encode(&ostream, MixedMessage_fields, &msg))
+ {
+ fprintf(stderr, "pb_encode() failed: %s\n", PB_GET_ERROR(&ostream));
+ return 1;
+ }
+
+ msglen = ostream.bytes_written;
+ TEST(msglen > 0);
+ }
+
+ {
+ pb_istream_t istream = pb_istream_from_buffer(buf, msglen);
+ MixedMessage msg = MixedMessage_init_default;
+
+ TEST(msg.proto2_value == 100);
+ TEST(msg.proto3_value == 200);
+
+ if (!pb_decode(&istream, MixedMessage_fields, &msg))
+ {
+ fprintf(stderr, "pb_decode() failed: %s\n", PB_GET_ERROR(&istream));
+ return 1;
+ }
+
+ TEST(msg.proto2_value == 0);
+ TEST(msg.proto3_value == 0);
+ }
+
+ return status;
+}
\ No newline at end of file
diff --git a/tests/regression/issue_558/mixed.proto b/tests/regression/issue_558/mixed.proto
new file mode 100644
index 0000000..6a41ed7
--- /dev/null
+++ b/tests/regression/issue_558/mixed.proto
@@ -0,0 +1,8 @@
+syntax = "proto2";
+
+import "nanopb.proto";
+
+message MixedMessage {
+ optional int32 proto2_value = 1 [default = 100];
+ optional int32 proto3_value = 2 [default = 200, (nanopb).proto3 = true];
+}