Protocol Buffers(2):编码与解码

本文详细介绍了Protocol Buffers的编码与解码过程,包括Message Structure、varint编码、整数和浮点数的处理以及Length-delimited相关类型的编码。解码过程通过example.pb.cc的源码展示,解析key-value对,并重点讨论了varint在 Protobuf 中的作用和实现。
摘要由CSDN通过智能技术生成

Message Structure

在上一篇文章中我们提到,对于序列化后字节流,需要回答的一个重要问题是“从哪里到哪里是哪个数据成员”。

message中每一个field的格式为:
required/optional/repeated FieldType FieldName = FieldNumber(a unique number in current message)
在序列化时,一个field对应一个key-value对,整个二进制文件就是一连串紧密排列的key-value对,key也称为tag,先上图直观感受一下,图片来自Encoding and Evolution
Example record encoded using Protocol Buffers

key由wire type和FieldNumber两部分编码而成, 具体地key = (field_number << 3) | wire_typefield_number 部分指示了当前是哪个数据成员,通过它将cc和h文件中的数据成员与当前的key-value对应起来

key的最低3个bit为wire type,**什么是wire type?**如下表所示:

wire types
wire type被如此设计,主要是为了解决一个问题,如何知道接下来value部分的长度(字节数),如果

  • wire type = 0、1、5,编码为 key + 数据,只有一个数据,可能占数个字节,数据在编码时自带终止标记
  • wire type = 2,编码为 key + length + 数据,length指示了数据长度,可能有多个数据,顺序排在length后

解码代码一窥

接下来,我们直接看一下example.pb.cc及相关的源码,看下key-value对是如何解析的。解码过程相对简单,理解了解码过程,编码也就比较显然了

// example.proto
package example;

message Person {
   
  required string name = 1;
  required int32 id = 2;
  optional string email = 3;
}
// in example.pb.cc
bool Person::MergePartialFromCodedStream(
    ::google::protobuf::io::CodedInputStream* input) {
   
#define DO_(EXPRESSION) if (!PROTOBUF_PREDICT_TRUE(EXPRESSION)) goto failure
  ::google::protobuf::uint32 tag;
  // @@protoc_insertion_point(parse_start:example.Person)
  for (;;) {
   
    ::std::pair<::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
    tag = p.first;
    if (!p.second) goto handle_unusual;
    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
   
      // required string name = 1;
      case 1: {
   
        if (static_cast< ::google::protobuf::uint8>(tag) == (10 & 0xFF)) {
    // 10 = (1 << 3) + 2
          DO_(
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值