varints
在了解protobuf编码原理之前,首先要了解的是varints
。
varints
是一种用一个或多个字节来序列化整数的方法。整数的值越小,占用的字节数就越少。
varints
的每个字节的第一个bit最高有效位
(msb
)是用来指示下一个字节是不是还是用来表示这个整数的。可以将它看成一个单链表的next指针,为1则指向下一个节点,为0则指向null。而varints
较低位的7个bit以二进制补码、低字节序(小端)的形式存储整数。
例如:
有以下varints表示的整数:
1010 1100 0000 0010
要解码得到原来的数值,首先要去掉每个字节的msb(msb只是用来告诉这个整数是不是已经到结尾了,计算数值时并没有用),得到了一下没有msb的形式:
010 1100 000 0010
然后,由于varints是低字节序的,因此需要先对字节进行一个反转(reverse)操作,得到:
000 0010 010 1100
→ 100101100
→ 256 + 32 + 8 + 4 = 300
Message
protobuf message是一系列的键值对,message的二进制形式使用字段的tag数值作为key,而其的字段名以及实际的数据类型则只能在解码端根据message的类型定义来决定。
编码message时,key和value被连接成字节流。当解码message的时候,解释器要有能力跳过那些他不能识别的字段,这样子,才能够添加新的字段进message而且不会影响不能识别这些新字段的老程序。
为此,每个字节流上的每个key实际上是由两个值组成的——一个是字段的tag number,另一个是
该字段的 wire type
,这是用来提供足够的信息来明确该字段的值得长度的。
下面是可选的wire type
:
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 repeat |