Protocol Buffer Encode 说明

  • 本文来自Google Protocol Buffer Encode说明文档的翻译以及记录原地址为:<a href = "https://developers.google.com/protocol-buffers/docs/encoding#structure">https://developers.google.com/protocol-buffers/docs/encoding#structure</a>

Protocol Buf 关于encode 和 decode的说明文档

如下一个简单的message定义

message Test1 {
    required int32 a = 1;
}

在应用中如果将Test1中的a变量赋值为150,那么经过encode之后的字节流为08 96 01,此文档将叙述这些字节所代表的意义。

动态int类型

动态int类型(varints)是一种用一个或者多个字节序列化整数的方法。每一个字节(除了最后一个)都有最高有效位,暗示将会有更多的字节到来。字节的低七位为实际的数值,采用的是小端法表示。
例如对于数字-1仅仅有一个字节,那么不存在最高有效位(0000 0001)
如果是300 那么在encode之后表示为(没有其它信息仅仅是300):
1010 1100 0000 0010
首先移除最高有效位:010 1100 000 0010
由于是小端法表示的需要调整字节顺序:
000 0010 010 1100 = 300

消息结构

protocol buffer 其实是一种序列化的键值对,key是由tag和类型(type)构成的,例如:
required string name = 1;
tag是1,类型(type)是string,而变量名仅仅被用于decode 之后与类型(type)的定义相关联。
当消息被encode的时候,key和value被串行进字节序列中,当被decode时,如果遇到不被识别的key,转换器将会跳过。类型以及对应的值如下表所示:

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

在字节流中每一个key都是一个varint值,通过(tag << 3 ) | (type)获得,也就是说,最后三个bit存储类型。
举个例子:key = 08时
0000 1000 分析可以知道,type = 0 即Varint类型变量,同时tag = 1。
那么回头看Test1的例子,由于字节序列为08 96 01,第一个字节08代表key,type = 0(varint) , tag = 1,后两个字节96 01代表value,1001 0110 0000 0001,舍弃最高有效位得到:001 0110 000 0001,由于小端法,需要将字节变换顺序得到:000 0001 001 0110 即是128 + 16 + 4 + 2 = 150

更多值类型

有符号整形

如前一节所述,所有type = 0 时都会被认为是varint类型,然而不同于有符号整形(sint32,sint64,int32,int64)encode负数的时候。encode负数的时候,总是会得到10个字节的varint,出于效率的考虑,会将负数变为非常大的无符号整数,并使用ZigZag编码。
ZigZag编码:对于32位整数编码之后得到的值(n<<1)(n>>31),对于64位(n<<1)(n>>63)

No-varint 数值

No-varint 数值编码采用固定长度,字节序列采用小端法。

Strings

type是2,字节序列除了指定key,还需要保存字符串的长度,如字符串"testing":
encode之后的字节序列为:12 07 74 65 73 74 69 6e 67,第一个字节表示key,tag = 2 , type = 2,07是字符串encode之后的长度。

消息

消息的处理与字符串类似,如下所示

message Test3 {
required Test1 c = 3;
}

同样将Test1中的a赋值150,得到encode之后的字节序列为:
1a 03 08 96 01,可以看到字节序列后三个值对应的是150的key和value,1a代表message 的key(type = 2 ,tag = 3),03表示之后的长度。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,845评论 18 139
  • 国家电网公司企业标准(Q/GDW)- 面向对象的用电信息数据交换协议 - 报批稿:20170802 前言: 排版 ...
    庭说阅读 11,092评论 6 13
  • 参考文章protobuf-encode-varint-and-zigzagprotobuf格式及实现源码官方文档 ...
    爱唱歌的王小猫阅读 1,888评论 0 0
  • 1.编译程序(1)gcc xx.c,他会默认生成一个a.out的可执行文件,在a.out所在目录,执行./a.o...
    萌面大叔2阅读 1,316评论 0 1
  • 1.输入不说明有多少个Input,以EOF为结束标志 (1)这里要说明的是如果输入 1 2 3 4 (回车),这时...
    nino天阅读 302评论 0 1