Set proto2 enum fields to first value when no default is given, even if nonzero (#532) (#539)
diff --git a/generator/nanopb_generator.py b/generator/nanopb_generator.py
index b572940..8eb351f 100755
--- a/generator/nanopb_generator.py
+++ b/generator/nanopb_generator.py
@@ -1231,7 +1231,6 @@
return b''
optional_only = copy.deepcopy(self.desc)
- enums = {}
# Remove fields without default values
# The iteration is done in reverse order to avoid remove() messing up iteration.
@@ -1241,18 +1240,28 @@
if parsed_field is None or parsed_field.allocation != 'STATIC':
optional_only.field.remove(field)
elif (field.label == FieldD.LABEL_REPEATED or
- field.type == FieldD.TYPE_MESSAGE or
- not field.HasField('default_value')):
+ field.type == FieldD.TYPE_MESSAGE):
optional_only.field.remove(field)
elif hasattr(field, 'oneof_index') and field.HasField('oneof_index'):
optional_only.field.remove(field)
elif field.type == FieldD.TYPE_ENUM:
# The partial descriptor doesn't include the enum type
# so we fake it with int64.
- enums[field.name] = (names_from_type_name(field.type_name), field.default_value)
- field.type = FieldD.TYPE_INT64
- field.ClearField(str('default_value'))
- field.ClearField(str('type_name'))
+ enumname = names_from_type_name(field.type_name)
+ enumtype = dependencies[str(enumname)]
+ if field.HasField('default_value'):
+ defvals = [v for n,v in enumtype.values if n.parts[-1] == field.default_value]
+ else:
+ # If no default is specified, the default is the first value.
+ defvals = [v for n,v in enumtype.values]
+ if defvals and defvals[0] != 0:
+ field.type = FieldD.TYPE_INT64
+ field.default_value = str(defvals[0])
+ field.ClearField(str('type_name'))
+ else:
+ optional_only.field.remove(field)
+ elif not field.HasField('default_value'):
+ optional_only.field.remove(field)
if len(optional_only.field) == 0:
return b''
@@ -1273,14 +1282,6 @@
setattr(msg, field.name, float(field.default_value))
elif field.type == FieldD.TYPE_BOOL:
setattr(msg, field.name, field.default_value == 'true')
- elif field.name in enums:
- # Lookup the enum default value
- enumname = enums[field.name][0]
- defval = enums[field.name][1]
- enumtype = dependencies[str(enumname)]
- defvals = [v for n,v in enumtype.values if n.parts[-1] == defval]
- if defvals:
- setattr(msg, field.name, defvals[0])
else:
setattr(msg, field.name, int(field.default_value))
diff --git a/tests/alltypes/alltypes.proto b/tests/alltypes/alltypes.proto
index df15d40..317b783 100644
--- a/tests/alltypes/alltypes.proto
+++ b/tests/alltypes/alltypes.proto
@@ -1,6 +1,12 @@
syntax = "proto2";
// package name placeholder
+enum NonZeroBasedEnum {
+ Two = 2;
+ Three = 3;
+ Four = 4;
+}
+
message SubMessage {
required string substuff1 = 1 [default = "1"];
required int32 substuff2 = 2 [default = 2];
@@ -127,6 +133,8 @@
SubMessage oneof_msg1 = 60;
EmptyMessage oneof_msg2 = 61;
}
+
+ optional NonZeroBasedEnum opt_non_zero_based_enum = 62;
// Check support for custom integer sizes
required IntSizes req_intsizes = 96;
diff --git a/tests/alltypes/decode_alltypes.c b/tests/alltypes/decode_alltypes.c
index 1c49080..3b92614 100644
--- a/tests/alltypes/decode_alltypes.c
+++ b/tests/alltypes/decode_alltypes.c
@@ -158,6 +158,9 @@
TEST(memcmp(alltypes.opt_fbytes, "4059", 4) == 0);
TEST(alltypes.which_oneof == 0);
+
+ TEST(alltypes.has_opt_non_zero_based_enum == false);
+ TEST(alltypes.opt_non_zero_based_enum == NonZeroBasedEnum_Two);
}
else if (mode == 1)
{
@@ -209,6 +212,9 @@
TEST(alltypes.which_oneof == AllTypes_oneof_msg1_tag);
TEST(strcmp(alltypes.oneof.oneof_msg1.substuff1, "4059") == 0);
TEST(alltypes.oneof.oneof_msg1.substuff2 == 4059);
+
+ TEST(alltypes.has_opt_non_zero_based_enum == true);
+ TEST(alltypes.opt_non_zero_based_enum == NonZeroBasedEnum_Three);
}
else if (mode == 2)
{
@@ -285,6 +291,8 @@
TEST(alltypes.has_opt_fbytes == false);
TEST(alltypes.which_oneof == 0);
+
+ TEST(alltypes.has_opt_non_zero_based_enum == false);
}
TEST(alltypes.end == 1099);
diff --git a/tests/alltypes/encode_alltypes.c b/tests/alltypes/encode_alltypes.c
index 00d2615..7f4ad2b 100644
--- a/tests/alltypes/encode_alltypes.c
+++ b/tests/alltypes/encode_alltypes.c
@@ -150,6 +150,9 @@
alltypes.which_oneof = AllTypes_oneof_msg1_tag;
strcpy(alltypes.oneof.oneof_msg1.substuff1, "4059");
alltypes.oneof.oneof_msg1.substuff2 = 4059;
+
+ alltypes.has_opt_non_zero_based_enum = true;
+ alltypes.opt_non_zero_based_enum = NonZeroBasedEnum_Three;
}
alltypes.end = 1099;
diff --git a/tests/alltypes_callback/decode_alltypes_callback.c b/tests/alltypes_callback/decode_alltypes_callback.c
index 8079a04..71da215 100644
--- a/tests/alltypes_callback/decode_alltypes_callback.c
+++ b/tests/alltypes_callback/decode_alltypes_callback.c
@@ -450,6 +450,9 @@
alltypes.oneof_msg1.funcs.decode = &read_submsg;
alltypes.oneof_msg1.arg = &oneof_msg1;
+
+ alltypes.opt_non_zero_based_enum.funcs.decode = &read_varint;
+ alltypes.opt_non_zero_based_enum.arg = (void *)NonZeroBasedEnum_Three;
}
status = pb_decode(stream, AllTypes_fields, &alltypes);
diff --git a/tests/alltypes_callback/encode_alltypes_callback.c b/tests/alltypes_callback/encode_alltypes_callback.c
index 8f00b77..d123bf7 100644
--- a/tests/alltypes_callback/encode_alltypes_callback.c
+++ b/tests/alltypes_callback/encode_alltypes_callback.c
@@ -447,6 +447,9 @@
alltypes.oneof_msg1.funcs.encode = &write_submsg;
alltypes.oneof_msg1.arg = &oneof_msg1;
+
+ alltypes.opt_non_zero_based_enum.funcs.encode = &write_varint;
+ alltypes.opt_non_zero_based_enum.arg = (void *)NonZeroBasedEnum_Three;
}
alltypes.end.funcs.encode = &write_varint;
diff --git a/tests/alltypes_pointer/decode_alltypes_pointer.c b/tests/alltypes_pointer/decode_alltypes_pointer.c
index 5659012..f652b17 100644
--- a/tests/alltypes_pointer/decode_alltypes_pointer.c
+++ b/tests/alltypes_pointer/decode_alltypes_pointer.c
@@ -103,6 +103,8 @@
TEST(alltypes.opt_fbytes == NULL);
TEST(alltypes.which_oneof == 0);
+
+ TEST(alltypes.opt_non_zero_based_enum == NULL);
}
else
{
@@ -134,6 +136,8 @@
TEST(alltypes.which_oneof == AllTypes_oneof_msg1_tag);
TEST(alltypes.oneof.oneof_msg1 && strcmp(alltypes.oneof.oneof_msg1->substuff1, "4059") == 0);
TEST(alltypes.oneof.oneof_msg1->substuff2 && *alltypes.oneof.oneof_msg1->substuff2 == 4059);
+
+ TEST(alltypes.opt_non_zero_based_enum && *alltypes.opt_non_zero_based_enum == NonZeroBasedEnum_Three);
}
TEST(alltypes.req_limits->int32_min && *alltypes.req_limits->int32_min == INT32_MIN);
diff --git a/tests/alltypes_pointer/encode_alltypes_pointer.c b/tests/alltypes_pointer/encode_alltypes_pointer.c
index ed780de..7f4b391 100644
--- a/tests/alltypes_pointer/encode_alltypes_pointer.c
+++ b/tests/alltypes_pointer/encode_alltypes_pointer.c
@@ -91,6 +91,8 @@
static int32_t oneof_substuff = 4059;
SubMessage oneof_msg1 = {"4059", &oneof_substuff};
+ NonZeroBasedEnum opt_non_zero_based_enum = NonZeroBasedEnum_Three;
+
/* Values for the Limits message. */
static int32_t int32_min = INT32_MIN;
static int32_t int32_max = INT32_MAX;
@@ -197,6 +199,8 @@
alltypes.which_oneof = AllTypes_oneof_msg1_tag;
alltypes.oneof.oneof_msg1 = &oneof_msg1;
+
+ alltypes.opt_non_zero_based_enum = &opt_non_zero_based_enum;
}
alltypes.end = &end;
diff --git a/tests/common_unittests/common_unittests.c b/tests/common_unittests/common_unittests.c
index faa8173..fabe67c 100644
--- a/tests/common_unittests/common_unittests.c
+++ b/tests/common_unittests/common_unittests.c
@@ -91,6 +91,8 @@
TEST(iter.required_field_index == 19)
TEST(iter.submessage_index == 7)
+ TEST(pb_field_iter_next(&iter) && iter.tag == 62 && iter.pData == &msg.opt_non_zero_based_enum && iter.pSize == &msg.has_opt_non_zero_based_enum)
+
TEST(pb_field_iter_next(&iter) && iter.tag == 96 && iter.pData == &msg.req_intsizes && !iter.pSize)
TEST(iter.required_field_index == 19)
TEST(iter.submessage_index == 8)
diff --git a/tests/field_size_16/alltypes.proto b/tests/field_size_16/alltypes.proto
index c094421..9191ca0 100644
--- a/tests/field_size_16/alltypes.proto
+++ b/tests/field_size_16/alltypes.proto
@@ -1,5 +1,11 @@
syntax = "proto2";
+enum NonZeroBasedEnum {
+ Two = 2;
+ Three = 3;
+ Four = 4;
+}
+
message SubMessage {
required string substuff1 = 1 [default = "1"];
required int32 substuff2 = 2 [default = 2];
@@ -127,6 +133,8 @@
EmptyMessage oneof_msg2 = 10061;
}
+ optional NonZeroBasedEnum opt_non_zero_based_enum = 10062;
+
// Check support for custom integer sizes
required IntSizes req_intsizes = 96;
diff --git a/tests/field_size_32/alltypes.proto b/tests/field_size_32/alltypes.proto
index 536fc2a..2ae0f1f 100644
--- a/tests/field_size_32/alltypes.proto
+++ b/tests/field_size_32/alltypes.proto
@@ -1,5 +1,11 @@
syntax = "proto2";
+enum NonZeroBasedEnum {
+ Two = 2;
+ Three = 3;
+ Four = 4;
+}
+
message SubMessage {
required string substuff1 = 1 [default = "1"];
required int32 substuff2 = 2 [default = 2];
@@ -127,6 +133,8 @@
EmptyMessage oneof_msg2 = 10061;
}
+ optional NonZeroBasedEnum opt_non_zero_based_enum = 10062;
+
// Check support for custom integer sizes
required IntSizes req_intsizes = 96;
diff --git a/tests/package_name/SConscript b/tests/package_name/SConscript
index 4afc503..071a3e8 100644
--- a/tests/package_name/SConscript
+++ b/tests/package_name/SConscript
@@ -22,7 +22,7 @@
data = open(str(source[0]), 'r').read()
- type_names = ['AllTypes', 'MyEnum', 'HugeEnum']
+ type_names = ['AllTypes', 'MyEnum', 'HugeEnum', 'NonZeroBasedEnum']
for name in type_names:
data = data.replace(name, 'test_package_' + name)
diff --git a/tests/package_name_nanopb/SConscript b/tests/package_name_nanopb/SConscript
index 990602d..9088f12 100644
--- a/tests/package_name_nanopb/SConscript
+++ b/tests/package_name_nanopb/SConscript
@@ -24,7 +24,7 @@
data = open(str(source[0]), 'r').read()
- type_names = ['AllTypes', 'MyEnum', 'HugeEnum']
+ type_names = ['AllTypes', 'MyEnum', 'HugeEnum', 'NonZeroBasedEnum']
for name in type_names:
data = data.replace(name, 'test_package_' + name)