protobuf
pb2与pb3
https://stackoverflow.com/questions/56673362/can-proto2-talk-to-proto3
https://stackoverflow.com/questions/42622015/how-to-define-an-optional-field-in-protobuf-3
Encode
Type | Meaning | Used For |
---|---|---|
0 | Varint | int32, int64, uint32, uint64, sint32, sint64, bool, enum |
1 | 64-bit | fixed64, sfixed64, double |
2 | Length-delimited | string, bytes, embedded messages, packed repeated fields |
3 | Start group | groups (deprecated) |
4 | End group | groups (deprecated) |
5 | 32-bit | fixed32, sfixed32, float |
Each key in the streamed message is a varint with the value (field_number << 3) | wire_type
– in other words, the last three bits of the number store the wire type.
zigzag算法, 小整数压缩算法
// 以int为例, 先将int转成前导0的整数(最低位表示最高位符号位, 其余31位用符号位异或), 再自低位开始每隔7位进行划分, 最高位表示后续是否还有信息
int int_to_zigzag(int n) {
return (n <<1) ^ (n >>31);
}
int zigzag_to_int(int n) {
return (((unsignedint)n) >>1) ^ -(n & 1);
}
int write_to_buffer(int zz, byte* buf, int size) {
int ret = 0;
for (int i = 0; i < size; i++) {
if ((zz & (~0x7f)) ==0) {
buf[i] = (byte)zz;
ret = i + 1;
break;
}
else {
buf[i] = (byte)((zz & 0x7f) | 0x80);
zz = ((unsignedint)zz) >> 7;
}
}
return ret;
}
int read_from_buffer(byte* buf, int max_size) {
int ret = 0;
int offset = 0;
for (int i = 0; i < max_size; i++, offset += 7) {
byte n = buf[i];
if ((n & 0x80) != 0x80) {
ret |= (n << offset);
break;
}
else {
ret |= ((n & 0x7f) << offset);
}
}
return ret;
}
-
optional字段如果不填会占用空间吗?
答:不会。 -
int32、fixed32、sint32有什么区别?uint32和enum在序列化后是否有什么区别?
答:int32和sint32类似,都是变长存储,适合大多数情况下数值较小的场景,sint32更适合用在负数较多的场景。fixed32是定长存储,适合数值较大的场景(有效位在4字节)。所谓适合,是指序列化后更省空间。
enum和uint32在序列化后没有区别,反序列化解析时,对于enum会判断有效性,若无效(超出定义范围),则忽略。 -
如果有一方把某字段类型从uint32升级成了uint64会怎样?即双方不一致
答:uint32和uint64在序列化后是同一种类型,即varint(变长整数)。如果是接收方升级成uint64,正常工作;如果发送方升级成uint64,接收方对于超出uint32的值会截断,只保留低32位。 -
string和bytes有什么区别?
答:序列化后没有区别;代码实现看,调试版string比bytes多了utf-8的检查,非调试版没有区别。 -
生成的字节流是否有压缩?是否有加密?
答:对于整数类型,有简单压缩,即varint编码。没有加密,纯明文。 -
不同版本的protobuf生成的字节流是否有差异?
答:没有差异。也没有包头字段表示字节流是哪个版本的protobuf生成的。