java 协议缓冲区和枚举组合?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/26810188/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Protocol buffers and enums combinations?
提问by Royi Namir
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 :
在我的 C# 中,我试图:
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
)
但是 JAVA 告诉我:缺少 MsgCode(这是一个required
)
Removing the combination - doessolve 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...:-(
奇怪的是,如果我创建一个msg
并设置多个 enums ,然后再次在 C# 中读取它 - 它确实有效...:-(
采纳答案by Kenton Varda
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 cannotuse 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.
在 Protobufs 中,枚举类型的字段只允许具有枚举中指定的精确数值之一。也就是说,您不能将枚举类型的字段用作位字段。如果你想要一个位域,你需要使用像int32
. 这个规则实际上甚至适用于具有数字枚举类型的语言,如 C++——如果从线路读取的枚举类型的 protobuf 字段具有无效值,它将被视为未知字段并因此隐藏。
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.
如果您切换到整数,您当然会遇到如何声明标志值的问题。不幸的是,Protobufs 没有提供定义常量的好方法。正如您在自我回答中所建议的那样,您可以使用虚拟枚举定义作为一种技巧,但请注意,该数值不一定适用于所有语言。它适用于 C++ 和 Python,因为它们使用数字枚举(显然也是 C#?)。在 Java 中,Protobuf 枚举有一个.getNumber()
方法可以用来获取数值;否则,普通的 Java 枚举不是数字。
(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!).)
(另外:我是 Google 大部分开源 Protobuf 代码的作者。我也是Cap'n Proto的作者,这是一个旨在取代 Protobufs 的较新的非 Google 项目。除其他优点外,Cap'n Proto 支持定义模式文件中的常量。但是,在撰写本文时,C# 支持还没有准备好(尽管正在开发中!)。
回答by Louis CAD
You can use message instead of enums, and use bool type for the flags you need.
您可以使用消息而不是枚举,并使用 bool 类型作为您需要的标志。
Here's an example for a simple Alarm Clock schema where it can be set for multiple days in the week:
下面是一个简单的闹钟模式的例子,它可以设置为一周中的多天:
message Alarm {
uint32 hour = 1;
uint32 minute = 2;
bool repeat = 3;
DaysOfWeek daysOfWeek = 4;
message DaysOfWeek {
bool sunday = 1;
bool monday = 2;
bool tuesday = 3;
bool wednesday = 4;
bool thursday = 5;
bool friday = 6;
bool saturday = 7;
}
}
回答by Arthur Tacca
If you don't need to squeeze out every last inch of efficiency (hint: you probably don't), then just use an array of enum values.
如果您不需要挤出最后一英寸的效率(提示:您可能不需要),那么只需使用枚举值数组。
message Msg {
// ...
enum Code
{
MSG = 0;
FILE = 1;
APPROVE = 2;
ACK = 3;
ERROR_SENDING = 4;
WORLD = 5;
}
repeated Code codes = 5;
}
回答by Edward Brey
Define the field as an integer:
将字段定义为整数:
required int32 MsgCode = 1;
Define the enum as in your question, even though nothing in the .proto file will reference it.
将枚举定义为您的问题,即使 .proto 文件中没有任何内容会引用它。
Use the enum fields in your code. In C#, it's like your example (although it depends on which library you use (e.g. protobuf-netis excellent and has a lightweight Enum.Field syntax). In Java, use the fields with the _VALUE
suffix, e.g. MsgCodes.APPROVE_VALUE
.
在代码中使用枚举字段。在 C# 中,它就像您的示例(尽管这取决于您使用的库(例如protobuf-net非常出色并且具有轻量级的 Enum.Field 语法)。在 Java 中,使用带有_VALUE
后缀的字段,例如MsgCodes.APPROVE_VALUE
.
回答by Royi Namir
I found a solution (sort of)
我找到了一个解决方案(有点)
need an int holder.
需要一个 int 持有人。
message Foo {
enum Flags {
FLAG1 = 0x01;
FLAG2 = 0x02;
FLAG3 = 0x04;
}
// Bitwise-OR of Flags.
optional uint32 flags = 1;
- Mmm, Is it the only solution ?
- 嗯,这是唯一的解决方案吗?