Protobuf数据编码规则

  • ProtoBuf编码基础:——Varints, varints是一种将一个整数序列化为一个或者多个Bytes的方法,越小的整数,使用的Bytes越少。Varints的基本规则是:
  •  每个Byte的最高位(msb)是标志位,如果该位为1,表示该Byte后面还有其它Byte,如果该位为0,表示该Byte是最后一个Byte。
  • 每个Byte的低7位是用来存数值的位
  • Varints方法用Litte-Endian(小端)字节序
  • 举个例子:300用Varints序列化的结果是1010 1100 0000 0010,运算过程如下 所示:

        1010 1100 0000 0010->010 1100 000 0010(去标志位)->000 0010 010 1100(调整字节序)-> 1 0010 1100 ->256+32+8+4=300(计算值)

  • ProtoBuf把message看成是 key - value的组合

    (c)key由两部分组成,一部分是在定义消息时对字段的编号(field_num),另一部分是字段类型(wire_type)。字段类型定义如下表所示。

    TypeMeaningUsed For
    0Varintint32, int64, uint32, uint64, sint32, sint64, bool, enum
    164-bitfixed64, sfixed64, double
    2Length-delimitedstring, bytes, embedded messages, packed repeated fields
    3Start groupgroups (deprecated)
    4End groupgroups (deprecated)
    532-bitfixed32, sfixed32, float

    (d)key的编码方式:field_num << 3 | wire_type

    (e)varint类型(wire_type=0)的编码,与第(1)部分中介绍的方法基本一致,但是int32, int64和sint32,sint64有些特别之处:int32和int64就是简单的按varints方法来编码,所以像-1、-2这样负数也会占比较多的Bytes。于是sint32和sint64采用了一种改进的方法:先采用Zigzag方法将所有的整数(正数、0和负数)一一映射到所有的无符号数上,然后再采用varints编码方法进行编码。Zigzag映射函数为:

    Zigzag(n) = (n << 1) ^ (n >> 31),  n为sint32时

    Zigzag(n) = (n << 1) ^ (n >> 63),  n为sint64时

    下表是一个比较直观的映射表,这样映射后再进行编码的好处就是绝对值比较小的负数序列化后的结果占的Bytes数也会比较少。

    Signed OriginalEncoded As
    00
    -11
    12
    -23
    24
    -35
    21474836474294967294
    -21474836484294967295

    (f)64-bit(wire_type=1)和32-bit(wire_type=5)的编码方式就比较简单了,直接在key后面跟上64bits或32bits,采用Little-Endian(小端)字节序。

    (g)length-delimited(wire_type=2)的编码方式:key+length+content, key的编码方式是统一的,length采用varints编码方式,content就是由length指定的长度的Bytes。

    (h)wire_type=3和4的现在已经不推荐使用了,因此这里也不再做介绍。

    3)ProtoBuf编解码中字段顺序(Field order)的问题:

    (a) 编码/解码与字段顺序无关,这一点由key-value机制就能保证

    (b)对于未知的字段,编码的时候会把它写在序列化完的已知字段后面。
  • 编码分为三段:      
12 07 74 65 73 74 69 6e 67

The red bytes are the UTF8 of "testing". The key here is 0x12 → tag = 2, type = 2. The length varint in the value is 7 and lo and behold, we find seven bytes following it – our string.



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值