2

考虑以下 proto 文件。

syntax="proto3";
message MessageWithInternalMessage { 
    string F1 = 1;
    _S1 s2 = 5;
    message _S1 {
        string C1 = 1;
        string C2 = 2;
    }
}

当我们为它生成代码时。使用 readTag() 完成解析,然后使用 switch 语句设置相应的字段。或考虑以下代码段。

 while (!done) {
    int tag = input.readTag();
    switch (tag) {
        case 0:
            done = true;
            break;
        default: {
            if (!parseUnknownFieldProto3(input, unknownFields, extensionRegistry, tag)) {
                done = true;
            }
            break;
        }
        case 10: {
            java.lang.String s = input.readStringRequireUtf8();
            f1_ = s;
            break;
        }
        case 42: {
            Test.InternalMessageWithSeciton._S1.Builder subBuilder = null;
            if (s2_ != null) {
            subBuilder = s2_.toBuilder();
            }
            s2_ = input.readMessage(Test.InternalMessageWithSeciton._S1.parser(), extensionRegistry);
            if (subBuilder != null) {
                subBuilder.mergeFrom(s2_);
                s2_ = subBuilder.buildPartial();
            }
            break;
        }
    }
}

我的问题是 proto 文件中的“字段 F1 的标签 1”与“生成代码中的案例 10”和“字段 s2 的标签 5”与“生成代码中的案例 42”之间的关系是什么。

4

1 回答 1

2

标头的编码格式基本上是:

header = (fieldNumber << 3) | expectedWireType;

其中“线型”是 0 到 7 之间的整数。

  • 0 = varint - 带有延续位的 base-128 编码整数
  • 1 = 64 位(整数或浮点数)
  • 2 = 以长度为前缀的数据 - 字节数的变体,后跟那么多字节(字符串、BLOB、子消息、打包数组)
  • 5 = 32 位(整数或浮点数)

所以字段 1 作为字符串是 (1 << 3) | 2 是二进制 1010,或者:10。作为子消息的字段 5 同样是 (5 << 3) | 2,或:42

于 2017-11-24T10:56:03.443 回答