diff options
author | Noah Pendleton <2538614+noahp@users.noreply.github.com> | 2019-05-31 21:09:57 -0400 |
---|---|---|
committer | Petteri Aimonen <jpa@git.mail.kapsi.fi> | 2019-06-01 09:37:32 +0300 |
commit | 0381b5f0abaa0c627a8ee8291f1281f97aec5d6c (patch) | |
tree | 1e7820841215f5e23f8be6eaaf507c2af6deaf56 | |
parent | 3c69a905b16df149e1bda12f25e0522073a24678 (diff) | |
download | nanopb-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-x | generator/nanopb_generator.py | 9 | ||||
-rw-r--r-- | tests/enum_minmax/SConscript | 8 | ||||
-rw-r--r-- | tests/enum_minmax/enumminmax.proto | 22 | ||||
-rw-r--r-- | tests/enum_minmax/enumminmax_unittests.c | 16 |
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; +} |