On Mon, Oct 30, 2017 at 6:19 PM, <[email protected]> wrote:

> Hi Feng,
>
> Thanks for answering.
>
> As suggested by the official documentation:
> https://developers.google.com/protocol-buffers/docs/
> reference/cpp-generated#enum
> We can handle the unknown enum value through either a `default` clause or
> an `if` check as follows:
>
> // Wrong version of client-side code:
> int HandleFoo(Foo foo) {
>   if (Foo::Type_IsValid(foo.type()) {
>     switch (foo.type()) {
>       case FOO: return ...;
>       case BAR: return ...;
>       case google::protobuf::kint32min:
>       case google::protobuf::kint32max:
>         // UNREACHABLE.
>     }
>   } else {
>     // Handle the unknown enum value properly.
>   }
> }
>
> So this way we can ensure that the unknown enum values are handled,
> and also the compiler can check if an enum value is missing in the
> `switch` statement for us.
> Is it future-proof to use `google::protobuf::kint32max` or
> `*_INT_MAX_SENTINEL_DO_NOT_USE_`?
>
No, it will break right away when we add another
"*_XXX_SENTINEL_DO_NOT_USE_", or when we want to rename "XXX_DO_NOT_USE" to
"XXX_DO_NOT_USE_PLEASE_ADD_DEFAULT_CASE".


> It seems to me that there's some merit to formalize this in the proto3
> language. Thoughts?
>
> Best,
> Chun-Hung
>
>
> On Monday, October 30, 2017 at 12:29:26 PM UTC-7, Feng Xiao wrote:
>>
>>
>>
>> On Mon, Oct 30, 2017 at 9:57 AM, <[email protected]> wrote:
>>
>>> Hi all,
>>>
>>> I'm from the Apache Mesos community and we're working on things that
>>> uses proto3.
>>> We usually turn on compiler options to report missing values in switch
>>> statements,
>>> and don't do a "default" clause. This gives us the benefit of capturing
>>> missing enum
>>> values during compile time. However, it seems that for proto3's open
>>> enum values,
>>> we need to either manually adding those `*_INT_MAX_SENTINEL_DO_NOT_USE_`
>>> values
>>> in switch statements, or add a default clause to avoid such errors but
>>> then we lose
>>> the benefit I mentioned above. It seems that the compiler is not clever
>>> enough
>>> to infer that clauses for those sentinel values are not needed for
>>> switch statements
>>> that are inside `if(Enum_IsValid(...))` statements.
>>>
>>> My question is, what's the best practice if I don't want to add a
>>> default clause?
>>> Is it safe to add either `*_INT_MAX_SENTINEL_DO_NOT_USE_` symbols
>>> or `google::protobuf::kint32max` into switch statements, such that these
>>> will
>>> remain unchanged in future versions of protobuf library? Or is there a
>>> better way
>>> to address this?
>>>
>> The recommendation is to always have a default case when handling proto3
>> enums. Unlike regular enums that fall in a defined list of possible values,
>> proto3 enums can have unrecognized values when a client receives data from
>> a remote server with a new enum definition. To ensure such unrecognized
>> values are correctly handled, a default case must be added.
>>
>> For example, suppose you have a client built with such a proto:
>> message Foo {
>>   enum Type {
>>     FOO = 0;
>>     BAR = 1;
>>   }
>>   Type type = 1;
>> }
>>
>> and later someone adds a new value into the enum and uses the new
>> definition on the server side:
>> message Foo {
>>   enum Type {
>>     FOO = 0;
>>     BAR = 1;
>>     BAZ = 2;
>>   }
>>   Type type = 1;
>> }
>>
>> If your client receives data from the server with type = BAZ, foo.type()
>> will return 2, which you can't catch with any predefined values. If you
>> don't have default case, undefined behavior ensures.
>>
>> // Wrong version of client-side code:
>> int HandleFoo(Foo foo) {
>>   switch (foo.type()) {
>>     case FOO: return ...;
>>     case BAR: return ...;
>>     case *_INT_MAX_SENTINEL_DO_NOT_USE: return ...;
>>   }
>>   // You can never get here, or maybe you can?
>> }
>>
>> // The correct version
>> int HandleFoo(Foo foo) {
>>   switch (foo.type()) {
>>     case FOO: return ...;
>>     case BAR: return ...;
>>     default: return ...;  // There is an enum value we don't know about,
>> handle it appropriately.
>>   }
>>   // You can never get here.
>> }
>>
>>
>>>
>>> Thanks,
>>> Chun-Hung
>>>
>>> --
>>> You received this message because you are subscribed to the Google
>>> Groups "Protocol Buffers" group.
>>> To unsubscribe from this group and stop receiving emails from it, send
>>> an email to [email protected].
>>> To post to this group, send email to [email protected].
>>> Visit this group at https://groups.google.com/group/protobuf.
>>> For more options, visit https://groups.google.com/d/optout.
>>>
>>
>> --
> You received this message because you are subscribed to the Google Groups
> "Protocol Buffers" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to [email protected].
> To post to this group, send email to [email protected].
> Visit this group at https://groups.google.com/group/protobuf.
> For more options, visit https://groups.google.com/d/optout.
>

-- 
You received this message because you are subscribed to the Google Groups 
"Protocol Buffers" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
Visit this group at https://groups.google.com/group/protobuf.
For more options, visit https://groups.google.com/d/optout.

Reply via email to