aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNoah Pendleton <2538614+noahp@users.noreply.github.com>2019-05-31 21:09:57 -0400
committerPetteri Aimonen <jpa@git.mail.kapsi.fi>2019-06-01 09:37:32 +0300
commit0381b5f0abaa0c627a8ee8291f1281f97aec5d6c (patch)
tree1e7820841215f5e23f8be6eaaf507c2af6deaf56
parent3c69a905b16df149e1bda12f25e0522073a24678 (diff)
downloadnanopb-c-0381b5f0abaa0c627a8ee8291f1281f97aec5d6c.tar.gz
🔀 use min/max enum value for min/max
Unsorted enums in message specifications do not result in correct min/max values per the protobuf spec for cpp code: https://developers.google.com/protocol-buffers/docs/reference/cpp-generated#enum The google cpp compiler uses the min/max _value_ instead of the position of the enum entry in the message spec, so this patch updates nanopb to do the same. Example input: ```protobuf syntax = "proto3"; enum Language { UNKNOWN = 0; ENGLISH_EN_GB = 12; ENGLISH_EN_US = 1; FRENCH_FR_FR = 2; ITALIAN_IT_IT = 3; GERMAN_DE_DE = 4; SPANISH_ES_AR = 13; SPANISH_ES_ES = 5; SPANISH_ES_MX = 14; SWEDISH_SV_SE = 6; DUTCH_NL_NL = 7; KOREAN_KO_KR = 8; JAPANESE_JA_JP = 9; CHINESE_SIMPLIFIED_ZH_CN = 10; CHINESE_TRADITIONAL_ZH_TW = 11; } ``` This would previously result in: ```c #define _Language_MIN Language_UNKNOWN #define _Language_MAX Language_CHINESE_TRADITIONAL_ZH_TW #define _Language_ARRAYSIZE ((Language)(Language_CHINESE_TRADITIONAL_ZH_TW+1)) ``` After this patch, ```c #define _Language_MIN Language_UNKNOWN #define _Language_MAX Language_SPANISH_ES_MX #define _Language_ARRAYSIZE ((Language)(Language_SPANISH_ES_MX+1)) ``` Add a test `enum_minmax` to cover this case.
-rwxr-xr-xgenerator/nanopb_generator.py9
-rw-r--r--tests/enum_minmax/SConscript8
-rw-r--r--tests/enum_minmax/enumminmax.proto22
-rw-r--r--tests/enum_minmax/enumminmax_unittests.c16
4 files changed, 52 insertions, 3 deletions
diff --git a/generator/nanopb_generator.py b/generator/nanopb_generator.py
index 03f41a0..63983e5 100755
--- a/generator/nanopb_generator.py
+++ b/generator/nanopb_generator.py
@@ -224,9 +224,12 @@ class Enum:
result += ' %s;' % self.names
- result += '\n#define _%s_MIN %s' % (self.names, self.values[0][0])
- result += '\n#define _%s_MAX %s' % (self.names, self.values[-1][0])
- result += '\n#define _%s_ARRAYSIZE ((%s)(%s+1))' % (self.names, self.names, self.values[-1][0])
+ # sort the enum by value
+ sorted_values = sorted(self.values, key = lambda x: (x[1], x[0]))
+
+ result += '\n#define _%s_MIN %s' % (self.names, sorted_values[0][0])
+ result += '\n#define _%s_MAX %s' % (self.names, sorted_values[-1][0])
+ result += '\n#define _%s_ARRAYSIZE ((%s)(%s+1))' % (self.names, self.names, sorted_values[-1][0])
if not self.options.long_names:
# Define the long names always so that enum value references
diff --git a/tests/enum_minmax/SConscript b/tests/enum_minmax/SConscript
new file mode 100644
index 0000000..6a66cbd
--- /dev/null
+++ b/tests/enum_minmax/SConscript
@@ -0,0 +1,8 @@
+# Test that different sizes of enum fields are properly encoded and decoded.
+
+Import('env')
+
+env.NanopbProto('enumminmax')
+
+p = env.Program(["enumminmax_unittests.c",])
+env.RunTest(p)
diff --git a/tests/enum_minmax/enumminmax.proto b/tests/enum_minmax/enumminmax.proto
new file mode 100644
index 0000000..482a8db
--- /dev/null
+++ b/tests/enum_minmax/enumminmax.proto
@@ -0,0 +1,22 @@
+/* Test out-of-order enum values.
+ */
+
+syntax = "proto3";
+
+enum Language {
+ UNKNOWN = 0;
+ ENGLISH_EN_GB = 12;
+ ENGLISH_EN_US = 1;
+ FRENCH_FR_FR = 2;
+ ITALIAN_IT_IT = 3;
+ GERMAN_DE_DE = 4;
+ SPANISH_ES_AR = 13;
+ SPANISH_ES_ES = 5;
+ SPANISH_ES_MX = 14;
+ SWEDISH_SV_SE = 6;
+ DUTCH_NL_NL = 7;
+ KOREAN_KO_KR = 8;
+ JAPANESE_JA_JP = 9;
+ CHINESE_SIMPLIFIED_ZH_CN = 10;
+ CHINESE_TRADITIONAL_ZH_TW = 11;
+}
diff --git a/tests/enum_minmax/enumminmax_unittests.c b/tests/enum_minmax/enumminmax_unittests.c
new file mode 100644
index 0000000..ccb10a4
--- /dev/null
+++ b/tests/enum_minmax/enumminmax_unittests.c
@@ -0,0 +1,16 @@
+#include "unittests.h"
+#include "enumminmax.pb.h"
+
+int main()
+{
+ int status = 0;
+
+ COMMENT("Verify min/max on unsorted enum");
+ {
+ TEST(_Language_MIN == Language_UNKNOWN);
+ TEST(_Language_MAX == Language_SPANISH_ES_MX);
+ TEST(_Language_ARRAYSIZE == (Language_SPANISH_ES_MX+1));
+ }
+
+ return status;
+}