Protobuf如何编码消息构造之一

时间:2018-09-07 16:23:52

标签: python serialization protocol-buffers

对于此在编码时运行protobuf编码的python程序,其输出如下:

  

0a 10 08 7f 8a 01 04 08 02 10 03 92 01 04 08 02 10 03 18 01

我不明白的是为什么在8a之后有一个01,又为什么在92a之后有01。 似乎对于oneof类型的信息元素,添加了额外的01,但是为什么呢? 如果有人能理解protobuf编码,请帮助我

import sys
import test2_pb2

def write_to_file(file,value):
    with open(file, "wb") as f:
        f.write(value)

def cell_test_dct():

  msg=test2_pb2.TestPrimM();
  msg.textx=1
  msg.testmsg.testint=127
  msg.testmsg.prbbundlingtype.x =2
  msg.testmsg.prbbundlingtype.static=
   test2_pb2.BUNDLE_SIZE_N_4_WIDEBAND
  msg.testmsg.bundlingtype.x =2
  msg.testmsg.bundlingtype.static=
  test2_pb2.BUNDLE_SIZE_N_4_WIDEBAND
  print (msg)
  str = msg.SerializeToString()
  #write_to_file("/tmp/protobuf_test_file.bin",str)

def main_test():
    cell_test_dct()

main_test()

对于以下protobuf文件:

package NR_TEST;

enum BundleSizeE {
    BUNDLE_SIZE_N_4 = 0;
    BUNDLE_SIZE_WIDEBAND = 1;
    BUNDLE_SIZE_N_2_WIDEBAND = 2;
    BUNDLE_SIZE_N_4_WIDEBAND = 3;
}

message DynamicBundleSizesM {
    // bundleSizeSet1
    optional BundleSizeE bundleSizeSet1 = 1;
    // bundleSizeSet2
    optional BundleSizeE bundleSizeSet2 = 2;
}

message PrbBundlingTypeM {
    optional uint32 x=1;
    oneof BundlingTypeC {
    BundleSizeE static = 2;
    DynamicBundleSizesM dynamic = 3;
    }
}

message Test {
    required int32 testint   =1;
    required PrbBundlingTypeM prbbundlingtype = 17;
    required PrbBundlingTypeM bundlingtype = 18;
}
message TestPrimM
{
  oneof TestMsgC {
    Test testmsg=1;
    int32  nomsg=2;
    }
    required  int32 textx=3;
}

1 个答案:

答案 0 :(得分:0)

给出protobuf encoding,您的消息如下:

0a .. varint key '1|010' -> field 1, type LENGTH_DELIMITED
    10 .. varint length -> 16
    Contents:
        08 .. varint key '1|000' -> field 1, type VARINT
            7f .. varint value -> 127
        8a 01 .. varint key '00000010001|010' -> field 17, type LENGTH_DELIMITED
            04 .. varint length -> 4
            Contents:
                08 .. varint key '1|000' -> field 1, type VARINT
                    02 .. varint value -> 2
                10 .. varint key '10|000' -> field 2, type VARINT
                    03 .. varint value -> 3
        92 01 .. varint key '00000010010|010' -> field 18, type LENGTH_DELIMITED
            04 .. varint length -> 4
            Contents:
                08 .. varint key '1|000' -> field 1, type VARINT
                    02 .. varint value -> 2
                10 .. varint key '10|000' -> field 2, type VARINT
                    03 .. varint value -> 3
18 .. varint key '11|000' field 3, type VARINT
    01 .. varint value -> 1

长度分隔字段17的标记的整数值是二进制的:10001|01010001是17而010是长度分隔的wire type)->给定{ {1}}(二进制)。

要将这个数字编码为varint,您需要将总位长调整为7的倍数(用零填充):

  

-> 000000 10001010

然后将其分成7位:

  

-> 0000001 0001010

然后颠倒这些组的顺序:

  

-> 0001010 0000001

然后为每个组(MSB)添加一个额外的位-在最后一个组中添加零,在所有其他组中添加一个(MSB等于1告诉解析器后面还有另一个组):

  

-> 1 0001010 0 0000001

哪个以十六进制(您的值)给出10001010

Varint编码为here


据我所知,oneof构造不会更改线路格式(它仅扩展了解析器逻辑,它忽略所有内容,但忽略单个oneof组中的最后一个字段)。

祝你好运!