java 协议缓冲区和枚举组合?

qeeaahzv  于 2023-01-19  发布在  Java
关注(0)|答案(5)|浏览(146)

这是我的原始文件:

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;
        }
}

在我的C#中,我尝试:

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

但是JAVA告诉我:缺少MsgCode(为required
删除组合-****是否解决了该问题
但我需要指定组合

    • 问题**

我该怎么解决呢?
编号:
奇怪的是,如果我创建一个msg并设置多个枚举,然后再次用C#读取它-它确实工作...:-(

inkz8wg9

inkz8wg91#

在Protobufs中,一个枚举类型的字段只允许有一个在枚举中指定的精确数值。也就是说,你 * 不能 * 使用一个枚举类型的字段作为位字段。如果你想要一个位字段,你需要使用一个整数类型,比如int32。这个规则实际上甚至在有数字枚举类型的语言中也适用。像C一样--如果从连接中读取的enum类型的protobuf字段具有无效值,则它将被视为未知字段并因此被隐藏。
如果你切换到整数,你当然会遇到如何声明标志值的问题。不幸的是,Protobufs没有提供定义常量的好方法。正如你在自己的答案中建议的,你可以使用一个伪枚举定义作为一个技巧。但是注意,数值并不一定在所有语言中都可用,它在C
和Python中有效,因为它们使用数字枚举在Java中,Protobuf枚举有一个.getNumber()方法,你可以用它来获取数值;否则,正常的Java枚举不是数字。
(题外话:我是Google大部分开源Protobuf代码的作者。我也是Cap'n Proto的作者,这是一个较新的非Google项目,旨在取代Protobuf。Cap 'n Proto支持在模式文件中定义常量。但是,截至本文撰写之时,C#支持还没有准备好(尽管正在开发中!)

s6fujrry

s6fujrry2#

如果你不需要挤出每一寸效率(提示:您可能不需要),那么就使用枚举值数组。

message Msg {
    // ...
    enum Code
    {
        CODE_UNSPECIFIED = 0;
        CODE_MSG = 1;
        CODE_FILE = 2;
        CODE_APPROVE = 3;
        CODE_ACK = 4;
        CODE_ERROR_SENDING = 5;
        CODE_WORLD = 6;
    }
    repeated Code codes = 5;
}

官方的protobuf文档建议你保留一个等于0的枚举项来表示“未知”之类的东西。它实际上是针对那些用作非重复值的枚举(因为在proto3中0枚举值和unset之间没有区别),但值得所有枚举遵循,以及上面用枚举名作为枚举值前缀的约定。

bkhjykvo

bkhjykvo3#

我找到了一个解决办法(算是)
我需要一个整数保持器。

message Foo {
  enum Flags {
    FLAG1 = 0x01;
    FLAG2 = 0x02;
    FLAG3 = 0x04;
  }

  // Bitwise-OR of Flags.
  optional uint32 flags = 1;
  • 这是唯一的解决办法吗
b4wnujal

b4wnujal4#

您可以使用message来代替enums,并使用bool类型来表示您需要的标志。
下面是一个简单的闹钟模式示例,可以将其设置为一周中的多天:

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;
    }
}
x8goxv8g

x8goxv8g5#

将字段定义为整数:

required int32 MsgCode = 1;

按照您的问题定义枚举,即使.proto文件中没有任何内容引用它。
在你的代码中使用枚举域。在C#中,这就像你的例子(尽管这取决于你使用的库,例如protobuf-net是优秀的,并且有一个轻量级的Enum.Field语法)。在Java中,使用带有_VALUE后缀的域,例如MsgCodes.APPROVE_VALUE

相关问题