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];
+}