Protocol buffers and enums combinations?

Royi Namir picture Royi Namir · Nov 7, 2014 · Viewed 21.3k times · Source

This is my proto file :

message MSG {

  required MsgCodes MsgCode = 1;
  optional int64 Serial = 2;        // Unique ID number for this person.
  required int32 From = 3;  
  required int32 To = 4;  
  //bla bla...
        enum MsgCodes
        {
            MSG = 1;
            FILE = 2;
            APPROVE=4;
            ACK=8;
            ERROR_SENDING=16;
            WORLD=32;
        }
}

In my C# I'm trying to :

 msg = msg.ToBuilder().SetMsgCode(msg.MsgCode | MSG.Types.MsgCodes.ACK | MSG.Types.MsgCodes.APPROVE).Build();
 SendToJava(msg);

But the JAVA tells me : missing MsgCode ( which is a required)

Removing the combination - does solve it

But I need to specify combinations

Question

How can I solve it ?

nb :

The weird thing is that if I create a msg and set multiple enums , and then reads it in C# again - it does work...:-(

Answer

Kenton Varda picture Kenton Varda · Nov 8, 2014

In Protobufs, an enum-typed field is only allowed to have one of the exact numeric values specified in the enum. That is to say, you cannot use an enum-typed field as a bitfield. If you want a bitfield, you need to use an integer type like int32. This rule actually applies even in languages that have numeric enum types, like C++ -- if an enum-typed protobuf field read from the wire has an invalid value, it will be treated like an unknown field and thus hidden.

If you switch to integers, you of course now have the problem of how to declare flag values. Unfortunately Protobufs provides no good way to define constants. As you suggested in your self-answer, you can use a dummy enum definition as a hack, but note that the numeric value won't necessarily be available in all languages. It works in C++ and Python since they use numeric enums (and apparently C# too?). In Java, Protobuf enums have a .getNumber() method which you can use to get the numeric value; otherwise, normal Java enums are not numeric.

(Aside: I'm the author of most of Google's open source Protobuf code. I'm also the author of Cap'n Proto, a newer non-Google project aimed at replacing Protobufs. Among other advantages, Cap'n Proto supports defining constants in schema files. But, as of this writing C# support is not ready yet (though being worked on!).)