Protocol Buffers编码详解,例子,图解
本文不是让你掌握protobuf的使用,而是以超级细致的例子的方式分析protobuf的编码设计。通过此文你可以了解protobuf的数据压缩能力来自什么地方,版本兼容如何做到的,其Key-Value编码的设计思路。如果你详细了解此文,你应该就能具备自己造一套编解码轮子的能力(至少基本思路)。
测试的例子
阅读图片时请对比前面的例子和表格。每个字段的名称都是包含了tag的。
message S2
{
optional int32 s2_1 = 1;
optional string s2_2 = 2 ;
}
enum E1
{
E1_1 = 1;
E1_3 = 3;
E1_5 = 5;
}
message S3
{
optional int32 s3_1 = 1; //设置为0x88
optional int32 s3_2 = 2; //设置为0x8888
optional uint32 s3_3 = 3; //设置为0xE8E8E8
optional uint32 s3_4 = 4; //设置为0xE8E8E8E8
optional int64 s3_5 = 5; //设置为0x8888
optional int64 s3_6 = 6; //设置为0xE8E8E8E8
optional uint64 s3_7 = 7; //设置为0xE8E8E8E8
optional uint64 s3_8 = 8; //设置为0xE8E8E8E8E8E8E8E8
optional sint32 s3_9 = 9; //设置为0x8888
optional sint32 s3_10 = 10; //设置为-0x8888
optional sint64 s3_64 = 64; //注意这个tag id 设置为0xE8E8E8E8
optional sint64 s3_65 = 65; //注意这个tag id 设置为-0xE8E8E8E8
optional E1 s3_11 = 11; //设置为E1_5
optional bool s3_12 = 12; //设置为true
optional float s3_13 = 13; //设置 float,设置为88.888
optional fixed32 s3_14 = 14; //设置为 0x8888
optional sfixed32 s3_15 = 15; //设置为 -0x8888
optional double s3_16 = 16; //设置 double,设置为8888.8888
optional fixed64 s3_17 = 17; //设置为 0x8888888888
optional sfixed64 s3_18 = 18; //设置为 -0x8888888888
optional string s3_19 = 19; //设置为 "I love you,C++!"
optional bytes s3_20 = 20; //设置为 "I hate you,C++!"
repeated int32 s3_21 = 21; //设置为3, 270, and 86942, 用google文档的例子
repeated int32 s3_22 = 22 [packed = true]; //设置为3, 270, and 86942
repeated string s3_23 = 23; //设置为"love","hate","C++"
optional S2 s3_24 = 24; //设置为 0x1,"love"
repeated S2 s3_25 = 25; //设置为 0x16,"love" and 0x16,"hate"
repeated fixed32 s3_26 = 26; //设置为1,2,3
optional int32 s3_27 = 27; //不设置
}
编码的的数据表格如下,后面的剖析都会依赖这个表格进行。
分类说明 |
定义 |
TAG |
WriteType |
设置的值 |
编码后的16进制数据 KEY+(LENGTH)+VLAUE |
函数 |
VALUE用VARINT表示 |
optional int32 |
1 |
0 |
0x88 |
08 88 01 |
WriteInt32ToArray |
optional int32 |
2 |
0 |
0x8888 |
10 88 91 02 |
WriteInt32ToArray |
|
optional uint32 |
3 |
0 |
0xE8E8E8 |
18 e8 d1 a3 07 |
WriteUInt32ToArray |
|
optional uint32 |
4 |
0 |
0xE8E8E8E8 |
20 e8 d1 a3 c7 0e |
WriteUInt32ToArray |
|
optional int64 |
5 |
0 |
0x8888 |
28 88 91 02 |
WriteInt64ToArray |
|
optional int64 |
6 |
0 |
0xE8E8E8E8 |
30 e8 d1 a3 c7 0e |
WriteInt64ToArray |
|
optional uint64 |
7 |
0 |
0xE8E8E8E8 |
38 e8 d1 a3 c7 0e |
WriteUInt64ToArray |
|