Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

solutions to resolve enum field naming restriction in Google protobuf due to C++

Tags:

As you might know, when you define enums in Google protobuf either with global scope or in same message, you can't define enum field name to be same if enums are sibling.

Even if you are going to generate Java code with proto file, protoc complains about it and doens't generate any code with following message.

"XXX" is already defined in "your.package.name". Note that enum values use C++ scoping rules, meaning that enum values are siblings of their type, not children of it.  Therefore, "XXX" must be unique within "your.package.name", not just within "your_enum_name". 

so, which means you should do something like

  1. wrapping the colliding enums with message.
    • Pros : well... protoc doesn't fail?
    • Cons : generate code is going to have one extra static wrapper class so that it will increase SerDes cost a little bit + naming seems long enough. e.g, CURRENCY.NAMESPACE(wrapper message name).USD

or

  1. use prefix for the field, so if your conflicting field name is UNKNOWN and it's in CURRENCY, it's going to be CURRENCY.CURRENCY_UNKNOWN or something like that.
    • Pros : simple
    • Cons : as ugly as #1, inconsistency with existing enum field naming that doesn't have any prefix.

or

  1. Just don't use Enum. Use string type.
    • Pros : simple, don't need to define fallback enum field like UNKNOWN = 1 as default.
    • Cons : losing benefit of having enum.

Seems like C++ 11 supports better enums that doesn't have this issue, but unfortunately latest protoc doesn't support it, and we can't simply ask other consumers to switch their side to use C++ if they are not using it.

So, it's going to be choosing less worse solution rather than best solution, and probably we are going to use #2 at this point. Does anyone have same experience and tell me what was your solution and how is it ended up?

like image 609
wonhee Avatar asked Nov 20 '14 01:11

wonhee


People also ask

How do enums work in protobuf?

enum is one of the composite datatypes of Protobuf. It translates to an enum in the languages that we use, for example, Java. Now our message class contains an Enum for payment. Each of them also has a position which is what Protobuf uses while serialization and deserialization.

What is protobuf C++?

Protocol Buffers (Protobuf) is a free and open-source cross-platform data format used to serialize structured data. It is useful in developing programs to communicate with each other over a network or for storing data.

What is the difference between proto2 and Proto3?

Proto3 is the latest version of Protocol Buffers and includes the following changes from proto2: Field presence, also known as hasField , is removed by default for primitive fields. An unset primitive field has a language-defined default value.


1 Answers

The prevailing solution in existing code is option (2): give each enumerant name a prefix corresponding to its type. This also helps reduce collisions with macros. It's verbose, but unlike the other options suggested, it has no runtime overhead and it creates the least confusion for people reading the code.

(FWIW, Cap'n Proto has escaped this problem by using C++11 enum classes. It's unlikely that protobufs will ever do this since it would break existing code.)

(Disclosure: I am the author of Cap'n Proto as well as of most of Google's open source Protobuf code.)

like image 174
Kenton Varda Avatar answered Sep 19 '22 15:09

Kenton Varda