【发布时间】:2021-12-08 04:23:56
【问题描述】:
我想让以下 ProtoBuffer 消息向前兼容。
当前 Storage 消息将 state 字段定义为 bool 类型:
message Storage {
bool state = 1;
}
在 Protobuffer 编码中,它将 Varint 类型如 bool 和 enum 类型编码为以下格式:
|1-bit sequence number|4-bit serial number|3-bit data type|n-bit payload|
对于Varint类型,数据类型值会变成000:
|X|XXXX|000|XXXX...|
由于Storage消息结构只包含一个序列号为1的字段,由于序列号尚未解析到最后一个字节。因此,上述格式将变为:
|0|0001|000|XXXX...|
现在,如果设置 Storage.state = 0,它将按如下方式存储:
|0|0001|000|<0 will not be encoded>
Storage 消息的 Protobuffer 值将变为 0x8。
如果设置Storage.state = 1,则存储如下:
|0|0001|000|00000001|
Storage 消息的 Protobuffer 值将变为 0x8 0x1。
现在,我想将上述 Storage.state 定义从 bool 类型更改为 enum输入如下:
// BIT7 | BIT6 | BIT5 | BIT4 | BIT3 | BIT2 | BIT1 | BIT0 |
//-------------------------------------------------------
// 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | = STATE0 (0)
// 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | = STATE1 (1)
// 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | = STATE2 (2)
// 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | = STATE2 (3)
//... so go on
// 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | = STATE2 (254)
// 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | = STATE2 (255)
enum State {
STATE0 = 0;
STATE1 = 1;
STATE2 = 2;
STATE3 = 3;
//... so go on
STATE254 = 254;
STATE255 = 255;
}
message Storage {
State state = 1
}
所以现在,在 Protobuf 编码中,
如果设置Storage.state = State.STATE0,则存储如下:
|0|0001|000|<0 will not be encoded>
Storage 消息的 Protobuffer 值将变为 0x8。
如果设置Storage.state = State.STATE1,则存储如下:
|0|0001|000|00000001|
Storage 消息的 Protobuffer 值将变为 0x8 0x1。
如果设置Storage.state = State.STATE2,则存储如下:
|0|0001|000|00000010|
Storage 消息的 Protobuffer 值将变为 0x8 0x2。
如果设置Storage.state = State.STATE255,则存储如下:
|0|0001|000|11111111|
Storage 消息的 Protobuffer 值将变为 0x8 0xFF。
此更改是否仍向前兼容 proto2 和 proto3 以及 C 和 Java?
我的问题基于以下参考: google protocol buffer -- the coding principle of protobuf II
【问题讨论】:
-
问题:你的状态 - 这 256 个选项都是独立的东西,还是你实际上试图表示按位状态值,即 C# 术语中的
[Flags] enum(是的,我知道你没有问关于 C#) -
是的,按位状态值,但专门用于 C 和 Java 实现。
标签: protocol-buffers proto protobuf-java protobuf-c