Как Protobuf кодирует одну из конструкций сообщения - PullRequest
0 голосов
/ 07 сентября 2018

Для этой программы на Python, выполняющей кодирование protobuf при кодировании, выдается следующий вывод:

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

Чего я не понимаю, так это того, почему после 8а есть 01, и опять же, почему 01 после 92. Кажется, для информационного элемента типа 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 голосов
/ 13 сентября 2018

Учитывая кодирование protobuf Ваше сообщение выглядит следующим образом:

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|010 (10001 равно 17 и 010 с разделителями по длине тип провода ) -> предоставление 10001010 ( двоичный).

Чтобы закодировать это число как varint, вам нужно настроить общую длину в битах, кратную 7 (заполнить нулями):

-> 000000 10001010

Затем разделите его на группы по 7 бит:

-> 0000001 0001010

Затем измените порядок этих групп:

-> 0001010 0000001

И добавить дополнительный бит для каждой группы ( MSB ) - ноль для последней группы и один для всех других групп (MSB, равный 1, говорит парсеру, что существует следующая следующая группа):

-> 1 0001010 0 0000001

Что дает 0x8A 0x01 в шестнадцатеричном (ваше значение).

Расшифровывается кодировка Varint здесь .


Насколько мне известно, конструкция oneof не меняет формат проводника (он расширяет только логику синтаксического анализатора, игнорируя все, кроме последнего поля из одной группы).

Удачи!

...